Compare commits

..
81 Commits
Author SHA1 Message Date
Nassim Jahnke 489b28e520 4.8.0 Release 2023-09-21 10:34:20 +10:00
Nassim Jahnke d23e743550 Fix particle handling 2023-09-21 10:33:58 +10:00
Nassim Jahnke 16f89f2638 Don't re-enter config state if the dimension registry did not change 2023-09-19 21:14:45 +10:00
Nassim Jahnke fe5646a68c Re-send last resource pack on server switch 2023-09-19 11:54:03 +10:00
Nassim Jahnke 53aca791dd Fix reentering of the configuration state 2023-09-19 00:37:55 +10:00
Nassim Jahnke 1f0a4c26db 1.20.2-rc2 2023-09-19 00:07:43 +10:00
Nassim Jahnke 4c34ced240 Fix record handling due to no mappings
Fixes #3422
2023-09-16 13:28:15 +10:00
Nassim Jahnke 18c4f90cb0 Don't cancel system chat messages 2023-09-16 13:27:44 +10:00
Nassim Jahnke 9c90445c9c Release ConfigurationState buffers on disconnect
They're heap buffers, but still good practice
2023-09-16 13:27:23 +10:00
Nassim Jahnke 494e6ffc05 1.20.2-rc1 2023-09-16 10:19:49 +10:00
Nassim Jahnke a196dbc16b 1.20.2-pre4 2023-09-14 09:03:13 +10:00
Nassim Jahnke 8934bbdfc3 1.20.2-pre3 2023-09-12 23:06:54 +10:00
Myles 8316c59010 Merge pull request #3420 from Kichura/dev 2023-09-11 19:55:27 +01:00
Kichura 5ea1c1ec95 Use https instead of http for wiki.vg source. 2023-09-11 20:06:27 +02:00
Nassim Jahnke cc7c571a3c 1.20.2-pre2 2023-09-08 09:05:31 +10:00
Nassim Jahnke 06b4678b2d [ci skip] Add IDEA extension plugin 2023-09-06 11:20:32 +10:00
Nassim Jahnke a109118a97 1.20.2-pre1 2023-09-06 00:56:31 +10:00
Nassim Jahnke a135a1414c [ci skip] Update Gradle wrapper 2023-09-05 21:16:24 +10:00
Nassim Jahnke f50751ed48 [ci skip] Update blossom 2023-09-05 21:10:43 +10:00
Kichura 4b7998b4ea [ci skip] Update checkout to v4, Check for latest JDK 11 build (#3416) 2023-09-05 20:48:36 +10:00
Nassim Jahnke 6db1a2a614 Fix wrong packet type being used 2023-08-31 11:49:54 +10:00
Nassim Jahnke 625373827c Fix MetaTypes1_20_2 item type 2023-08-31 11:44:55 +10:00
Nassim Jahnke a9288ebd3a 23w35a 2023-08-31 00:42:47 +10:00
Nassim Jahnke 01bbb2c1c2 [ci skip] Update Hangar publish plugin 2023-08-26 20:04:06 +10:00
Nassim Jahnke 8dbc8e8eba Update mappings file for 23w33a 2023-08-18 01:28:55 +10:00
Nassim Jahnke 0c9f3aa080 23w33a 2023-08-18 01:27:00 +10:00
EnZaXD 00625be890 Move 1.9 backwards protocols to VB and move Chunk Types to the correct package (#3404) 2023-08-14 10:46:30 +10:00
Pablo Herrera e112f81ec8 Optimize memory allocation for data palette (#3402) 2023-08-14 10:40:10 +10:00
Nassim Jahnke 23f776a6ee Handle minecart blocks 2023-08-11 21:12:23 +10:00
Nassim Jahnke 0050872950 Update README 2023-08-11 21:12:03 +10:00
Nassim Jahnke 7e53f55509 Also publish dev branch builds to Hangar 2023-08-11 20:33:47 +10:00
Nassim Jahnke 1bf7962dc3 Call latestCommitHash only once 2023-08-11 16:24:27 +10:00
Nassim Jahnke 50176dc317 Include link to commit in autopublished changelog 2023-08-11 16:21:44 +10:00
Nassim Jahnke 9ed074d0d5 Handle changes block state ids 2023-08-11 15:52:53 +10:00
Nassim Jahnke 8bad8a10be Finish publishing action 2023-08-11 12:28:38 +10:00
Nassim Jahnke 34509e86c0 [ci skip] Add Velocity and Waterfall to publish config 2023-08-11 00:39:45 +10:00
Nassim Jahnke ef75bd567d [ci skip] GH already skips all actions with ci skip 2023-08-10 22:48:22 +10:00
Nassim Jahnke 7ed3e50e93 [ci skip] Skip commits with ci skip prefix 2023-08-10 22:46:15 +10:00
Nassim Jahnke a45eceaf1d Hello Hangar 😎 2023-08-10 22:18:23 +10:00
Nassim Jahnke 573cdfb3ac Merge remote-tracking branch 'origin/master' into dev 2023-08-10 21:49:26 +10:00
Nassim Jahnke 28787340d1 Setup Hangar and modrinth autopublishing 2023-08-10 21:29:03 +10:00
Nassim Jahnke c358245c0b Fix spawn tracker mapping data check 2023-08-10 17:14:01 +10:00
Nassim Jahnke cb073405b7 Effect ids start at 1 before 1.20.2 2023-08-10 17:08:36 +10:00
Nassim Jahnke f618f6a7d6 Actually write effect key 2023-08-10 13:51:15 +10:00
Nassim Jahnke c5e066e050 23w32a 2023-08-10 13:35:47 +10:00
riku6460 d954e1745d Fix itemArrayType of ItemRewriter on dev branch (#3398) 2023-08-09 07:38:24 +10:00
Nassim Jahnke 9c92ccea77 Finish up state switching 2023-08-06 15:40:15 +10:00
RK_01 2b9e0cec5c Fix maps with no map id set showing up as empty on 1.17+ (#3395) 2023-08-06 11:11:42 +10:00
RK_01 c1cd8bc03e Allow skylight to be set to null (#3396) 2023-08-06 11:08:52 +10:00
Nassim Jahnke 39efc5262e Add todo 2023-08-05 13:31:43 +10:00
Nassim Jahnke 6e5e115c3b Remove unnecessary rewriting code, fix recipe handlers 2023-08-05 12:28:39 +10:00
Nassim Jahnke fbcbd33c66 Small refactors 2023-08-04 12:35:35 +10:00
Nassim Jahnke 7bea3142bc Fix baseprotocol registration 2023-08-04 12:26:07 +10:00
Nassim Jahnke fb472c3454 Cleanup imports 2023-08-04 12:25:29 +10:00
Nassim Jahnke ac10bb3fd0 Complete 23w31a protocol 2023-08-04 12:22:18 +10:00
Nassim Jahnke 1bc3d407d1 More juicy, untested work 2023-08-03 23:03:42 +10:00
Nassim Jahnke 62c0ef360f More absolutely cursed WIP 2023-08-03 21:58:23 +10:00
Nassim Jahnke 8c6d104faa 23w31a eletric boogaloo 2023-08-03 19:47:18 +10:00
Nassim Jahnke f6b8c4a8c8 Rename rewriter classes 2023-08-03 18:38:18 +10:00
Nassim Jahnke 6586fc1436 More work on the snapshot 2023-08-03 18:36:30 +10:00
Nassim Jahnke 6dfd4747ee Start working on 23w31a 2023-08-03 13:58:22 +10:00
Nassim Jahnke 6377721ebd Fix non item display rotation
Fixes #3383
2023-07-24 20:56:45 +10:00
RK_01 2ec6185c46 Fix <= 1.14 position y sign reading (#3381) 2023-07-12 19:10:49 +02:00
Nassim Jahnke b22907748a Update gradle wrapper 2023-07-11 23:34:37 +02:00
Nassim Jahnke 1aee8a7a6c Don't create ack task when already disabled
Fixes #3373
2023-07-02 13:29:07 +02:00
Nassim Jahnke 7edb43844c Properly handle item display rotation change
Fixes #3354
2023-07-02 13:27:03 +02:00
sandtechnology f28aac5eb3 Handle more null TextComponent for 1.19 to 1.18.2 (#3366) 2023-06-24 11:12:14 +02:00
Nassim Jahnke 4971eeab6a Don't check block items for armor swapping 2023-06-22 11:03:11 +02:00
Pablo Herrera 0bb940e42d Fix missing block connection updates on cancelled place/remove (#3359) 2023-06-20 13:39:02 +02:00
Pablo Herrera e32933ada9 Fix late registration of join listener (#3360) 2023-06-19 17:02:05 +02:00
EnZaXD a817746edc Remove requirement for MovementTransmitterProvider (#3355) 2023-06-18 15:30:58 +02:00
RK_01 408392e796 Fixed some 1.9 -> 1.8 movement issues (#3353) 2023-06-18 14:51:37 +02:00
Kichura 20a4ae3e4b Use friendly names in CI tasks, Update shadow and blossom (#3349) 2023-06-15 09:48:13 +02:00
Nassim Jahnke 08b2d78165 Move dump creation to util class 2023-06-14 23:13:44 +02:00
FlorianMichael 17eb7b676a Remap old smithing menu to furnace in 1.20 2023-06-12 18:57:20 +02:00
Nassim Jahnke 9a1598b9ed Update 1.20/1.20.1 protocol version 2023-06-12 16:47:22 +02:00
Myles 9e7cd151bc Update version table to 1.20 2023-06-11 12:02:25 +01:00
David Luedtke 2a14f9a0cd Fix display rotation change 2023-06-09 12:17:11 +02:00
Ossi Erkkilä bf825d5ef6 Fix SpongeViaInjector#getServerProtocolVersion() for Sponge API-10+ (#3337) 2023-06-09 11:29:55 +02:00
EnZaXD 28ba4afc27 Added VersionInfo#getVersion to bypass Java inlining (#3344) 2023-06-09 08:52:30 +02:00
Nassim Jahnke 7f347231bb Bump version to 4.7.1-SNAPSHOT 2023-06-08 13:21:19 +02:00
105 changed files with 3133 additions and 896 deletions

No files matched your search

+5 -9
View File
@@ -1,6 +1,3 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Java CI with Gradle
on: [push, pull_request]
@@ -13,16 +10,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
+27
View File
@@ -0,0 +1,27 @@
name: Publish to Hangar and Modrinth
on:
push:
branches:
- master
- dev
jobs:
publish:
if: github.repository_owner == 'ViaVersion'
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
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
+39 -34
View File
@@ -1,61 +1,49 @@
# ViaVersion - Spigot, Sponge, BungeeCord, Velocity
# ViaVersion
[![Latest Release](https://img.shields.io/github/v/release/ViaVersion/ViaVersion)](https://viaversion.com)
[![Build Status](https://github.com/ViaVersion/ViaVersion/actions/workflows/gradle.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaVersion/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**Allows the connection of higher client versions to lower server versions**
**Allows the connection of higher client versions to lower server versions -
it works on any platform you can think of.**
The base ViaVersion jar runs on Paper, Velocity, Bungee, and Sponge. We also have projects integrating ViaVersion to run
on Fabric, Forge, or as a standalone proxy to join from basically any client version on any server version from the
past decade. **See [HERE](https://github.com/ViaVersion) for an overview of the different Via\* projects.**
Supported Versions:
![Table (https://i.imgur.com/aSjHvQk.png)](https://i.imgur.com/aSjHvQk.png)
On Paper you may also use ProtocolSupport, but ensure you have the right build for your server version.
![Table (https://i.imgur.com/sTrVnC2.png)](https://i.imgur.com/sTrVnC2.png)
**User Docs:** https://docs.viaversion.com/display/VIAVERSION/
Sources
Releases/Dev Builds
--------
**[OpenNBT](https://github.com/ViaVersion/OpenNBT)**
You can find official releases in the following places:
**[Via Mappings Generator](https://github.com/ViaVersion/Mappings)**
- **Hangar (for our plugins)**: https://hangar.papermc.io/ViaVersion/ViaVersion
- **Modrinth (for our mods)**: https://modrinth.com/mod/viaversion
- **GitHub**: https://github.com/ViaVersion/ViaVersion/releases
**[Mojang mappings](https://minecraft.fandom.com/wiki/Obfuscation_map)** (Thank you, Mojang, very cool)
Dev builds for **all** of our projects are on our Jenkins server:
**[wiki.vg](https://wiki.vg)** (Used for historic information regarding packet structure, we also contribute back)
**[Burger](https://github.com/Pokechu22/Burger)** (See [PAaaS](https://github.com/Matsv/Paaas))
Releases / Dev Builds
--------
You can find official releases here:
https://www.spigotmc.org/resources/viaversion.19254/history
- **Jenkins**: https://ci.viaversion.com
ViaVersion as a Dependency
----------
You can find official dev builds here:
**Jenkins:** https://ci.viaversion.com
**JavaDocs:** https://jd.viaversion.com
**Maven Repository:**
**Maven:**
```xml
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
</repository>
```
**API-artifact:**
```xml
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
@@ -64,7 +52,17 @@ You can find official dev builds here:
</dependency>
```
Replace the version depending on your needs.
**Gradle:**
```kotlin
repositories {
maven("https://repo.viaversion.com")
}
dependencies {
compileOnly("com.viaversion:viaversion-api:VERSION") // Replace the version
}
```
If you need access to the existing protocol or platform implementations, use the parent artifact `viaversion`.
Please note the [differences in licensing](#license).
@@ -73,8 +71,7 @@ Please note the [differences in licensing](#license).
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.
of the `build/libs` directory.
Mapping Files
@@ -82,13 +79,21 @@ Mapping Files
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings).
Resources
--------
- **[Via Mappings Generator](https://github.com/ViaVersion/Mappings)**
- **[Mojang mappings](https://minecraft.fandom.com/wiki/Obfuscation_map)** (Thank you, Mojang, very cool)
- **[wiki.vg](https://wiki.vg)** (Used for historic information regarding packet structure, we also contribute back)
- **[Burger](https://github.com/Pokechu22/Burger)** (See [PAaaS](https://github.com/Matsv/Paaas))
License
--------
The entirety of the [API directory](api) (including the legacy API directory) is licensed under the MIT License;
see [licenses/MIT.md](licenses/MIT.md) for
details.
Everything else, unless explicitly stated otherwise, is licensed under the GNU General Public License, including the end
product as a whole; see [licenses/GPL.md](licenses/GPL.md) for details.
Everything else, unless explicitly stated otherwise, is licensed under the GNU General Public License v3, including the
end-product as a whole; see [licenses/GPL.md](licenses/GPL.md) for details.
Special thanks to all our [Contributors](https://github.com/ViaVersion/ViaVersion/graphs/contributors).
@@ -83,10 +83,11 @@ public class ProtocolVersion {
public static final ProtocolVersion v1_18 = register(757, "1.18/1.18.1", new VersionRange("1.18", 0, 1));
public static final ProtocolVersion v1_18_2 = register(758, "1.18.2");
public static final ProtocolVersion v1_19 = register(759, "1.19");
public static final ProtocolVersion v1_19_1 = register(760, "1.19.1");
public static final ProtocolVersion v1_19_1 = register(760, "1.19.1/2", new VersionRange("1.19", 1, 2));
public static final ProtocolVersion v1_19_3 = register(761, "1.19.3");
public static final ProtocolVersion v1_19_4 = register(762, "1.19.4");
public static final ProtocolVersion v1_20 = register(763, "1.20");
public static final ProtocolVersion v1_20 = register(763, "1.20/1.20.1", new VersionRange("1.20", 0, 1));
public static final ProtocolVersion v1_20_2 = register(764, "1.20.2");
public static final ProtocolVersion unknown = register(-1, "UNKNOWN");
public static ProtocolVersion register(int version, String name) {
+10 -3
View File
@@ -1,11 +1,18 @@
plugins {
id("net.kyori.blossom")
id("org.jetbrains.gradle.plugin.idea-ext")
id("via.shadow-conventions")
}
blossom {
replaceToken("\$VERSION", project.version)
replaceToken("\$IMPL_VERSION", "git-ViaVersion-${project.version}:${rootProject.latestCommitHash()}")
sourceSets {
main {
blossom {
javaSources {
property("version", project.version.toString())
property("impl_version", "git-ViaVersion-${project.version}:${rootProject.latestCommitHash()}")
}
}
}
}
dependencies {
@@ -31,5 +31,14 @@ public final class VersionInfo {
*
* @see ViaPlatform#getPluginVersion()
*/
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;
}
}
@@ -63,7 +63,7 @@ public interface ViaAPI<T> {
* @return API version incremented with meaningful API changes
*/
default int apiVersion() {
return 19;
return 20;
}
/**
@@ -38,4 +38,7 @@ public interface StorableObject {
default boolean clearOnServerSwitch() {
return true;
}
default void onRemove() {
}
}
@@ -50,4 +50,14 @@ public final class Quaternion {
public float w() {
return w;
}
@Override
public String toString() {
return "Quaternion{" +
"x=" + x +
", y=" + y +
", z=" + z +
", w=" + w +
'}';
}
}
@@ -47,6 +47,11 @@ public class ChunkSectionLightImpl implements ChunkSectionLight {
@Override
public void setSkyLight(byte[] data) {
if (data == null) {
this.skyLight = null;
return;
}
if (data.length != LIGHT_LENGTH) throw new IllegalArgumentException("Data length != " + LIGHT_LENGTH);
if (this.skyLight == null) {
this.skyLight = new NibbleArray(data);
@@ -29,21 +29,24 @@ import it.unimi.dsi.fastutil.ints.IntList;
public final class DataPaletteImpl implements DataPalette {
private static final int DEFAULT_INITIAL_SIZE = 16;
private final IntList palette;
private final Int2IntMap inversePalette;
private final int[] values;
private final int sizeBits;
private ChunkData values;
public DataPaletteImpl(final int valuesLength) {
this(valuesLength, 8);
this(valuesLength, DEFAULT_INITIAL_SIZE);
}
public DataPaletteImpl(final int valuesLength, final int expectedPaletteLength) {
this.values = new int[valuesLength];
public DataPaletteImpl(final int valuesLength, final int initialSize) {
values = new EmptyChunkData(valuesLength);
sizeBits = Integer.numberOfTrailingZeros(valuesLength) / 3;
// Pre-size the palette array/map
palette = new IntArrayList(expectedPaletteLength);
inversePalette = new Int2IntOpenHashMap(expectedPaletteLength);
palette = new IntArrayList(initialSize);
// To get an initial table size of initialSize, need to scale it down by load factor.
inversePalette = new Int2IntOpenHashMap((int) (initialSize * Int2IntOpenHashMap.DEFAULT_LOAD_FACTOR));
inversePalette.defaultReturnValue(-1);
}
@@ -54,7 +57,7 @@ public final class DataPaletteImpl implements DataPalette {
@Override
public int idAt(final int sectionCoordinate) {
final int index = values[sectionCoordinate];
final int index = values.get(sectionCoordinate);
return palette.getInt(index);
}
@@ -67,17 +70,17 @@ public final class DataPaletteImpl implements DataPalette {
inversePalette.put(id, index);
}
values[sectionCoordinate] = index;
values.set(sectionCoordinate, index);
}
@Override
public int paletteIndexAt(final int packedCoordinate) {
return values[packedCoordinate];
return values.get(packedCoordinate);
}
@Override
public void setPaletteIndexAt(final int sectionCoordinate, final int index) {
values[sectionCoordinate] = index;
values.set(sectionCoordinate, index);
}
@Override
@@ -131,4 +134,77 @@ public final class DataPaletteImpl implements DataPalette {
palette.clear();
inversePalette.clear();
}
interface ChunkData {
int get(int idx);
void set(int idx, int val);
}
private class EmptyChunkData implements ChunkData {
private final int size;
public EmptyChunkData(int size) {
this.size = size;
}
@Override
public int get(int idx) {
return 0;
}
@Override
public void set(int idx, int val) {
if (val != 0) {
values = new ByteChunkData(size);
values.set(idx, val);
}
}
}
private class ByteChunkData implements ChunkData {
private final byte[] data;
public ByteChunkData(int size) {
this.data = new byte[size];
}
@Override
public int get(int idx) {
return data[idx] & 0xFF;
}
@Override
public void set(int idx, int val) {
// Overflowed size of byte (over 256 different materials), go up to short
if (val > 0xFF) {
values = new ShortChunkData(data);
values.set(idx, val);
return;
}
data[idx] = (byte) val;
}
}
private static class ShortChunkData implements ChunkData {
private final short[] data;
public ShortChunkData(byte[] data) {
this.data = new short[data.length];
for (int i = 0; i < data.length; i++) {
this.data[i] = (short) (data[i] & 0xFF);
}
}
@Override
public int get(int idx) {
return data[idx];
}
@Override
public void set(int idx, int val) {
data[idx] = (short) val;
}
}
}
@@ -0,0 +1,73 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.metadata;
import java.util.Objects;
public final class ChunkPosition {
private final int chunkX;
private final int chunkZ;
public ChunkPosition(int chunkX, int chunkZ) {
this.chunkX = chunkX;
this.chunkZ = chunkZ;
}
public ChunkPosition(long chunkKey) {
this.chunkX = (int) chunkKey;
this.chunkZ = (int) (chunkKey >> 32);
}
public int chunkX() {
return chunkX;
}
public int chunkZ() {
return chunkZ;
}
public long chunkKey() {
return (long) chunkX & 0xffffffffL | ((long) chunkZ & 0xffffffffL) << 32;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ChunkPosition that = (ChunkPosition) o;
return chunkX == that.chunkX && chunkZ == that.chunkZ;
}
@Override
public int hashCode() {
return Objects.hash(chunkX, chunkZ);
}
@Override
public String toString() {
return "ChunkPosition{" +
"chunkX=" + chunkX +
", chunkZ=" + chunkZ +
'}';
}
}
@@ -0,0 +1,64 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.metadata.types;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.ParticleType;
public final class MetaTypes1_20_2 extends AbstractMetaTypes {
public final MetaType byteType = add(0, Type.BYTE);
public final MetaType varIntType = add(1, Type.VAR_INT);
public final MetaType longType = add(2, Type.VAR_LONG);
public final MetaType floatType = add(3, Type.FLOAT);
public final MetaType stringType = add(4, Type.STRING);
public final MetaType componentType = add(5, Type.COMPONENT);
public final MetaType optionalComponentType = add(6, Type.OPTIONAL_COMPONENT);
public final MetaType itemType = add(7, Type.ITEM1_20_2);
public final MetaType booleanType = add(8, Type.BOOLEAN);
public final MetaType rotationType = add(9, Type.ROTATION);
public final MetaType positionType = add(10, Type.POSITION1_14);
public final MetaType optionalPositionType = add(11, Type.OPTIONAL_POSITION_1_14);
public final MetaType directionType = add(12, Type.VAR_INT);
public final MetaType optionalUUIDType = add(13, Type.OPTIONAL_UUID);
public final MetaType blockStateType = add(14, Type.VAR_INT);
public final MetaType optionalBlockStateType = add(15, Type.VAR_INT);
public final MetaType nbtType = add(16, Type.NAMELESS_NBT);
public final MetaType particleType;
public final MetaType villagerDatatType = add(18, Type.VILLAGER_DATA);
public final MetaType optionalVarIntType = add(19, Type.OPTIONAL_VAR_INT);
public final MetaType poseType = add(20, Type.VAR_INT);
public final MetaType catVariantType = add(21, Type.VAR_INT);
public final MetaType frogVariantType = add(22, Type.VAR_INT);
public final MetaType optionalGlobalPosition = add(23, Type.OPTIONAL_GLOBAL_POSITION);
public final MetaType paintingVariantType = add(24, Type.VAR_INT);
public final MetaType snifferState = add(25, Type.VAR_INT);
public final MetaType vectorType = add(26, Type.VECTOR3F);
public final MetaType quaternionType = add(27, Type.QUATERNION);
public MetaTypes1_20_2(final ParticleType particleType) {
super(28);
this.particleType = add(17, particleType);
}
}
@@ -77,6 +77,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
/**
* Creates a protocol with automated id mapping if the respective packet type classes are not null.
* They are also required to track the CONFIGURATION state.
*/
protected AbstractProtocol(@Nullable Class<CU> unmappedClientboundPacketType, @Nullable Class<CM> mappedClientboundPacketType,
@Nullable Class<SM> mappedServerboundPacketType, @Nullable Class<SU> unmappedServerboundPacketType) {
@@ -96,6 +97,19 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
registerPackets();
// Register handlers for protocol state switching
// TODO Only register one of those handlers, possibly somehow in the base protocol
final SU configurationAcknowledgedPacket = configurationAcknowledgedPacket();
if (configurationAcknowledgedPacket != null) {
registerServerbound(configurationAcknowledgedPacket, wrapper -> wrapper.user().getProtocolInfo().setState(State.CONFIGURATION));
}
final ServerboundPacketType finishConfigurationPacket = finishConfigurationPacket();
if (finishConfigurationPacket != null) {
final int id = finishConfigurationPacket.getId();
registerServerbound(State.CONFIGURATION, id, id, wrapper -> wrapper.user().getProtocolInfo().setState(State.PLAY));
}
// Register the rest of the ids with no handlers if necessary
if (unmappedClientboundPacketType != null && mappedClientboundPacketType != null
&& unmappedClientboundPacketType != mappedClientboundPacketType) {
@@ -208,6 +222,17 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
return Collections.emptyMap();
}
protected @Nullable SU configurationAcknowledgedPacket() {
final Map<State, PacketTypeMap<SU>> packetTypes = packetTypesProvider.unmappedServerboundPacketTypes();
final PacketTypeMap<SU> packetTypeMap = packetTypes.get(State.PLAY);
return packetTypeMap != null ? packetTypeMap.typeByName("CONFIGURATION_ACKNOWLEDGED") : null;
}
protected @Nullable ServerboundPacketType finishConfigurationPacket() {
// To be overridden
return null;
}
// ---------------------------------------------------------------------------------
@Override
@@ -361,7 +386,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
}
}
private void throwRemapError(Direction direction, State state, int unmappedPacketId, int mappedPacketId, InformativeException e) throws InformativeException {
protected void throwRemapError(Direction direction, State state, int unmappedPacketId, int mappedPacketId, InformativeException e) throws InformativeException {
// Don't print errors during handshake/login/status
if (state != State.PLAY && direction == Direction.SERVERBOUND && !Via.getManager().debugHandler().enabled()) {
e.setShouldBePrinted(false);
@@ -27,5 +27,6 @@ public enum State {
HANDSHAKE,
STATUS,
LOGIN,
PLAY
PLAY,
CONFIGURATION
}
@@ -25,9 +25,11 @@ package com.viaversion.viaversion.api.protocol.packet.provider;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
import org.checkerframework.checker.nullness.qual.Nullable;
final class PacketTypeArrayMap<P> implements PacketTypeMap<P> {
final class PacketTypeArrayMap<P extends PacketType> implements PacketTypeMap<P> {
private final Map<String, P> packetsByName;
private final P[] packets;
@@ -29,7 +29,7 @@ import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface PacketTypeMap<P> {
public interface PacketTypeMap<P extends PacketType> {
/**
* Returns the packet type by the given name.
@@ -67,11 +67,11 @@ public interface PacketTypeMap<P> {
return of(byName, types);
}
static <T> PacketTypeMap<T> of(final Map<String, T> packetsByName, final Int2ObjectMap<T> packetsById) {
static <T extends PacketType> PacketTypeMap<T> of(final Map<String, T> packetsByName, final Int2ObjectMap<T> packetsById) {
return new PacketTypeMapMap<>(packetsByName, packetsById);
}
static <T> PacketTypeMap<T> of(final Map<String, T> packetsByName, final T[] packets) {
static <T extends PacketType> PacketTypeMap<T> of(final Map<String, T> packetsByName, final T[] packets) {
return new PacketTypeArrayMap<>(packetsByName, packets);
}
}
@@ -22,12 +22,13 @@
*/
package com.viaversion.viaversion.api.protocol.packet.provider;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import java.util.Collection;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
final class PacketTypeMapMap<P> implements PacketTypeMap<P> {
final class PacketTypeMapMap<P extends PacketType> implements PacketTypeMap<P> {
private final Map<String, P> packetsByName;
private final Int2ObjectMap<P> packetsById;
@@ -83,7 +83,8 @@ public class ProtocolVersion {
public static final ProtocolVersion v1_19_1 = register(760, "1.19.1/2", new VersionRange("1.19", 1, 2));
public static final ProtocolVersion v1_19_3 = register(761, "1.19.3");
public static final ProtocolVersion v1_19_4 = register(762, "1.19.4");
public static final ProtocolVersion v1_20 = register(763, "1.20");
public static final ProtocolVersion v1_20 = register(763, "1.20/1.20.1", new VersionRange("1.20", 0, 1));
public static final ProtocolVersion v1_20_2 = register(764, "1.20.2");
public static final ProtocolVersion unknown = register(-1, "UNKNOWN");
public static ProtocolVersion register(int version, String name) {
@@ -22,7 +22,6 @@
*/
package com.viaversion.viaversion.api.type;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.google.gson.JsonElement;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
@@ -36,6 +35,7 @@ import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.Vector3f;
import com.viaversion.viaversion.api.minecraft.VillagerData;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.ChunkPosition;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.BooleanType;
import com.viaversion.viaversion.api.type.types.ByteArrayType;
@@ -59,15 +59,18 @@ import com.viaversion.viaversion.api.type.types.VarIntType;
import com.viaversion.viaversion.api.type.types.VarLongType;
import com.viaversion.viaversion.api.type.types.VoidType;
import com.viaversion.viaversion.api.type.types.minecraft.BlockChangeRecordType;
import com.viaversion.viaversion.api.type.types.minecraft.ChunkPositionType;
import com.viaversion.viaversion.api.type.types.minecraft.EulerAngleType;
import com.viaversion.viaversion.api.type.types.minecraft.FlatItemArrayType;
import com.viaversion.viaversion.api.type.types.minecraft.FlatItemType;
import com.viaversion.viaversion.api.type.types.minecraft.FlatVarIntItemArrayType;
import com.viaversion.viaversion.api.type.types.minecraft.FlatVarIntItemType;
import com.viaversion.viaversion.api.type.types.minecraft.GlobalPositionType;
import com.viaversion.viaversion.api.type.types.minecraft.Item1_20_2Type;
import com.viaversion.viaversion.api.type.types.minecraft.ItemArrayType;
import com.viaversion.viaversion.api.type.types.minecraft.ItemType;
import com.viaversion.viaversion.api.type.types.minecraft.NBTType;
import com.viaversion.viaversion.api.type.types.minecraft.NamelessNBTType;
import com.viaversion.viaversion.api.type.types.minecraft.OptionalVarIntType;
import com.viaversion.viaversion.api.type.types.minecraft.PlayerMessageSignatureType;
import com.viaversion.viaversion.api.type.types.minecraft.Position1_14Type;
@@ -163,10 +166,11 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
public static final Type<Vector3f> VECTOR3F = new Vector3fType();
public static final Type<Quaternion> QUATERNION = new QuaternionType();
public static final Type<CompoundTag> NBT = new NBTType();
public static final Type<CompoundTag> NAMELESS_NBT = new NamelessNBTType();
public static final Type<CompoundTag[]> NBT_ARRAY = new ArrayType<>(Type.NBT);
public static final Type<GlobalPosition> GLOBAL_POSITION = new GlobalPositionType();
public static final Type<GlobalPosition> OPTIONAL_GLOBAL_POSITION = new GlobalPositionType.OptionalGlobalPositionType();
public static final Type<ChunkPosition> CHUNK_POSITION = new ChunkPositionType();
public static final Type<BlockChangeRecord> BLOCK_CHANGE_RECORD = new BlockChangeRecordType();
public static final Type<BlockChangeRecord[]> BLOCK_CHANGE_RECORD_ARRAY = new ArrayType<>(Type.BLOCK_CHANGE_RECORD);
@@ -194,6 +198,9 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
public static final Type<Item[]> FLAT_ITEM_ARRAY_VAR_INT = new ArrayType<>(FLAT_ITEM);
public static final Type<Item[]> FLAT_VAR_INT_ITEM_ARRAY_VAR_INT = new ArrayType<>(FLAT_VAR_INT_ITEM);
public static final Type<Item> ITEM1_20_2 = new Item1_20_2Type();
public static final Type<Item[]> ITEM1_20_2_VAR_INT_ARRAY = new ArrayType<>(ITEM1_20_2);
/* Actual Class */
private final Class<? super T> outputClass;
private final String typeName;
@@ -0,0 +1,45 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.minecraft.metadata.ChunkPosition;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class ChunkPositionType extends Type<ChunkPosition> {
public ChunkPositionType() {
super(ChunkPosition.class);
}
@Override
public ChunkPosition read(ByteBuf buffer) throws Exception {
final long chunkKey = Type.LONG.readPrimitive(buffer);
return new ChunkPosition(chunkKey);
}
@Override
public void write(ByteBuf buffer, ChunkPosition chunkPosition) throws Exception {
Type.LONG.writePrimitive(buffer, chunkPosition.chunkKey());
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public class Item1_20_2Type extends BaseItemType {
public Item1_20_2Type() {
super("Item1_20_2Type");
}
@Override
public @Nullable Item read(final ByteBuf buffer) throws Exception {
if (!buffer.readBoolean()) {
return null;
}
final Item item = new DataItem();
item.setIdentifier(VAR_INT.readPrimitive(buffer));
item.setAmount(buffer.readByte());
item.setTag(NAMELESS_NBT.read(buffer));
return item;
}
@Override
public void write(final ByteBuf buffer, @Nullable final Item object) throws Exception {
if (object == null) {
buffer.writeBoolean(false);
} else {
buffer.writeBoolean(true);
VAR_INT.writePrimitive(buffer, object.identifier());
buffer.writeByte(object.amount());
NAMELESS_NBT.write(buffer, object.tag());
}
}
}
@@ -28,6 +28,7 @@ import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ItemType extends BaseItemType {
public ItemType() {
super("Item");
}
@@ -22,15 +22,15 @@
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.github.steveice10.opennbt.NBTIO;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.limiter.TagLimiter;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.IOException;
public class NBTType extends Type<CompoundTag> {
@@ -43,23 +43,50 @@ public class NBTType extends Type<CompoundTag> {
@Override
public CompoundTag read(ByteBuf buffer) throws Exception {
int readerIndex = buffer.readerIndex();
byte b = buffer.readByte();
if (b == 0) {
return null;
} else {
buffer.readerIndex(readerIndex);
return NBTIO.readTag((DataInput) new ByteBufInputStream(buffer), TagLimiter.create(MAX_NBT_BYTES, MAX_NESTING_LEVEL));
}
return read(buffer, true);
}
@Override
public void write(ByteBuf buffer, CompoundTag object) throws Exception {
if (object == null) {
buffer.writeByte(0);
} else {
ByteBufOutputStream bytebufStream = new ByteBufOutputStream(buffer);
NBTIO.writeTag((DataOutput) bytebufStream, object);
write(buffer, object, "");
}
public static CompoundTag read(final ByteBuf buffer, final boolean readName) throws Exception {
final int readerIndex = buffer.readerIndex();
final byte b = buffer.readByte();
if (b == 0) {
return null;
}
buffer.readerIndex(readerIndex);
final ByteBufInputStream in = new ByteBufInputStream(buffer);
final int id = in.readByte();
if (id != CompoundTag.ID) {
throw new IOException(String.format("Expected root tag to be a CompoundTag, was %s", id));
}
if (readName) {
in.skipBytes(in.readUnsignedShort());
}
final TagLimiter tagLimiter = TagLimiter.create(MAX_NBT_BYTES, MAX_NESTING_LEVEL);
final CompoundTag tag = new CompoundTag();
tag.read(in, tagLimiter);
return tag;
}
public static void write(final ByteBuf buffer, final CompoundTag tag, final @Nullable String name) throws Exception {
if (tag == null) {
buffer.writeByte(0);
return;
}
final ByteBufOutputStream out = new ByteBufOutputStream(buffer);
out.writeByte(CompoundTag.ID);
if (name != null) {
out.writeUTF(name);
}
tag.write(out);
}
}
@@ -0,0 +1,44 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class NamelessNBTType extends Type<CompoundTag> {
public NamelessNBTType() {
super(CompoundTag.class);
}
@Override
public CompoundTag read(final ByteBuf buffer) throws Exception {
return NBTType.read(buffer, false);
}
@Override
public void write(final ByteBuf buffer, final CompoundTag tag) throws Exception {
NBTType.write(buffer, tag, null);
}
}
@@ -28,26 +28,24 @@ import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class PositionType extends Type<Position> {
public PositionType() {
super(Position.class);
}
@Override
public Position read(ByteBuf buffer) {
long val = buffer.readLong();
long x = (val >> 38); // signed
long y = (val >> 26) & 0xfff; // unsigned
// this shifting madness is used to preserve sign
long z = (val << 38) >> 38; // signed
final long val = buffer.readLong();
final long x = (val >> 38);
final long y = (val << 26) >> 52;
final long z = (val << 38) >> 38;
return new Position((int) x, (short) y, (int) z);
}
@Override
public void write(ByteBuf buffer, Position object) {
buffer.writeLong((((long) object.x() & 0x3ffffff) << 38)
| ((((long) object.y()) & 0xfff) << 26)
| (object.z() & 0x3ffffff));
buffer.writeLong((object.x() & 0X3FFFFFFL) << 38 | (object.y() & 0XFFFL) << 26 | (object.z() & 0X3FFFFFFL));
}
public static final class OptionalPositionType extends OptionalType<Position> {
@@ -0,0 +1,53 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntityImpl;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class BlockEntityType1_20_2 extends Type<BlockEntity> {
public BlockEntityType1_20_2() {
super(BlockEntity.class);
}
@Override
public BlockEntity read(final ByteBuf buffer) throws Exception {
final byte xz = buffer.readByte();
final short y = buffer.readShort();
final int typeId = Type.VAR_INT.readPrimitive(buffer);
final CompoundTag tag = Type.NAMELESS_NBT.read(buffer);
return new BlockEntityImpl(xz, y, typeId, tag);
}
@Override
public void write(final ByteBuf buffer, final BlockEntity entity) throws Exception {
buffer.writeByte(entity.packedXZ());
buffer.writeShort(entity.y());
Type.VAR_INT.writePrimitive(buffer, entity.typeId());
Type.NAMELESS_NBT.write(buffer, entity.tag());
}
}
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaTypes1_20_2;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.MetaListType;
import com.viaversion.viaversion.api.type.types.minecraft.ParticleType;
import java.util.List;
public final class Types1_20_2 {
public static final Type<BlockEntity> BLOCK_ENTITY = new BlockEntityType1_20_2();
public static final ParticleType PARTICLE = Types1_20.PARTICLE; // Only safe to use after protocol loading
public static final MetaTypes1_20_2 META_TYPES = new MetaTypes1_20_2(PARTICLE);
public static final Type<Metadata> METADATA = new MetadataType(META_TYPES);
public static final Type<List<Metadata>> METADATA_LIST = new MetaListType(METADATA);
}
+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")
}
+18
View File
@@ -38,6 +38,24 @@ 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 JavaPluginExtension.javaTarget(version: Int) {
toolchain.languageVersion.set(JavaLanguageVersion.of(version))
}
@@ -103,6 +103,12 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player>
manager.init();
}
if (Via.getConfig().shouldRegisterUserConnectionOnJoin()) {
// When event priority ties, registration order is used.
// Must register without delay to ensure other plugins on lowest get the fix applied.
getServer().getPluginManager().registerEvents(new JoinListener(), this);
}
if (FOLIA) {
// Use Folia's RegionizedServerInitEvent to run code after the server has loaded
final Class<? extends Event> serverInitEventClass;
@@ -39,12 +39,16 @@ public final class ArmorToggleListener extends ViaBukkitListener {
public void itemUse(final PlayerInteractEvent event) {
final Player player = event.getPlayer();
final ItemStack item = event.getItem();
if (item == null || event.getHand() == null || !isOnPipe(player)) {
if (item == null || event.getHand() == null) {
return;
}
final EquipmentSlot armorItemSlot = item.getType().getEquipmentSlot();
if (armorItemSlot != EquipmentSlot.HAND && armorItemSlot != EquipmentSlot.OFF_HAND) {
if (armorItemSlot == EquipmentSlot.HAND || armorItemSlot == EquipmentSlot.OFF_HAND || item.getType().isBlock()) {
return;
}
if (isOnPipe(player)) {
final PlayerInventory inventory = player.getInventory();
final ItemStack armor = inventory.getItem(armorItemSlot);
// If two pieces of armor are equal, the client will do nothing.
@@ -79,10 +79,6 @@ public class BukkitViaLoader implements ViaPlatformLoader {
public void load() {
registerListener(new UpdateListener());
if (Via.getConfig().shouldRegisterUserConnectionOnJoin()) {
registerListener(new JoinListener());
}
/* Base Protocol */
final ViaVersionPlugin plugin = (ViaVersionPlugin) Bukkit.getPluginManager().getPlugin("ViaVersion");
@@ -39,7 +39,10 @@ public final class BukkitAckSequenceProvider extends AckSequenceProvider {
if (previousSequence == -1) {
final int serverProtocolVersion = connection.getProtocolInfo().getServerProtocolVersion();
final long delay = serverProtocolVersion > ProtocolVersion.v1_8.getVersion() && serverProtocolVersion < ProtocolVersion.v1_14.getVersion() ? 2 : 1;
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new AckSequenceTask(connection, sequenceStorage), delay);
if (plugin.isEnabled()) {
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new AckSequenceTask(connection, sequenceStorage), delay);
}
}
}
}
@@ -25,6 +25,9 @@ import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.MovementTrac
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.viaversion.viaversion.util.PipelineUtil;
import io.netty.channel.ChannelHandlerContext;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -79,17 +82,15 @@ public class BukkitViaMovementTransmitter extends MovementTransmitterProvider {
}
}
@Override
public Object getFlyingPacket() {
if (idlePacket == null)
throw new NullPointerException("Could not locate flying packet");
if (idlePacket == null) throw new NullPointerException("Could not locate flying packet");
return idlePacket;
}
@Override
public Object getGroundPacket() {
if (idlePacket == null)
throw new NullPointerException("Could not locate flying packet");
if (idlePacket == null) throw new NullPointerException("Could not locate flying packet");
return idlePacket2;
}
@@ -112,7 +113,15 @@ public class BukkitViaMovementTransmitter extends MovementTransmitterProvider {
}
}
} else {
super.sendPlayer(info);
ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", info.getChannel().pipeline());
if (context != null) {
if (info.get(MovementTracker.class).isGround()) {
context.fireChannelRead(getGroundPacket());
} else {
context.fireChannelRead(getFlyingPacket());
}
info.get(MovementTracker.class).incrementIdlePacket();
}
}
}
}
@@ -28,12 +28,10 @@ import com.viaversion.viaversion.bungee.listeners.UpdateListener;
import com.viaversion.viaversion.bungee.providers.BungeeBossBarProvider;
import com.viaversion.viaversion.bungee.providers.BungeeEntityIdProvider;
import com.viaversion.viaversion.bungee.providers.BungeeMainHandProvider;
import com.viaversion.viaversion.bungee.providers.BungeeMovementTransmitter;
import com.viaversion.viaversion.bungee.providers.BungeeVersionProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.BossBarProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.EntityIdProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MainHandProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -71,7 +69,6 @@ public class BungeeViaLoader implements ViaPlatformLoader {
Via.getManager().getProviders().use(EntityIdProvider.class, new BungeeEntityIdProvider());
if (Via.getAPI().getServerVersion().lowestSupportedVersion() < ProtocolVersion.v1_9.getVersion()) {
Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter());
Via.getManager().getProviders().use(BossBarProvider.class, new BungeeBossBarProvider());
Via.getManager().getProviders().use(MainHandProvider.class, new BungeeMainHandProvider());
}
@@ -1,53 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.bungee.providers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.MovementTracker;
public class BungeeMovementTransmitter extends MovementTransmitterProvider {
@Override
public Object getFlyingPacket() {
return null;
}
@Override
public Object getGroundPacket() {
return null;
}
public void sendPlayer(UserConnection userConnection) {
if (userConnection.getProtocolInfo().getState() == State.PLAY) {
PacketWrapper wrapper = PacketWrapper.create(ServerboundPackets1_8.PLAYER_MOVEMENT, null, userConnection);
MovementTracker tracker = userConnection.get(MovementTracker.class);
wrapper.write(Type.BOOLEAN, tracker.isGround());
try {
wrapper.scheduleSendToServer(Protocol1_9To1_8.class);
} catch (Exception e) {
e.printStackTrace();
}
tracker.incrementIdlePacket();
}
}
}
-9
View File
@@ -1,12 +1,3 @@
plugins {
id("net.kyori.blossom")
}
blossom {
replaceToken("\$VERSION", project.version)
replaceToken("\$IMPL_VERSION", "git-ViaVersion-${project.version}:${rootProject.latestCommitHash()}")
}
dependencies {
api(projects.viaversionApi)
api(projects.viaversionApiLegacy)
@@ -17,32 +17,9 @@
*/
package com.viaversion.viaversion.commands.defaultsubs;
import com.google.common.io.CharStreams;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import com.viaversion.viaversion.api.command.ViaSubCommand;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.dump.DumpTemplate;
import com.viaversion.viaversion.dump.VersionInfo;
import com.viaversion.viaversion.util.GsonUtil;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InvalidObjectException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.logging.Level;
import com.viaversion.viaversion.util.DumpUtil;
public class DumpSubCmd extends ViaSubCommand {
@@ -57,124 +34,15 @@ public class DumpSubCmd extends ViaSubCommand {
}
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
VersionInfo version = new VersionInfo(
System.getProperty("java.version"),
System.getProperty("os.name"),
Via.getAPI().getServerVersion().lowestSupportedVersion(),
Via.getManager().getProtocolManager().getSupportedVersions(),
Via.getPlatform().getPlatformName(),
Via.getPlatform().getPlatformVersion(),
Via.getPlatform().getPluginVersion(),
"$IMPL_VERSION",
Via.getManager().getSubPlatforms()
);
Map<String, Object> configuration = Via.getPlatform().getConfigurationProvider().getValues();
DumpTemplate template = new DumpTemplate(version, configuration, Via.getPlatform().getDump(), Via.getManager().getInjector().getDump(), getPlayerSample(sender.getUUID()));
Via.getPlatform().runAsync(new Runnable() {
@Override
public void run() {
HttpURLConnection con;
try {
con = (HttpURLConnection) new URL("https://dump.viaversion.com/documents").openConnection();
} catch (IOException e) {
sender.sendMessage("§4Failed to dump, please check the console for more information");
Via.getPlatform().getLogger().log(Level.WARNING, "Could not paste ViaVersion dump to ViaVersion Dump", e);
return;
}
try {
con.setRequestProperty("Content-Type", "application/json");
con.addRequestProperty("User-Agent", "ViaVersion/" + version.getPluginVersion());
con.setRequestMethod("POST");
con.setDoOutput(true);
OutputStream out = con.getOutputStream();
out.write(new GsonBuilder().setPrettyPrinting().create().toJson(template).getBytes(StandardCharsets.UTF_8));
out.close();
if (con.getResponseCode() == 429) {
sender.sendMessage("§4You can only paste once every minute to protect our systems.");
return;
}
String rawOutput = CharStreams.toString(new InputStreamReader(con.getInputStream()));
con.getInputStream().close();
JsonObject output = GsonUtil.getGson().fromJson(rawOutput, JsonObject.class);
if (!output.has("key"))
throw new InvalidObjectException("Key is not given in Hastebin output");
sender.sendMessage("§2We've made a dump with useful information, report your issue and provide this url: " + getUrl(output.get("key").getAsString()));
} catch (Exception e) {
sender.sendMessage("§4Failed to dump, please check the console for more information");
Via.getPlatform().getLogger().log(Level.WARNING, "Could not paste ViaVersion dump to Hastebin", e);
try {
if (con.getResponseCode() < 200 || con.getResponseCode() > 400) {
String rawOutput = CharStreams.toString(new InputStreamReader(con.getErrorStream()));
con.getErrorStream().close();
Via.getPlatform().getLogger().log(Level.WARNING, "Page returned: " + rawOutput);
}
} catch (IOException e1) {
Via.getPlatform().getLogger().log(Level.WARNING, "Failed to capture further info", e1);
}
}
public boolean execute(final ViaCommandSender sender, final String[] args) {
DumpUtil.postDump(sender.getUUID()).whenComplete((url, e) -> {
if (e != null) {
sender.sendMessage("§4" + e.getMessage());
return;
}
});
sender.sendMessage("§2We've made a dump with useful information, report your issue and provide this url: " + url);
});
return true;
}
private String getUrl(String id) {
return String.format("https://dump.viaversion.com/%s", id);
}
private JsonObject getPlayerSample(UUID senderUuid) {
JsonObject playerSample = new JsonObject();
// Player versions
JsonObject versions = new JsonObject();
playerSample.add("versions", versions);
Map<ProtocolVersion, Integer> playerVersions = new TreeMap<>((o1, o2) -> ProtocolVersion.getIndex(o2) - ProtocolVersion.getIndex(o1));
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
ProtocolVersion protocolVersion = ProtocolVersion.getProtocol(connection.getProtocolInfo().getProtocolVersion());
playerVersions.compute(protocolVersion, (v, num) -> num != null ? num + 1 : 1);
}
for (Map.Entry<ProtocolVersion, Integer> entry : playerVersions.entrySet()) {
versions.addProperty(entry.getKey().getName(), entry.getValue());
}
// Pipeline of sender
Set<List<String>> pipelines = new HashSet<>();
UserConnection senderConnection = Via.getAPI().getConnection(senderUuid);
if (senderConnection != null && senderConnection.getChannel() != null) {
pipelines.add(senderConnection.getChannel().pipeline().names());
}
// Other pipelines if different ones are found (3 max)
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
if (connection.getChannel() == null) {
continue;
}
List<String> names = connection.getChannel().pipeline().names();
if (pipelines.add(names) && pipelines.size() == 3) {
break;
}
}
int i = 0;
for (List<String> pipeline : pipelines) {
JsonArray senderPipeline = new JsonArray(pipeline.size());
for (String name : pipeline) {
senderPipeline.add(name);
}
playerSample.add("pipeline-" + i++, senderPipeline);
}
return playerSample;
}
}
@@ -72,6 +72,8 @@ public class ConnectionManagerImpl implements ConnectionManager {
UUID id = connection.getProtocolInfo().getUuid();
clients.remove(id);
}
connection.clearStoredObjects();
}
@Override
@@ -94,12 +94,19 @@ public class UserConnectionImpl implements UserConnection {
@Override
public <T extends StorableObject> @Nullable T remove(Class<T> objectClass) {
return (T) storedObjects.remove(objectClass);
final StorableObject object = storedObjects.remove(objectClass);
if (object != null) {
object.onRemove();
}
return (T) object;
}
@Override
public void put(StorableObject object) {
storedObjects.put(object.getClass(), object);
final StorableObject previousObject = storedObjects.put(object.getClass(), object);
if (previousObject != null) {
previousObject.onRemove();
}
}
@Override
@@ -122,12 +129,21 @@ public class UserConnectionImpl implements UserConnection {
@Override
public void clearStoredObjects(boolean isServerSwitch) {
if (isServerSwitch) {
storedObjects.values().removeIf(StorableObject::clearOnServerSwitch);
storedObjects.values().removeIf(storableObject -> {
if (storableObject.clearOnServerSwitch()) {
storableObject.onRemove();
return true;
}
return false;
});
for (EntityTracker tracker : entityTrackers.values()) {
tracker.clearEntities();
tracker.trackClientEntity();
}
} else {
for (StorableObject object : storedObjects.values()) {
object.onRemove();
}
storedObjects.clear();
entityTrackers.clear();
}
@@ -70,18 +70,20 @@ import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.Protocol1_19_1To
import com.viaversion.viaversion.protocols.protocol1_19_3to1_19_1.Protocol1_19_3To1_19_1;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.Protocol1_19_4To1_19_3;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.Protocol1_19To1_18_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To1_20;
import com.viaversion.viaversion.protocols.protocol1_20to1_19_4.Protocol1_20To1_19_4;
import com.viaversion.viaversion.protocols.protocol1_9_1_2to1_9_3_4.Protocol1_9_1_2To1_9_3_4;
import com.viaversion.viaversion.protocols.protocol1_9_1to1_9.Protocol1_9_1To1_9;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.Protocol1_9_3To1_9_1_2;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_9_1.Protocol1_9To1_9_1;
import com.viaversion.viaversion.util.Pair;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMap;
import org.checkerframework.checker.nullness.qual.Nullable;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -102,8 +104,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
public class ProtocolManagerImpl implements ProtocolManager {
private static final Protocol BASE_PROTOCOL = new BaseProtocol();
@@ -140,8 +140,6 @@ public class ProtocolManagerImpl implements ProtocolManager {
registerProtocol(new Protocol1_9_1To1_9(), Arrays.asList(ProtocolVersion.v1_9_1.getVersion(), ProtocolVersion.v1_9_2.getVersion()), ProtocolVersion.v1_9.getVersion());
registerProtocol(new Protocol1_9_3To1_9_1_2(), ProtocolVersion.v1_9_3, ProtocolVersion.v1_9_2);
registerProtocol(new Protocol1_9To1_9_1(), ProtocolVersion.v1_9, ProtocolVersion.v1_9_1);
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());
registerProtocol(new Protocol1_10To1_9_3_4(), ProtocolVersion.v1_10, ProtocolVersion.v1_9_3);
registerProtocol(new Protocol1_11To1_10(), ProtocolVersion.v1_11, ProtocolVersion.v1_10);
@@ -183,6 +181,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
registerProtocol(new Protocol1_19_4To1_19_3(), ProtocolVersion.v1_19_4, ProtocolVersion.v1_19_3);
registerProtocol(new Protocol1_20To1_19_4(), ProtocolVersion.v1_20, ProtocolVersion.v1_19_4);
registerProtocol(new Protocol1_20_2To1_20(), ProtocolVersion.v1_20_2, ProtocolVersion.v1_20);
}
@Override
@@ -19,6 +19,7 @@ package com.viaversion.viaversion.protocols.base;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import java.util.UUID;
public class BaseProtocol1_16 extends BaseProtocol1_7 {
@@ -33,10 +33,12 @@ import com.viaversion.viaversion.api.protocol.version.VersionProvider;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocol.ProtocolManagerImpl;
import com.viaversion.viaversion.protocol.ServerProtocolVersionSingleton;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viaversion.util.ChatColorUtil;
import com.viaversion.viaversion.util.GsonUtil;
import io.netty.channel.ChannelFuture;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
@@ -45,9 +47,6 @@ public class BaseProtocol1_7 extends AbstractProtocol {
@Override
protected void registerPackets() {
/* Outgoing Packets */
// Status Response Packet
registerClientbound(ClientboundStatusPackets.STATUS_RESPONSE, new PacketHandlers() { // Status Response Packet
@Override
public void register() {
@@ -122,7 +121,9 @@ public class BaseProtocol1_7 extends AbstractProtocol {
// Login Success Packet
registerClientbound(ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
ProtocolInfo info = wrapper.user().getProtocolInfo();
info.setState(State.PLAY);
if (info.getProtocolVersion() < ProtocolVersion.v1_20_2.getVersion()) {
info.setState(State.PLAY);
}
UUID uuid = passthroughLoginUUID(wrapper);
info.setUuid(uuid);
@@ -147,7 +148,6 @@ public class BaseProtocol1_7 extends AbstractProtocol {
}
});
/* Incoming Packets */
// Login Start Packet
registerServerbound(ServerboundLoginPackets.HELLO, wrapper -> {
int protocol = wrapper.user().getProtocolInfo().getProtocolVersion();
@@ -164,6 +164,8 @@ public class BaseProtocol1_7 extends AbstractProtocol {
future.addListener(f -> wrapper.user().getChannel().close());
}
});
registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> wrapper.user().getProtocolInfo().setState(State.CONFIGURATION));
}
@Override
@@ -23,7 +23,8 @@ import com.viaversion.viaversion.api.protocol.packet.State;
public enum ServerboundLoginPackets implements ServerboundPacketType {
HELLO, // 0x00
ENCRYPTION_KEY, // 0x01
CUSTOM_QUERY; // 0x02
CUSTOM_QUERY_ANSWER, // 0x02
LOGIN_ACKNOWLEDGED; // 0x03
@Override
public final int getId() {
@@ -31,9 +31,9 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_10to1_9_3.packets.InventoryPackets;
import com.viaversion.viaversion.protocols.protocol1_10to1_9_3.storage.ResourcePackTracker;
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.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -33,9 +33,9 @@ import com.viaversion.viaversion.protocols.protocol1_11to1_10.data.PotionColorMa
import com.viaversion.viaversion.protocols.protocol1_11to1_10.metadata.MetadataRewriter1_11To1_10;
import com.viaversion.viaversion.protocols.protocol1_11to1_10.packets.InventoryPackets;
import com.viaversion.viaversion.protocols.protocol1_11to1_10.storage.EntityTracker1_11;
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.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.util.Pair;
@@ -40,9 +40,9 @@ import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.packets.Inventor
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.providers.InventoryQuickMoveProvider;
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_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.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viaversion.rewriter.SoundRewriter;
@@ -64,6 +64,8 @@ public final class ConnectionData {
}
public static void update(UserConnection user, Position position) throws Exception {
Boolean inSync = null;
for (BlockFace face : BlockFace.values()) {
Position pos = position.getRelative(face);
int blockState = blockConnectionProvider.getBlockData(user, pos.x(), pos.y(), pos.z());
@@ -73,8 +75,14 @@ public final class ConnectionData {
}
int newBlockState = handler.connect(user, pos, blockState);
if (newBlockState == blockState && blockConnectionProvider.storesBlocks()) {
continue;
if (newBlockState == blockState) {
if (inSync == null) {
inSync = blockConnectionProvider.storesBlocks(user, position);
}
// Blocks-states are the same, and known to be stored and not de-synced, skip update
if (inSync) {
continue;
}
}
updateBlockStorage(user, pos.x(), pos.y(), pos.z(), newBlockState);
@@ -100,8 +108,13 @@ public final class ConnectionData {
blockConnectionProvider.clearStorage(connection);
}
public static void markModified(UserConnection connection, Position pos) {
if (!needStoreBlocks()) return;
blockConnectionProvider.modifiedBlock(connection, pos);
}
public static boolean needStoreBlocks() {
return blockConnectionProvider.storesBlocks();
return blockConnectionProvider.storesBlocks(null, null);
}
public static void connectBlocks(UserConnection user, Chunk chunk) {
@@ -726,7 +739,7 @@ public final class ConnectionData {
Position pos = new Position(x, y, z);
int newBlockState = handler.connect(user, pos, blockState);
if (blockState != newBlockState || !blockConnectionProvider.storesBlocks()) {
if (blockState != newBlockState || !blockConnectionProvider.storesBlocks(user, null)) {
records.add(new BlockChangeRecord1_8(x & 0xF, y, z & 0xF, newBlockState));
updateBlockStorage(user, x, y, z, newBlockState);
}
@@ -18,8 +18,10 @@
package com.viaversion.viaversion.protocols.protocol1_13to1_12_2.blockconnections.providers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.platform.providers.Provider;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
import org.checkerframework.checker.nullness.qual.Nullable;
public class BlockConnectionProvider implements Provider {
@@ -44,6 +46,10 @@ public class BlockConnectionProvider implements Provider {
}
public void modifiedBlock(UserConnection connection, Position position) {
}
public void unloadChunk(UserConnection connection, int x, int z) {
}
@@ -52,7 +58,14 @@ public class BlockConnectionProvider implements Provider {
}
public boolean storesBlocks() {
/**
* True if blocks are stored, and are known to be accurate around the given position.
* If the client has modified the position (ie: placed or broken a block) this should return false.
*
* @param position The position at which block reliability should be checked, null for general-purpose
* @return true if the block & its neighbors are known to be correct
*/
public boolean storesBlocks(UserConnection user, @Nullable Position position) {
return false;
}
@@ -18,7 +18,9 @@
package com.viaversion.viaversion.protocols.protocol1_13to1_12_2.blockconnections.providers;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.storage.BlockConnectionStorage;
import org.checkerframework.checker.nullness.qual.Nullable;
public class PacketBlockConnectionProvider extends BlockConnectionProvider {
@@ -42,6 +44,10 @@ public class PacketBlockConnectionProvider extends BlockConnectionProvider {
connection.get(BlockConnectionStorage.class).clear();
}
public void modifiedBlock(UserConnection connection, Position position) {
connection.get(BlockConnectionStorage.class).markModified(position);
}
@Override
public void unloadChunk(UserConnection connection, int x, int z) {
connection.get(BlockConnectionStorage.class).unloadChunk(x, z);
@@ -53,8 +59,10 @@ public class PacketBlockConnectionProvider extends BlockConnectionProvider {
}
@Override
public boolean storesBlocks() {
return true;
public boolean storesBlocks(UserConnection connection, @Nullable Position pos) {
if (pos == null || connection == null) return true;
return !connection.get(BlockConnectionStorage.class).recentlyModified(pos);
}
@Override
@@ -72,7 +72,7 @@ public class InventoryPackets extends ItemRewriter<ClientboundPackets1_12_1, Ser
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.ITEM_ARRAY, Type.FLAT_ITEM_ARRAY); // 1 - Window Values
handler(itemArrayHandler(Type.FLAT_ITEM_ARRAY));
handler(itemArrayToClientHandler(Type.FLAT_ITEM_ARRAY));
}
});
protocol.registerClientbound(ClientboundPackets1_12_1.WINDOW_PROPERTY, new PacketHandlers() {
@@ -36,6 +36,7 @@ import com.viaversion.viaversion.api.type.types.Particle;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
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_13to1_12_2.blockconnections.ConnectionData;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.blockconnections.ConnectionHandler;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.data.NamedSoundRewriter;
@@ -44,10 +45,11 @@ import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.providers.BlockE
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.providers.PaintingProvider;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.storage.BlockStorage;
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.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
@@ -56,7 +58,7 @@ public class WorldPackets {
private static final IntSet VALID_BIOMES = new IntOpenHashSet(70, .99F);
static {
// Client will crash if it receives a invalid biome id
// Client will crash if it receives an invalid biome id
for (int i = 0; i < 50; i++) {
VALID_BIOMES.add(i);
}
@@ -535,6 +537,32 @@ public class WorldPackets {
});
}
});
// Incoming Packets
protocol.registerServerbound(ServerboundPackets1_13.PLAYER_BLOCK_PLACEMENT, wrapper -> {
Position pos = wrapper.passthrough(Type.POSITION);
wrapper.passthrough(Type.VAR_INT); // block face
wrapper.passthrough(Type.VAR_INT); // hand
wrapper.passthrough(Type.FLOAT); // cursor x
wrapper.passthrough(Type.FLOAT); // cursor y
wrapper.passthrough(Type.FLOAT); // cursor z
if (Via.getConfig().isServersideBlockConnections() && ConnectionData.needStoreBlocks()) {
ConnectionData.markModified(wrapper.user(), pos);
}
});
protocol.registerServerbound(ServerboundPackets1_13.PLAYER_DIGGING, wrapper -> {
int status = wrapper.passthrough(Type.VAR_INT); // Status
Position pos = wrapper.passthrough(Type.POSITION); // Location
wrapper.passthrough(Type.UNSIGNED_BYTE); // block face
// 0 = Started digging: if in creative this causes the block to break directly
// There's no point in storing the finished digging as it may never show-up (creative)
if (status == 0 && Via.getConfig().isServersideBlockConnections() && ConnectionData.needStoreBlocks()) {
ConnectionData.markModified(wrapper.user(), pos);
}
});
}
public static int toNewId(int oldId) {
@@ -17,21 +17,28 @@
*/
package com.viaversion.viaversion.protocols.protocol1_13to1_12_2.storage;
import com.google.common.collect.EvictingQueue;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.StorableObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import com.viaversion.viaversion.api.minecraft.Position;
import org.checkerframework.checker.nullness.qual.Nullable;
public class BlockConnectionStorage implements StorableObject {
private static Constructor<?> fastUtilLongObjectHashMap;
private final Map<Long, SectionData> blockStorage = createLongObjectMap();
@SuppressWarnings("UnstableApiUsage")
private final Queue<Position> modified = EvictingQueue.create(5);
// Cache to retrieve section quicker
private Long lastIndex;
private long lastIndex = -1;
private SectionData lastSection;
static {
@@ -88,10 +95,27 @@ public class BlockConnectionStorage implements StorableObject {
}
}
public void markModified(Position pos) {
// Avoid saving the same pos twice
if (!modified.contains(pos)) {
this.modified.add(pos);
}
}
public boolean recentlyModified(Position pos) {
for (Position p : modified) {
if (Math.abs(pos.x() - p.x()) + Math.abs(pos.y() - p.y()) + Math.abs(pos.z() - p.z()) <= 2) {
return true;
}
}
return false;
}
public void clear() {
blockStorage.clear();
lastSection = null;
lastIndex = null;
lastIndex = -1;
modified.clear();
}
public void unloadChunk(int x, int z) {
@@ -105,7 +129,7 @@ public class BlockConnectionStorage implements StorableObject {
}
private @Nullable SectionData getSection(long index) {
if (lastIndex != null && lastIndex == index) {
if (lastIndex == index) {
return lastSection;
}
lastIndex = index;
@@ -114,8 +138,8 @@ public class BlockConnectionStorage implements StorableObject {
private void removeSection(long index) {
blockStorage.remove(index);
if (lastIndex != null && lastIndex == index) {
lastIndex = null;
if (lastIndex == index) {
lastIndex = -1;
lastSection = null;
}
}
@@ -17,6 +17,9 @@
*/
package com.viaversion.viaversion.protocols.protocol1_17to1_16_4.packets;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.NumberTag;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
@@ -122,4 +125,23 @@ public final class InventoryPackets extends ItemRewriter<ClientboundPackets1_16_
wrapper.cancel();
});
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (item.identifier() == 733) {
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
if (!(tag.get("map") instanceof NumberTag)) {
tag.put("map", new IntTag(0));
}
}
item.setIdentifier(this.protocol.getMappingData().getNewItemId(item.identifier()));
return item;
}
}
@@ -48,7 +48,7 @@ public class RecipeRewriter1_19_3<C extends ClientboundPacketType> extends Recip
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
handleIngredients(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
@Override
@@ -59,7 +59,7 @@ public class RecipeRewriter1_19_3<C extends ClientboundPacketType> extends Recip
for (int i = 0; i < ingredients; i++) {
handleIngredient(wrapper);
}
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
@Override
@@ -67,7 +67,7 @@ public class RecipeRewriter1_19_3<C extends ClientboundPacketType> extends Recip
wrapper.passthrough(Type.STRING); // Group
wrapper.passthrough(Type.VAR_INT); // Crafting book category
handleIngredient(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
wrapper.passthrough(Type.FLOAT); // EXP
wrapper.passthrough(Type.VAR_INT); // Cooking time
}
@@ -64,6 +64,14 @@ public final class Protocol1_19To1_18_2 extends AbstractProtocol<ClientboundPack
return element == null || element.isJsonNull() || (element.isJsonArray() && element.getAsJsonArray().size() == 0);
}
public static JsonElement mapTextComponentIfNull(JsonElement component) {
if (!isTextComponentNull(component)) {
return component;
} else {
return ChatRewriter.emptyComponent();
}
}
@Override
protected void registerPackets() {
final TagRewriter<ClientboundPackets1_18> tagRewriter = new TagRewriter<>(this);
@@ -118,16 +126,32 @@ public final class Protocol1_19To1_18_2 extends AbstractProtocol<ClientboundPack
new StatisticsRewriter<>(this).register(ClientboundPackets1_18.STATISTICS);
final PacketHandler titleHandler = wrapper -> {
final JsonElement component = wrapper.read(Type.COMPONENT);
if (!isTextComponentNull(component)) {
wrapper.write(Type.COMPONENT, component);
} else {
wrapper.write(Type.COMPONENT, ChatRewriter.emptyComponent());
}
final PacketHandler singleNullTextComponentMapper = wrapper -> {
wrapper.write(Type.COMPONENT, mapTextComponentIfNull(wrapper.read(Type.COMPONENT)));
};
registerClientbound(ClientboundPackets1_18.TITLE_TEXT, titleHandler);
registerClientbound(ClientboundPackets1_18.TITLE_SUBTITLE, titleHandler);
registerClientbound(ClientboundPackets1_18.TITLE_TEXT, singleNullTextComponentMapper);
registerClientbound(ClientboundPackets1_18.TITLE_SUBTITLE, singleNullTextComponentMapper);
registerClientbound(ClientboundPackets1_18.ACTIONBAR, singleNullTextComponentMapper);
registerClientbound(ClientboundPackets1_18.SCOREBOARD_OBJECTIVE, wrapper -> {
wrapper.passthrough(Type.STRING); // Objective Name
byte action = wrapper.passthrough(Type.BYTE); // Mode
if (action == 0 || action == 2) {
wrapper.write(Type.COMPONENT, mapTextComponentIfNull(wrapper.read(Type.COMPONENT))); // Display Name
}
});
registerClientbound(ClientboundPackets1_18.TEAMS, wrapper -> {
wrapper.passthrough(Type.STRING); // Team Name
byte action = wrapper.passthrough(Type.BYTE); // Mode
if (action == 0 || action == 2) {
wrapper.write(Type.COMPONENT, mapTextComponentIfNull(wrapper.read(Type.COMPONENT))); // Display Name
wrapper.passthrough(Type.BYTE); // Flags
wrapper.passthrough(Type.STRING); // Name Tag Visibility
wrapper.passthrough(Type.STRING); // Collision rule
wrapper.passthrough(Type.VAR_INT); // Color
wrapper.write(Type.COMPONENT, mapTextComponentIfNull(wrapper.read(Type.COMPONENT))); // Prefix
wrapper.write(Type.COMPONENT, mapTextComponentIfNull(wrapper.read(Type.COMPONENT))); // Suffix
}
});
final CommandRewriter<ClientboundPackets1_18> commandRewriter = new CommandRewriter<>(this);
registerClientbound(ClientboundPackets1_18.DECLARE_COMMANDS, wrapper -> {
@@ -69,7 +69,7 @@ public final class InventoryPackets extends ItemRewriter<ClientboundPackets1_18,
}
}
});
handler(getSpawnParticleHandler(Type.VAR_INT, Type.FLAT_VAR_INT_ITEM));
handler(getSpawnParticleHandler(Type.VAR_INT));
}
});
@@ -0,0 +1,290 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.google.gson.JsonElement;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_19_4Types;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
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.protocol.remapper.PacketHandler;
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.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.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 com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.BlockItemPacketRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.EntityPacketRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState.BridgePhase;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.LastResourcePack;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPackets1_19_4, ClientboundPackets1_20_2, ServerboundPackets1_19_4, ServerboundPackets1_20_2> {
public static final MappingData MAPPINGS = new MappingDataBase("1.20", "1.20.2");
private final EntityPacketRewriter1_20_2 entityPacketRewriter = new EntityPacketRewriter1_20_2(this);
private final BlockItemPacketRewriter1_20_2 itemPacketRewriter = new BlockItemPacketRewriter1_20_2(this);
public Protocol1_20_2To1_20() {
super(ClientboundPackets1_19_4.class, ClientboundPackets1_20_2.class, ServerboundPackets1_19_4.class, ServerboundPackets1_20_2.class);
}
@Override
protected void registerPackets() {
// Close your eyes and turn around while you still can
super.registerPackets();
final SoundRewriter<ClientboundPackets1_19_4> soundRewriter = new SoundRewriter<>(this);
soundRewriter.register1_19_3Sound(ClientboundPackets1_19_4.SOUND);
soundRewriter.registerEntitySound(ClientboundPackets1_19_4.ENTITY_SOUND);
registerClientbound(ClientboundPackets1_19_4.RESOURCE_PACK, wrapper -> {
final String url = wrapper.passthrough(Type.STRING);
final String hash = wrapper.passthrough(Type.STRING);
final boolean required = wrapper.passthrough(Type.BOOLEAN);
final JsonElement prompt = wrapper.passthrough(Type.OPTIONAL_COMPONENT);
wrapper.user().put(new LastResourcePack(url, hash, required, prompt));
});
registerClientbound(ClientboundPackets1_19_4.DISPLAY_SCOREBOARD, wrapper -> {
final byte slot = wrapper.read(Type.BYTE);
wrapper.write(Type.VAR_INT, (int) slot);
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO.getId(), ServerboundLoginPackets.HELLO.getId(), wrapper -> {
wrapper.passthrough(Type.STRING); // Name
final UUID uuid = wrapper.read(Type.UUID);
wrapper.write(Type.OPTIONAL_UUID, uuid);
});
// Deal with the new CONFIGURATION protocol state the client expects
// After the game profile is received by the client, it will send its login ack,
// switch to the configuration protocol state and send its brand.
// We need to wait for it send the login ack before actually sending the play login,
// hence packets are added to a queue. With the data from the login packet, we sent what is needed
// during the configuration phase before finally transitioning to the play state with the client as well.
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), wrapper -> {
wrapper.user().get(ConfigurationState.class).setBridgePhase(BridgePhase.PROFILE_SENT);
// Set the state according to what the server expects. All packets between now and when the client
// switches to PLAY as well will be discarded after being dealt with.
wrapper.user().getProtocolInfo().setState(State.PLAY);
});
registerServerbound(State.LOGIN, ServerboundLoginPackets.LOGIN_ACKNOWLEDGED.getId(), -1, wrapper -> {
wrapper.cancel();
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
configurationState.setBridgePhase(BridgePhase.CONFIGURATION);
configurationState.sendQueuedPackets(wrapper.user());
});
cancelServerbound(State.LOGIN, ServerboundLoginPackets.CUSTOM_QUERY_ANSWER.getId());
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.getId(), -1, wrapper -> {
wrapper.cancel();
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
configurationState.setBridgePhase(BridgePhase.NONE);
configurationState.sendQueuedPackets(wrapper.user());
configurationState.clear();
});
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CLIENT_INFORMATION.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.CLIENT_SETTINGS));
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PLUGIN_MESSAGE));
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.KEEP_ALIVE.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.KEEP_ALIVE));
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.PONG.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PONG));
// Cancel this, as it will always just be the response to a re-sent pack from us
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.RESOURCE_PACK.getId(), -1, PacketWrapper::cancel);
cancelClientbound(ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES); // TODO Sad emoji
registerServerbound(ServerboundPackets1_20_2.CONFIGURATION_ACKNOWLEDGED, null, wrapper -> {
wrapper.cancel();
final ConfigurationState configurationState = wrapper.user().get(ConfigurationState.class);
if (configurationState.bridgePhase() != BridgePhase.REENTERING_CONFIGURATION) {
return;
}
// Reenter the configuration state
configurationState.setBridgePhase(BridgePhase.CONFIGURATION);
final LastResourcePack lastResourcePack = wrapper.user().get(LastResourcePack.class);
sendConfigurationPackets(wrapper.user(), configurationState.lastDimensionRegistry(), lastResourcePack);
});
cancelServerbound(ServerboundPackets1_20_2.CHUNK_BATCH_RECEIVED);
registerServerbound(ServerboundPackets1_20_2.PING_REQUEST, null, wrapper -> {
wrapper.cancel();
final long time = wrapper.read(Type.LONG);
final PacketWrapper responsePacket = wrapper.create(ClientboundPackets1_20_2.PONG_RESPONSE);
responsePacket.write(Type.LONG, time);
responsePacket.sendFuture(Protocol1_20_2To1_20.class);
});
}
private PacketHandler queueServerboundPacket(final ServerboundPackets1_20_2 packetType) {
return wrapper -> {
wrapper.setPacketType(packetType);
wrapper.user().get(ConfigurationState.class).addPacketToQueue(wrapper, false);
wrapper.cancel();
};
}
@Override
public void transform(final Direction direction, final State state, final PacketWrapper packetWrapper) throws Exception {
final ConfigurationState configurationBridge = packetWrapper.user().get(ConfigurationState.class);
if (configurationBridge == null) {
// Bad state during an unexpected disconnect
return;
}
final BridgePhase phase = configurationBridge.bridgePhase();
if (phase == BridgePhase.NONE) {
super.transform(direction, state, packetWrapper);
return;
}
if (direction == Direction.SERVERBOUND) {
// Client and server will be on different protocol states, pick the right client protocol state
super.transform(direction, phase == BridgePhase.PROFILE_SENT ? State.LOGIN
: phase == BridgePhase.REENTERING_CONFIGURATION ? State.PLAY : State.CONFIGURATION, packetWrapper);
return;
}
if (phase == BridgePhase.PROFILE_SENT || phase == BridgePhase.REENTERING_CONFIGURATION) {
// Queue packets sent by the server while we wait for the client to transition to the configuration state
configurationBridge.addPacketToQueue(packetWrapper, true);
throw CancelException.generate();
}
if (packetWrapper.getPacketType() == null || packetWrapper.getPacketType().state() != State.CONFIGURATION) {
// Map some of them to their configuration state counterparts, but make sure to let join game through
final int unmappedId = packetWrapper.getId();
if (unmappedId == ClientboundPackets1_19_4.JOIN_GAME.getId()) {
super.transform(direction, state, packetWrapper);
return;
}
if (configurationBridge.queuedOrSentJoinGame()) {
if (!packetWrapper.user().isClientSide() && !Via.getPlatform().isProxy() && unmappedId == ClientboundPackets1_19_4.SYSTEM_CHAT.getId()) {
// Cancelling this on the Vanilla server will cause it to exceptionally resend a message
// Assume that we have already sent the login packet and just let it through
super.transform(direction, State.PLAY, packetWrapper);
return;
}
configurationBridge.addPacketToQueue(packetWrapper, true);
throw CancelException.generate();
}
if (unmappedId == ClientboundPackets1_19_4.PLUGIN_MESSAGE.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD);
} else if (unmappedId == ClientboundPackets1_19_4.DISCONNECT.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.DISCONNECT);
} else if (unmappedId == ClientboundPackets1_19_4.KEEP_ALIVE.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.KEEP_ALIVE);
} else if (unmappedId == ClientboundPackets1_19_4.PING.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.PING);
} else if (unmappedId == ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES);
} else if (unmappedId == ClientboundPackets1_19_4.TAGS.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS);
} else {
// Not a packet that can be mapped to the configuration protocol
// Includes resource pack packets to make sure it is not applied sooner than the server expects
configurationBridge.addPacketToQueue(packetWrapper, true);
throw CancelException.generate();
}
return;
}
// Redirect packets during the fake configuration phase
// This might mess up people using Via API/other protocols down the line, but such is life. We can't have different states for server and client
super.transform(direction, State.CONFIGURATION, packetWrapper);
}
public static void sendConfigurationPackets(final UserConnection connection, final CompoundTag dimensionRegistry, @Nullable final LastResourcePack lastResourcePack) throws Exception {
final PacketWrapper registryDataPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.REGISTRY_DATA, connection);
registryDataPacket.write(Type.NAMELESS_NBT, dimensionRegistry);
registryDataPacket.send(Protocol1_20_2To1_20.class);
// Enabling features is only possible during the configuration phase
// TODO Sad emoji
final PacketWrapper enableFeaturesPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES, connection);
enableFeaturesPacket.write(Type.VAR_INT, 1);
enableFeaturesPacket.write(Type.STRING, "minecraft:vanilla");
enableFeaturesPacket.send(Protocol1_20_2To1_20.class);
if (lastResourcePack != null) {
// The client for some reason drops the resource pack when reentering the configuration state
final PacketWrapper resourcePackPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK, connection);
resourcePackPacket.write(Type.STRING, lastResourcePack.url());
resourcePackPacket.write(Type.STRING, lastResourcePack.hash());
resourcePackPacket.write(Type.BOOLEAN, lastResourcePack.required());
resourcePackPacket.write(Type.OPTIONAL_COMPONENT, lastResourcePack.prompt());
resourcePackPacket.send(Protocol1_20_2To1_20.class);
}
final PacketWrapper finishConfigurationPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION, connection);
finishConfigurationPacket.send(Protocol1_20_2To1_20.class);
}
@Override
public MappingData getMappingData() {
return MAPPINGS;
}
@Override
protected @Nullable ServerboundPackets1_20_2 configurationAcknowledgedPacket() {
return null; // Don't handle it in the transitioning protocol
}
@Override
public void init(final UserConnection user) {
user.put(new ConfigurationState());
addEntityTracker(user, new EntityTrackerBase(user, Entity1_19_4Types.PLAYER));
}
@Override
public EntityRewriter<Protocol1_20_2To1_20> getEntityRewriter() {
return entityPacketRewriter;
}
@Override
public ItemRewriter<Protocol1_20_2To1_20> getItemRewriter() {
return itemPacketRewriter;
}
}
@@ -0,0 +1,49 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.packet;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.State;
public enum ClientboundConfigurationPackets1_20_2 implements ClientboundPacketType {
CUSTOM_PAYLOAD, // 0x00
DISCONNECT, // 0x01
FINISH_CONFIGURATION, // 0x02
KEEP_ALIVE, // 0x03
PING, // 0x04
REGISTRY_DATA, // 0x05
RESOURCE_PACK, // 0x06
UPDATE_ENABLED_FEATURES, // 0x07
UPDATE_TAGS; // 0x08
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
@Override
public State state() {
return State.CONFIGURATION;
}
}
@@ -0,0 +1,147 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.packet;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
public enum ClientboundPackets1_20_2 implements ClientboundPacketType {
BUNDLE, // 0x00
SPAWN_ENTITY, // 0x01
SPAWN_EXPERIENCE_ORB, // 0x02
ENTITY_ANIMATION, // 0x03
STATISTICS, // 0x04
BLOCK_CHANGED_ACK, // 0x05
BLOCK_BREAK_ANIMATION, // 0x06
BLOCK_ENTITY_DATA, // 0x07
BLOCK_ACTION, // 0x08
BLOCK_CHANGE, // 0x09
BOSSBAR, // 0x0A
SERVER_DIFFICULTY, // 0x0B
CHUNK_BATCH_FINISHED, // 0x0C
CHUNK_BATCH_START, // 0x0D
CHUNK_BIOMES, // 0x0E
CLEAR_TITLES, // 0x0F
TAB_COMPLETE, // 0x10
DECLARE_COMMANDS, // 0x11
CLOSE_WINDOW, // 0x12
WINDOW_ITEMS, // 0x13
WINDOW_PROPERTY, // 0x14
SET_SLOT, // 0x15
COOLDOWN, // 0x16
CUSTOM_CHAT_COMPLETIONS, // 0x17
PLUGIN_MESSAGE, // 0x18
DAMAGE_EVENT, // 0x19
DELETE_CHAT_MESSAGE, // 0x1A
DISCONNECT, // 0x1B
DISGUISED_CHAT, // 0x1C
ENTITY_STATUS, // 0x1D
EXPLOSION, // 0x1E
UNLOAD_CHUNK, // 0x1F
GAME_EVENT, // 0x20
OPEN_HORSE_WINDOW, // 0x21
HIT_ANIMATION, // 0x22
WORLD_BORDER_INIT, // 0x23
KEEP_ALIVE, // 0x24
CHUNK_DATA, // 0x25
EFFECT, // 0x26
SPAWN_PARTICLE, // 0x27
UPDATE_LIGHT, // 0x28
JOIN_GAME, // 0x29
MAP_DATA, // 0x2A
TRADE_LIST, // 0x2B
ENTITY_POSITION, // 0x2C
ENTITY_POSITION_AND_ROTATION, // 0x2D
ENTITY_ROTATION, // 0x2E
VEHICLE_MOVE, // 0x2F
OPEN_BOOK, // 0x30
OPEN_WINDOW, // 0x31
OPEN_SIGN_EDITOR, // 0x32
PING, // 0x33
PONG_RESPONSE, // 0x34
CRAFT_RECIPE_RESPONSE, // 0x35
PLAYER_ABILITIES, // 0x36
PLAYER_CHAT, // 0x37
COMBAT_END, // 0x38
COMBAT_ENTER, // 0x39
COMBAT_KILL, // 0x3A
PLAYER_INFO_REMOVE, // 0x3B
PLAYER_INFO_UPDATE, // 0x3C
FACE_PLAYER, // 0x3D
PLAYER_POSITION, // 0x3E
UNLOCK_RECIPES, // 0x3F
REMOVE_ENTITIES, // 0x40
REMOVE_ENTITY_EFFECT, // 0x41
RESOURCE_PACK, // 0x42
RESPAWN, // 0x43
ENTITY_HEAD_LOOK, // 0x44
MULTI_BLOCK_CHANGE, // 0x45
SELECT_ADVANCEMENTS_TAB, // 0x46
SERVER_DATA, // 0x47
ACTIONBAR, // 0x48
WORLD_BORDER_CENTER, // 0x49
WORLD_BORDER_LERP_SIZE, // 0x4A
WORLD_BORDER_SIZE, // 0x4B
WORLD_BORDER_WARNING_DELAY, // 0x4C
WORLD_BORDER_WARNING_DISTANCE, // 0x4D
CAMERA, // 0x4E
HELD_ITEM_CHANGE, // 0x4F
UPDATE_VIEW_POSITION, // 0x50
UPDATE_VIEW_DISTANCE, // 0x51
SPAWN_POSITION, // 0x52
DISPLAY_SCOREBOARD, // 0x53
ENTITY_METADATA, // 0x54
ATTACH_ENTITY, // 0x55
ENTITY_VELOCITY, // 0x56
ENTITY_EQUIPMENT, // 0x57
SET_EXPERIENCE, // 0x58
UPDATE_HEALTH, // 0x59
SCOREBOARD_OBJECTIVE, // 0x5A
SET_PASSENGERS, // 0x5B
TEAMS, // 0x5C
UPDATE_SCORE, // 0x5D
SET_SIMULATION_DISTANCE, // 0x5E
TITLE_SUBTITLE, // 0x5F
TIME_UPDATE, // 0x60
TITLE_TEXT, // 0x61
TITLE_TIMES, // 0x62
ENTITY_SOUND, // 0x63
SOUND, // 0x64
START_CONFIGURATION, // 0x65
STOP_SOUND, // 0x66
SYSTEM_CHAT, // 0x67
TAB_LIST, // 0x68
NBT_QUERY, // 0x69
COLLECT_ITEM, // 0x6A
ENTITY_TELEPORT, // 0x6B
ADVANCEMENTS, // 0x6C
ENTITY_PROPERTIES, // 0x6D
ENTITY_EFFECT, // 0x6E
DECLARE_RECIPES, // 0x6F
TAGS; // 0x70
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
}
@@ -0,0 +1,46 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.packet;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.State;
public enum ServerboundConfigurationPackets1_20_2 implements ServerboundPacketType {
CLIENT_INFORMATION, // 0x00
CUSTOM_PAYLOAD, // 0x01
FINISH_CONFIGURATION, // 0x02
KEEP_ALIVE, // 0x03
PONG, // 0x04
RESOURCE_PACK; // 0x05
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
@Override
public State state() {
return State.CONFIGURATION;
}
}
@@ -0,0 +1,88 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.packet;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
public enum ServerboundPackets1_20_2 implements ServerboundPacketType {
TELEPORT_CONFIRM, // 0x00
QUERY_BLOCK_NBT, // 0x01
SET_DIFFICULTY, // 0x02
CHAT_ACK, // 0x03
CHAT_COMMAND, // 0x04
CHAT_MESSAGE, // 0x05
CHAT_SESSION_UPDATE, // 0x06
CHUNK_BATCH_RECEIVED, // 0x07
CLIENT_STATUS, // 0x08
CLIENT_SETTINGS, // 0x09
TAB_COMPLETE, // 0x0A
CONFIGURATION_ACKNOWLEDGED, // 0x0B
CLICK_WINDOW_BUTTON, // 0x0C
CLICK_WINDOW, // 0x0D
CLOSE_WINDOW, // 0x0E
PLUGIN_MESSAGE, // 0x0F
EDIT_BOOK, // 0x10
ENTITY_NBT_REQUEST, // 0x11
INTERACT_ENTITY, // 0x12
GENERATE_JIGSAW, // 0x13
KEEP_ALIVE, // 0x14
LOCK_DIFFICULTY, // 0x15
PLAYER_POSITION, // 0x16
PLAYER_POSITION_AND_ROTATION, // 0x17
PLAYER_ROTATION, // 0x18
PLAYER_MOVEMENT, // 0x19
VEHICLE_MOVE, // 0x1A
STEER_BOAT, // 0x1B
PICK_ITEM, // 0x1C
PING_REQUEST, // 0x1D
CRAFT_RECIPE_REQUEST, // 0x1E
PLAYER_ABILITIES, // 0x1F
PLAYER_DIGGING, // 0x20
ENTITY_ACTION, // 0x21
STEER_VEHICLE, // 0x22
PONG, // 0x23
RECIPE_BOOK_DATA, // 0x24
SEEN_RECIPE, // 0x25
RENAME_ITEM, // 0x26
RESOURCE_PACK_STATUS, // 0x27
ADVANCEMENT_TAB, // 0x28
SELECT_TRADE, // 0x29
SET_BEACON_EFFECT, // 0x2A
HELD_ITEM_CHANGE, // 0x2B
UPDATE_COMMAND_BLOCK, // 0x2C
UPDATE_COMMAND_BLOCK_MINECART, // 0x2D
CREATIVE_INVENTORY_ACTION, // 0x2E
UPDATE_JIGSAW_BLOCK, // 0x2F
UPDATE_STRUCTURE_BLOCK, // 0x30
UPDATE_SIGN, // 0x31
ANIMATION, // 0x32
SPECTATE, // 0x33
PLAYER_BLOCK_PLACEMENT, // 0x34
USE_ITEM; // 0x35
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
}
@@ -0,0 +1,393 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.rewriter;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
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.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.rewriter.RecipeRewriter1_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.ServerboundPackets1_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.rewriter.ItemRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.MathUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<ClientboundPackets1_19_4, ServerboundPackets1_20_2, Protocol1_20_2To1_20> {
public static final String[] POTION_EFFECTS = {
"", // No effect
"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"
};
public BlockItemPacketRewriter1_20_2(final Protocol1_20_2To1_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.registerVarLongMultiBlockChange1_20(ClientboundPackets1_19_4.MULTI_BLOCK_CHANGE);
blockRewriter.registerEffect(ClientboundPackets1_19_4.EFFECT, 1010, 2001);
protocol.registerServerbound(ServerboundPackets1_20_2.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);
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.UNLOAD_CHUNK, wrapper -> {
final int x = wrapper.read(Type.INT);
final int z = wrapper.read(Type.INT);
wrapper.write(Type.CHUNK_POSITION, new ChunkPosition(x, z));
});
protocol.registerClientbound(ClientboundPackets1_19_4.NBT_QUERY, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Transaction id
wrapper.write(Type.NAMELESS_NBT, wrapper.read(Type.NBT));
});
protocol.registerClientbound(ClientboundPackets1_19_4.BLOCK_ENTITY_DATA, wrapper -> {
wrapper.passthrough(Type.POSITION1_14); // Position
wrapper.passthrough(Type.VAR_INT); // Type
wrapper.write(Type.NAMELESS_NBT, handleBlockEntity(wrapper.read(Type.NBT)));
});
protocol.registerClientbound(ClientboundPackets1_19_4.CHUNK_DATA, wrapper -> {
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
final Type<Chunk> chunkType = new Chunk1_18Type(tracker.currentWorldSectionHeight(),
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().size()),
MathUtil.ceilLog2(tracker.biomesSent()));
final Chunk chunk = wrapper.read(chunkType);
final Type<Chunk> newChunkType = new ChunkType1_20_2(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());
}
});
// Replace the NBT type everywhere
protocol.registerClientbound(ClientboundPackets1_19_4.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.ITEM1_20_2_VAR_INT_ARRAY, wrapper.read(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT)); // Items
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Carried item
});
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.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.FLAT_VAR_INT_ITEM, Type.ITEM1_20_2); // Item
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.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.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // 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
}
// Remove criterion triggers
wrapper.read(Type.STRING_ARRAY); // 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_19_4.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.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM));
} while ((slot & 0xFFFFFF80) != 0);
});
}
});
protocol.registerServerbound(ServerboundPackets1_20_2.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.FLAT_VAR_INT_ITEM, wrapper.read(Type.ITEM1_20_2));
}
// Carried item
wrapper.write(Type.FLAT_VAR_INT_ITEM, wrapper.read(Type.ITEM1_20_2));
});
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.TRADE_LIST, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Container id
final int size = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < size; i++) {
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Input
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // Output
wrapper.write(Type.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM)); // 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_20_2.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT); // 0 - Slot
map(Type.ITEM1_20_2, Type.FLAT_VAR_INT_ITEM); // 1 - Clicked Item
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.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_20_2To1_20.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.ITEM1_20_2, wrapper.read(Type.FLAT_VAR_INT_ITEM));
}
});
}
});
new RecipeRewriter1_19_4<ClientboundPackets1_19_4>(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.ITEM1_20_2, 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.ITEM1_20_2, 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.ITEM1_20_2, 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.ITEM1_20_2, 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.ITEM1_20_2, 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.ITEM1_20_2, result);
}
@Override
protected void handleIngredient(final PacketWrapper wrapper) throws Exception {
final Item[] items = wrapper.read(itemArrayType());
wrapper.write(Type.ITEM1_20_2_VAR_INT_ARRAY, items);
for (final Item item : items) {
rewrite(item);
}
}
}.register(ClientboundPackets1_19_4.DECLARE_RECIPES);
}
private @Nullable CompoundTag handleBlockEntity(@Nullable final CompoundTag tag) {
if (tag == null) {
return null;
}
final IntTag primaryEffect = tag.remove("Primary");
if (primaryEffect != null && primaryEffect.asInt() != 0) {
tag.put("primary_effect", new StringTag(effect(primaryEffect.asInt())));
}
final IntTag secondaryEffect = tag.remove("Secondary");
if (secondaryEffect != null && secondaryEffect.asInt() != 0) {
tag.put("secondary_effect", new StringTag(effect(secondaryEffect.asInt())));
}
return tag;
}
private String effect(final int id) {
return id >= 1 && id < POTION_EFFECTS.length ? Key.namespaced(POTION_EFFECTS[id]) : "minecraft:luck";
}
}
@@ -0,0 +1,186 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.rewriter;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
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.Protocol1_20_2To1_20;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState;
import com.viaversion.viaversion.rewriter.EntityRewriter;
public final class EntityPacketRewriter1_20_2 extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_20_2To1_20> {
public EntityPacketRewriter1_20_2(final Protocol1_20_2To1_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_20_2.METADATA_LIST);
registerRemoveEntities(ClientboundPackets1_19_4.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundPackets1_19_4.SPAWN_PLAYER, ClientboundPackets1_20_2.SPAWN_ENTITY, wrapper -> {
wrapper.passthrough(Type.VAR_INT); // Entity id
wrapper.passthrough(Type.UUID); // UUID
wrapper.write(Type.VAR_INT, Entity1_19_4Types.PLAYER.getId()); // Entity type id
wrapper.passthrough(Type.DOUBLE); // X
wrapper.passthrough(Type.DOUBLE); // Y
wrapper.passthrough(Type.DOUBLE); // Z
final byte yaw = wrapper.read(Type.BYTE); // Yaw
wrapper.passthrough(Type.BYTE); // Pitch
wrapper.write(Type.BYTE, yaw);
wrapper.write(Type.BYTE, yaw); // Head yaw
wrapper.write(Type.VAR_INT, 0); // Data
wrapper.write(Type.SHORT, (short) 0); // Velocity X
wrapper.write(Type.SHORT, (short) 0); // Velocity Y
wrapper.write(Type.SHORT, (short) 0); // Velocity Z
});
protocol.registerClientbound(ClientboundPackets1_19_4.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
// Just reorder written data, move dimension data to configuration phase
wrapper.passthrough(Type.INT); // Entity id
wrapper.passthrough(Type.BOOLEAN); // Hardcore
final byte gamemode = wrapper.read(Type.UNSIGNED_BYTE).byteValue();
final byte previousGamemode = wrapper.read(Type.BYTE);
wrapper.passthrough(Type.STRING_ARRAY); // World List
final CompoundTag dimensionRegistry = wrapper.read(Type.NBT);
final String dimensionType = wrapper.read(Type.STRING);
final String world = wrapper.read(Type.STRING);
final long seed = wrapper.read(Type.LONG);
trackBiomeSize(wrapper.user(), dimensionRegistry); // Caches dimensions to access data like height later
cacheDimensionData(wrapper.user(), dimensionRegistry); // Tracks the amount of biomes sent for chunk data
wrapper.passthrough(Type.VAR_INT); // Max players
wrapper.passthrough(Type.VAR_INT); // View distance
wrapper.passthrough(Type.VAR_INT); // Simulation distance
wrapper.passthrough(Type.BOOLEAN); // Reduced debug info
wrapper.passthrough(Type.BOOLEAN); // Show death screen
wrapper.write(Type.BOOLEAN, false); // Limited crafting
wrapper.write(Type.STRING, dimensionType);
wrapper.write(Type.STRING, world);
wrapper.write(Type.LONG, seed);
wrapper.write(Type.BYTE, gamemode);
wrapper.write(Type.BYTE, previousGamemode);
// Debug, flat, last death pos, and portal cooldown at the end unchanged
final ConfigurationState configurationBridge = wrapper.user().get(ConfigurationState.class);
if (!configurationBridge.setLastDimensionRegistry(dimensionRegistry)) {
// No change, so no need to re-enter the configuration state - just let this one through
return;
}
if (configurationBridge.bridgePhase() == ConfigurationState.BridgePhase.NONE) {
// Reenter the configuration state
final PacketWrapper configurationPacket = wrapper.create(ClientboundPackets1_20_2.START_CONFIGURATION);
configurationPacket.send(Protocol1_20_2To1_20.class);
configurationBridge.setBridgePhase(ConfigurationState.BridgePhase.REENTERING_CONFIGURATION);
configurationBridge.setJoinGamePacket(wrapper);
wrapper.cancel();
return;
}
Protocol1_20_2To1_20.sendConfigurationPackets(wrapper.user(), dimensionRegistry, null);
// Manually send it at the end and hope nothing breaks
configurationBridge.setJoinGamePacket(wrapper);
wrapper.cancel();
});
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.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.BYTE, wrapper.read(Type.UNSIGNED_BYTE).byteValue()); // Gamemode
wrapper.passthrough(Type.BYTE); // Previous gamemode
wrapper.passthrough(Type.BOOLEAN); // Debug
wrapper.passthrough(Type.BOOLEAN); // Flat
// Move this to the end
final byte dataToKeep = wrapper.read(Type.BYTE);
wrapper.passthrough(Type.OPTIONAL_GLOBAL_POSITION); // Last death position
wrapper.passthrough(Type.VAR_INT); // Portal cooldown
wrapper.write(Type.BYTE, dataToKeep);
});
handler(worldDataTrackerHandlerByKey()); // Tracks world height and name for chunk data and entity (un)tracking
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.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.NAMELESS_NBT, wrapper.read(Type.NBT)); // Factor data
}
});
protocol.registerClientbound(ClientboundPackets1_19_4.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_2.META_TYPES.byId(meta.metaType().typeId())));
registerMetaTypeHandler(null, Types1_20_2.META_TYPES.blockStateType, Types1_20_2.META_TYPES.optionalBlockStateType, Types1_20_2.META_TYPES.particleType);
filter().filterFamily(Entity1_19_4Types.DISPLAY).addIndex(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,41 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.rewriter;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_19_4to1_19_3.rewriter.RecipeRewriter1_19_4;
public class RecipeRewriter1_20_2<C extends ClientboundPacketType> extends RecipeRewriter1_19_4<C> {
public RecipeRewriter1_20_2(final Protocol<C, ?, ?, ?> protocol) {
super(protocol);
}
@Override
protected Type<Item> itemType() {
return Type.ITEM1_20_2;
}
@Override
protected Type<Item[]> itemArrayType() {
return Type.ITEM1_20_2_VAR_INT_ARRAY;
}
}
@@ -0,0 +1,192 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.storage;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.Protocol1_20_2To1_20;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ConfigurationState implements StorableObject {
private final List<QueuedPacket> packetQueue = new ArrayList<>();
private BridgePhase bridgePhase = BridgePhase.NONE;
private QueuedPacket joinGamePacket;
private boolean queuedJoinGame;
private CompoundTag lastDimensionRegistry;
public BridgePhase bridgePhase() {
return bridgePhase;
}
public void setBridgePhase(final BridgePhase bridgePhase) {
this.bridgePhase = bridgePhase;
}
public @Nullable CompoundTag lastDimensionRegistry() {
return lastDimensionRegistry;
}
/**
* Sets the last dimension registry and returns whether it differs from the previously stored one.
*
* @param dimensionRegistry dimension registry to set
* @return whether the dimension registry differs from the previously stored one
*/
public boolean setLastDimensionRegistry(final CompoundTag dimensionRegistry) {
final boolean equals = Objects.equals(this.lastDimensionRegistry, dimensionRegistry);
this.lastDimensionRegistry = dimensionRegistry;
return !equals;
}
public void addPacketToQueue(final PacketWrapper wrapper, final boolean clientbound) throws Exception {
packetQueue.add(toQueuedPacket(wrapper, clientbound, false));
}
private QueuedPacket toQueuedPacket(final PacketWrapper wrapper, final boolean clientbound, final boolean skipCurrentPipeline) throws Exception {
// Caching packet buffers is cursed, copy to heap buffers to make sure we don't start leaking in dumb cases
final ByteBuf copy = Unpooled.buffer();
final PacketType packetType = wrapper.getPacketType();
final int packetId = wrapper.getId();
// Don't write the packet id to the buffer
//noinspection deprecation
wrapper.setId(-1);
wrapper.writeToBuffer(copy);
return new QueuedPacket(copy, clientbound, packetType, packetId, skipCurrentPipeline);
}
public void setJoinGamePacket(final PacketWrapper wrapper) throws Exception {
this.joinGamePacket = toQueuedPacket(wrapper, true, true);
queuedJoinGame = true;
}
@Override
public boolean clearOnServerSwitch() {
return false; // This might be bad
}
@Override
public void onRemove() {
for (final QueuedPacket packet : packetQueue) {
packet.buf().release();
}
if (joinGamePacket != null) {
joinGamePacket.buf().release();
}
}
public void sendQueuedPackets(final UserConnection connection) throws Exception {
if (joinGamePacket != null) {
packetQueue.add(0, joinGamePacket);
joinGamePacket = null;
}
final ConfigurationState.QueuedPacket[] queuedPackets = packetQueue.toArray(new ConfigurationState.QueuedPacket[0]);
packetQueue.clear();
for (final ConfigurationState.QueuedPacket packet : queuedPackets) {
final PacketWrapper queuedWrapper;
try {
if (packet.packetType() != null) {
queuedWrapper = PacketWrapper.create(packet.packetType(), packet.buf(), connection);
} else {
//noinspection deprecation
queuedWrapper = PacketWrapper.create(packet.packetId(), packet.buf(), connection);
}
if (packet.clientbound()) {
queuedWrapper.send(Protocol1_20_2To1_20.class, packet.skipCurrentPipeline());
} else {
queuedWrapper.sendToServer(Protocol1_20_2To1_20.class, packet.skipCurrentPipeline());
}
} finally {
packet.buf().release();
}
}
}
public void clear() {
packetQueue.clear();
bridgePhase = BridgePhase.NONE;
queuedJoinGame = false;
}
public boolean queuedOrSentJoinGame() {
return queuedJoinGame;
}
public enum BridgePhase {
NONE, PROFILE_SENT, CONFIGURATION, REENTERING_CONFIGURATION
}
public static final class QueuedPacket {
private final ByteBuf buf;
private final boolean clientbound;
private final PacketType packetType;
private final int packetId;
private final boolean skipCurrentPipeline;
private QueuedPacket(final ByteBuf buf, final boolean clientbound, final PacketType packetType,
final int packetId, final boolean skipCurrentPipeline) {
this.buf = buf;
this.clientbound = clientbound;
this.packetType = packetType;
this.packetId = packetId;
this.skipCurrentPipeline = skipCurrentPipeline;
}
public ByteBuf buf() {
return buf;
}
public boolean clientbound() {
return clientbound;
}
public int packetId() {
return packetId;
}
public @Nullable PacketType packetType() {
return packetType;
}
public boolean skipCurrentPipeline() {
return skipCurrentPipeline;
}
@Override
public String toString() {
return "QueuedPacket{" +
"buf=" + buf +
", clientbound=" + clientbound +
", packetType=" + packetType +
", packetId=" + packetId +
", skipCurrentPipeline=" + skipCurrentPipeline +
'}';
}
}
}
@@ -0,0 +1,53 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.storage;
import com.google.gson.JsonElement;
import com.viaversion.viaversion.api.connection.StorableObject;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class LastResourcePack implements StorableObject {
private final String url;
private final String hash;
private final boolean required;
private final JsonElement prompt;
public LastResourcePack(final String url, final String hash, final boolean required, @Nullable final JsonElement prompt) {
this.url = url;
this.hash = hash;
this.required = required;
this.prompt = prompt;
}
public String url() {
return url;
}
public String hash() {
return hash;
}
public boolean required() {
return required;
}
public @Nullable JsonElement prompt() {
return prompt;
}
}
@@ -0,0 +1,100 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_20_2to1_20.type;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_18;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.BaseChunkType;
import com.viaversion.viaversion.api.type.types.version.ChunkSectionType1_18;
import com.viaversion.viaversion.api.type.types.version.Types1_20_2;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public final class ChunkType1_20_2 extends Type<Chunk> {
private final ChunkSectionType1_18 sectionType;
private final int ySectionCount;
public ChunkType1_20_2(final int ySectionCount, final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(Chunk.class);
Preconditions.checkArgument(ySectionCount > 0);
this.sectionType = new ChunkSectionType1_18(globalPaletteBlockBits, globalPaletteBiomeBits);
this.ySectionCount = ySectionCount;
}
@Override
public Chunk read(final ByteBuf buffer) throws Exception {
final int chunkX = buffer.readInt();
final int chunkZ = buffer.readInt();
final CompoundTag heightMap = Type.NAMELESS_NBT.read(buffer);
// Read sections
final ByteBuf sectionsBuf = buffer.readBytes(Type.VAR_INT.readPrimitive(buffer));
final ChunkSection[] sections = new ChunkSection[ySectionCount];
try {
for (int i = 0; i < ySectionCount; i++) {
sections[i] = sectionType.read(sectionsBuf);
}
} finally {
sectionsBuf.release();
}
final int blockEntitiesLength = Type.VAR_INT.readPrimitive(buffer);
final List<BlockEntity> blockEntities = new ArrayList<>(blockEntitiesLength);
for (int i = 0; i < blockEntitiesLength; i++) {
blockEntities.add(Types1_20_2.BLOCK_ENTITY.read(buffer));
}
return new Chunk1_18(chunkX, chunkZ, sections, heightMap, blockEntities);
}
@Override
public void write(final ByteBuf buffer, final Chunk chunk) throws Exception {
buffer.writeInt(chunk.getX());
buffer.writeInt(chunk.getZ());
Type.NAMELESS_NBT.write(buffer, chunk.getHeightMap());
final ByteBuf sectionBuffer = buffer.alloc().buffer();
try {
for (final ChunkSection section : chunk.getSections()) {
sectionType.write(sectionBuffer, section);
}
sectionBuffer.readerIndex(0);
Type.VAR_INT.writePrimitive(buffer, sectionBuffer.readableBytes());
buffer.writeBytes(sectionBuffer);
} finally {
sectionBuffer.release(); // release buffer
}
Type.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size());
for (final BlockEntity blockEntity : chunk.blockEntities()) {
Types1_20_2.BLOCK_ENTITY.write(buffer, blockEntity);
}
}
@Override
public Class<? extends Type> getBaseClass() {
return BaseChunkType.class;
}
}
@@ -23,8 +23,10 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
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;
@@ -35,6 +37,8 @@ import com.viaversion.viaversion.rewriter.EntityRewriter;
public final class EntityPackets extends EntityRewriter<ClientboundPackets1_19_4, Protocol1_20To1_19_4> {
private static final Quaternion Y_FLIPPED_ROTATION = new Quaternion(0, 1, 0, 0);
public EntityPackets(final Protocol1_20To1_19_4 protocol) {
super(protocol);
}
@@ -127,6 +131,21 @@ public final class EntityPackets extends EntityRewriter<ClientboundPackets1_19_4
filter().handler((event, meta) -> meta.setMetaType(Types1_20.META_TYPES.byId(meta.metaType().typeId())));
registerMetaTypeHandler(Types1_20.META_TYPES.itemType, Types1_20.META_TYPES.blockStateType, Types1_20.META_TYPES.optionalBlockStateType, Types1_20.META_TYPES.particleType);
// 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_20.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));
});
filter().filterFamily(Entity1_19_4Types.MINECART_ABSTRACT).index(11).handler((event, meta) -> {
final int blockState = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(blockState));
@@ -137,4 +156,8 @@ public final class EntityPackets extends EntityRewriter<ClientboundPackets1_19_4
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());
}
}
@@ -67,9 +67,9 @@ public final class InventoryPackets extends ItemRewriter<ClientboundPackets1_19_
for (int i = 0; i < size; i++) {
wrapper.passthrough(Type.STRING); // Identifier
// Parent
if (wrapper.passthrough(Type.BOOLEAN))
wrapper.passthrough(Type.STRING);
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.STRING); // Parent
}
// Display data
if (wrapper.passthrough(Type.BOOLEAN)) {
@@ -85,11 +85,11 @@ public final class InventoryPackets extends ItemRewriter<ClientboundPackets1_19_
wrapper.passthrough(Type.FLOAT); // Y
}
wrapper.passthrough(Type.STRING_ARRAY); // Criteria
wrapper.passthrough(Type.STRING_ARRAY); // Critereon triggers
int arrayLength = wrapper.passthrough(Type.VAR_INT);
for (int array = 0; array < arrayLength; array++) {
wrapper.passthrough(Type.STRING_ARRAY); // String array
int requirements = wrapper.passthrough(Type.VAR_INT);
for (int array = 0; array < requirements; array++) {
wrapper.passthrough(Type.STRING_ARRAY);
}
wrapper.write(Type.BOOLEAN, false); // Sends telemetry
@@ -1,121 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_9_1_2to1_9_3_4;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
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.protocols.protocol1_9_1_2to1_9_3_4.chunks.BlockEntity;
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_1_2Type;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
// Goes BACKWARDS from 1.9.3/4 to 1.9.1/2
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));
}
}
}
@@ -1,84 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.protocol1_9_1_2to1_9_3_4.chunks;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.NumberTag;
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.protocols.protocol1_9_1_2to1_9_3_4.Protocol1_9_1_2To1_9_3_4;
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);
}
}
@@ -15,7 +15,7 @@
* 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.viaversion.protocols.protocol1_9_3to1_9_1_2.types;
package com.viaversion.viaversion.protocols.protocol1_9_1to1_9.types;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.chunks.BaseChunk;
@@ -32,10 +32,10 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
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.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.chunks.FakeTileEntity;
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_1_2Type;
import com.viaversion.viaversion.protocols.protocol1_9_1to1_9.types.Chunk1_9_1_2Type;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import java.util.List;
@@ -15,7 +15,7 @@
* 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.viaversion.protocols.protocol1_9_1_2to1_9_3_4.types;
package com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.types;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.Via;
@@ -122,4 +122,4 @@ public class Chunk1_9_3_4Type extends PartialType<Chunk, ClientWorld> {
public Class<? extends Type> getBaseClass() {
return BaseChunkType.class;
}
}
}
@@ -37,13 +37,7 @@ import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.InventoryPac
import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.PlayerPackets;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.SpawnPackets;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.packets.WorldPackets;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.BossBarProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.CommandBlockProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.CompressionProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.EntityIdProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.HandItemProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MainHandProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.*;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.ClientChunks;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.CommandBlockStorage;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.EntityTracker1_9;
@@ -137,7 +131,7 @@ public class Protocol1_9To1_8 extends AbstractProtocol<ClientboundPackets1_8, Cl
providers.register(BossBarProvider.class, new BossBarProvider());
providers.register(MainHandProvider.class, new MainHandProvider());
providers.register(CompressionProvider.class, new CompressionProvider());
providers.require(MovementTransmitterProvider.class);
providers.register(MovementTransmitterProvider.class, new MovementTransmitterProvider());
}
@Override
@@ -33,7 +33,7 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
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_1_2Type;
import com.viaversion.viaversion.protocols.protocol1_9_1to1_9.types.Chunk1_9_1_2Type;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
@@ -17,27 +17,34 @@
*/
package com.viaversion.viaversion.protocols.protocol1_9to1_8.providers;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.platform.providers.Provider;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.MovementTracker;
import com.viaversion.viaversion.util.PipelineUtil;
import io.netty.channel.ChannelHandlerContext;
public abstract class MovementTransmitterProvider implements Provider {
public abstract Object getFlyingPacket();
import java.util.logging.Level;
public abstract Object getGroundPacket();
public class MovementTransmitterProvider implements Provider {
public void sendPlayer(UserConnection userConnection) {
// Old method using packets.
ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", userConnection.getChannel().pipeline());
if (context != null) {
if (userConnection.get(MovementTracker.class).isGround()) {
context.fireChannelRead(getGroundPacket());
} else {
context.fireChannelRead(getFlyingPacket());
}
userConnection.get(MovementTracker.class).incrementIdlePacket();
if (userConnection.getProtocolInfo().getState() != State.PLAY || userConnection.getEntityTracker(Protocol1_9To1_8.class).clientEntityId() == -1) {
return;
}
final MovementTracker movementTracker = userConnection.get(MovementTracker.class);
movementTracker.incrementIdlePacket();
try {
final PacketWrapper playerMovement = PacketWrapper.create(ServerboundPackets1_8.PLAYER_MOVEMENT, userConnection);
playerMovement.write(Type.BOOLEAN, movementTracker.isGround()); // on ground
playerMovement.scheduleSendToServer(Protocol1_9To1_8.class);
} catch (Throwable e) {
Via.getPlatform().getLogger().log(Level.WARNING, "Failed to send player movement packet", e);
}
}
}
@@ -42,8 +42,8 @@ public class Effect {
addRewrite(1020, 1029); //Anvil break
addRewrite(1021, 1030); //Anvil use
addRewrite(1022, 1031); //Anvil land
addRewrite(1013, 1023);
addRewrite(1018, 1028);
addRewrite(1013, 1023); //Wither spawn
addRewrite(1018, 1028); //EnderDragon end
}
public static int getNewId(int id) {
@@ -23,7 +23,7 @@ public class MovementTracker implements StorableObject {
private static final long IDLE_PACKET_DELAY = 50L; // Update every 50ms (20tps)
private static final long IDLE_PACKET_LIMIT = 20; // Max 20 ticks behind
private long nextIdlePacket = 0L;
private boolean ground = true;
private boolean ground = false;
public void incrementIdlePacket() {
// Notify of next update
@@ -1,64 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.protocols.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);
});
}
});
}
}
@@ -42,10 +42,16 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public class BlockRewriter<C extends ClientboundPacketType> {
private final Protocol<C, ?, ?, ?> protocol;
private final Type<Position> positionType;
private final Type<CompoundTag> nbtType;
public BlockRewriter(Protocol<C, ?, ?, ?> protocol, Type<Position> positionType) {
this(protocol, positionType, Type.NBT);
}
public BlockRewriter(Protocol<C, ?, ?, ?> protocol, Type<Position> positionType, Type<CompoundTag> nbtType) {
this.protocol = protocol;
this.positionType = positionType;
this.nbtType = nbtType;
}
public void registerBlockAction(C packetType) {
@@ -145,9 +151,9 @@ public class BlockRewriter<C extends ClientboundPacketType> {
handler(wrapper -> {
int id = wrapper.get(Type.INT, 0);
int data = wrapper.get(Type.INT, 1);
if (id == playRecordId) { // Play record
if (id == playRecordId && protocol.getMappingData().getItemMappings() != null) {
wrapper.set(Type.INT, 1, protocol.getMappingData().getNewItemId(data));
} else if (id == blockBreakId) { // Block break + block break sound
} else if (id == blockBreakId && protocol.getMappingData().getBlockStateMappings() != null) {
wrapper.set(Type.INT, 1, protocol.getMappingData().getNewBlockStateId(data));
}
});
@@ -203,7 +209,7 @@ public class BlockRewriter<C extends ClientboundPacketType> {
public void registerBlockEntityData(C packetType, @Nullable Consumer<BlockEntity> blockEntityHandler) {
protocol.registerClientbound(packetType, wrapper -> {
final Position position = wrapper.passthrough(Type.POSITION1_14);
final Position position = wrapper.passthrough(positionType);
final int blockEntityId = wrapper.read(Type.VAR_INT);
final Mappings mappings = protocol.getMappingData().getBlockEntityMappings();
@@ -214,7 +220,7 @@ public class BlockRewriter<C extends ClientboundPacketType> {
}
final CompoundTag tag;
if (blockEntityHandler != null && (tag = wrapper.passthrough(Type.NBT)) != null) {
if (blockEntityHandler != null && (tag = wrapper.passthrough(nbtType)) != null) {
final BlockEntity blockEntity = new BlockEntityImpl(BlockEntity.pack(position.x(), position.z()), (short) position.y(), blockEntityId, tag);
blockEntityHandler.accept(blockEntity);
}
@@ -101,11 +101,11 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
}
@Override
public void handleMetadata(int entityId, List<Metadata> metadataList, UserConnection connection) {
public void handleMetadata(final int entityId, final List<Metadata> metadataList, final UserConnection connection) {
final TrackedEntity entity = tracker(connection).entity(entityId);
final EntityType type = entity != null ? entity.entityType() : null;
int i = 0; // Count index for fast removal
for (Metadata metadata : metadataList.toArray(EMPTY_ARRAY)) { // Copy the list to allow mutation
for (final Metadata metadata : metadataList.toArray(EMPTY_ARRAY)) { // Copy the list to allow mutation
// Call handlers implementing the old handleMetadata
if (!callOldMetaHandler(entityId, type, metadata, metadataList, connection)) {
metadataList.remove(i--);
@@ -113,18 +113,18 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
}
MetaHandlerEvent event = null;
for (MetaFilter filter : metadataFilters) {
for (final MetaFilter filter : metadataFilters) {
if (!filter.isFiltered(type, metadata)) {
continue;
}
if (event == null) {
// Only initialize when needed and share event instance
event = new MetaHandlerEventImpl(connection, type, entityId, metadata, metadataList);
event = new MetaHandlerEventImpl(connection, entity, entityId, metadata, metadataList);
}
try {
filter.handler().handle(event, metadata);
} catch (Exception e) {
} catch (final Exception e) {
logException(e, type, metadataList, metadata);
metadataList.remove(i--);
break;
@@ -311,6 +311,10 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
map(Type.VAR_INT); // Data
handler(trackerHandler());
handler(wrapper -> {
if (protocol.getMappingData() == null) {
return;
}
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityType entityType = tracker(wrapper.user()).entityType(entityId);
if (entityType == fallingBlockType) {
@@ -468,32 +472,32 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
}
public PacketHandler biomeSizeTracker() {
return wrapper -> {
final CompoundTag registry = wrapper.get(Type.NBT, 0);
final CompoundTag biomeRegistry = registry.get("minecraft:worldgen/biome");
final ListTag biomes = biomeRegistry.get("value");
tracker(wrapper.user()).setBiomesSent(biomes.size());
};
return wrapper -> trackBiomeSize(wrapper.user(), wrapper.get(Type.NBT, 0));
}
public void trackBiomeSize(final UserConnection connection, final CompoundTag registry) {
final CompoundTag biomeRegistry = registry.get("minecraft:worldgen/biome");
final ListTag biomes = biomeRegistry.get("value");
tracker(connection).setBiomesSent(biomes.size());
}
public PacketHandler dimensionDataHandler() {
return wrapper -> cacheDimensionData(wrapper.user(), wrapper.get(Type.NBT, 0));
}
/**
* Returns a handler to cache dimension data, later used to get height values and other important info.
*
* @return handler to cache dimension data
* Caches dimension data, later used to get height values and other important info.
*/
public PacketHandler dimensionDataHandler() {
return wrapper -> {
final CompoundTag tag = wrapper.get(Type.NBT, 0);
final ListTag dimensions = ((CompoundTag) tag.get("minecraft:dimension_type")).get("value");
final Map<String, DimensionData> dimensionDataMap = new HashMap<>(dimensions.size());
for (final Tag dimension : dimensions) {
final CompoundTag dimensionCompound = (CompoundTag) dimension;
final CompoundTag element = dimensionCompound.get("element");
final String name = (String) dimensionCompound.get("name").getValue();
dimensionDataMap.put(name, new DimensionDataImpl(element));
}
tracker(wrapper.user()).setDimensions(dimensionDataMap);
};
public void cacheDimensionData(final UserConnection connection, final CompoundTag registry) {
final ListTag dimensions = ((CompoundTag) registry.get("minecraft:dimension_type")).get("value");
final Map<String, DimensionData> dimensionDataMap = new HashMap<>(dimensions.size());
for (final Tag dimension : dimensions) {
final CompoundTag dimensionCompound = (CompoundTag) dimension;
final CompoundTag element = dimensionCompound.get("element");
final String name = (String) dimensionCompound.get("name").getValue();
dimensionDataMap.put(name, new DimensionDataImpl(element));
}
tracker(connection).setDimensions(dimensionDataMap);
}
// ---------------------------------------------------------------------------
@@ -31,9 +31,17 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class ItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends Protocol<C, ?, ?, S>> extends RewriterBase<T> implements com.viaversion.viaversion.api.rewriter.ItemRewriter<T> {
private final Type<Item> itemType;
private final Type<Item[]> itemArrayType;
protected ItemRewriter(T protocol) {
this(protocol, Type.FLAT_VAR_INT_ITEM, Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT);
}
public ItemRewriter(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType) {
super(protocol);
this.itemType = itemType;
this.itemArrayType = itemArrayType;
}
// These two methods always return the same item instance *for now*
@@ -62,7 +70,7 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
public void register() {
map(Type.UNSIGNED_BYTE); // Window id
map(type); // Items
handler(itemArrayHandler(type));
handler(itemArrayToClientHandler(type));
}
});
}
@@ -74,12 +82,12 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
map(Type.UNSIGNED_BYTE); // Window id
map(Type.VAR_INT); // State id
handler(wrapper -> {
Item[] items = wrapper.passthrough(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT);
Item[] items = wrapper.passthrough(itemArrayType);
for (Item item : items) {
handleItemToClient(item);
}
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Carried item
handleItemToClient(wrapper.passthrough(itemType)); // Carried item
});
}
});
@@ -123,8 +131,8 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
map(Type.UNSIGNED_BYTE); // Window id
map(Type.VAR_INT); // State id
map(Type.SHORT); // Slot id
map(Type.FLAT_VAR_INT_ITEM); // Item
handler(itemToClientHandler(Type.FLAT_VAR_INT_ITEM));
map(itemType); // Item
handler(itemToClientHandler(itemType));
}
});
}
@@ -155,7 +163,7 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
do {
slot = wrapper.passthrough(Type.BYTE);
// & 0x7F into an extra variable if slot is needed
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM));
handleItemToClient(wrapper.passthrough(itemType));
} while ((slot & 0xFFFFFF80) != 0);
});
}
@@ -168,7 +176,6 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
public void register() {
map(Type.SHORT); // 0 - Slot
map(type); // 1 - Clicked Item
handler(itemToServerHandler(type));
}
});
@@ -205,11 +212,11 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
int length = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < length; i++) {
wrapper.passthrough(Type.SHORT); // Slot
handleItemToServer(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM));
handleItemToServer(wrapper.passthrough(itemType));
}
// Carried item
handleItemToServer(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM));
handleItemToServer(wrapper.passthrough(itemType));
});
}
});
@@ -228,11 +235,11 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
wrapper.passthrough(Type.VAR_INT);
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Input
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Output
handleItemToClient(wrapper.passthrough(itemType)); // Input
handleItemToClient(wrapper.passthrough(itemType)); // Output
if (wrapper.passthrough(Type.BOOLEAN)) { // Has second item
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Second Item
handleItemToClient(wrapper.passthrough(itemType)); // Second Item
}
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
@@ -253,9 +260,9 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
wrapper.passthrough(Type.VAR_INT); // Container id
int size = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < size; i++) {
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Input
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Output
handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Second Item
handleItemToClient(wrapper.passthrough(itemType)); // Input
handleItemToClient(wrapper.passthrough(itemType)); // Output
handleItemToClient(wrapper.passthrough(itemType)); // Second Item
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
@@ -304,6 +311,41 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
});
}
public void registerAdvancements1_20_2(C packetType) {
protocol.registerClientbound(packetType, 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(itemType)); // 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
}
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
}
});
}
public void registerWindowPropertyEnchantmentHandler(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
@@ -340,7 +382,7 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
map(Type.FLOAT); // 7 - Offset Z
map(Type.FLOAT); // 8 - Particle Data
map(Type.INT); // 9 - Particle Count
handler(getSpawnParticleHandler(itemType));
handler(getSpawnParticleHandler());
}
});
}
@@ -359,16 +401,16 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
map(Type.FLOAT); // 7 - Offset Z
map(Type.FLOAT); // 8 - Particle Data
map(Type.INT); // 9 - Particle Count
handler(getSpawnParticleHandler(Type.VAR_INT, Type.FLAT_VAR_INT_ITEM));
handler(getSpawnParticleHandler(Type.VAR_INT));
}
});
}
public PacketHandler getSpawnParticleHandler(Type<Item> itemType) {
return getSpawnParticleHandler(Type.INT, itemType);
public PacketHandler getSpawnParticleHandler() {
return getSpawnParticleHandler(Type.INT);
}
public PacketHandler getSpawnParticleHandler(Type<Integer> idType, Type<Item> itemType) {
public PacketHandler getSpawnParticleHandler(Type<Integer> idType) {
return wrapper -> {
int id = wrapper.get(idType, 0);
if (id == -1) {
@@ -390,8 +432,7 @@ public abstract class ItemRewriter<C extends ClientboundPacketType, S extends Se
};
}
// Only sent to the client
public PacketHandler itemArrayHandler(Type<Item[]> type) {
public PacketHandler itemArrayToClientHandler(Type<Item[]> type) {
return wrapper -> {
Item[] items = wrapper.get(type, 0);
for (Item item : items) {
@@ -82,19 +82,19 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
for (int i = 0; i < ingredientsNo; i++) {
handleIngredient(wrapper);
}
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleCraftingShapeless(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
handleIngredients(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleSmelting(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
handleIngredient(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
wrapper.passthrough(Type.FLOAT); // EXP
wrapper.passthrough(Type.VAR_INT); // Cooking time
}
@@ -102,13 +102,13 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
public void handleStonecutting(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.STRING); // Group
handleIngredient(wrapper);
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleSmithing(PacketWrapper wrapper) throws Exception {
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Addition
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleSimpleRecipe(final PacketWrapper wrapper) throws Exception {
@@ -119,7 +119,7 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
handleIngredient(wrapper); // Template
handleIngredient(wrapper); // Base
handleIngredient(wrapper); // Additions
rewrite(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result
rewrite(wrapper.passthrough(itemType())); // Result
}
public void handleSmithingTrim(final PacketWrapper wrapper) throws Exception {
@@ -135,7 +135,7 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
}
protected void handleIngredient(final PacketWrapper wrapper) throws Exception {
final Item[] items = wrapper.passthrough(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT);
final Item[] items = wrapper.passthrough(itemArrayType());
for (final Item item : items) {
rewrite(item);
}
@@ -153,4 +153,12 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
void accept(PacketWrapper wrapper) throws Exception;
}
protected Type<Item> itemType() {
return Type.FLAT_VAR_INT_ITEM;
}
protected Type<Item[]> itemArrayType() {
return Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT;
}
}
@@ -37,7 +37,6 @@ public class SoundRewriter<C extends ClientboundPacketType> {
this.idRewriter = idRewriter;
}
// The same for entity sound
public void registerSound(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
@@ -48,6 +47,10 @@ public class SoundRewriter<C extends ClientboundPacketType> {
});
}
public void registerEntitySound(C packetType) {
this.registerSound(packetType);
}
// Not for entity sounds
public void register1_19_3Sound(C packetType) {
protocol.registerClientbound(packetType, wrapper -> {
@@ -18,11 +18,13 @@
package com.viaversion.viaversion.rewriter.meta;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
public interface MetaHandlerEvent {
/**
@@ -39,12 +41,21 @@ public interface MetaHandlerEvent {
*/
int entityId();
/**
* Returns the tracked entity if present.
*
* @return tracked entity if present, else null
*/
@Nullable TrackedEntity trackedEntity();
/**
* Returns the entity type of the entity the metadata belongs to if tracked.
*
* @return entity type of the entity if tracked, else null
*/
@Nullable EntityType entityType();
default @Nullable EntityType entityType() {
return trackedEntity() != null ? trackedEntity().entityType() : null;
}
/**
* Returns the metadata index.
@@ -110,6 +121,15 @@ public interface MetaHandlerEvent {
*/
@Nullable List<Metadata> extraMeta();
/**
* Returns whether additionally created metadata will be added.
*
* @return true if additionally created metadata is present
*/
default boolean hasExtraMeta() {
return extraMeta() != null;
}
/**
* Adds the given metadata to the metadata list.
* This metadata will not be passed through handlers of the current loop.
@@ -19,25 +19,26 @@
package com.viaversion.viaversion.rewriter.meta;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public class MetaHandlerEventImpl implements MetaHandlerEvent {
private final UserConnection connection;
private final EntityType entityType;
private final TrackedEntity trackedEntity;
private final int entityId;
private final List<Metadata> metadataList;
private final Metadata meta;
private List<Metadata> extraData;
private boolean cancel;
public MetaHandlerEventImpl(UserConnection connection, @Nullable EntityType entityType, int entityId, Metadata meta, List<Metadata> metadataList) {
public MetaHandlerEventImpl(UserConnection connection, @Nullable TrackedEntity trackedEntity, int entityId, Metadata meta, List<Metadata> metadataList) {
this.connection = connection;
this.entityType = entityType;
this.trackedEntity = trackedEntity;
this.entityId = entityId;
this.meta = meta;
this.metadataList = metadataList;
@@ -54,8 +55,8 @@ public class MetaHandlerEventImpl implements MetaHandlerEvent {
}
@Override
public @Nullable EntityType entityType() {
return entityType;
public @Nullable TrackedEntity trackedEntity() {
return trackedEntity;
}
@Override
@@ -0,0 +1,215 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* 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.viaversion.util;
import com.google.common.io.CharStreams;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.dump.DumpTemplate;
import com.viaversion.viaversion.dump.VersionInfo;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InvalidObjectException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class DumpUtil {
/**
* Creates a platform dump and posts it to ViaVersion's dump server asychronously.
* May complete exceptionally with {@link DumpException}.
*
* @param playerToSample uuid of the player to include the pipeline of
* @return completable future that completes with the url of the dump
*/
public static CompletableFuture<String> postDump(@Nullable final UUID playerToSample) {
final VersionInfo version = new VersionInfo(
System.getProperty("java.version"),
System.getProperty("os.name"),
Via.getAPI().getServerVersion().lowestSupportedVersion(),
Via.getManager().getProtocolManager().getSupportedVersions(),
Via.getPlatform().getPlatformName(),
Via.getPlatform().getPlatformVersion(),
Via.getPlatform().getPluginVersion(),
com.viaversion.viaversion.util.VersionInfo.getImplementationVersion(),
Via.getManager().getSubPlatforms()
);
final Map<String, Object> configuration = Via.getPlatform().getConfigurationProvider().getValues();
final DumpTemplate template = new DumpTemplate(version, configuration, Via.getPlatform().getDump(), Via.getManager().getInjector().getDump(), getPlayerSample(playerToSample));
final CompletableFuture<String> result = new CompletableFuture<>();
Via.getPlatform().runAsync(() -> {
final HttpURLConnection con;
try {
con = (HttpURLConnection) new URL("https://dump.viaversion.com/documents").openConnection();
} catch (final IOException e) {
Via.getPlatform().getLogger().log(Level.SEVERE, "Error when opening connection to ViaVersion dump service", e);
result.completeExceptionally(new DumpException(DumpErrorType.CONNECTION, e));
return;
}
try {
con.setRequestProperty("Content-Type", "application/json");
con.addRequestProperty("User-Agent", "ViaVersion-" + Via.getPlatform().getPlatformName() + "/" + version.getPluginVersion());
con.setRequestMethod("POST");
con.setDoOutput(true);
try (final OutputStream out = con.getOutputStream()) {
out.write(new GsonBuilder().setPrettyPrinting().create().toJson(template).getBytes(StandardCharsets.UTF_8));
}
if (con.getResponseCode() == 429) {
result.completeExceptionally(new DumpException(DumpErrorType.RATE_LIMITED));
return;
}
final String rawOutput;
try (final InputStream inputStream = con.getInputStream()) {
rawOutput = CharStreams.toString(new InputStreamReader(inputStream));
}
final JsonObject output = GsonUtil.getGson().fromJson(rawOutput, JsonObject.class);
if (!output.has("key")) {
throw new InvalidObjectException("Key is not given in Hastebin output");
}
result.complete(urlForId(output.get("key").getAsString()));
} catch (final Exception e) {
Via.getPlatform().getLogger().log(Level.SEVERE, "Error when posting ViaVersion dump", e);
result.completeExceptionally(new DumpException(DumpErrorType.POST, e));
printFailureInfo(con);
}
});
return result;
}
private static void printFailureInfo(final HttpURLConnection connection) {
try {
if (connection.getResponseCode() < 200 || connection.getResponseCode() > 400) {
try (final InputStream errorStream = connection.getErrorStream()) {
final String rawOutput = CharStreams.toString(new InputStreamReader(errorStream));
Via.getPlatform().getLogger().log(Level.SEVERE, "Page returned: " + rawOutput);
}
}
} catch (final IOException e) {
Via.getPlatform().getLogger().log(Level.SEVERE, "Failed to capture further info", e);
}
}
public static String urlForId(final String id) {
return String.format("https://dump.viaversion.com/%s", id);
}
private static JsonObject getPlayerSample(@Nullable final UUID uuid) {
final JsonObject playerSample = new JsonObject();
// Player versions
final JsonObject versions = new JsonObject();
playerSample.add("versions", versions);
final Map<ProtocolVersion, Integer> playerVersions = new TreeMap<>((o1, o2) -> ProtocolVersion.getIndex(o2) - ProtocolVersion.getIndex(o1));
for (final UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final ProtocolVersion protocolVersion = ProtocolVersion.getProtocol(connection.getProtocolInfo().getProtocolVersion());
playerVersions.compute(protocolVersion, (v, num) -> num != null ? num + 1 : 1);
}
for (final Map.Entry<ProtocolVersion, Integer> entry : playerVersions.entrySet()) {
versions.addProperty(entry.getKey().getName(), entry.getValue());
}
final Set<List<String>> pipelines = new HashSet<>();
if (uuid != null) {
// Pipeline of sender
final UserConnection senderConnection = Via.getAPI().getConnection(uuid);
if (senderConnection != null && senderConnection.getChannel() != null) {
pipelines.add(senderConnection.getChannel().pipeline().names());
}
}
// Other pipelines if different ones are found (3 max)
for (final UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
if (connection.getChannel() == null) {
continue;
}
final List<String> names = connection.getChannel().pipeline().names();
if (pipelines.add(names) && pipelines.size() == 3) {
break;
}
}
int i = 0;
for (final List<String> pipeline : pipelines) {
final JsonArray senderPipeline = new JsonArray(pipeline.size());
for (final String name : pipeline) {
senderPipeline.add(name);
}
playerSample.add("pipeline-" + i++, senderPipeline);
}
return playerSample;
}
public static final class DumpException extends RuntimeException {
private final DumpErrorType errorType;
private DumpException(final DumpErrorType errorType, final Throwable cause) {
super(errorType.message(), cause);
this.errorType = errorType;
}
private DumpException(final DumpErrorType errorType) {
super(errorType.message());
this.errorType = errorType;
}
public DumpErrorType errorType() {
return errorType;
}
}
public enum DumpErrorType {
CONNECTION("Failed to dump, please check the console for more information"),
RATE_LIMITED("Please wait before creating another dump"),
POST("Failed to dump, please check the console for more information");
private final String message;
DumpErrorType(final String message) {
this.message = message;
}
public String message() {
return message;
}
}
}
@@ -18,7 +18,7 @@ send-supported-versions: false
# You can use both this and the block-protocols option at the same time as well.
block-versions: []
# Block specific Minecraft protocol version numbers.
# List of all Minecraft protocol versions: http://wiki.vg/Protocol_version_numbers, or use a generator: https://via.krusic22.com
# List of all Minecraft protocol versions: https://wiki.vg/Protocol_version_numbers, or use a generator: https://via.krusic22.com
block-protocols: []
# Change the blocked disconnect message
block-disconnect-msg: "You are using an unsupported Minecraft version!"
@@ -47,7 +47,7 @@ bungee-ping-save: true
#
# The format for the following is:
# servername: protocolversion
# You can find protocol ids on http://wiki.vg/Protocol_version_numbers
# You can find protocol ids on https://wiki.vg/Protocol_version_numbers
# It will fallback to the default option if none found.
bungee-servers: {}
#
@@ -69,7 +69,7 @@ velocity-ping-save: true
#
# The format for the following is:
# servername: protocolversion
# You can find protocol ids on http://wiki.vg/Protocol_version_numbers
# You can find protocol ids on https://wiki.vg/Protocol_version_numbers
# It will fallback to the default option if none found.
velocity-servers: {}
#
+7 -1
View File
@@ -1,5 +1,11 @@
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
projectVersion=4.7.0
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, 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9, 1.8.9
mcVersionRange=1.8-1.20.2
waterfallVersion=1.20
velocityVersion=3.2
# Gradle properties
org.gradle.daemon=true
+1 -1
View File
@@ -2,7 +2,7 @@ metadata.format.version = "1.1"
[versions]
adventure = "4.13.1"
adventure = "4.14.0"
gson = "2.10.1"
fastutil = "8.5.12"
flare = "2.0.1"
Binary file not shown.
+2 -1
View File
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+6 -2
View File
@@ -83,7 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -130,10 +131,13 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
Vendored
+92 -92
View File
@@ -1,92 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
Loaded 100 of 105 files, more files were not shown because too many files have changed in this diff. Show more