96 Commits
Author SHA1 Message Date
FlorianMichael d85e043325 3.1.0 Release 2024-04-26 15:32:46 +02:00
FlorianMichael 967adaa607 Update item mappings
Adds support for https://github.com/ViaVersion/ViaBackwards/pull/728 as well as missing blockstate mappings from before the rewrite.
2024-04-26 00:27:44 +02:00
FlorianMichael e233b0fa09 Fix and clean hologram emulation 2024-04-24 18:10:29 +02:00
FlorianMichael 2e52a396d3 Migrate 1.7->1.8 as well 2024-04-24 16:57:00 +02:00
FlorianMichael 93731be764 Add new config options for /offhand, also some cleanup 2024-04-23 23:49:43 +02:00
FlorianMichael 8a5d826fd3 Tidy up a few things and fixed tons of bugs 2024-04-23 22:29:37 +02:00
FlorianMichael d5fa0ff8e8 Migrate 1.8->1.9 and removed tons of outdated code 2024-04-23 20:35:27 +02:00
FlorianMichael 823b00930e Merge remote-tracking branch 'refs/remotes/origin/dev' into refactor/viabackwards
# Conflicts:
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/packets/BlockItemPackets1_8.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/rewriter/ReplacementItemRewriter1_7_6_10.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_8to1_9/metadata/MetadataRewriter.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_8to1_9/packets/InventoryPackets.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_8to1_9/rewriter/ReplacementItemRewriter1_8.java
2024-04-22 11:46:53 +02:00
Nassim Jahnke da449f2a9e Add UserConnection param to item rewriter methods 2024-04-21 22:48:30 +02:00
FlorianMichael 8835ee4ed2 Update metadata rewriter 2024-04-09 16:00:48 +02:00
FlorianMichael 3ef9dbec1f Merge branch 'refs/heads/dev' into refactor/viabackwards
# Conflicts:
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_8to1_9/metadata/MetadataRewriter.java
2024-04-09 15:59:31 +02:00
FlorianMichael b2a78d6dd2 Merge remote-tracking branch 'refs/remotes/origin/master' into dev 2024-04-09 15:57:56 +02:00
FlorianMichael 1aaba348d2 Update build script 2024-04-09 15:56:46 +02:00
FlorianMichael 4d5c4e6223 Removed non-existent meta type 2024-04-09 15:53:42 +02:00
FlorianMichael d08739839e Fix universal module name 2024-04-09 15:51:35 +02:00
FlorianMichael e891696387 Start with porting protocol code 2024-04-09 15:47:45 +02:00
vadage 08cb78f065 Support config loading from input stream (#502)
* Support config loading from input stream

* Fix formatting issue to be consistent with spaces
2024-04-05 20:38:35 +02:00
FlorianMichael 819a4d8bb3 More work 2024-03-29 18:13:05 +01:00
FlorianMichael aa5696e586 Overall improvements to README.md 2024-03-29 13:00:02 +01:00
FlorianMichael 3c9232949a Rename classes to match VB 2024-03-29 12:47:38 +01:00
FlorianMichael a43ad2b737 Prepare entity rewriter migration 2024-03-29 12:41:17 +01:00
FlorianMichael 7e5e8fd2c1 Fix enchantments in 1.7->1.8 2024-03-28 18:08:24 +01:00
FlorianMichael 7fc2530693 Compile from repository server 2024-03-28 11:46:11 +01:00
FlorianMichael e104df51b0 Drop format reset 2024-03-28 10:44:32 +01:00
FlorianMichael 6d237cc337 Deprecate and move classes 2024-03-27 20:34:23 +01:00
FlorianMichael a982ac8c38 Move particle class 2024-03-27 20:26:28 +01:00
FlorianMichael 8494976e4f Port 1.8 -> 1.9 item rewriter as well 2024-03-27 20:02:50 +01:00
FlorianMichael 7b2ad249da Use EnchantmentRewriter base (probably) 2024-03-27 18:22:31 +01:00
FlorianMichael 5f73bee3c5 Start with using ViaBackwards API 2024-03-27 18:04:04 +01:00
FlorianMichael 709f918272 Generate item mappings 2024-03-27 13:55:39 +01:00
FlorianMichael dca9854486 Removed support status from README 2024-03-27 13:54:44 +01:00
FlorianMichael d93dce88d8 So it begins... 2024-03-27 11:12:37 +01:00
FlorianMichael 5ae0f29f42 Fixed version range 2024-03-25 17:35:55 +01:00
FlorianMichael eae4a3ac09 Renamed universal artifact to viarewind, fixed platform name in Via dumps 2024-03-25 17:34:07 +01:00
FlorianMichael 5e1ae7ac0f Back to VV dev 2024-03-24 13:06:13 +01:00
FlorianMichael 2422588db5 Remove viafabricplus from dependency list 2024-03-24 13:01:43 +01:00
FlorianMichael 0a1707f1d0 Fix up again 2024-03-23 13:18:47 +01:00
FlorianMichael c6d6128c5e Update publishing plugin usage 2024-03-23 13:11:40 +01:00
FlorianMichael 8f2072d2af [ci skip] Removed unused import 2024-03-23 12:32:59 +01:00
FlorianMichael 42fbcfb26a Gradle 8.7 2024-03-23 12:31:27 +01:00
FlorianMichael a9568d388f Update Hangar publish plugin 2024-03-23 12:29:42 +01:00
FlorianMichael 36ea0fecc6 Fixed compile error 2024-03-09 14:11:41 +01:00
FlorianMichael 6a26bbdf84 Back to VV master 2024-03-09 14:09:30 +01:00
FlorianMichael 45deefdea3 Update ViaNBT API usage 2024-03-09 14:04:37 +01:00
FlorianMichael 476c5f2077 Updated Via API usage 2024-03-09 13:51:19 +01:00
FlorianMichael aaddfb186b Fixed API usage 2024-03-05 21:02:35 +01:00
FlorianMichael 5407bf9922 Bump version to 3.0.7-24w09a-SNAPSHOT 2024-03-05 20:13:44 +01:00
FlorianMichael 8aea3e43aa Bump version to 3.0.7-SNAPSHOT 2024-03-05 20:11:38 +01:00
FlorianMichael 38e59d7cb5 3.0.6 2024-03-05 19:55:56 +01:00
FlorianMichael 66851feaff [ci skip] Create FUNDING.yml 2024-03-05 13:46:58 +01:00
FlorianMichael 2474f2f347 Merge remote-tracking branch 'origin/master' 2024-03-04 22:18:51 +01:00
FlorianMichael 3322b77afb Merge dev changes into master 2024-03-04 22:18:39 +01:00
FlorianMichael fc7b10e4aa Merge remote-tracking branch 'origin/dev' 2024-03-04 22:15:27 +01:00
FlorianMichael 000c414418 Change dev branch version to 3.0.6-24w07a-SNAPSHOT 2024-03-04 22:13:44 +01:00
FlorianMichael 26b9a83f5a Fixed api usages 2024-02-29 15:25:04 +01:00
FlorianMichael 37a671dfa1 Simplified entity rewriter 2024-02-29 15:21:01 +01:00
FlorianMichael 6a1c89676c Fixed painting rotations in 1.7 -> 1.8 2024-02-29 14:51:56 +01:00
FlorianMichael f0706eca23 Cleaned up token replacement 2024-02-29 14:22:15 +01:00
FlorianMichael 0610ed53ab Finished ReplacementEntityTracker rewrite for now (?) 2024-02-29 14:10:11 +01:00
FlorianMichael dbe26e0ecc Move some classes 2024-02-29 14:04:17 +01:00
FlorianMichael 62606d604e Random code cleanup 2024-02-29 14:01:44 +01:00
FlorianMichael 7254e1ce42 [ci skip] Removed debug code 2024-02-29 13:53:32 +01:00
FlorianMichael b3b6bb325f Proper include of project description 2024-02-29 13:33:21 +01:00
FlorianMichael a0eb8aee24 Mark VR as library for ModMenu 2024-02-29 12:25:16 +01:00
FlorianMichael 630e0224e6 Use equals in legacy custom payload channel comparisons 2024-02-29 12:23:12 +01:00
EnZaXD 224cc121d7 Merge pull request #488 from Kichura/master
paste.gg -> mclo.gs
2024-02-18 23:12:57 +01:00
Kichura a6d9b601d1 paste.gg -> mclo.gs. 2024-02-18 23:10:28 +01:00
FlorianMichael 97044dbe2c Back to VV master 2024-02-18 22:43:35 +01:00
FlorianMichael bb5610c072 Added ViaRewindPlatform#getDataFolder to match VV/VB style 2024-02-18 22:27:08 +01:00
FlorianMichael 57997b25cf Sync fabric.mod.json description with project description 2024-02-18 22:18:33 +01:00
FlorianMichael fc85a00d8c Updated mcVersions in gradle.properties 2024-02-14 20:41:47 +01:00
FlorianMichael f6ceeba636 Updated Via API usage 2024-02-14 20:39:57 +01:00
FlorianMichael 66c810c284 Merge remote-tracking branch 'origin/master' into dev 2024-01-26 15:28:48 +01:00
EnZaXD 3422d90882 Merge pull request #481 from Kichura/master
Update JDK to 17, Cache to v4
2024-01-20 21:24:04 +01:00
Kichura 1f4ab995c5 Update JDK to 17, Cache to v4. 2024-01-20 21:13:17 +01:00
EnZaXD 6a726a289d Merge pull request #479 from ItsClairton/master
fix: Add missing creeper metadata
2024-01-19 14:04:00 +01:00
Clairton (Aiko - W11) 4abe3fb7e8 Add missing creeper metadata, index 18 2024-01-18 00:17:13 -03:00
EnZaXD db93bbbc3e Merge pull request #476 from Kichura/master
Update Velocity to 3.3
2024-01-14 17:25:20 +01:00
Kichura dd220ccf7f Update Velocity to 3.3. 2024-01-14 13:09:37 +01:00
FlorianMichael 0a20ead08b Compile against dev branch of VV again ™️ 2024-01-13 06:37:57 +01:00
FlorianMichael 1eb0d1672e Merge branch 'master' into dev 2024-01-13 06:36:29 +01:00
FlorianMichael f0969b5515 Fixed Via API usage 2024-01-13 06:35:20 +01:00
FlorianMichael 05dea07d99 Delete a lot unused code 2024-01-02 18:53:03 +01:00
FlorianMichael 4d3e5264bc Read names 2024-01-02 18:49:13 +01:00
FlorianMichael fba5a1c7d1 Compile against master branch of VV 2024-01-02 18:21:14 +01:00
EnZaXD 171d33525f Merge pull request #473 from ViaVersion/master
Update dev branch for master changes
2024-01-02 18:20:45 +01:00
FlorianMichael 8d35b00fd7 2024 2024-01-01 00:47:57 +01:00
FlorianMichael 572551b670 Fixed 1.8 -> 1.9 explosion packet translation being broken.
Closes https://github.com/ViaVersion/ViaRewind/issues/471
2023-12-28 00:27:33 +01:00
FlorianMichael 531e564d0b Use correct version for serializing the json component 2023-12-27 20:09:35 +01:00
FlorianMichael 81840dc643 Updated Via API usage 2023-12-27 20:03:00 +01:00
FlorianMichael a9f0b72adc Merge remote-tracking branch 'origin/master' 2023-12-27 17:55:23 +01:00
FlorianMichael e1b9c76063 Updated copyright profile 2023-12-27 17:54:52 +01:00
Kichura 2da271ffe7 [ci skip] Update checkout and setup-java to v4. (#470) 2023-12-27 17:26:33 +01:00
Kichura f27b4f0df6 Add description for ViaRewind. (#468)
This properly describes on what viarewind is for when viewing it in Mod Menu.
2023-12-23 11:51:37 +01:00
SplotyCode cf64b7ffcc Fix 1.9->1.8 use item (#466) 2023-12-21 10:19:12 +01:00
FlorianMichael 6829af6cb7 Bump version to 3.0.6-SNAPSHOT 2023-12-13 23:21:04 +01:00
135 changed files with 5230 additions and 6430 deletions

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
github: FlorianMichael
custom: ['https://florianmichael.de/donate', 'https://viaversion.com/donate', 'https://creeper123123321.github.io/#donate']
+2 -2
View File
@@ -23,11 +23,11 @@ body:
attributes:
label: Console Error
description: |
If you encounter warnings/errors in your console, **paste them with https://paste.gg/ and put the paste link here**.
If you encounter warnings/errors in your console, **paste them with https://mclo.gs/ and put the paste link here**.
If the error is small/less than 10 lines, you may put it directly into this field.
value: |
```
Put the paste.gg link or text here.
Put the mclo.gs link or text here.
```
placeholder: Please do not remove the grave accents; simply replace the line of text in the middle.
validations:
+5 -5
View File
@@ -6,17 +6,17 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 8
uses: actions/setup-java@v3
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 8
java-version: 17
check-latest: true
- name: Cache Dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
+4 -4
View File
@@ -11,14 +11,14 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 8
uses: actions/setup-java@v3
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 8
java-version: 17
check-latest: true
- name: Publish
env:
+1 -1
View File
@@ -1,6 +1,6 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind&#10;Copyright (C) &amp;#36;originalComment.match(&quot;Copyright \(C\) (\d+)&quot;, 1, &quot;-&quot;)&amp;#36;today.year ViaVersion and contributors&#10;&#10;This program is free software: you can redistribute it and/or modify&#10;it under the terms of the GNU General Public License as published by&#10;the Free Software Foundation, either version 3 of the License, or&#10;(at your option) any later version.&#10;&#10;This program is distributed in the hope that it will be useful,&#10;but WITHOUT ANY WARRANTY; without even the implied warranty of&#10;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#10;GNU General Public License for more details.&#10;&#10;You should have received a copy of the GNU General Public License&#10;along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;." />
<option name="notice" value="This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind&#10;Copyright (C) 2018-&amp;#36;today.year ViaVersion and contributors&#10;&#10;This program is free software: you can redistribute it and/or modify&#10;it under the terms of the GNU General Public License as published by&#10;the Free Software Foundation, either version 3 of the License, or&#10;(at your option) any later version.&#10;&#10;This program is distributed in the hope that it will be useful,&#10;but WITHOUT ANY WARRANTY; without even the implied warranty of&#10;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#10;GNU General Public License for more details.&#10;&#10;You should have received a copy of the GNU General Public License&#10;along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;." />
<option name="myName" value="viarewind-gpl" />
</copyright>
</component>
+19 -7
View File
@@ -1,22 +1,25 @@
# ViaRewind
[![Latest Release](https://img.shields.io/github/v/release/ViaVersion/ViaRewind)](https://github.com/ViaVersion/ViaRewind/releases)
[![Build Status](https://github.com/ViaVersion/ViaRewind/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaRewind/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**ViaVersion addon to allow 1.8.x and 1.7.x clients on newer server versions.** <br>
**ViaBackwards addon to allow 1.8.x and 1.7.x clients on newer server versions.** <br>
Runs on 1.9-latest servers or 1.8 clients and lower.
**You can override the included version in [ViaFabric](https://modrinth.com/mod/viafabric) or [ViaProxy](https://github.com/ViaVersion/ViaProxy):**
- in **ViaFabric**, put ViaRewind into the `mods` folder
- in **ViaProxy**, put ViaRewind into the `jars` folder
**Depending on the platform and version, this also requires [ViaVersion](https://modrinth.com/mod/viaversion) and [ViaBackwards](https://modrinth.com/mod/viabackwards).**
**Requires [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) and [ViaBackwards](https://hangar.papermc.io/ViaVersion/ViaBackwards) to be installed..**
Support Status
Releases/Dev Builds
-
While ViaRewind will keep getting updates to function with changes to ViaVersion or ViaBackwards, it will likely not receive many bug fixes or additional features anymore.
You can find releases in the following places:
- **Hangar (for our plugins)**: https://hangar.papermc.io/ViaVersion/ViaRewind
- **Modrinth (for our mods)**: https://modrinth.com/mod/viarewind
- **GitHub**: https://github.com/ViaVersion/ViaRewind/releases
Releases / Dev Builds
-
Dev builds for **all** of our projects are on our Jenkins server:
- **Jenkins**: https://ci.viaversion.com/view/ViaRewind/
@@ -27,4 +30,13 @@ Other Links
**Issue tracker:** https://github.com/ViaVersion/ViaRewind/issues
**List of contributors:** https://github.com/ViaVersion/ViaRewind/graphs/contributors
**List of contributors:** https://github.com/ViaVersion/ViaRewind/graphs/contributors
Building
-
After cloning this repository, build the project with Gradle by running `./gradlew build` and take the created jar out
of the `universal/build/libs` directory.
License
-
This project is licensed under the [GNU General Public License Version 3](LICENSE).
@@ -4,7 +4,6 @@ plugins {
}
repositories {
mavenLocal()
maven {
url = uri("https://repo.viaversion.com")
}
@@ -36,24 +35,29 @@ repositories {
dependencies {
compileOnly "com.viaversion:viaversion:${project.viaversion_version}"
compileOnly "com.viaversion:viabackwards:${project.viabackwards_version}"
compileOnly "io.netty:netty-all:${project.netty_version}"
compileOnly "com.google.guava:guava:${project.guava_version}"
}
archivesBaseName = project.maven_name
group = project.maven_group
version = project.maven_version
base {
archivesName = project.maven_name
group = project.maven_group
version = project.maven_version
description = "ViaVersion addon to allow 1.8.x and 1.7.x clients on newer server versions."
}
java.sourceCompatibility = JavaVersion.VERSION_1_8
tasks {
// Variable replacements
processResources {
inputs.property "version", project.version
for (final def file in ["plugin.yml", "bungee.yml", "META-INF/sponge_plugins.json", "fabric.mod.json"]) {
filesMatching(file) {
expand "version": version
expand(
"version": project.version,
"description": project.description
)
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
+5 -7
View File
@@ -1,12 +1,10 @@
name: ViaRewind
version: ${version}
main: com.viaversion.viarewind.BukkitPlugin
authors: [FlorianMichael/EnZaXD, Gerrygames, creeper123321123]
version: ${version}
description: ${description}
website: https://viaversion.com/rewind
api-version: 1.13
folia-supported: true
authors: [Gerrygames, FlorianMichael/EnZaXD, creeper123321123]
website: https://viaversion.com/rewind
load: STARTUP
depend: [ViaVersion]
softdepend: [ViaBackwards]
depend: [ViaVersion, ViaBackwards]
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
+2 -3
View File
@@ -1,7 +1,6 @@
name: ViaRewind
main: com.viaversion.viarewind.BungeePlugin
authors: [Gerrygames, FlorianMichael/EnZaXD, creeper123321123]
authors: [FlorianMichael/EnZaXD, Gerrygames, creeper123321123]
version: ${version}
depends: [ViaVersion]
softdepends: [ViaBackwards]
depends: [ViaVersion, ViaBackwards]
website: https://viaversion.com/rewind
+1 -1
View File
@@ -13,7 +13,7 @@ sourceSets {
main {
classTokenReplacer {
property("\${version}", rootProject.maven_version)
property("\${impl_version}", "git-${project.name}-${rootProject.maven_version}:${project.latestCommitHash()}")
property("\${impl_version}", "git-ViaRewind-${rootProject.maven_version}:${project.latestCommitHash()}")
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind;
import com.google.common.base.Preconditions;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,12 +15,12 @@
* 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.viarewind;
import com.viaversion.viaversion.util.Config;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.List;
@@ -28,44 +28,88 @@ import java.util.Map;
public class ViaRewindConfig extends Config implements com.viaversion.viarewind.api.ViaRewindConfig {
private CooldownIndicator cooldownIndicator;
private boolean replaceAdventureMode;
private boolean replaceParticles;
private int maxBookPages;
private int maxBookPageSize;
private boolean emulateWorldBorder;
private boolean alwaysShowOriginalMobName;
private String worldBorderParticle;
private boolean enableOffhand;
private String offhandCommand;
public ViaRewindConfig(File configFile) {
super(configFile);
reload();
}
@Override
@Override
public void reload() {
super.reload();
loadFields();
}
private void loadFields() {
cooldownIndicator = CooldownIndicator.valueOf(getString("cooldown-indicator", "TITLE").toUpperCase());
replaceAdventureMode = getBoolean("replace-adventure", false);
replaceParticles = getBoolean("replace-particles", false);
maxBookPages = getInt("max-book-pages", 100);
maxBookPageSize = getInt("max-book-page-length", 5000);
emulateWorldBorder = getBoolean("emulate-world-border", true);
alwaysShowOriginalMobName = getBoolean("always-show-original-mob-name", true);
worldBorderParticle = getString("world-border-particle", "fireworksSpark");
enableOffhand = getBoolean("enable-offhand", true);
offhandCommand = getString("offhand-command", "/offhand");
}
@Override
public CooldownIndicator getCooldownIndicator() {
return CooldownIndicator.valueOf(getString("cooldown-indicator", "TITLE").toUpperCase());
return cooldownIndicator;
}
@Override
public boolean isReplaceAdventureMode() {
return getBoolean("replace-adventure", false);
return replaceAdventureMode;
}
@Override
public boolean isReplaceParticles() {
return getBoolean("replace-particles", false);
return replaceParticles;
}
@Override
public int getMaxBookPages() {
return getInt("max-book-pages", 100);
return maxBookPages;
}
@Override
public int getMaxBookPageSize() {
return getInt("max-book-page-length", 5000);
return maxBookPageSize;
}
@Override
public boolean isEmulateWorldBorder() {
return getBoolean("emulate-world-border", true);
return emulateWorldBorder;
}
@Override
public boolean alwaysShowOriginalMobName() {
return alwaysShowOriginalMobName;
}
@Override
public String getWorldBorderParticle() {
return getString("world-border-particle", "fireworksSpark");
return worldBorderParticle;
}
@Override
public boolean isEnableOffhand() {
return enableOffhand;
}
@Override
public String getOffhandCommand() {
return offhandCommand;
}
@Override
@@ -74,8 +118,12 @@ public class ViaRewindConfig extends Config implements com.viaversion.viarewind.
}
@Override
protected void handleConfig(Map<String, Object> map) {
public InputStream getDefaultConfigInputStream() {
return getClass().getClassLoader().getResourceAsStream("assets/viarewind/config.yml");
}
@Override
protected void handleConfig(Map<String, Object> map) {
}
@Override
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.api;
import com.viaversion.viaversion.api.configuration.Config;
@@ -77,10 +76,31 @@ public interface ViaRewindConfig extends Config {
*/
boolean isEmulateWorldBorder();
/**
* Always shows the original mob's name instead of only when hovering over them with the cursor.
*
* @return true if enabled
*/
boolean alwaysShowOriginalMobName();
/**
* The particle to show the world border for the 1.8+ world border for 1.7.x clients
*
* @return the particle name (see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Particle_2">Particle registry for Packet</a>)
*/
String getWorldBorderParticle();
/**
* If enabled, 1.8 players on 1.9+ servers can use /offhand to switch items between their main hand and offhand.
*
* @return true if enabled
*/
boolean isEnableOffhand();
/**
* Allows to define the offhand command
*
* @return the offhand command
*/
String getOffhandCommand();
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.api;
import com.viaversion.viarewind.ViaRewind;
@@ -50,10 +49,11 @@ public interface ViaRewindPlatform {
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
getLogger().info("Registering protocols...");
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.registerProtocol(new Protocol1_7_2_5To1_7_6_10(), ProtocolVersion.v1_7_1, ProtocolVersion.v1_7_6);
protocolManager.registerProtocol(new Protocol1_7_2_5To1_7_6_10(), ProtocolVersion.v1_7_2, ProtocolVersion.v1_7_6);
protocolManager.registerProtocol(new Protocol1_7_6_10To1_8(), ProtocolVersion.v1_7_6, ProtocolVersion.v1_8);
protocolManager.registerProtocol(new Protocol1_8To1_9(), ProtocolVersion.v1_8, ProtocolVersion.v1_9);
}
@@ -63,4 +63,11 @@ public interface ViaRewindPlatform {
* @return the logger
*/
Logger getLogger();
/**
* Returns ViaRewind's data folder.
*
* @return data folder
*/
File getDataFolder();
}
@@ -0,0 +1,41 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.data;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import java.util.logging.Logger;
public class RewindMappings extends BackwardsMappings {
public RewindMappings(String unmappedVersion, String mappedVersion) {
super(unmappedVersion, mappedVersion);
}
@Override
protected Logger getLogger() {
return ViaRewind.getPlatform().getLogger();
}
@Override
protected CompoundTag readMappingsFile(String name) {
return VRMappingDataLoader.INSTANCE.loadNBTFromDir(name);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,25 +15,30 @@
* 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.viarewind.api.data;
package com.viaversion.viarewind.utils;
import com.viaversion.viabackwards.api.data.BackwardsMappingDataLoader;
import com.viaversion.viarewind.ViaRewind;
import java.util.HashMap;
import java.util.Map;
import java.io.File;
import java.util.logging.Logger;
public class Enchantments {
public final static Map<Short, String> ENCHANTMENTS = new HashMap<>();
public class VRMappingDataLoader extends BackwardsMappingDataLoader {
static {
ENCHANTMENTS.put((short) 1, "I");
ENCHANTMENTS.put((short) 2, "II");
ENCHANTMENTS.put((short) 3, "III");
ENCHANTMENTS.put((short) 4, "IV");
ENCHANTMENTS.put((short) 5, "V");
ENCHANTMENTS.put((short) 6, "VI");
ENCHANTMENTS.put((short) 7, "VII");
ENCHANTMENTS.put((short) 8, "VIII");
ENCHANTMENTS.put((short) 9, "IX");
ENCHANTMENTS.put((short) 10, "X");
public static final VRMappingDataLoader INSTANCE = new VRMappingDataLoader();
public VRMappingDataLoader() {
super(VRMappingDataLoader.class, "assets/viarewind/data/");
}
@Override
public Logger getLogger() {
return ViaRewind.getPlatform().getLogger();
}
@Override
public File getDataFolder() {
return ViaRewind.getPlatform().getDataFolder();
}
}
@@ -1,102 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.api.minecraft;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
import java.util.List;
/**
* Represents a model that is replacing an entity on the client side (e.g. armor stand)
*/
public abstract class EntityModel<T extends Protocol<?, ?, ?, ?>> {
protected final UserConnection user;
protected final T protocol;
public EntityModel(final UserConnection user, final T protocol) {
this.user = user;
this.protocol = protocol;
}
/**
* @return The entity id of the entity this model is replacing
*/
public abstract int getEntityId();
/**
* Updates the position of the entity this model is replacing
*
* @param x The new x position
* @param y The new y position
* @param z The new z position
*/
public abstract void updateReplacementPosition(final double x, final double y, final double z);
/**
* Handles the original movement packet of the entity this model is replacing
*
* @param x The x position
* @param y The y position
* @param z The z position
*/
public abstract void handleOriginalMovementPacket(final double x, final double y, final double z);
/**
* Sets the yaw and pitch of the entity this model is replacing
*
* @param yaw The new yaw
* @param pitch The new pitch
*/
public abstract void setYawPitch(final float yaw, final float pitch);
/**
* Sets the head yaw of the entity this model is replacing
*
* @param yaw The new head yaw
*/
public abstract void setHeadYaw(final float yaw);
/**
* Spawns the entity this model is replacing
*/
public abstract void sendSpawnPacket();
/**
* Destroys the entity this model is replacing
*/
public abstract void deleteEntity();
/**
* Updates the metadata of the entity this model is replacing
*
* @param metadataList The new metadata
*/
public abstract void updateMetadata(final List<Metadata> metadataList);
public UserConnection getUser() {
return user;
}
public T getProtocol() {
return protocol;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.api.netty;
import io.netty.channel.ChannelHandler;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.api.netty;
import io.netty.buffer.ByteBuf;
@@ -1,86 +0,0 @@
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.MetaIndex1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.ClientEntityIdChangeListener;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ReplacementEntityTracker extends StoredObject implements ClientEntityIdChangeListener {
private final Map<EntityTypes1_10.EntityType, Pair<EntityTypes1_10.EntityType, String>> ENTITY_REPLACEMENTS = new HashMap<>();
private final Map<Integer, EntityTypes1_10.EntityType> entityMap = new HashMap<>();
private final Map<Integer, EntityTypes1_10.EntityType> entityReplacementMap = new HashMap<>();
private int playerId = -1;
private final ProtocolVersion version;
public ReplacementEntityTracker(UserConnection user, final ProtocolVersion version) {
super(user);
this.version = version;
}
public void registerEntity(final EntityTypes1_10.EntityType oldType, final EntityTypes1_10.EntityType newType, final String name) {
ENTITY_REPLACEMENTS.put(oldType, new Pair<>(newType, this.version.getName() + " " + name));
}
public void addEntity(final int entityId, final EntityTypes1_10.EntityType type) {
entityMap.put(entityId, type);
}
public int replaceEntity(final int entityId, final EntityTypes1_10.EntityType type) {
entityReplacementMap.put(entityId, type);
return ENTITY_REPLACEMENTS.get(type).key().getId();
}
public void removeEntity(final int entityId) {
entityMap.remove(entityId);
entityReplacementMap.remove(entityId);
}
public void clear() {
entityMap.clear();
entityReplacementMap.clear();
}
public boolean isReplaced(final EntityTypes1_10.EntityType type) {
return ENTITY_REPLACEMENTS.containsKey(type);
}
public void updateMetadata(final int entityId, final List<Metadata> metadata) throws Exception {
final String name = ENTITY_REPLACEMENTS.get(entityMap.get(entityId)).value();
metadata.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG_VISIBILITY.getNewIndex(), MetaType1_7_6_10.Byte, (byte) 1)); // TODO: Make this definable for 1.8 -> 1.9 ?
metadata.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG.getNewIndex(), MetaType1_7_6_10.String, name));
}
@Override
public void setClientEntityId(int entityId) {
removeEntity(this.playerId);
addEntity(entityId, EntityTypes1_10.EntityType.ENTITY_HUMAN);
this.playerId = entityId;
}
public Map<Integer, EntityTypes1_10.EntityType> getEntityMap() {
return entityMap;
}
public Map<Integer, EntityTypes1_10.EntityType> getEntityReplacementMap() {
return entityReplacementMap;
}
public int getPlayerId() {
return playerId;
}
}
@@ -0,0 +1,42 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.LegacyBlockItemRewriter;
import com.viaversion.viarewind.api.data.VRMappingDataLoader;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.libs.gson.JsonObject;
public class VRBlockItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType, T extends BackwardsProtocol<C, ?, ?, S>> extends LegacyBlockItemRewriter<C, S, T> {
protected VRBlockItemRewriter(T protocol, String name) {
super(protocol, name);
}
@Override
protected JsonObject readMappingsFile(String name) {
return VRMappingDataLoader.INSTANCE.loadFromDataDir(name);
}
@Override
public String nbtTagName() {
return "VR|" + protocol.getClass().getSimpleName();
}
}
@@ -0,0 +1,71 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
public abstract class VREntityRewriter<C extends ClientboundPacketType, T extends BackwardsProtocol<C, ?, ?, ?>> extends LegacyEntityRewriter<C, T> {
public VREntityRewriter(T protocol) {
super(protocol, MetaType1_8.String, MetaType1_8.Byte);
}
public VREntityRewriter(T protocol, MetaType displayType, MetaType displayVisibilityType) {
super(protocol, displayType, displayVisibilityType);
}
protected void registerJoinGame1_8(final C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
protected void register() {
map(Type.INT); // Entity id
map(Type.UNSIGNED_BYTE); // Game mode
map(Type.BYTE); // Dimension
handler(playerTrackerHandler());
handler(wrapper -> wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Type.BYTE, 0)));
}
});
}
protected void untrackEntities(final UserConnection connection, final int[] entities) {
final EntityTrackerBase tracker = tracker(connection);
for (int entityId : entities) {
tracker.removeEntity(entityId);
}
}
@Override
protected Object getDisplayVisibilityMetaValue() {
return (byte) 1;
}
@Override
protected boolean alwaysShowOriginalMobName() {
return ViaRewind.getConfig().alwaysShowOriginalMobName();
}
}
@@ -1,106 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.api.rewriter.item;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.util.ChatColorUtil;
public class Replacement {
private final int id;
private final int data;
private final String name;
private String resetName;
private String bracketName;
public Replacement(final int id) {
this(id, -1);
}
public Replacement(final int id, final int data) {
this(id, data, null);
}
public Replacement(final int id, final String name) {
this(id, -1, name);
}
public Replacement(final int id, final int data, final String name) {
this.id = id;
this.data = data;
this.name = name;
}
public void buildNames(final String protocolVersion) {
if (this.name != null) {
this.resetName = ChatColorUtil.translateAlternateColorCodes("&r" + protocolVersion + " " + this.name);
this.bracketName = ChatColorUtil.translateAlternateColorCodes(" &r&7(" + protocolVersion + " " + this.name + "&r&7)");
}
}
public int getId() {
return id;
}
public int getData() {
return data;
}
public String getName() {
return name;
}
/**
* @param item The item to replace
* @return The replacement for the item or the item if not found
*/
public Item replace(final Item item) {
item.setIdentifier(id); // Set the new id
if (data != -1) {
item.setData((short) data); // Set the new data
}
if (name != null) { // Set the new name
CompoundTag rootTag = item.tag() == null ? new CompoundTag() : item.tag(); // Get root tag or create new one if not exists
if (!rootTag.contains("display")) rootTag.put("display", new CompoundTag()); // Create display tag if not exists
final CompoundTag display = rootTag.get("display");
if (display.contains("Name")) {
final StringTag name = display.get("Name");
if (!name.getValue().equals(resetName) && !name.getValue().endsWith(bracketName)) {
name.setValue(name.getValue() + bracketName); // Append the new name tag
}
} else {
display.put("Name", new StringTag(resetName)); // Set the new name tag
}
item.setTag(rootTag);
}
return item;
}
/**
* @param data The data of the item/block
* @return The replacement data for the item/block
*/
public int replaceData(int data) {
return this.data == -1 ? data : this.data;
}
}
@@ -1,115 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.api.rewriter.item;
import com.viaversion.viarewind.api.minecraft.IdDataCombine;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
public abstract class ReplacementItemRewriter<T extends AbstractProtocol<?, ?, ?, ?>> implements ItemRewriter<T> {
private final Int2ObjectMap<Replacement> ITEM_REPLACEMENTS = new Int2ObjectOpenHashMap<>();
private final Int2ObjectMap<Replacement> BLOCK_REPLACEMENTS = new Int2ObjectOpenHashMap<>();
private final T protocol;
private final ProtocolVersion protocolVersion;
public ReplacementItemRewriter(final T protocol, final ProtocolVersion protocolVersion) {
this.protocol = protocol;
this.protocolVersion = protocolVersion;
}
public void registerItem(int id, Replacement replacement) {
registerItem(id, -1, replacement);
}
public void registerBlock(int id, Replacement replacement) {
registerBlock(id, -1, replacement);
}
public void registerItemBlock(int id, Replacement replacement) {
registerItemBlock(id, -1, replacement);
}
public void registerItem(int id, int data, Replacement replacement) {
ITEM_REPLACEMENTS.put(generateTrackingId(id, data), replacement);
replacement.buildNames(protocolVersion.getName());
}
public void registerBlock(int id, int data, Replacement replacement) {
BLOCK_REPLACEMENTS.put(generateTrackingId(id, data), replacement);
replacement.buildNames(protocolVersion.getName());
}
public void registerItemBlock(int id, int data, Replacement replacement) {
registerItem(id, data, replacement);
registerBlock(id, data, replacement);
}
/**
* @param item The item to replace
* @return The replacement for the item or the item if not found
*/
public Item replace(Item item) {
Replacement replacement = ITEM_REPLACEMENTS.get(generateTrackingId(item.identifier(), item.data()));
if (replacement == null) replacement = ITEM_REPLACEMENTS.get(generateTrackingId(item.identifier(), -1));
return replacement == null ? item : replacement.replace(item);
}
/**
* @param id The id of the item/block
* @param data The data of the item/block
* @return The replacement for the item/block or null if not found
*/
public Replacement replace(int id, int data) {
Replacement replacement = BLOCK_REPLACEMENTS.get(generateTrackingId(id, data));
if (replacement == null) replacement = BLOCK_REPLACEMENTS.get(generateTrackingId(id, -1));
return replacement;
}
/**
* @param combined The combined id and data
* @return The generated tracking id for the item/block
*/
public int replace(int combined) {
final int data = IdDataCombine.dataFromCombined(combined);
final Replacement replace = replace(IdDataCombine.idFromCombined(combined), data);
return replace != null ? IdDataCombine.toCombined(replace.getId(), replace.replaceData(data)) : combined;
}
/**
* @param id The id of the item/block
* @param data The data of the item/block
* @return The generated tracking id for the item/block
*/
private int generateTrackingId(int id, int data) {
return (id << 16) | (data & 0xFFFF);
}
@Override
public T protocol() {
return this.protocol;
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type;
import com.viaversion.viarewind.api.type.item.NBTType;
import com.viaversion.viarewind.api.type.item.ItemArrayType;
import com.viaversion.viarewind.api.type.item.ItemType;
import com.viaversion.viarewind.api.type.metadata.MetadataListType;
import com.viaversion.viarewind.api.type.metadata.MetadataType;
import com.viaversion.viarewind.api.type.primitive.ByteIntArrayType;
import com.viaversion.viarewind.api.type.primitive.PositionUYType;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import java.util.List;
public class Types1_7_6_10 {
// Primitives
public static final Type<int[]> BYTE_INT_ARRAY = new ByteIntArrayType(); // Integer array with byte as length indicator
// Positions /shrug
public static final Type<Position> SHORT_POSITION = new PositionUYType<>(Type.SHORT, value -> (short) value);
public static final Type<Position> INT_POSITION = new PositionUYType<>(Type.INT, value -> value);
public static final Type<Position> BYTE_POSITION = new PositionUYType<>(Type.BYTE, value -> (byte) value);
public static final Type<Position> U_BYTE_POSITION = new PositionUYType<>(Type.UNSIGNED_BYTE, value -> (short) value);
// Items
public static final Type<CompoundTag> COMPRESSED_NBT = new NBTType();
public static final Type<Item> COMPRESSED_NBT_ITEM = new ItemType();
public static final Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType();
// Metadata
public static final Type<Metadata> METADATA = new MetadataType();
public static final Type<List<Metadata>> METADATA_LIST = new MetadataListType();
}
@@ -1,4 +1,21 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk;
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
@@ -11,7 +28,7 @@ import java.util.zip.Deflater;
public class BulkChunkType1_7_6 extends Type<Chunk[]> {
public final static BulkChunkType1_7_6 TYPE = new BulkChunkType1_7_6();
public static final BulkChunkType1_7_6 TYPE = new BulkChunkType1_7_6();
public BulkChunkType1_7_6() {
super(Chunk[].class);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,10 +15,9 @@
* 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.viarewind.api.type.chunk;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk;
import com.viaversion.viarewind.api.minecraft.ExtendedBlockStorage;
import com.viaversion.viarewind.utils.ExtendedBlockStorage;
import com.viaversion.viaversion.api.minecraft.chunks.*;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Pair;
@@ -30,7 +29,7 @@ import java.util.zip.Deflater;
public class ChunkType1_7_6 extends Type<Chunk> {
public final static ChunkType1_7_6 TYPE = new ChunkType1_7_6();
public static final ChunkType1_7_6 TYPE = new ChunkType1_7_6();
public ChunkType1_7_6() {
super(Chunk.class);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,20 +15,17 @@
* 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.viarewind.api.type.item;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class ItemArrayType extends Type<Item[]> {
private final boolean compressed;
public ItemArrayType(boolean compressed) {
public ItemArrayType() {
super(Item[].class);
this.compressed = compressed;
}
@Override
@@ -37,7 +34,7 @@ public class ItemArrayType extends Type<Item[]> {
Item[] items = new Item[amount];
for (int i = 0; i < amount; ++i) {
items[i] = (compressed ? Types1_7_6_10.COMPRESSED_NBT_ITEM : Types1_7_6_10.ITEM).read(buffer);
items[i] = Types1_7_6_10.COMPRESSED_NBT_ITEM.read(buffer);
}
return items;
}
@@ -46,7 +43,7 @@ public class ItemArrayType extends Type<Item[]> {
public void write(ByteBuf buffer, Item[] items) throws Exception {
Type.SHORT.writePrimitive(buffer, (short) items.length);
for (Item item : items) {
(compressed ? Types1_7_6_10.COMPRESSED_NBT_ITEM : Types1_7_6_10.ITEM).write(buffer, item);
Types1_7_6_10.COMPRESSED_NBT_ITEM.write(buffer, item);
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,21 +15,18 @@
* 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.viarewind.api.type.item;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class ItemType extends Type<Item> {
private final boolean compressed;
public ItemType(boolean compressed) {
public ItemType() {
super(Item.class);
this.compressed = compressed;
}
@Override
@@ -42,7 +39,7 @@ public class ItemType extends Type<Item> {
item.setIdentifier(id);
item.setAmount(buffer.readByte());
item.setData(buffer.readShort());
item.setTag((compressed ? Types1_7_6_10.COMPRESSED_NBT : Types1_7_6_10.NBT).read(buffer));
item.setTag(Types1_7_6_10.COMPRESSED_NBT.read(buffer));
return item;
}
@@ -54,7 +51,7 @@ public class ItemType extends Type<Item> {
buffer.writeShort(item.identifier());
buffer.writeByte(item.amount());
buffer.writeShort(item.data());
(compressed ? Types1_7_6_10.COMPRESSED_NBT : Types1_7_6_10.NBT).write(buffer, item.tag());
Types1_7_6_10.COMPRESSED_NBT.write(buffer, item.tag());
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,12 +15,11 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
package com.viaversion.viarewind.api.type.item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.NBTIO;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.io.NBTIO;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
@@ -29,8 +28,8 @@ import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class CompressedNBTType extends Type<CompoundTag> {
public CompressedNBTType() {
public class NBTType extends Type<CompoundTag> {
public NBTType() {
super(CompoundTag.class);
}
@@ -44,7 +43,7 @@ public class CompressedNBTType extends Type<CompoundTag> {
ByteBuf compressed = buffer.readSlice(length);
try (GZIPInputStream gzipStream = new GZIPInputStream(new ByteBufInputStream(compressed))) {
return NBTIO.readTag(gzipStream);
return NBTIO.reader(CompoundTag.class).named().read(gzipStream);
}
}
@@ -58,7 +57,7 @@ public class CompressedNBTType extends Type<CompoundTag> {
ByteBuf compressedBuf = buffer.alloc().buffer();
try {
try (GZIPOutputStream gzipStream = new GZIPOutputStream(new ByteBufOutputStream(compressedBuf))) {
NBTIO.writeTag(gzipStream, nbt);
NBTIO.writer().named().write(gzipStream, nbt);
}
buffer.writeShort(compressedBuf.readableBytes());
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,13 +15,11 @@
* 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.viarewind.api.type.metadata;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.VoidType;
public enum MetaType1_7_6_10 implements MetaType {
Byte(0, Type.BYTE),
@@ -30,8 +28,7 @@ public enum MetaType1_7_6_10 implements MetaType {
Float(3, Type.FLOAT),
String(4, Type.STRING),
Slot(5, Types1_7_6_10.COMPRESSED_NBT_ITEM),
Position(6, Type.VECTOR),
NonExistent(-1, new VoidType());
Position(6, Type.VECTOR);
private final int typeID;
private final Type<?> type;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,10 +15,9 @@
* 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.viarewind.api.type.metadata;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.types.metadata.MetaListTypeTemplate;
import io.netty.buffer.ByteBuf;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,8 +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.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
package com.viaversion.viarewind.api.type.metadata;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.types.metadata.MetaTypeTemplate;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,8 +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.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive;
package com.viaversion.viarewind.api.type.primitive;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
@@ -1,4 +1,21 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive;
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.primitive;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.type.Type;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,10 +15,9 @@
* 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.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
@@ -32,9 +31,10 @@ import java.util.List;
import java.util.stream.Collectors;
public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPackets1_7_2_5, ClientboundPackets1_7_2_5, ServerboundPackets1_7_2_5, ServerboundPackets1_7_2_5> {
public final static ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<String, String>(Type.STRING) {
public static final ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<String, String>(Type.STRING) {
@Override
public String transform(PacketWrapper packetWrapper, String s) {
public String transform(PacketWrapper wrapper, String s) {
return s.replace("-", "");
}
};
@@ -59,12 +59,12 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
map(Type.VAR_INT); // entity id
map(Type.STRING, REMOVE_DASHES); // uuid
map(Type.STRING); // name
handler(packetWrapper -> { // delete data introduced in 1.7.6
final int size = packetWrapper.read(Type.VAR_INT); // data count
handler(wrapper -> { // delete data introduced in 1.7.6
final int size = wrapper.read(Type.VAR_INT); // data count
for (int i = 0; i < size; i++) {
packetWrapper.read(Type.STRING); // data name
packetWrapper.read(Type.STRING); // data value
packetWrapper.read(Type.STRING); // data signature
wrapper.read(Type.STRING); // data name
wrapper.read(Type.STRING); // data value
wrapper.read(Type.STRING); // data signature
}
});
map(Type.INT); // x
@@ -72,7 +72,7 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // item in hand
map(Type.SHORT); // item in hand
map(Types1_7_6_10.METADATA_LIST); // metadata
}
});
@@ -82,29 +82,29 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
public void register() {
map(Type.STRING); // team name
map(Type.BYTE); // mode
handler(packetWrapper -> {
byte mode = packetWrapper.get(Type.BYTE, 0);
handler(wrapper -> {
final byte mode = wrapper.get(Type.BYTE, 0);
if (mode == 0 || mode == 2) { // team is created or information is updated
packetWrapper.passthrough(Type.STRING); // team display name
packetWrapper.passthrough(Type.STRING); // team prefix
packetWrapper.passthrough(Type.STRING); // team suffix
packetWrapper.passthrough(Type.BYTE); // friendly fire
wrapper.passthrough(Type.STRING); // team display name
wrapper.passthrough(Type.STRING); // team prefix
wrapper.passthrough(Type.STRING); // team suffix
wrapper.passthrough(Type.BYTE); // friendly fire
}
if (mode == 0 || mode == 3 || mode == 4) { // team is created, player is added or player is removed
List<String> entryList = new ArrayList<>();
final int size = packetWrapper.read(Type.SHORT);
final int size = wrapper.read(Type.SHORT);
for (int i = 0; i < size; i++) {
entryList.add(packetWrapper.read(Type.STRING));
entryList.add(wrapper.read(Type.STRING));
}
entryList = entryList.stream()
.map(it -> it.length() > 16 ? it.substring(0, 16) : it) // trim to 16 characters
.distinct() // remove duplicates
.collect(Collectors.toList());
.map(it -> it.length() > 16 ? it.substring(0, 16) : it) // trim to 16 characters
.distinct() // remove duplicates
.collect(Collectors.toList());
packetWrapper.write(Type.SHORT, (short) entryList.size());
wrapper.write(Type.SHORT, (short) entryList.size());
for (String entry : entryList) {
packetWrapper.write(Type.STRING, entry);
wrapper.write(Type.STRING, entry);
}
}
});
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,25 +15,23 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.api.data.RewindMappings;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.CompressionHandlerProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression.TrackingCompressionHandlerProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.ReplacementItemRewriter1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.task.WorldBorderUpdateTask;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
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;
@@ -46,10 +44,12 @@ import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import java.util.concurrent.TimeUnit;
public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_8, ClientboundPackets1_7_2_5, ServerboundPackets1_8, ServerboundPackets1_7_2_5> {
public class Protocol1_7_6_10To1_8 extends BackwardsProtocol<ClientboundPackets1_8, ClientboundPackets1_7_2_5, ServerboundPackets1_8, ServerboundPackets1_7_2_5> {
private final ReplacementItemRewriter<Protocol1_7_6_10To1_8> itemRewriter = new ReplacementItemRewriter1_7_6_10(this);
private final MetadataRewriter metadataRewriter = new MetadataRewriter(this);
public static final RewindMappings MAPPINGS = new RewindMappings("1.8", "1.7.10");
private final BlockItemPackets1_8 itemRewriter = new BlockItemPackets1_8(this);
private final MetadataRewriter1_7_6_10To1_8 metadataRewriter = new MetadataRewriter1_7_6_10To1_8(this);
public Protocol1_7_6_10To1_8() {
super(ClientboundPackets1_8.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_8.class, ServerboundPackets1_7_2_5.class);
@@ -58,13 +58,12 @@ public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_
@Override
protected void registerPackets() {
itemRewriter.register();
metadataRewriter.register();
EntityPackets.register(this);
InventoryPackets.register(this);
PlayerPackets.register(this);
ScoreboardPackets.register(this);
SpawnPackets.register(this);
WorldPackets.register(this);
EntityPackets1_8.register(this);
PlayerPackets1_8.register(this);
ScoreboardPackets1_8.register(this);
WorldPackets1_8.register(this);
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketHandlers() {
@Override
@@ -113,33 +112,22 @@ public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onTransformPacket(packetWrapper.user());
// if (direction == Direction.CLIENTBOUND) {
// System.out.println("Pre: " + direction + " " + state + " " + packetWrapper.getId() + " " + ClientboundPackets1_8.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// } else {
// System.out.println("Pre: " + direction + " " + state + " " + packetWrapper.getId() + " " + ServerboundPackets1_7_2_5.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// }
super.transform(direction, state, packetWrapper);
// if (direction == Direction.CLIENTBOUND) {
// System.out.println("Post: " + direction + " " + state + " " + packetWrapper.getId() + " " + ClientboundPackets1_7_2_5.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// } else {
// System.out.println("Post: " + direction + " " + state + " " + packetWrapper.getId() + " " + ServerboundPackets1_8.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// }
}
@Override
public void init(UserConnection userConnection) {
userConnection.put(new InventoryTracker(userConnection));
userConnection.put(new EntityTracker1_7_6_10(userConnection, metadataRewriter));
userConnection.put(new PlayerSessionStorage(userConnection));
userConnection.put(new GameProfileStorage(userConnection));
userConnection.put(new Scoreboard(userConnection));
userConnection.put(new CompressionStatusTracker(userConnection));
userConnection.put(new WorldBorderEmulator(userConnection));
public void init(UserConnection connection) {
connection.addEntityTracker(this.getClass(), new EntityTracker1_8(connection));
if (!userConnection.has(ClientWorld.class)) {
userConnection.put(new ClientWorld());
connection.put(new InventoryTracker(connection));
connection.put(new PlayerSessionStorage(connection));
connection.put(new GameProfileStorage(connection));
connection.put(new Scoreboard(connection));
connection.put(new CompressionStatusTracker(connection));
connection.put(new WorldBorderEmulator(connection));
if (!connection.has(ClientWorld.class)) {
connection.put(new ClientWorld());
}
}
@@ -153,11 +141,22 @@ public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_
}
@Override
public ReplacementItemRewriter<Protocol1_7_6_10To1_8> getItemRewriter() {
public RewindMappings getMappingData() {
return MAPPINGS;
}
@Override
public BlockItemPackets1_8 getItemRewriter() {
return itemRewriter;
}
public MetadataRewriter getMetadataRewriter() {
@Override
public MetadataRewriter1_7_6_10To1_8 getEntityRewriter() {
return metadataRewriter;
}
@Override
public boolean hasMappingDataToLoad() {
return true;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,8 +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.viarewind.protocol.protocol1_7_6_10to1_8.model;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.data;
import java.util.HashMap;
@@ -66,7 +65,7 @@ public enum ParticleIndex1_7_6_10 {
public final String name;
public final int extra;
private final static HashMap<String, ParticleIndex1_7_6_10> particleMap = new HashMap<>();
private static final HashMap<String, ParticleIndex1_7_6_10> particleMap = new HashMap<>();
ParticleIndex1_7_6_10(String name) {
this(name, 0);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,15 +15,14 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.model;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.emulation;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetaIndex;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.api.type.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter1_7_6_10To1_8;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Vector3d;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -32,6 +31,9 @@ import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.TrackedEntityImpl;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEventImpl;
import java.util.ArrayList;
import java.util.List;
@@ -41,76 +43,63 @@ public class VirtualHologramEntity {
private double locX, locY, locZ;
private final UserConnection user;
private final MetadataRewriter metadataRewriter;
private final int entityId;
private int[] entityIds = null;
private State currentState = null;
private boolean invisible = false;
private String name = null;
private float yaw, pitch;
private float headYaw;
private boolean small = false;
private boolean marker = false;
public VirtualHologramEntity(final UserConnection user, final MetadataRewriter metadataRewriter, final int entityId) {
public VirtualHologramEntity(final UserConnection user, final int entityId) {
this.user = user;
this.metadataRewriter = metadataRewriter;
this.entityId = entityId;
}
public void updateReplacementPosition(double x, double y, double z) {
if (x == this.locX && y == this.locY && z == this.locZ) {
return;
}
public void setPosition(final double x, final double y, final double z) throws Exception {
if (x == this.locX && y == this.locY && z == this.locZ) return;
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation(false);
}
public void handleOriginalMovementPacket(double x, double y, double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) {
return;
}
public void setRelativePosition(final double x, final double y, final double z) throws Exception {
if (x == 0.0 && y == 0.0 && z == 0.0) return;
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation(false);
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw == yaw || this.headYaw == yaw || this.pitch == pitch) {
return;
}
public void setRotation(final float yaw, final float pitch) throws Exception {
if (this.yaw == yaw || this.headYaw == yaw || this.pitch == pitch) return;
this.yaw = yaw;
this.headYaw = yaw;
this.pitch = pitch;
updateLocation(false);
}
public void setHeadYaw(float yaw) {
if (this.headYaw == yaw) {
return;
}
public void setHeadYaw(float yaw) throws Exception {
if (this.headYaw == yaw) return;
this.headYaw = yaw;
updateLocation(false);
}
public void updateMetadata(final List<Metadata> metadataList) {
public void syncState(final MetadataRewriter1_7_6_10To1_8 entityRewriter, final List<Metadata> metadataList) throws Exception {
// Merge metadata updates into current tracker
for (Metadata metadata : metadataList) {
metadataTracker.removeIf(m -> m.id() == metadata.id());
metadataTracker.add(metadata);
}
updateState();
}
public void updateState() {
// Filter armor stand data to calculate emulation
byte flags = 0;
byte armorStandFlags = 0;
for (Metadata metadata : metadataTracker) {
@@ -123,7 +112,7 @@ public class VirtualHologramEntity {
armorStandFlags = ((Number) metadata.getValue()).byteValue();
}
}
invisible = (flags & 0x20) != 0;
final boolean invisible = (flags & 0x20) != 0;
small = (armorStandFlags & 0x01) != 0;
marker = (armorStandFlags & 0x10) != 0;
@@ -136,16 +125,17 @@ public class VirtualHologramEntity {
if (currentState != prevState) {
deleteEntity();
sendSpawnPacket();
sendSpawnPacket(entityRewriter);
} else {
updateMetadata();
sendMetadataUpdate(entityRewriter);
updateLocation(false);
}
}
public void updateLocation(boolean remount) {
if (entityIds == null) return;
private void updateLocation(final boolean remount) throws Exception {
if (entityIds == null) {
return;
}
if (currentState == State.ZOMBIE) {
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
@@ -154,14 +144,14 @@ public class VirtualHologramEntity {
entityHeadLook.write(Type.INT, entityId);
entityHeadLook.write(Type.BYTE, (byte) ((headYaw / 360f) * 256));
PacketUtil.sendPacket(entityHeadLook, Protocol1_7_6_10To1_8.class, true, true);
entityHeadLook.send(Protocol1_7_6_10To1_8.class);
} else if (currentState == State.HOLOGRAM) {
if (remount) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, null, user);
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, user);
detach.write(Type.INT, entityIds[1]);
detach.write(Type.INT, -1);
detach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(detach, Protocol1_7_6_10To1_8.class, true, true);
detach.send(Protocol1_7_6_10To1_8.class);
}
// Don't ask me where this offset is coming from
@@ -174,12 +164,12 @@ public class VirtualHologramEntity {
attach.write(Type.INT, entityIds[1]);
attach.write(Type.INT, entityIds[0]);
attach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(attach, Protocol1_7_6_10To1_8.class, true, true);
attach.send(Protocol1_7_6_10To1_8.class);
}
}
}
protected void teleportEntity(final int entityId, final double x, final double y, final double z, final float yaw, final float pitch) {
protected void teleportEntity(final int entityId, final double x, final double y, final double z, final float yaw, final float pitch) throws Exception {
final PacketWrapper entityTeleport = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_TELEPORT, user);
entityTeleport.write(Type.INT, entityId); // entity id
@@ -189,10 +179,10 @@ public class VirtualHologramEntity {
entityTeleport.write(Type.BYTE, (byte) ((yaw / 360f) * 256)); // yaw
entityTeleport.write(Type.BYTE, (byte) ((pitch / 360f) * 256)); // pitch
PacketUtil.sendPacket(entityTeleport, Protocol1_7_6_10To1_8.class, true, true);
entityTeleport.send(Protocol1_7_6_10To1_8.class);
}
protected void spawnEntity(final int entityId, final int type, final double locX, final double locY, final double locZ) {
protected void spawnEntity(final int entityId, final int type, final double locX, final double locY, final double locZ) throws Exception {
final PacketWrapper spawnMob = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_MOB, null, user);
spawnMob.write(Type.VAR_INT, entityId); // entity id
@@ -208,61 +198,82 @@ public class VirtualHologramEntity {
spawnMob.write(Type.SHORT, (short) 0); // velocity z
spawnMob.write(Types1_7_6_10.METADATA_LIST, new ArrayList<>()); // metadata
PacketUtil.sendPacket(spawnMob, Protocol1_7_6_10To1_8.class, true, true);
spawnMob.send(Protocol1_7_6_10To1_8.class);
}
public void updateMetadata() {
if (entityIds == null) return;
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_METADATA, null, user);
public void sendMetadataUpdate(final MetadataRewriter1_7_6_10To1_8 entityRewriter) throws Exception {
if (entityIds == null) {
return;
}
final PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_METADATA, user);
if (currentState == State.ZOMBIE) {
writeZombieMeta(metadataPacket);
writeZombieMeta(entityRewriter, metadataPacket);
} else if (currentState == State.HOLOGRAM) {
writeHologramMeta(metadataPacket);
} else {
return;
}
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class, true, true);
metadataPacket.send(Protocol1_7_6_10To1_8.class);
}
private void writeZombieMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[0]);
private void writeZombieMeta(final MetadataRewriter1_7_6_10To1_8 entityRewriter, PacketWrapper wrapper) {
wrapper.write(Type.INT, entityIds[0]);
List<Metadata> metadataList = new ArrayList<>();
// Filter metadata sent by the server and convert them together with our custom metadata
final List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : metadataTracker) {
if (metadata.id() < 0 || metadata.id() > 9) continue;
// Remove non existent metadata
if (metadata.id() < 0 || metadata.id() > 9) {
continue;
}
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
if (small) metadataList.add(new Metadata(12, MetaType1_8.Byte, (byte) 1));
metadataRewriter.transform(EntityTypes1_10.EntityType.ZOMBIE, metadataList);
if (small) {
metadataList.add(new Metadata(12, MetaType1_8.Byte, (byte) 1));
}
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
// Push metadata from the server through metadata conversion 1.7->1.8
for (Metadata metadata : metadataList.toArray(new Metadata[0])) {
final MetaHandlerEvent event = new MetaHandlerEventImpl(wrapper.user(), new TrackedEntityImpl(EntityTypes1_10.EntityType.ZOMBIE), -1, metadata, metadataList);
try {
entityRewriter.handleMetadata(event, metadata);
} catch (Exception e) {
metadataList.remove(metadata);
break;
}
if (event.cancelled()) {
metadataList.remove(metadata);
break;
}
}
wrapper.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
private void writeHologramMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[1]);
private void writeHologramMeta(PacketWrapper wrapper) {
wrapper.write(Type.INT, entityIds[1]);
List<Metadata> metadataList = new ArrayList<>();
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_AGEABLE_AGE.getIndex(), MetaType1_7_6_10.Int, -1700000));
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG.getIndex(), MetaType1_7_6_10.String, name));
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG_VISIBILITY.getIndex(), MetaType1_7_6_10.Byte, (byte) 1));
// Directly write 1.7 metadata here since we are making them up
final List<Metadata> metadataList = new ArrayList<>();
metadataList.add(new Metadata(MetaIndex.ENTITY_AGEABLE_AGE.getIndex(), MetaType1_7_6_10.Int, -1700000));
metadataList.add(new Metadata(MetaIndex.ENTITY_LIVING_NAME_TAG.getIndex(), MetaType1_7_6_10.String, name));
metadataList.add(new Metadata(MetaIndex.ENTITY_LIVING_NAME_TAG_VISIBILITY.getIndex(), MetaType1_7_6_10.Byte, (byte) 1));
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
wrapper.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
public void sendSpawnPacket() {
if (entityIds != null) deleteEntity();
public void sendSpawnPacket(final MetadataRewriter1_7_6_10To1_8 entityRewriter) throws Exception {
if (entityIds != null) {
deleteEntity();
}
if (currentState == State.ZOMBIE) {
spawnEntity(entityId, 54, locX, locY, locZ);
entityIds = new int[]{entityId};
} else if (currentState == State.HOLOGRAM) {
int[] entityIds = {entityId, additionalEntityId()};
final int[] entityIds = { entityId, additionalEntityId() };
PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_ENTITY, null, user);
final PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_ENTITY, user);
spawnSkull.write(Type.VAR_INT, entityIds[0]);
spawnSkull.write(Type.BYTE, (byte) 66);
spawnSkull.write(Type.INT, (int) (locX * 32.0));
@@ -271,14 +282,14 @@ public class VirtualHologramEntity {
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.INT, 0);
PacketUtil.sendPacket(spawnSkull, Protocol1_7_6_10To1_8.class, true, true);
spawnSkull.send(Protocol1_7_6_10To1_8.class);
spawnEntity(entityIds[1], 100, locX, locY, locZ); // Horse
this.entityIds = entityIds;
}
updateMetadata();
sendMetadataUpdate(entityRewriter);
updateLocation(true);
}
@@ -296,16 +307,17 @@ public class VirtualHologramEntity {
return Integer.MAX_VALUE - 16000 - entityId;
}
public void deleteEntity() {
if (entityIds == null) return;
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.DESTROY_ENTITIES, null, user);
public void deleteEntity() throws Exception {
if (entityIds == null) {
return;
}
final PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.DESTROY_ENTITIES, user);
despawn.write(Type.BYTE, (byte) entityIds.length);
for (int id : entityIds) {
despawn.write(Type.INT, id);
}
entityIds = null;
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
despawn.send(Protocol1_7_6_10To1_8.class);
}
private enum State {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,10 +15,10 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.metadata;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.api.type.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.util.Pair;
@@ -26,92 +26,124 @@ import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.Optional;
public enum MetaIndex1_7_6_10To1_8 {
public enum MetaIndex {
ENTITY_FLAGS(EntityTypes1_10.EntityType.ENTITY, 0, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_AIR(EntityTypes1_10.EntityType.ENTITY, 1, MetaType1_7_6_10.Short, MetaType1_8.Short),
ENTITY_NAME_TAG(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 2, MetaType1_8.String),
ENTITY_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 3, MetaType1_8.Byte),
ENTITY_SILENT(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 4, MetaType1_8.Byte),
ENTITY_NAME_TAG(EntityTypes1_10.EntityType.ENTITY, -1, null, 2, MetaType1_8.String),
ENTITY_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY, -1, null, 3, MetaType1_8.Byte),
ENTITY_SILENT(EntityTypes1_10.EntityType.ENTITY, -1, null, 4, MetaType1_8.Byte),
ENTITY_LIVING_HEALTH(EntityTypes1_10.EntityType.ENTITY_LIVING, 6, MetaType1_7_6_10.Float, MetaType1_8.Float),
ENTITY_LIVING_POTION_EFFECT_COLOR(EntityTypes1_10.EntityType.ENTITY_LIVING, 7, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENTITY_LIVING_IS_POTION_EFFECT_AMBIENT(EntityTypes1_10.EntityType.ENTITY_LIVING, 8, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_ARROWS(EntityTypes1_10.EntityType.ENTITY_LIVING, 9, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_NAME_TAG(EntityTypes1_10.EntityType.ENTITY_LIVING, 10, MetaType1_7_6_10.String, 2, MetaType1_8.String),
ENTITY_LIVING_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY_LIVING, 11, MetaType1_7_6_10.Byte, 3, MetaType1_8.Byte),
ENTITY_LIVING_AI(EntityTypes1_10.EntityType.ENTITY_LIVING, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Byte),
ENTITY_LIVING_AI(EntityTypes1_10.EntityType.ENTITY_LIVING, -1, null, 15, MetaType1_8.Byte),
ENTITY_AGEABLE_AGE(EntityTypes1_10.EntityType.ENTITY_AGEABLE, 12, MetaType1_7_6_10.Int, MetaType1_8.Byte),
ARMOR_STAND_FLAGS(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 10, MetaType1_8.Byte),
ARMOR_STAND_HEAD_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 11, MetaType1_8.Rotation),
ARMOR_STAND_BODY_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 12, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 13, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 14, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Rotation),
ARMOR_STAND_FLAGS(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 10, MetaType1_8.Byte),
ARMOR_STAND_HEAD_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 11, MetaType1_8.Rotation),
ARMOR_STAND_BODY_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 12, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 13, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 14, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 15, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 16, MetaType1_8.Rotation),
HUMAN_SKIN_FLAGS(EntityTypes1_10.EntityType.ENTITY_HUMAN, 16, MetaType1_7_6_10.Byte, 10, MetaType1_8.Byte),
HUMAN_UNUSED(EntityTypes1_10.EntityType.ENTITY_HUMAN, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Byte),
HUMAN_UNUSED(EntityTypes1_10.EntityType.ENTITY_HUMAN, -1, null, 16, MetaType1_8.Byte),
HUMAN_ABSORPTION_HEATS(EntityTypes1_10.EntityType.ENTITY_HUMAN, 17, MetaType1_7_6_10.Float, MetaType1_8.Float),
HUMAN_SCORE(EntityTypes1_10.EntityType.ENTITY_HUMAN, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_FLAGS(EntityTypes1_10.EntityType.HORSE, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_TYPE(EntityTypes1_10.EntityType.HORSE, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
HORSE_COLOR(EntityTypes1_10.EntityType.HORSE, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_OWNER(EntityTypes1_10.EntityType.HORSE, 21, MetaType1_7_6_10.String, MetaType1_8.String),
HORSE_ARMOR(EntityTypes1_10.EntityType.HORSE, 22, MetaType1_7_6_10.Int, MetaType1_8.Int),
BAT_HANGING(EntityTypes1_10.EntityType.BAT, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_FLAGS(EntityTypes1_10.EntityType.ENTITY_TAMEABLE_ANIMAL, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_OWNER(EntityTypes1_10.EntityType.ENTITY_TAMEABLE_ANIMAL, 17, MetaType1_7_6_10.String, MetaType1_8.String),
OCELOT_TYPE(EntityTypes1_10.EntityType.OCELOT, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_FLAGS(EntityTypes1_10.EntityType.WOLF, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_HEALTH(EntityTypes1_10.EntityType.WOLF, 18, MetaType1_7_6_10.Float, MetaType1_8.Float),
WOLF_BEGGING(EntityTypes1_10.EntityType.WOLF, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_COLLAR_COLOR(EntityTypes1_10.EntityType.WOLF, 20, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
PIG_SADDLE(EntityTypes1_10.EntityType.PIG, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SHEEP_COLOR_OR_SHEARED(EntityTypes1_10.EntityType.SHEEP, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
VILLAGER_TYPE(EntityTypes1_10.EntityType.VILLAGER, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENDERMAN_CARRIED_BLOCK(EntityTypes1_10.EntityType.ENDERMAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Short),
ENDERMAN_CARRIED_BLOCK_DATA(EntityTypes1_10.EntityType.ENDERMAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
ENDERMAN_CARRIED_BLOCK(EntityTypes1_10.EntityType.ENDERMAN, 16, null, MetaType1_8.Short),
ENDERMAN_CARRIED_BLOCK_DATA(EntityTypes1_10.EntityType.ENDERMAN, 17, null, MetaType1_8.Byte),
ENDERMAN_IS_SCREAMING(EntityTypes1_10.EntityType.ENDERMAN, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CHILD(EntityTypes1_10.EntityType.ZOMBIE, 12, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_VILLAGER(EntityTypes1_10.EntityType.ZOMBIE, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CONVERTING(EntityTypes1_10.EntityType.ZOMBIE, 14, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
BLAZE_ON_FIRE(EntityTypes1_10.EntityType.BLAZE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SPIDER_CLIMBING(EntityTypes1_10.EntityType.SPIDER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_STATE(EntityTypes1_10.EntityType.CREEPER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_POWERED(EntityTypes1_10.EntityType.CREEPER, 17, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_IGNITED(EntityTypes1_10.EntityType.CREEPER, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_STATE(EntityTypes1_10.EntityType.GHAST, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_IS_POWERED(EntityTypes1_10.EntityType.GHAST, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
GHAST_IS_POWERED(EntityTypes1_10.EntityType.GHAST, 17, null, MetaType1_8.Byte),
SLIME_SIZE(EntityTypes1_10.EntityType.SLIME, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SKELETON_TYPE(EntityTypes1_10.EntityType.SKELETON, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITCH_AGGRESSIVE(EntityTypes1_10.EntityType.WITCH, 21, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
IRON_GOLEM_IS_PLAYER_CREATED(EntityTypes1_10.EntityType.IRON_GOLEM, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITHER_WATCHED_TARGET_1(EntityTypes1_10.EntityType.WITHER, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TARGET_2(EntityTypes1_10.EntityType.WITHER, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TARGET_3(EntityTypes1_10.EntityType.WITHER, 19, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_INVULNERABLE_TIME(EntityTypes1_10.EntityType.WITHER, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
GUARDIAN_FLAGS(EntityTypes1_10.EntityType.GUARDIAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
GUARDIAN_TARGET(EntityTypes1_10.EntityType.GUARDIAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Int),
GUARDIAN_FLAGS(EntityTypes1_10.EntityType.GUARDIAN, 16, null, MetaType1_8.Byte),
GUARDIAN_TARGET(EntityTypes1_10.EntityType.GUARDIAN, 17, null, MetaType1_8.Int),
BOAT_TIME_SINCE_HIT(EntityTypes1_10.EntityType.BOAT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_FORWARD_DIRECTION(EntityTypes1_10.EntityType.BOAT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_DAMAGE_TAKEN(EntityTypes1_10.EntityType.BOAT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_SHAKING_POWER(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHAKING_DIRECTION(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_DAMAGE_TAKEN(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_BLOCK_INSIDE(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_BLOCK_Y(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 21, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHOW_BLOCK(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 22, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FURNACE_MINECART_IS_POWERED(EntityTypes1_10.EntityType.MINECART_FURNACE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ITEM_ITEM(EntityTypes1_10.EntityType.DROPPED_ITEM, 10, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ARROW_IS_CRITICAL(EntityTypes1_10.EntityType.ARROW, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FIREWORK_INFO(EntityTypes1_10.EntityType.FIREWORK, 8, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ITEM_FRAME_ITEM(EntityTypes1_10.EntityType.ITEM_FRAME, 2, MetaType1_7_6_10.Slot, 8, MetaType1_8.Slot),
ITEM_FRAME_ROTATION(EntityTypes1_10.EntityType.ITEM_FRAME, 3, MetaType1_7_6_10.Byte, 9, MetaType1_8.Byte),
ENDER_CRYSTAL_HEALTH(EntityTypes1_10.EntityType.ENDER_CRYSTAL, 8, MetaType1_7_6_10.Int, 9, MetaType1_8.Int),
;
private final static HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex1_7_6_10To1_8> metadataRewrites = new HashMap<>();
ENDER_CRYSTAL_HEALTH(EntityTypes1_10.EntityType.ENDER_CRYSTAL, 8, MetaType1_7_6_10.Int, 9, MetaType1_8.Int);
private static final HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
static {
for (MetaIndex1_7_6_10To1_8 index : MetaIndex1_7_6_10To1_8.values()) {
for (MetaIndex index : MetaIndex.values()) {
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
}
@@ -122,7 +154,7 @@ public enum MetaIndex1_7_6_10To1_8 {
private final MetaType1_7_6_10 oldType;
private final int index;
MetaIndex1_7_6_10To1_8(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, MetaType1_8 newType) {
MetaIndex(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.newIndex = index;
@@ -130,7 +162,7 @@ public enum MetaIndex1_7_6_10To1_8 {
this.newType = newType;
}
MetaIndex1_7_6_10To1_8(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, int newIndex, MetaType1_8 newType) {
MetaIndex(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, int newIndex, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.oldType = oldType;
@@ -138,8 +170,8 @@ public enum MetaIndex1_7_6_10To1_8 {
this.newType = newType;
}
private static Optional<MetaIndex1_7_6_10To1_8> getIndex(EntityTypes1_10.EntityType type, int index) {
Pair<EntityTypes1_10.EntityType, Integer> pair = new Pair<>(type, index);
private static Optional<MetaIndex> getIndex(EntityType type, int index) {
Pair<EntityType, Integer> pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
@@ -167,10 +199,10 @@ public enum MetaIndex1_7_6_10To1_8 {
return index;
}
public static MetaIndex1_7_6_10To1_8 searchIndex(EntityTypes1_10.EntityType type, int index) {
EntityTypes1_10.EntityType currentType = type;
public static MetaIndex searchIndex(EntityType type, int index) {
EntityType currentType = type;
do {
Optional<MetaIndex1_7_6_10To1_8> optMeta = getIndex(currentType, index);
Optional<MetaIndex> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
@@ -0,0 +1,422 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.VREntityRewriter;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.api.type.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.emulation.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.Scoreboard;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
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_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent;
import com.viaversion.viaversion.util.IdAndData;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
public class MetadataRewriter1_7_6_10To1_8 extends VREntityRewriter<ClientboundPackets1_8, Protocol1_7_6_10To1_8> {
public MetadataRewriter1_7_6_10To1_8(Protocol1_7_6_10To1_8 protocol) {
super(protocol, MetaType1_7_6_10.String, MetaType1_7_6_10.Byte);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_8.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // Entity id
map(Type.UNSIGNED_BYTE); // Game mode
map(Type.BYTE); // Dimension
map(Type.UNSIGNED_BYTE); // Difficulty
map(Type.UNSIGNED_BYTE); // Max players
map(Type.STRING); // Level type
read(Type.BOOLEAN); // Reduced debug info
handler(playerTrackerHandler());
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 2) { // adventure
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) 0); // survival
}
}
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
tracker.addPlayer(entityId, wrapper.user().getProtocolInfo().getUuid());
tracker.setClientEntityGameMode(wrapper.get(Type.UNSIGNED_BYTE, 0));
wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Type.BYTE, 0));
// Reset on Velocity server change
wrapper.user().put(new Scoreboard(wrapper.user()));
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.DESTROY_ENTITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT_ARRAY_PRIMITIVE, Types1_7_6_10.BYTE_INT_ARRAY); // Entity ids
handler(wrapper -> {
final int[] entities = wrapper.get(Types1_7_6_10.BYTE_INT_ARRAY, 0);
untrackEntities(wrapper.user(), entities);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_METADATA, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // Entity id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // Metadata
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
final List<Metadata> metadata = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
handleMetadata(entityId, metadata, wrapper.user());
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.BYTE); // Type id
map(Type.INT); // X
map(Type.INT); // Y
map(Type.INT); // Z
map(Type.BYTE); // Pitch
map(Type.BYTE); // Yaw
map(Type.INT); // Data
// Track entity
handler(getObjectTrackerHandler());
handler(getObjectRewriter(id -> EntityTypes1_10.ObjectType.findById(id).orElse(null)));
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(wrapper.get(Type.BYTE, 0), true);
int x = wrapper.get(Type.INT, 0);
int y = wrapper.get(Type.INT, 1);
int z = wrapper.get(Type.INT, 2);
byte pitch = wrapper.get(Type.BYTE, 1);
byte yaw = wrapper.get(Type.BYTE, 2);
int data = wrapper.get(Type.INT, 3);
if (type == EntityTypes1_10.ObjectType.ITEM_FRAME.getType()) {
switch (yaw) {
case -128:
z += 32;
yaw = 0;
break;
case -64:
x -= 32;
yaw = -64;
break;
case 0:
z -= 32;
yaw = -128;
break;
case 64:
x += 32;
yaw = 64;
break;
}
} else if (type == EntityTypes1_10.ObjectType.ARMOR_STAND.getType()) {
wrapper.cancel();
final EntityTracker1_8 tracker = tracker(wrapper.user());
final VirtualHologramEntity hologram = tracker.getHolograms().get(entityId);
hologram.setPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(yaw * 360f / 256);
} else if (type != null && type.isOrHasParent(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
final IdAndData replace = protocol.getItemRewriter().handleBlock(blockId, blockData);
if (replace != null) {
blockId = replace.getId();
blockData = replace.getData();
}
wrapper.set(Type.INT, 3, data = (blockId | blockData << 16));
}
wrapper.set(Type.INT, 0, x);
wrapper.set(Type.INT, 1, y);
wrapper.set(Type.INT, 2, z);
wrapper.set(Type.BYTE, 2, yaw);
if (data > 0) {
wrapper.passthrough(Type.SHORT); // Velocity x
wrapper.passthrough(Type.SHORT); // Velocity y
wrapper.passthrough(Type.SHORT); // Velocity z
}
});
}
});
registerTracker(ClientboundPackets1_8.SPAWN_EXPERIENCE_ORB, EntityType.EXPERIENCE_ORB);
registerTracker(ClientboundPackets1_8.SPAWN_GLOBAL_ENTITY, EntityType.LIGHTNING);
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.STRING); // Title
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // Position
map(Type.UNSIGNED_BYTE, Type.INT); // Rotation
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final Position position = wrapper.get(Types1_7_6_10.INT_POSITION, 0);
final int rotation = wrapper.get(Type.INT, 0);
int modX = 0;
int modZ = 0;
switch (rotation) {
case 0:
modZ = -1;
break;
case 1:
modX = 1;
break;
case 2:
modZ = 1;
break;
case 3:
modX = -1;
break;
}
wrapper.set(Types1_7_6_10.INT_POSITION, 0, new Position(position.x() + modX, position.y(), position.z() + modZ));
addTrackedEntity(wrapper, entityId, EntityTypes1_10.EntityType.PAINTING);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.UNSIGNED_BYTE); // Entity type
map(Type.INT); // X
map(Type.INT); // Y
map(Type.INT); // Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
map(Type.BYTE); // Head yaw
map(Type.SHORT); // Velocity x
map(Type.SHORT); // Velocity y
map(Type.SHORT); // Velocity z
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // Metadata
handler(getTrackerHandler(Type.UNSIGNED_BYTE, 0));
handler(getMobSpawnRewriter(Types1_7_6_10.METADATA_LIST));
// Handle holograms
handler(wrapper -> {
final short typeId = wrapper.get(Type.UNSIGNED_BYTE, 0);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(typeId, false);
if (type == EntityTypes1_10.EntityType.ARMOR_STAND) {
wrapper.cancel();
final int entityId = wrapper.get(Type.VAR_INT, 0);
final int x = wrapper.get(Type.INT, 0);
final int y = wrapper.get(Type.INT, 1);
final int z = wrapper.get(Type.INT, 2);
final byte pitch = wrapper.get(Type.BYTE, 1);
final byte yaw = wrapper.get(Type.BYTE, 0);
final byte headYaw = wrapper.get(Type.BYTE, 2);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getHolograms().get(entityId);
hologram.setPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(headYaw * 360f / 256);
hologram.syncState(protocol().getEntityRewriter(), wrapper.get(Types1_7_6_10.METADATA_LIST, 0));
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
handler(wrapper -> {
final UUID uuid = wrapper.read(Type.UUID);
wrapper.write(Type.STRING, uuid.toString()); // map to string
final GameProfileStorage gameProfileStorage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) {
wrapper.write(Type.STRING, ""); // name
wrapper.write(Type.VAR_INT, 0); // properties count
} else {
wrapper.write(Type.STRING, gameProfile.name.length() > 16 ? gameProfile.name.substring(0, 16) : gameProfile.name); // name
wrapper.write(Type.VAR_INT, gameProfile.properties.size()); // properties count
for (GameProfileStorage.Property property : gameProfile.properties) {
wrapper.write(Type.STRING, property.name); // property name
wrapper.write(Type.STRING, property.value); // property value
wrapper.write(Type.STRING, property.signature == null ? "" : property.signature); // property signature
}
}
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (gameProfile != null && gameProfile.gamemode == 3) { // Spectator mode
for (short i = 0; i < 5; i++) {
final PacketWrapper entityEquipment = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, wrapper.user());
entityEquipment.write(Type.INT, entityId);
entityEquipment.write(Type.SHORT, i);
entityEquipment.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, i == 4 ? gameProfile.getSkull() : null);
entityEquipment.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
tracker.addPlayer(entityId, uuid);
});
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // Current item
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(getTrackerAndMetaHandler(Types1_7_6_10.METADATA_LIST, EntityTypes1_10.EntityType.PLAYER));
}
});
}
@Override
protected void registerRewrites() {
// Handle new entities
mapEntityTypeWithData(EntityType.GUARDIAN, EntityType.SQUID).plainName();
mapEntityTypeWithData(EntityType.ENDERMITE, EntityType.SQUID).plainName();
mapEntityTypeWithData(EntityType.RABBIT, EntityType.CHICKEN).plainName();
// Metadata rewrite
filter().handler((event, meta) -> {
try {
handleMetadata(event, meta);
} catch (Exception e) {
if (Via.getManager().isDebug()) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "An error occurred with entity metadata: " + meta, e);
}
event.cancel();
}
});
}
public void handleMetadata(MetaHandlerEvent event, Metadata metadata) throws Exception {
if (event.entityType() == EntityType.ARMOR_STAND) {
final EntityTracker1_8 tracker = tracker(event.user());
tracker.getHolograms().get(event.entityId()).syncState(this, event.metadataList());
event.cancel(); // We are rewriting metadata manually
return;
}
final MetaIndex metaIndex = MetaIndex.searchIndex(event.entityType(), metadata.id());
if (metaIndex == null) {
// Almost certainly bad data, remove it
event.cancel();
return;
}
if (metaIndex.getOldType() == null) {
event.cancel();
return;
}
final Object value = metadata.getValue();
metadata.setTypeAndValue(metaIndex.getNewType(), value);
metadata.setMetaTypeUnsafe(metaIndex.getOldType());
metadata.setId(metaIndex.getIndex());
switch (metaIndex.getOldType()) {
case Int:
if (metaIndex.getNewType() == MetaType1_8.Byte) {
metadata.setValue(((Byte) value).intValue());
if (metaIndex == MetaIndex.ENTITY_AGEABLE_AGE) {
if ((Integer) metadata.getValue() < 0) {
metadata.setValue(-25000);
}
}
}
if (metaIndex.getNewType() == MetaType1_8.Short) {
metadata.setValue(((Short) value).intValue());
}
if (metaIndex.getNewType() == MetaType1_8.Int) {
metadata.setValue(value);
}
break;
case Byte:
if (metaIndex.getNewType() == MetaType1_8.Int) {
metadata.setValue(((Integer) value).byteValue());
}
if (metaIndex.getNewType() == MetaType1_8.Byte) {
if (metaIndex == MetaIndex.ITEM_FRAME_ROTATION) {
metadata.setValue(Integer.valueOf((Byte) value % 4).byteValue());
} else {
metadata.setValue(value);
}
}
if (metaIndex == MetaIndex.HUMAN_SKIN_FLAGS) {
byte flags = (byte) value;
boolean cape = (flags & 0x01) != 0;
flags = (byte) (cape ? 0x00 : 0x02);
metadata.setValue(flags);
}
break;
case Slot:
metadata.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), (Item) value));
break;
default:
event.cancel();
break;
}
}
@Override
public EntityTypes1_10.EntityType typeFromId(int type) {
return EntityTypes1_10.getTypeFromId(type, false);
}
@Override
public EntityTypes1_10.EntityType objectTypeFromId(int type) {
return EntityTypes1_10.getTypeFromId(type, true);
}
}
@@ -1,9 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
public class FurnaceData {
public short fuelLeft = 0;
public short maxFuel = 0;
public short progress = 0;
public short maxProgress = 200;
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,28 +15,38 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
import com.viaversion.viarewind.api.rewriter.VRBlockItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.FurnaceData;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.InventoryTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.UUID;
public class InventoryPackets {
public class BlockItemPackets1_8 extends VRBlockItemRewriter<ClientboundPackets1_8, ServerboundPackets1_7_2_5, Protocol1_7_6_10To1_8> {
public static void register(Protocol1_7_6_10To1_8 protocol) {
private LegacyEnchantmentRewriter enchantmentRewriter;
public BlockItemPackets1_8(Protocol1_7_6_10To1_8 protocol) {
super(protocol, "1.8");
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_8.OPEN_WINDOW, wrapper -> {
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
@@ -47,7 +57,7 @@ public class InventoryPackets {
wrapper.write(Type.UNSIGNED_BYTE, windowTypeId); // window type id
final JsonElement titleComponent = wrapper.read(Type.COMPONENT); // Title
String title = ChatUtil.jsonToLegacy(titleComponent);
String title = ChatUtil.jsonToLegacy(wrapper.user(), titleComponent);
title = ChatUtil.removeUnusedColor(title, '8');
if (title.length() > 32) {
title = title.substring(0, 32);
@@ -91,7 +101,7 @@ public class InventoryPackets {
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
handleItemToClient(wrapper.user(), item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
@@ -105,9 +115,10 @@ public class InventoryPackets {
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
playerSession.setPlayerEquipment(wrapper.user().getProtocolInfo().getUuid(), item, 8 - slot);
if (playerSession.isSpectator()) { // Spectator mode didn't exist in 1.7.10
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.isSpectator()) { // Spectator mode didn't exist in 1.7.10
wrapper.cancel();
}
});
@@ -131,7 +142,7 @@ public class InventoryPackets {
System.arraycopy(old, 2, items, 1, old.length - 3);
}
for (int i = 0; i < items.length; i++) {
items[i] = protocol.getItemRewriter().handleItemToClient(items[i]);
items[i] = handleItemToClient(wrapper.user(), items[i]);
}
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, items); // items
});
@@ -140,17 +151,17 @@ public class InventoryPackets {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final UUID userId = wrapper.user().getProtocolInfo().getUuid();
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final Item[] items = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, 0);
for (int i = 5; i < 9; i++) {
playerSession.setPlayerEquipment(userId, items[i], 8 - i);
if (playerSession.isSpectator()) {
wrapper.user().get(PlayerSessionStorage.class).setPlayerEquipment(userId, items[i], 8 - i);
if (tracker.isSpectator()) {
items[i] = null;
}
}
if (playerSession.isSpectator()) {
if (tracker.isSpectator()) {
final GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(userId);
if (profile != null) {
items[5] = profile.getSkull();
@@ -177,7 +188,8 @@ public class InventoryPackets {
short progress = wrapper.get(Type.SHORT, 1);
if (windowType == 2) { // Furnace
final FurnaceData furnace = windowTracker.getFurnaceData().computeIfAbsent(windowId, x -> new FurnaceData());
// TODO | Proper methods (getOrCreate)=
final InventoryTracker.FurnaceData furnace = windowTracker.getFurnaceData().computeIfAbsent(windowId, x -> new InventoryTracker.FurnaceData());
if (progressBarId == 0 || progressBarId == 1) {
if (progressBarId == 0) {
furnace.fuelLeft = progress;
@@ -245,7 +257,7 @@ public class InventoryPackets {
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Type.ITEM1_8, 0);
protocol.getItemRewriter().handleItemToServer(item);
handleItemToServer(wrapper.user(), item);
wrapper.set(Type.ITEM1_8, 0, item);
});
}
@@ -257,13 +269,62 @@ public class InventoryPackets {
map(Type.SHORT); // slot
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM1_8); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Type.ITEM1_8, 0);
protocol.getItemRewriter().handleItemToServer(item);
wrapper.set(Type.ITEM1_8, 0, item);
});
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Type.ITEM1_8, 0)));
}
});
}
@Override
protected void registerRewrites() {
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName(), false);
enchantmentRewriter.registerEnchantment(8, "§7Depth Strider");
}
@Override
public Item handleItemToClient(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToClient(connection, item);
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
enchantmentRewriter.handleToClient(item);
if (item.identifier() == 387) {
final ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
if (pages == null) return item;
final ListTag<StringTag> oldPages = new ListTag<>(StringTag.class);
tag.put(nbtTagName() + "|pages", oldPages);
for (StringTag page : pages) {
final String value = page.getValue();
oldPages.add(new StringTag(value));
page.setValue(ChatUtil.jsonToLegacy(connection, value));
}
}
return item;
}
@Override
public Item handleItemToServer(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
final CompoundTag tag = item.tag();
if (tag == null) return item;
enchantmentRewriter.handleToServer(item);
if (item.identifier() == 387) {
final ListTag<StringTag> oldPages = tag.get(nbtTagName() + "|pages");
if (oldPages != null) {
tag.remove("pages");
tag.put("pages", oldPages);
}
}
return item;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,27 +15,23 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.emulation.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
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_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.List;
import java.util.UUID;
public class EntityPackets {
public class EntityPackets1_8 {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EQUIPMENT, new PacketHandlers() {
@@ -48,13 +44,14 @@ public class EntityPackets {
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
protocol.getItemRewriter().handleItemToClient(wrapper.user(), item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
handler(wrapper -> {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final short slot = wrapper.get(Type.SHORT, 0);
final UUID uuid = wrapper.user().get(EntityTracker1_7_6_10.class).getPlayerUUID(wrapper.get(Type.INT, 0));
final UUID uuid = tracker.getPlayerUUID(wrapper.get(Type.INT, 0));
if (uuid == null) return;
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
@@ -83,7 +80,7 @@ public class EntityPackets {
map(Type.VAR_INT, Type.INT); // collected entity id
map(Type.VAR_INT, Type.INT); // collector entity id
handler(wrapper -> wrapper.user().get(EntityTracker1_7_6_10.class).removeEntity(wrapper.get(Type.INT, 0)));
handler(wrapper -> wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class).removeEntity(wrapper.get(Type.INT, 0)));
}
});
@@ -91,25 +88,6 @@ public class EntityPackets {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.SHORT); // velocity x
map(Type.SHORT); // velocity y
map(Type.SHORT); // velocity z
}
});
protocol.registerClientbound(ClientboundPackets1_8.DESTROY_ENTITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT_ARRAY_PRIMITIVE, Types1_7_6_10.BYTE_INT_ARRAY); // entity ids
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
for (int entityId : wrapper.get(Types1_7_6_10.BYTE_INT_ARRAY, 0)) {
tracker.removeEntity(entityId);
}
});
}
});
@@ -130,16 +108,16 @@ public class EntityPackets {
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
final VirtualHologramEntity hologram = tracker.getHolograms().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.BYTE, 0);
final int y = wrapper.get(Type.BYTE, 1);
final int z = wrapper.get(Type.BYTE, 2);
hologram.handleOriginalMovementPacket(x / 32.0, y / 32.0, z / 32.0);
hologram.setRelativePosition(x / 32.0, y / 32.0, z / 32.0);
}
});
}
@@ -154,15 +132,15 @@ public class EntityPackets {
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
final VirtualHologramEntity hologram = tracker.getHolograms().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int yaw = wrapper.get(Type.BYTE, 0);
final int pitch = wrapper.get(Type.BYTE, 1);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
@@ -180,9 +158,9 @@ public class EntityPackets {
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
final VirtualHologramEntity hologram = tracker.getHolograms().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.BYTE, 0);
@@ -192,8 +170,8 @@ public class EntityPackets {
final int yaw = wrapper.get(Type.BYTE, 3);
final int pitch = wrapper.get(Type.BYTE, 4);
hologram.handleOriginalMovementPacket(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setRelativePosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
@@ -210,18 +188,16 @@ public class EntityPackets {
map(Type.BYTE); // pitch
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final int entityId = wrapper.get(Type.INT, 0);
final EntityTypes1_10.EntityType type = tracker.getEntityMap().get(entityId);
if (type == EntityTypes1_10.EntityType.MINECART_ABSTRACT) { // TODO | Realign all entities?
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.entityType(entityId) == EntityTypes1_10.EntityType.MINECART_ABSTRACT) { // TODO | Realign all entities?
int y = wrapper.get(Type.INT, 2);
y += 12;
wrapper.set(Type.INT, 2, y);
}
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(entityId);
final VirtualHologramEntity hologram = tracker.getHolograms().get(entityId);
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.INT, 1);
@@ -231,8 +207,8 @@ public class EntityPackets {
final int yaw = wrapper.get(Type.BYTE, 0);
final int pitch = wrapper.get(Type.BYTE, 1);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
@@ -245,9 +221,9 @@ public class EntityPackets {
map(Type.BYTE); // head yaw
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
final VirtualHologramEntity hologram = tracker.getHolograms().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int yaw = wrapper.get(Type.BYTE, 0);
@@ -264,13 +240,13 @@ public class EntityPackets {
map(Type.INT); // riding entity id
map(Type.INT); // vehicle entity id
map(Type.BOOLEAN); // leash state
handler(packetWrapper -> {
final boolean leash = packetWrapper.get(Type.BOOLEAN, 0);
handler(wrapper -> {
final boolean leash = wrapper.get(Type.BOOLEAN, 0);
if (!leash) {
final EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final int passenger = packetWrapper.get(Type.INT, 0);
final int vehicle = packetWrapper.get(Type.INT, 1);
final int passenger = wrapper.get(Type.INT, 0);
final int vehicle = wrapper.get(Type.INT, 1);
tracker.setPassenger(vehicle, passenger);
}
@@ -278,33 +254,6 @@ public class EntityPackets {
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_METADATA, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
final List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.getEntityReplacementMap().containsKey(entityId)) {
tracker.updateMetadata(entityId, metadataList);
wrapper.cancel();
return;
}
if (tracker.getEntityMap().containsKey(entityId)) {
protocol.getMetadataRewriter().transform(tracker.getEntityMap().get(entityId), metadataList);
if (metadataList.isEmpty()) {
wrapper.cancel();
}
} else {
wrapper.cancel();
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
@@ -329,12 +278,6 @@ public class EntityPackets {
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
if (wrapper.user().get(EntityTracker1_7_6_10.class).getEntityReplacementMap().containsKey(entityId)) {
wrapper.cancel();
return;
}
final int amount = wrapper.passthrough(Type.INT);
for (int i = 0; i < amount; i++) {
wrapper.passthrough(Type.STRING); // id
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.ViaRewind;
@@ -24,9 +23,8 @@ import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10T
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.TitleRenderProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Ray3d;
import com.viaversion.viarewind.utils.math.RayTracing;
@@ -40,12 +38,12 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.util.ComponentUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
@@ -54,40 +52,9 @@ import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;
public class PlayerPackets {
public class PlayerPackets1_8 {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // entity id
map(Type.UNSIGNED_BYTE);// game mode
map(Type.BYTE); // dimension
map(Type.UNSIGNED_BYTE); // difficulty
map(Type.UNSIGNED_BYTE); // max players
map(Type.STRING); // level type
read(Type.BOOLEAN); // reduced debug info
handler(wrapper -> {
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 2) { // adventure
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) 0); // survival
}
}
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.setClientEntityId(wrapper.get(Type.INT, 0));
tracker.addPlayer(wrapper.get(Type.INT, 0), wrapper.user().getProtocolInfo().getUuid());
wrapper.user().get(PlayerSessionStorage.class).gameMode = wrapper.get(Type.UNSIGNED_BYTE, 0);
wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Type.BYTE, 0));
// Reset on Velocity server change
wrapper.user().put(new Scoreboard(wrapper.user()));
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
@@ -123,7 +90,6 @@ public class PlayerPackets {
map(Type.INT); // dimension
map(Type.UNSIGNED_BYTE); // difficulty
map(Type.UNSIGNED_BYTE); // game mode
map(Type.STRING); // level type
handler(wrapper -> {
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 1) == 2) {
@@ -131,18 +97,17 @@ public class PlayerPackets {
}
}
wrapper.user().get(PlayerSessionStorage.class).gameMode = wrapper.get(Type.UNSIGNED_BYTE, 1);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
tracker.setClientEntityGameMode(wrapper.get(Type.UNSIGNED_BYTE, 1));
final ClientWorld world = wrapper.user().get(ClientWorld.class);
final Environment dimension = Environment.getEnvironmentById(wrapper.get(Type.INT, 0));
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final ClientWorld world = wrapper.user().get(ClientWorld.class);
if (world.getEnvironment() != dimension) {
// Clear entities on dimension change and re-track player
world.setEnvironment(dimension.id());
// Reset on dimension change
tracker.clear();
tracker.getEntityMap().put(tracker.getPlayerId(), EntityTypes1_10.EntityType.ENTITY_HUMAN);
tracker.clearEntities();
tracker.addEntity(tracker.clientEntityId(), EntityTypes1_10.EntityType.PLAYER);
}
});
}
@@ -182,8 +147,8 @@ public class PlayerPackets {
wrapper.write(Type.BOOLEAN, playerSession.onGround);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.spectatingPlayerId != tracker.getPlayerId()) {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.spectatingClientEntityId != tracker.clientEntityId()) {
wrapper.cancel();
}
});
@@ -208,8 +173,8 @@ public class PlayerPackets {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) != 3) return; // Change game mode
int gameMode = wrapper.get(Type.FLOAT, 0).intValue();
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
if (gameMode == 3 || playerSession.gameMode == 3) {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (gameMode == 3 || tracker.isSpectator()) {
UUID myId = wrapper.user().getProtocolInfo().getUuid();
Item[] equipment = new Item[4];
if (gameMode == 3) {
@@ -217,7 +182,7 @@ public class PlayerPackets {
equipment[3] = profile == null ? null : profile.getSkull();
} else {
for (int i = 0; i < equipment.length; i++) {
equipment[i] = playerSession.getPlayerEquipment(myId, i);
equipment[i] = wrapper.user().get(PlayerSessionStorage.class).getPlayerEquipment(myId, i);
}
}
@@ -226,7 +191,7 @@ public class PlayerPackets {
setSlot.write(Type.BYTE, (byte) 0);
setSlot.write(Type.SHORT, (short) (8 - i));
setSlot.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, equipment[i]);
PacketUtil.sendPacket(setSlot, Protocol1_7_6_10To1_8.class);
setSlot.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
@@ -234,7 +199,7 @@ public class PlayerPackets {
gameMode = 0;
wrapper.set(Type.FLOAT, 0, 0.0f);
}
wrapper.user().get(PlayerSessionStorage.class).gameMode = gameMode;
tracker.setClientEntityGameMode(gameMode);
});
}
});
@@ -249,51 +214,51 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.PLAYER_INFO, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
int action = packetWrapper.read(Type.VAR_INT);
int count = packetWrapper.read(Type.VAR_INT);
GameProfileStorage gameProfileStorage = packetWrapper.user().get(GameProfileStorage.class);
handler(wrapper -> {
wrapper.cancel();
int action = wrapper.read(Type.VAR_INT);
int count = wrapper.read(Type.VAR_INT);
GameProfileStorage gameProfileStorage = wrapper.user().get(GameProfileStorage.class);
for (int i = 0; i < count; i++) {
UUID uuid = packetWrapper.read(Type.UUID);
UUID uuid = wrapper.read(Type.UUID);
if (action == 0) {
String name = packetWrapper.read(Type.STRING);
String name = wrapper.read(Type.STRING);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) gameProfile = gameProfileStorage.put(uuid, name);
int propertyCount = packetWrapper.read(Type.VAR_INT);
int propertyCount = wrapper.read(Type.VAR_INT);
while (propertyCount-- > 0) {
String propertyName = packetWrapper.read(Type.STRING);
String propertyValue = packetWrapper.read(Type.STRING);
String propertySignature = packetWrapper.read(Type.OPTIONAL_STRING);
String propertyName = wrapper.read(Type.STRING);
String propertyValue = wrapper.read(Type.STRING);
String propertySignature = wrapper.read(Type.OPTIONAL_STRING);
gameProfile.properties.add(new GameProfileStorage.Property(propertyName, propertyValue, propertySignature));
}
int gamemode = packetWrapper.read(Type.VAR_INT);
int ping = packetWrapper.read(Type.VAR_INT);
int gamemode = wrapper.read(Type.VAR_INT);
int ping = wrapper.read(Type.VAR_INT);
gameProfile.ping = ping;
gameProfile.gamemode = gamemode;
JsonElement displayName = packetWrapper.read(Type.OPTIONAL_COMPONENT);
JsonElement displayName = wrapper.read(Type.OPTIONAL_COMPONENT);
if (displayName != null) {
gameProfile.setDisplayName(ChatUtil.jsonToLegacy(displayName));
gameProfile.setDisplayName(ChatUtil.jsonToLegacy(wrapper.user(), displayName));
}
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
} else if (action == 1) {
int gamemode = packetWrapper.read(Type.VAR_INT);
int gamemode = wrapper.read(Type.VAR_INT);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null || gameProfile.gamemode == gamemode) continue;
if (gamemode == 3 || gameProfile.gamemode == 3) {
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
int entityId = tracker.getPlayerEntityId(uuid);
boolean isOwnPlayer = entityId == tracker.getPlayerId();
boolean isOwnPlayer = entityId == tracker.clientEntityId();
if (entityId != -1) {
// Weirdly, PlayerEntity has only 4 slots instead of 5
Item[] equipment = new Item[isOwnPlayer ? 4 : 5];
@@ -301,71 +266,71 @@ public class PlayerPackets {
equipment[isOwnPlayer ? 3 : 4] = gameProfile.getSkull();
} else {
for (int j = 0; j < equipment.length; j++) {
equipment[j] = packetWrapper.user().get(PlayerSessionStorage.class).getPlayerEquipment(uuid, j);
equipment[j] = wrapper.user().get(PlayerSessionStorage.class).getPlayerEquipment(uuid, j);
}
}
for (short slot = 0; slot < equipment.length; slot++) {
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, packetWrapper.user());
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, wrapper.user());
equipmentPacket.write(Type.INT, entityId);
equipmentPacket.write(Type.SHORT, slot);
equipmentPacket.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, equipment[slot]);
PacketUtil.sendPacket(equipmentPacket, Protocol1_7_6_10To1_8.class);
equipmentPacket.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
}
gameProfile.gamemode = gamemode;
} else if (action == 2) {
int ping = packetWrapper.read(Type.VAR_INT);
int ping = wrapper.read(Type.VAR_INT);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
gameProfile.ping = ping;
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
} else if (action == 3) {
JsonElement displayNameComponent = packetWrapper.read(Type.OPTIONAL_COMPONENT);
String displayName = displayNameComponent != null ? ChatUtil.jsonToLegacy(displayNameComponent) : null;
JsonElement displayNameComponent = wrapper.read(Type.OPTIONAL_COMPONENT);
String displayName = displayNameComponent != null ? ChatUtil.jsonToLegacy(wrapper.user(), displayNameComponent) : null;
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null || gameProfile.displayName == null && displayName == null) continue;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
if (gameProfile.displayName == null && displayName != null || gameProfile.displayName != null && displayName == null || !gameProfile.displayName.equals(displayName)) {
gameProfile.setDisplayName(displayName);
}
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
} else if (action == 4) {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.remove(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
});
@@ -378,11 +343,11 @@ public class PlayerPackets {
map(Type.BYTE);
map(Type.FLOAT);
map(Type.FLOAT);
handler(packetWrapper -> {
byte flags = packetWrapper.get(Type.BYTE, 0);
float flySpeed = packetWrapper.get(Type.FLOAT, 0);
float walkSpeed = packetWrapper.get(Type.FLOAT, 1);
PlayerSessionStorage abilities = packetWrapper.user().get(PlayerSessionStorage.class);
handler(wrapper -> {
byte flags = wrapper.get(Type.BYTE, 0);
float flySpeed = wrapper.get(Type.FLOAT, 0);
float walkSpeed = wrapper.get(Type.FLOAT, 1);
PlayerSessionStorage abilities = wrapper.user().get(PlayerSessionStorage.class);
abilities.invincible = (flags & 8) == 8;
abilities.allowFly = (flags & 4) == 4;
abilities.flying = (flags & 2) == 2;
@@ -391,7 +356,7 @@ public class PlayerPackets {
abilities.walkSpeed = walkSpeed;
if (abilities.sprinting && abilities.flying) {
packetWrapper.set(Type.FLOAT, 0, abilities.flySpeed * 2.0f);
wrapper.set(Type.FLOAT, 0, abilities.flySpeed * 2.0f);
}
});
}
@@ -401,44 +366,44 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
if (channel.equalsIgnoreCase("MC|TrList")) {
packetWrapper.passthrough(Type.INT); //Window Id
handler(wrapper -> {
String channel = wrapper.get(Type.STRING, 0);
if (channel.equals("MC|TrList")) {
wrapper.passthrough(Type.INT); //Window Id
int size;
if (packetWrapper.isReadable(Type.BYTE, 0)) {
size = packetWrapper.passthrough(Type.BYTE);
if (wrapper.isReadable(Type.BYTE, 0)) {
size = wrapper.passthrough(Type.BYTE);
} else {
size = packetWrapper.passthrough(Type.UNSIGNED_BYTE);
size = wrapper.passthrough(Type.UNSIGNED_BYTE);
}
for (int i = 0; i < size; i++) {
Item item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 1
Item item = protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8));
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 1
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 3
item = protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8));
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 3
boolean has3Items = packetWrapper.passthrough(Type.BOOLEAN);
boolean has3Items = wrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 2
item = protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8));
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 2
}
packetWrapper.passthrough(Type.BOOLEAN); //Unavailable
packetWrapper.read(Type.INT); //Uses
packetWrapper.read(Type.INT); //Max Uses
wrapper.passthrough(Type.BOOLEAN); //Unavailable
wrapper.read(Type.INT); //Uses
wrapper.read(Type.INT); //Max Uses
}
} else if (channel.equalsIgnoreCase("MC|Brand")) {
packetWrapper.write(Type.REMAINING_BYTES, packetWrapper.read(Type.STRING).getBytes(StandardCharsets.UTF_8));
} else if (channel.equals("MC|Brand")) {
wrapper.write(Type.REMAINING_BYTES, wrapper.read(Type.STRING).getBytes(StandardCharsets.UTF_8));
}
packetWrapper.cancel();
packetWrapper.setPacketType(null);
wrapper.cancel();
wrapper.setPacketType(null);
ByteBuf newPacketBuf = Unpooled.buffer();
packetWrapper.writeToBuffer(newPacketBuf);
PacketWrapper newWrapper = PacketWrapper.create(ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, newPacketBuf, packetWrapper.user());
wrapper.writeToBuffer(newPacketBuf);
PacketWrapper newWrapper = PacketWrapper.create(ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, newPacketBuf, wrapper.user());
newWrapper.passthrough(Type.STRING);
if (newPacketBuf.readableBytes() <= Short.MAX_VALUE) {
newWrapper.write(Type.SHORT, (short) newPacketBuf.readableBytes());
@@ -448,19 +413,15 @@ public class PlayerPackets {
}
});
//Camera
protocol.registerClientbound(ClientboundPackets1_8.CAMERA, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
handler(wrapper -> {
wrapper.cancel();
final int entityId = wrapper.read(Type.VAR_INT);
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
int entityId = packetWrapper.read(Type.VAR_INT);
int spectating = tracker.spectatingPlayerId;
if (spectating != entityId) {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.spectatingClientEntityId != entityId) {
tracker.setSpectating(entityId);
}
});
@@ -471,21 +432,21 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.TITLE, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
handler(wrapper -> {
wrapper.cancel();
TitleRenderProvider titleRenderProvider = Via.getManager().getProviders().get(TitleRenderProvider.class);
if (titleRenderProvider == null) return;
int action = packetWrapper.read(Type.VAR_INT);
UUID uuid = packetWrapper.user().getProtocolInfo().getUuid();
int action = wrapper.read(Type.VAR_INT);
UUID uuid = wrapper.user().getProtocolInfo().getUuid();
switch (action) {
case 0:
titleRenderProvider.setTitle(uuid, packetWrapper.read(Type.STRING));
titleRenderProvider.setTitle(uuid, wrapper.read(Type.STRING));
break;
case 1:
titleRenderProvider.setSubTitle(uuid, packetWrapper.read(Type.STRING));
titleRenderProvider.setSubTitle(uuid, wrapper.read(Type.STRING));
break;
case 2:
titleRenderProvider.setTimings(uuid, packetWrapper.read(Type.INT), packetWrapper.read(Type.INT), packetWrapper.read(Type.INT));
titleRenderProvider.setTimings(uuid, wrapper.read(Type.INT), wrapper.read(Type.INT), wrapper.read(Type.INT));
break;
case 3:
titleRenderProvider.clear(uuid);
@@ -506,13 +467,13 @@ public class PlayerPackets {
@Override
public void register() {
create(Type.STRING, "MC|RPack");
handler(packetWrapper -> {
handler(wrapper -> {
ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
try {
// Url
Type.STRING.write(buf, packetWrapper.read(Type.STRING));
Type.STRING.write(buf, wrapper.read(Type.STRING));
packetWrapper.write(Type.SHORT_BYTE_ARRAY, Type.REMAINING_BYTES.read(buf));
wrapper.write(Type.SHORT_BYTE_ARRAY, Type.REMAINING_BYTES.read(buf));
} finally {
buf.release();
}
@@ -521,26 +482,24 @@ public class PlayerPackets {
}
});
/* INCOMING */
protocol.registerServerbound(ServerboundPackets1_7_2_5.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
int gamemode = packetWrapper.user().get(PlayerSessionStorage.class).gameMode;
if (gamemode == 3 && msg.toLowerCase().startsWith("/stp ")) {
handler(wrapper -> {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
String msg = wrapper.get(Type.STRING, 0);
if (tracker.isSpectator() && msg.toLowerCase().startsWith("/stp ")) { // TODO add setting
String username = msg.split(" ")[1];
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
GameProfileStorage storage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile profile = storage.get(username, true);
if (profile != null && profile.uuid != null) {
packetWrapper.cancel();
wrapper.cancel();
PacketWrapper teleportPacket = PacketWrapper.create(0x18, null, packetWrapper.user());
PacketWrapper teleportPacket = PacketWrapper.create(0x18, null, wrapper.user());
teleportPacket.write(Type.UUID, profile.uuid);
PacketUtil.sendToServer(teleportPacket, Protocol1_7_6_10To1_8.class, true, true);
teleportPacket.send(Protocol1_7_6_10To1_8.class);
}
}
});
@@ -558,11 +517,11 @@ public class PlayerPackets {
return;
}
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final PlayerSessionStorage position = wrapper.user().get(PlayerSessionStorage.class);
if (tracker.getVirtualHologramMap().containsKey(entityId)) {
final AABB boundingBox = tracker.getVirtualHologramMap().get(entityId).getBoundingBox();
if (tracker.getHolograms().containsKey(entityId)) {
final AABB boundingBox = tracker.getHolograms().get(entityId).getBoundingBox();
Vector3d pos = new Vector3d(position.getPosX(), position.getPosY() + 1.8, position.getPosZ());
double yaw = Math.toRadians(position.yaw);
@@ -591,9 +550,9 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
handler(wrapper -> {
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = wrapper.get(Type.BOOLEAN, 0);
});
}
});
@@ -606,14 +565,14 @@ public class PlayerPackets {
read(Type.DOUBLE);
map(Type.DOUBLE); //Z
map(Type.BOOLEAN); //OnGround
handler(packetWrapper -> {
double x = packetWrapper.get(Type.DOUBLE, 0);
double feetY = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
handler(wrapper -> {
double x = wrapper.get(Type.DOUBLE, 0);
double feetY = wrapper.get(Type.DOUBLE, 1);
double z = wrapper.get(Type.DOUBLE, 2);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.onGround = wrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
});
}
@@ -625,11 +584,11 @@ public class PlayerPackets {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.yaw = packetWrapper.get(Type.FLOAT, 0);
playerSession.pitch = packetWrapper.get(Type.FLOAT, 1);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
handler(wrapper -> {
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.yaw = wrapper.get(Type.FLOAT, 0);
playerSession.pitch = wrapper.get(Type.FLOAT, 1);
playerSession.onGround = wrapper.get(Type.BOOLEAN, 0);
});
}
});
@@ -644,17 +603,17 @@ public class PlayerPackets {
map(Type.FLOAT); //Yaw
map(Type.FLOAT); //Pitch
map(Type.BOOLEAN); //OnGround
handler(packetWrapper -> {
double x = packetWrapper.get(Type.DOUBLE, 0);
double feetY = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
handler(wrapper -> {
double x = wrapper.get(Type.DOUBLE, 0);
double feetY = wrapper.get(Type.DOUBLE, 1);
double z = wrapper.get(Type.DOUBLE, 2);
float yaw = packetWrapper.get(Type.FLOAT, 0);
float pitch = packetWrapper.get(Type.FLOAT, 1);
float yaw = wrapper.get(Type.FLOAT, 0);
float pitch = wrapper.get(Type.FLOAT, 1);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.onGround = wrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
playerSession.yaw = yaw;
playerSession.pitch = pitch;
@@ -666,11 +625,11 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.VAR_INT); //Status
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.UNSIGNED_BYTE);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
handler(wrapper -> {
int x = wrapper.read(Type.INT);
int y = wrapper.read(Type.UNSIGNED_BYTE);
int z = wrapper.read(Type.INT);
wrapper.write(Type.POSITION1_8, new Position(x, y, z));
});
}
});
@@ -678,19 +637,19 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.UNSIGNED_BYTE);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
handler(wrapper -> {
int x = wrapper.read(Type.INT);
int y = wrapper.read(Type.UNSIGNED_BYTE);
int z = wrapper.read(Type.INT);
wrapper.write(Type.POSITION1_8, new Position(x, y, z));
packetWrapper.passthrough(Type.BYTE); //Direction
Item item = packetWrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
item = protocol.getItemRewriter().handleItemToServer(item);
packetWrapper.write(Type.ITEM1_8, item);
wrapper.passthrough(Type.BYTE); //Direction
Item item = wrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
item = protocol.getItemRewriter().handleItemToServer(wrapper.user(), item);
wrapper.write(Type.ITEM1_8, item);
for (int i = 0; i < 3; i++) {
packetWrapper.passthrough(Type.BYTE);
wrapper.passthrough(Type.BYTE);
}
});
}
@@ -699,11 +658,11 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_7_2_5.ANIMATION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int entityId = packetWrapper.read(Type.INT);
int animation = packetWrapper.read(Type.BYTE); //Animation
handler(wrapper -> {
int entityId = wrapper.read(Type.INT);
int animation = wrapper.read(Type.BYTE); //Animation
if (animation == 1) return;
packetWrapper.cancel();
wrapper.cancel();
//1.7 vanilla client is not sending this packet with animation!=1
switch (animation) {
case 104:
@@ -718,11 +677,11 @@ public class PlayerPackets {
default:
return;
}
PacketWrapper entityAction = PacketWrapper.create(0x0B, null, packetWrapper.user());
PacketWrapper entityAction = PacketWrapper.create(0x0B, null, wrapper.user());
entityAction.write(Type.VAR_INT, entityId);
entityAction.write(Type.VAR_INT, animation);
entityAction.write(Type.VAR_INT, 0);
PacketUtil.sendPacket(entityAction, Protocol1_7_6_10To1_8.class, true, true);
entityAction.send(Protocol1_7_6_10To1_8.class);
});
}
});
@@ -731,18 +690,18 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.INT, Type.VAR_INT); //Entity Id
handler(packetWrapper -> packetWrapper.write(Type.VAR_INT, packetWrapper.read(Type.BYTE) - 1)); //Action Id
handler(wrapper -> wrapper.write(Type.VAR_INT, wrapper.read(Type.BYTE) - 1)); //Action Id
map(Type.INT, Type.VAR_INT); //Action Parameter
handler(packetWrapper -> {
int action = packetWrapper.get(Type.VAR_INT, 1);
handler(wrapper -> {
int action = wrapper.get(Type.VAR_INT, 1);
if (action == 3 || action == 4) {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.sprinting = action == 3;
PacketWrapper abilitiesPacket = PacketWrapper.create(0x39, null, packetWrapper.user());
PacketWrapper abilitiesPacket = PacketWrapper.create(0x39, null, wrapper.user());
abilitiesPacket.write(Type.BYTE, playerSession.combineAbilities());
abilitiesPacket.write(Type.FLOAT, playerSession.sprinting ? playerSession.flySpeed * 2.0f : playerSession.flySpeed);
abilitiesPacket.write(Type.FLOAT, playerSession.walkSpeed);
PacketUtil.sendPacket(abilitiesPacket, Protocol1_7_6_10To1_8.class);
abilitiesPacket.send(Protocol1_7_6_10To1_8.class);
}
});
}
@@ -753,28 +712,28 @@ public class PlayerPackets {
public void register() {
map(Type.FLOAT); //Sideways
map(Type.FLOAT); //Forwards
handler(packetWrapper -> {
boolean jump = packetWrapper.read(Type.BOOLEAN);
boolean unmount = packetWrapper.read(Type.BOOLEAN);
handler(wrapper -> {
boolean jump = wrapper.read(Type.BOOLEAN);
boolean unmount = wrapper.read(Type.BOOLEAN);
short flags = 0;
if (jump) flags += 0x01;
if (unmount) flags += 0x02;
packetWrapper.write(Type.UNSIGNED_BYTE, flags);
wrapper.write(Type.UNSIGNED_BYTE, flags);
if (unmount) {
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.spectatingPlayerId != tracker.getPlayerId()) {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, packetWrapper.user());
sneakPacket.write(Type.VAR_INT, tracker.getPlayerId());
EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.spectatingClientEntityId != tracker.clientEntityId()) {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, wrapper.user());
sneakPacket.write(Type.VAR_INT, tracker.clientEntityId());
sneakPacket.write(Type.VAR_INT, 0); //Start sneaking
sneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketWrapper unsneakPacket = PacketWrapper.create(0x0B, null, packetWrapper.user());
unsneakPacket.write(Type.VAR_INT, tracker.getPlayerId());
PacketWrapper unsneakPacket = PacketWrapper.create(0x0B, null, wrapper.user());
unsneakPacket.write(Type.VAR_INT, tracker.clientEntityId());
unsneakPacket.write(Type.VAR_INT, 1); //Stop sneaking
unsneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketUtil.sendToServer(sneakPacket, Protocol1_7_6_10To1_8.class);
sneakPacket.scheduleSendToServer(Protocol1_7_6_10To1_8.class);
}
}
});
@@ -784,15 +743,15 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_7_2_5.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.SHORT);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
handler(wrapper -> {
int x = wrapper.read(Type.INT);
int y = wrapper.read(Type.SHORT);
int z = wrapper.read(Type.INT);
wrapper.write(Type.POSITION1_8, new Position(x, y, z));
for (int i = 0; i < 4; i++) {
String line = packetWrapper.read(Type.STRING);
line = ChatUtil.legacyToJson(line);
packetWrapper.write(Type.COMPONENT, JsonParser.parseString(line));
final String line = wrapper.read(Type.STRING);
wrapper.write(Type.COMPONENT, ComponentUtil.legacyToJson(line));
}
});
}
@@ -804,13 +763,13 @@ public class PlayerPackets {
map(Type.BYTE);
map(Type.FLOAT);
map(Type.FLOAT);
handler(packetWrapper -> {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
handler(wrapper -> {
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
if (playerSession.allowFly) {
byte flags = packetWrapper.get(Type.BYTE, 0);
byte flags = wrapper.get(Type.BYTE, 0);
playerSession.flying = (flags & 2) == 2;
}
packetWrapper.set(Type.FLOAT, 0, playerSession.flySpeed);
wrapper.set(Type.FLOAT, 0, playerSession.flySpeed);
});
}
});
@@ -820,23 +779,23 @@ public class PlayerPackets {
public void register() {
map(Type.STRING);
create(Type.OPTIONAL_POSITION1_8, null);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
handler(wrapper -> {
String msg = wrapper.get(Type.STRING, 0);
if (msg.toLowerCase().startsWith("/stp ")) {
packetWrapper.cancel();
wrapper.cancel();
String[] args = msg.split(" ");
if (args.length <= 2) {
String prefix = args.length == 1 ? "" : args[1];
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
GameProfileStorage storage = wrapper.user().get(GameProfileStorage.class);
List<GameProfileStorage.GameProfile> profiles = storage.getAllWithPrefix(prefix, true);
PacketWrapper tabComplete = PacketWrapper.create(0x3A, null, packetWrapper.user());
PacketWrapper tabComplete = PacketWrapper.create(0x3A, null, wrapper.user());
tabComplete.write(Type.VAR_INT, profiles.size());
for (GameProfileStorage.GameProfile profile : profiles) {
tabComplete.write(Type.STRING, profile.name);
}
PacketUtil.sendPacket(tabComplete, Protocol1_7_6_10To1_8.class);
tabComplete.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
});
@@ -852,9 +811,9 @@ public class PlayerPackets {
map(Type.BYTE);
map(Type.BOOLEAN);
read(Type.BYTE);
handler(packetWrapper -> {
boolean cape = packetWrapper.read(Type.BOOLEAN);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) (cape ? 127 : 126));
handler(wrapper -> {
boolean cape = wrapper.read(Type.BOOLEAN);
wrapper.write(Type.UNSIGNED_BYTE, (short) (cape ? 127 : 126));
});
}
});
@@ -864,48 +823,48 @@ public class PlayerPackets {
public void register() {
map(Type.STRING);
read(Type.SHORT); // Length
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
handler(wrapper -> {
String channel = wrapper.get(Type.STRING, 0);
switch (channel) {
case "MC|TrSel": {
packetWrapper.passthrough(Type.INT);
packetWrapper.read(Type.REMAINING_BYTES); // unused data ???
wrapper.passthrough(Type.INT);
wrapper.read(Type.REMAINING_BYTES); // unused data ???
break;
}
case "MC|ItemName": {
byte[] data = packetWrapper.read(Type.REMAINING_BYTES);
byte[] data = wrapper.read(Type.REMAINING_BYTES);
String name = new String(data, StandardCharsets.UTF_8);
packetWrapper.write(Type.STRING, name);
wrapper.write(Type.STRING, name);
InventoryTracker windowTracker = packetWrapper.user().get(InventoryTracker.class);
PacketWrapper updateCost = PacketWrapper.create(0x31, null, packetWrapper.user());
InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
PacketWrapper updateCost = PacketWrapper.create(0x31, null, wrapper.user());
updateCost.write(Type.UNSIGNED_BYTE, windowTracker.anvilId);
updateCost.write(Type.SHORT, (short) 0);
updateCost.write(Type.SHORT, windowTracker.levelCost);
PacketUtil.sendPacket(updateCost, Protocol1_7_6_10To1_8.class, true, true);
updateCost.send(Protocol1_7_6_10To1_8.class);
break;
}
case "MC|BEdit":
case "MC|BSign": {
Item book = packetWrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
Item book = wrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
CompoundTag tag = book.tag();
if (tag != null && tag.contains("pages")) {
ListTag pages = tag.get("pages");
ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
value = ChatUtil.legacyToJson(value);
value = ComponentUtil.legacyToJsonString(value);
page.setValue(value);
}
}
packetWrapper.write(Type.ITEM1_8, book);
wrapper.write(Type.ITEM1_8, book);
break;
}
case "MC|Brand": {
packetWrapper.write(Type.STRING, new String(packetWrapper.read(Type.REMAINING_BYTES), StandardCharsets.UTF_8));
wrapper.write(Type.STRING, new String(wrapper.read(Type.REMAINING_BYTES), StandardCharsets.UTF_8));
break;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,12 +15,10 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.Scoreboard;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
@@ -31,80 +29,75 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class ScoreboardPackets {
public class ScoreboardPackets1_8 {
public static void register(Protocol1_7_6_10To1_8 protocol) {
/* OUTGOING */
//Scoreboard Objective
protocol.registerClientbound(ClientboundPackets1_8.SCOREBOARD_OBJECTIVE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
String name = packetWrapper.passthrough(Type.STRING);
handler(wrapper -> {
String name = wrapper.passthrough(Type.STRING);
if (name.length() > 16) {
packetWrapper.set(Type.STRING, 0, name = name.substring(0, 16));
wrapper.set(Type.STRING, 0, name = name.substring(0, 16));
}
byte mode = packetWrapper.read(Type.BYTE);
byte mode = wrapper.read(Type.BYTE);
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
Scoreboard scoreboard = wrapper.user().get(Scoreboard.class);
if (mode == 0) {
if (scoreboard.objectiveExists(name)) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
scoreboard.addObjective(name);
} else if (mode == 1) {
if (!scoreboard.objectiveExists(name)) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
if (scoreboard.getColorIndependentSidebar() != null) {
String username = packetWrapper.user().getProtocolInfo().getUsername();
String username = wrapper.user().getProtocolInfo().getUsername();
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
if (color.isPresent()) {
String sidebar = scoreboard.getColorDependentSidebar().get(color.get());
if (name.equals(sidebar)) {
PacketWrapper sidebarPacket = PacketWrapper.create(0x3D, null, packetWrapper.user());
PacketWrapper sidebarPacket = PacketWrapper.create(0x3D, null, wrapper.user());
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, scoreboard.getColorIndependentSidebar());
PacketUtil.sendPacket(sidebarPacket, Protocol1_7_6_10To1_8.class);
sidebarPacket.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
}
scoreboard.removeObjective(name);
} else if (mode == 2) {
if (!scoreboard.objectiveExists(name)) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
}
if (mode == 0 || mode == 2) {
String displayName = packetWrapper.passthrough(Type.STRING);
String displayName = wrapper.passthrough(Type.STRING);
if (displayName.length() > 32) {
packetWrapper.set(Type.STRING, 1, displayName.substring(0, 32));
wrapper.set(Type.STRING, 1, displayName.substring(0, 32));
}
packetWrapper.read(Type.STRING);
wrapper.read(Type.STRING);
} else {
packetWrapper.write(Type.STRING, "");
wrapper.write(Type.STRING, "");
}
packetWrapper.write(Type.BYTE, mode);
wrapper.write(Type.BYTE, mode);
});
}
});
//Update Score
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_SCORE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // Name
map(Type.VAR_INT, Type.BYTE); // Mode
handler(packetWrapper -> {
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
String name = packetWrapper.get(Type.STRING, 0);
byte mode = packetWrapper.get(Type.BYTE, 0);
handler(wrapper -> {
Scoreboard scoreboard = wrapper.user().get(Scoreboard.class);
String name = wrapper.get(Type.STRING, 0);
byte mode = wrapper.get(Type.BYTE, 0);
if (mode == 1) {
name = scoreboard.removeTeamForScore(name);
@@ -118,17 +111,17 @@ public class ScoreboardPackets {
name = name.substring(0, 16);
}
}
packetWrapper.set(Type.STRING, 0, name);
wrapper.set(Type.STRING, 0, name);
String objective = packetWrapper.read(Type.STRING);
String objective = wrapper.read(Type.STRING);
if (objective.length() > 16) {
objective = objective.substring(0, 16);
}
if (mode != 1) {
int score = packetWrapper.read(Type.VAR_INT);
packetWrapper.write(Type.STRING, objective);
packetWrapper.write(Type.INT, score);
int score = wrapper.read(Type.VAR_INT);
wrapper.write(Type.STRING, objective);
wrapper.write(Type.INT, score);
}
});
}
@@ -139,15 +132,15 @@ public class ScoreboardPackets {
public void register() {
map(Type.BYTE); // Position
map(Type.STRING); // Score name
handler(packetWrapper -> {
byte position = packetWrapper.get(Type.BYTE, 0);
String name = packetWrapper.get(Type.STRING, 0);
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
handler(wrapper -> {
byte position = wrapper.get(Type.BYTE, 0);
String name = wrapper.get(Type.STRING, 0);
Scoreboard scoreboard = wrapper.user().get(Scoreboard.class);
if (position > 2) { // team specific sidebar
byte receiverTeamColor = (byte) (position - 3);
scoreboard.getColorDependentSidebar().put(receiverTeamColor, name);
String username = packetWrapper.user().getProtocolInfo().getUsername();
String username = wrapper.user().getProtocolInfo().getUsername();
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
if (color.isPresent() && color.get() == receiverTeamColor) {
position = 1;
@@ -156,17 +149,17 @@ public class ScoreboardPackets {
}
} else if (position == 1) { // team independent sidebar
scoreboard.setColorIndependentSidebar(name);
String username = packetWrapper.user().getProtocolInfo().getUsername();
String username = wrapper.user().getProtocolInfo().getUsername();
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
if (color.isPresent() && scoreboard.getColorDependentSidebar().containsKey(color.get())) {
position = -1;
}
}
if (position == -1) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
packetWrapper.set(Type.BYTE, 0, position);
wrapper.set(Type.BYTE, 0, position);
});
}
});
@@ -175,26 +168,26 @@ public class ScoreboardPackets {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String team = packetWrapper.get(Type.STRING, 0);
handler(wrapper -> {
String team = wrapper.get(Type.STRING, 0);
if (team == null) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
byte mode = packetWrapper.passthrough(Type.BYTE);
byte mode = wrapper.passthrough(Type.BYTE);
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
Scoreboard scoreboard = wrapper.user().get(Scoreboard.class);
if (mode != 0 && !scoreboard.teamExists(team)) {
packetWrapper.cancel();
wrapper.cancel();
return;
} else if (mode == 0 && scoreboard.teamExists(team)) {
scoreboard.removeTeam(team);
PacketWrapper remove = PacketWrapper.create(0x3E, null, packetWrapper.user());
PacketWrapper remove = PacketWrapper.create(0x3E, null, wrapper.user());
remove.write(Type.STRING, team);
remove.write(Type.BYTE, (byte) 1);
PacketUtil.sendPacket(remove, Protocol1_7_6_10To1_8.class, true, true);
remove.send(Protocol1_7_6_10To1_8.class);
}
if (mode == 0) {
@@ -204,55 +197,54 @@ public class ScoreboardPackets {
}
if (mode == 0 || mode == 2) {
packetWrapper.passthrough(Type.STRING); // Display name
packetWrapper.passthrough(Type.STRING); // prefix
packetWrapper.passthrough(Type.STRING); // suffix
packetWrapper.passthrough(Type.BYTE); // friendly fire
packetWrapper.read(Type.STRING); // name tag visibility
byte color = packetWrapper.read(Type.BYTE);
wrapper.passthrough(Type.STRING); // Display name
wrapper.passthrough(Type.STRING); // prefix
wrapper.passthrough(Type.STRING); // suffix
wrapper.passthrough(Type.BYTE); // friendly fire
wrapper.read(Type.STRING); // name tag visibility
byte color = wrapper.read(Type.BYTE);
if (mode == 2 && scoreboard.getTeamColor(team).get() != color) {
String username = packetWrapper.user().getProtocolInfo().getUsername();
String username = wrapper.user().getProtocolInfo().getUsername();
String sidebar = scoreboard.getColorDependentSidebar().get(color);
PacketWrapper sidebarPacket = packetWrapper.create(0x3D);
PacketWrapper sidebarPacket = wrapper.create(0x3D);
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, sidebar == null ? "" : sidebar);
PacketUtil.sendPacket(sidebarPacket, Protocol1_7_6_10To1_8.class);
sidebarPacket.scheduleSend(Protocol1_7_6_10To1_8.class);
}
scoreboard.setTeamColor(team, color);
}
if (mode == 0 || mode == 3 || mode == 4) {
byte color = scoreboard.getTeamColor(team).get();
String[] entries = packetWrapper.read(Type.STRING_ARRAY);
String[] entries = wrapper.read(Type.STRING_ARRAY);
List<String> entryList = new ArrayList<>();
for (int i = 0; i < entries.length; i++) {
String entry = entries[i];
String username = packetWrapper.user().getProtocolInfo().getUsername();
for (String entry : entries) {
String username = wrapper.user().getProtocolInfo().getUsername();
if (mode == 4) {
if (!scoreboard.isPlayerInTeam(entry, team)) continue;
scoreboard.removePlayerFromTeam(entry, team);
if (entry.equals(username)) {
PacketWrapper sidebarPacket = packetWrapper.create(0x3D);
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, scoreboard.getColorIndependentSidebar() == null ? "" : scoreboard.getColorIndependentSidebar());
PacketUtil.sendPacket(sidebarPacket, Protocol1_7_6_10To1_8.class);
}
} else {
scoreboard.addPlayerToTeam(entry, team);
if (entry.equals(username) && scoreboard.getColorDependentSidebar().containsKey(color)) {
PacketWrapper displayObjective = packetWrapper.create(0x3D);
displayObjective.write(Type.BYTE, (byte) 1);
displayObjective.write(Type.STRING, scoreboard.getColorDependentSidebar().get(color));
PacketUtil.sendPacket(displayObjective, Protocol1_7_6_10To1_8.class);
}
}
entryList.add(entry);
}
if (mode == 4) {
if (!scoreboard.isPlayerInTeam(entry, team)) continue;
scoreboard.removePlayerFromTeam(entry, team);
if (entry.equals(username)) {
PacketWrapper sidebarPacket = wrapper.create(0x3D);
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, scoreboard.getColorIndependentSidebar() == null ? "" : scoreboard.getColorIndependentSidebar());
sidebarPacket.scheduleSend(Protocol1_7_6_10To1_8.class);
}
} else {
scoreboard.addPlayerToTeam(entry, team);
if (entry.equals(username) && scoreboard.getColorDependentSidebar().containsKey(color)) {
PacketWrapper displayObjective = wrapper.create(0x3D);
displayObjective.write(Type.BYTE, (byte) 1);
displayObjective.write(Type.STRING, scoreboard.getColorDependentSidebar().get(color));
displayObjective.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
entryList.add(entry);
}
packetWrapper.write(Type.SHORT, (short) entryList.size());
wrapper.write(Type.SHORT, (short) entryList.size());
for (String entry : entryList) {
packetWrapper.write(Type.STRING, entry);
wrapper.write(Type.STRING, entry);
}
}
});
@@ -1,301 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
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_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.List;
import java.util.UUID;
public class SpawnPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
handler(wrapper -> {
final UUID uuid = wrapper.read(Type.UUID);
wrapper.write(Type.STRING, uuid.toString()); // map to string
final GameProfileStorage gameProfileStorage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) {
wrapper.write(Type.STRING, ""); // name
wrapper.write(Type.VAR_INT, 0); // properties count
} else {
wrapper.write(Type.STRING, gameProfile.name.length() > 16 ? gameProfile.name.substring(0, 16) : gameProfile.name); // name
wrapper.write(Type.VAR_INT, gameProfile.properties.size()); // properties count
for (GameProfileStorage.Property property : gameProfile.properties) {
wrapper.write(Type.STRING, property.name); // property name
wrapper.write(Type.STRING, property.value); // property value
wrapper.write(Type.STRING, property.signature == null ? "" : property.signature); // property signature
}
}
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (gameProfile != null && gameProfile.gamemode == 3) { // Spectator mode
for (short i = 0; i < 5; i++) {
final PacketWrapper entityEquipment = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, wrapper.user());
entityEquipment.write(Type.INT, entityId);
entityEquipment.write(Type.SHORT, i);
entityEquipment.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, i == 4 ? gameProfile.getSkull() : null);
entityEquipment.scheduleSend(Protocol1_7_6_10To1_8.class, true);
}
}
tracker.addPlayer(entityId, uuid);
});
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // item in hand id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final List<Metadata> metadata = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
protocol.getMetadataRewriter().transform(EntityTypes1_10.EntityType.PLAYER, metadata);
wrapper.set(Types1_7_6_10.METADATA_LIST, 0, metadata);
});
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.PLAYER);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // pitch
map(Type.BYTE); // yaw
map(Type.INT); // data
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(wrapper.get(Type.BYTE, 0), true);
final int entityId = wrapper.get(Type.VAR_INT, 0);
int x = wrapper.get(Type.INT, 0);
int y = wrapper.get(Type.INT, 1);
int z = wrapper.get(Type.INT, 2);
byte pitch = wrapper.get(Type.BYTE, 1);
byte yaw = wrapper.get(Type.BYTE, 2);
int data = wrapper.get(Type.INT, 3);
if (type == EntityTypes1_10.ObjectType.ITEM_FRAME.getType()) {
switch (yaw) {
case -128:
z += 32;
yaw = 0;
break;
case -64:
x -= 32;
yaw = -64;
break;
case 0:
z -= 32;
yaw = -128;
break;
case 64:
x += 32;
yaw = 64;
break;
}
} else if (type == EntityTypes1_10.ObjectType.ARMOR_STAND.getType()) {
wrapper.cancel();
final VirtualHologramEntity hologram = new VirtualHologramEntity(wrapper.user(), protocol.getMetadataRewriter(), entityId);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(yaw * 360f / 256);
tracker.trackHologram(entityId, hologram);
}
// TODO | Realign all entities
wrapper.set(Type.INT, 0, x);
wrapper.set(Type.INT, 1, y);
wrapper.set(Type.INT, 2, z);
wrapper.set(Type.BYTE, 2, yaw);
tracker.addEntity(entityId, type);
if (type != null && type.isOrHasParent(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
final Replacement replace = protocol.getItemRewriter().replace(blockId, blockData);
if (replace != null) {
blockId = replace.getId();
blockData = replace.replaceData(blockData);
}
wrapper.set(Type.INT, 3, data = (blockId | blockData << 16));
}
if (data > 0) {
wrapper.passthrough(Type.SHORT); // velocity x
wrapper.passthrough(Type.SHORT); // velocity y
wrapper.passthrough(Type.SHORT); // velocity z
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.UNSIGNED_BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.BYTE); // head yaw
map(Type.SHORT); // velocity x
map(Type.SHORT); // velocity y
map(Type.SHORT); // velocity z
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final short typeId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (typeId == 255 || typeId == -1) {
wrapper.cancel();
}
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(typeId, false);
final int entityId = wrapper.get(Type.VAR_INT, 0);
final int x = wrapper.get(Type.INT, 0);
final int y = wrapper.get(Type.INT, 1);
final int z = wrapper.get(Type.INT, 2);
final byte pitch = wrapper.get(Type.BYTE, 1);
final byte yaw = wrapper.get(Type.BYTE, 0);
final byte headYaw = wrapper.get(Type.BYTE, 2);
final List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
if (type == EntityTypes1_10.EntityType.ARMOR_STAND) {
final VirtualHologramEntity hologram = new VirtualHologramEntity(wrapper.user(), protocol.getMetadataRewriter(), entityId);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(headYaw * 360f / 256);
tracker.trackHologram(entityId, hologram);
tracker.updateMetadata(entityId, metadataList); // Track and remap hologram <-> zombie metadata
wrapper.cancel();
} else {
protocol.getMetadataRewriter().transform(type, metadataList);
tracker.addEntity(entityId, type);
if (tracker.isReplaced(type)) {
final int newTypeId = tracker.replaceEntity(entityId, type);
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) newTypeId);
tracker.updateMetadata(entityId, metadataList);
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.STRING); // title
handler(wrapper -> {
final Position position = wrapper.read(Type.POSITION1_8);
wrapper.write(Type.INT, position.x());
wrapper.write(Type.INT, position.y());
wrapper.write(Type.INT, position.z());
});
map(Type.UNSIGNED_BYTE, Type.INT); // rotation
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.PAINTING);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_EXPERIENCE_ORB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.SHORT); // count
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.EXPERIENCE_ORB);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_GLOBAL_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.LIGHTNING);
});
}
});
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,21 +15,17 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.WorldBorderEmulator;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk.ChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk.BulkChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.ParticleIndex1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.chunk.ChunkType1_7_6;
import com.viaversion.viarewind.api.type.chunk.BulkChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.data.ParticleIndex1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
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.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
@@ -39,29 +35,33 @@ import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.util.ChatColorUtil;
import com.viaversion.viaversion.util.IdAndData;
public class WorldPackets {
private static void rewriteBlockIds(final Protocol1_7_6_10To1_8 protocol, final Chunk chunk) {
for (ChunkSection section : chunk.getSections()) {
if (section == null) continue;
final DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < palette.size(); i++) {
palette.setIdByIndex(i, protocol.getItemRewriter().replace(palette.idByIndex(i)));
}
}
}
public class WorldPackets1_8 {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.CHUNK_DATA, wrapper -> {
final ClientWorld world = wrapper.user().get(ClientWorld.class);
final Chunk chunk = wrapper.read(ChunkType1_8.forEnvironment(world.getEnvironment()));
rewriteBlockIds(protocol, chunk);
protocol.getItemRewriter().handleChunk(chunk);
wrapper.write(ChunkType1_7_6.TYPE, chunk);
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_CHANGE, new PacketHandlers() {
@Override
protected void register() {
map(Type.POSITION1_8, Types1_7_6_10.U_BYTE_POSITION); // position
handler(wrapper -> {
int data = wrapper.read(Type.VAR_INT); // block data
data = protocol.getItemRewriter().handleBlockId(data);
wrapper.write(Type.VAR_INT, IdAndData.getId(data)); // block id
wrapper.write(Type.UNSIGNED_BYTE, (short) IdAndData.getData(data)); // block data
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.MULTI_BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
@@ -76,26 +76,12 @@ public class WorldPackets {
for (BlockChangeRecord record : records) {
wrapper.write(Type.SHORT, (short) (record.getSectionX() << 12 | record.getSectionZ() << 8 | record.getY())); // position
wrapper.write(Type.SHORT, (short) protocol.getItemRewriter().replace(record.getBlockId())); // block id
wrapper.write(Type.SHORT, (short) protocol.getItemRewriter().handleBlockId(record.getBlockId())); // block id
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_CHANGE, new PacketHandlers() {
@Override
protected void register() {
map(Type.POSITION1_8, Types1_7_6_10.U_BYTE_POSITION); // position
handler(wrapper -> {
int data = wrapper.read(Type.VAR_INT); // block data
data = protocol.getItemRewriter().replace(data);
wrapper.write(Type.VAR_INT, data >> 4); // block id
wrapper.write(Type.UNSIGNED_BYTE, (short) (data & 0xF)); // block data
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ACTION, new PacketHandlers() {
@Override
public void register() {
@@ -118,7 +104,7 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.MAP_BULK_CHUNK, wrapper -> {
final Chunk[] chunks = wrapper.read(BulkChunkType1_8.TYPE);
for (Chunk chunk : chunks) {
rewriteBlockIds(protocol, chunk);
protocol.getItemRewriter().handleChunk(chunk);
}
wrapper.write(BulkChunkType1_7_6.TYPE, chunks);
@@ -164,7 +150,8 @@ public class WorldPackets {
if (id >= 256 && id <= 422 || id >= 2256 && id <= 2267) { //item
particle = ParticleIndex1_7_6_10.ICON_CRACK;
} else if (id >= 0 && id <= 164 || id >= 170 && id <= 175) {
if (particle == ParticleIndex1_7_6_10.ICON_CRACK) particle = ParticleIndex1_7_6_10.BLOCK_CRACK;
if (particle == ParticleIndex1_7_6_10.ICON_CRACK)
particle = ParticleIndex1_7_6_10.BLOCK_CRACK;
} else {
wrapper.cancel();
return;
@@ -184,7 +171,7 @@ public class WorldPackets {
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
String line = wrapper.read(Type.STRING);
line = ChatUtil.jsonToLegacy(line);
line = ChatUtil.jsonToLegacy(wrapper.user(), line);
line = ChatUtil.removeUnusedColor(line, '0');
if (line.length() > 15) {
@@ -262,7 +249,7 @@ public class WorldPackets {
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_DATA, wrapper.user());
mapData.write(Type.VAR_INT, id); // map id
mapData.write(Type.SHORT, (short) 2); // data length
mapData.write(new FixedByteArrayType(2), new byte[]{ 2, scale }); // data
mapData.write(new FixedByteArrayType(2), new byte[]{2, scale}); // data
mapData.send(Protocol1_7_6_10To1_8.class, true);
});
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.provider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.CompressionStatusTracker;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.provider;
import com.viaversion.viaversion.api.platform.providers.Provider;
@@ -1,3 +1,20 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viaversion.api.type.Type;
@@ -1,3 +1,20 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viaversion.api.type.Type;
@@ -1,3 +1,20 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viarewind.api.netty.EmptyChannelHandler;
@@ -9,8 +26,8 @@ import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
public class TrackingCompressionHandlerProvider extends CompressionHandlerProvider {
public final static String COMPRESS_HANDLER_NAME = "compress";
public final static String DECOMPRESS_HANDLER_NAME = "decompress";
public static final String COMPRESS_HANDLER_NAME = "compress";
public static final String DECOMPRESS_HANDLER_NAME = "decompress";
@Override
public void onHandleLoginCompressionPacket(UserConnection user, int threshold) {
@@ -1,115 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_7_6_10to1_8.rewriter;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.MetaIndex1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
@SuppressWarnings({"deprecation"})
public class MetadataRewriter {
private final Protocol1_7_6_10To1_8 protocol;
public MetadataRewriter(Protocol1_7_6_10To1_8 protocol) {
this.protocol = protocol;
}
public void transform(EntityTypes1_10.EntityType type, List<Metadata> list) {
for (Metadata entry : new ArrayList<>(list)) {
final MetaIndex1_7_6_10To1_8 metaIndex = MetaIndex1_7_6_10To1_8.searchIndex(type, entry.id());
try {
if (metaIndex == null) {
ViaRewind.getPlatform().getLogger().warning("Could not find 1.8 metadata for " + type + " with index " + entry.id());
list.remove(entry);
continue;
}
if (metaIndex.getOldType() == MetaType1_7_6_10.NonExistent) {
list.remove(entry);
continue;
}
final Object value = entry.getValue();
entry.setTypeAndValue(metaIndex.getNewType(), value);
entry.setMetaTypeUnsafe(metaIndex.getOldType());
entry.setId(metaIndex.getIndex());
switch (metaIndex.getOldType()) {
case Int:
if (metaIndex.getNewType() == MetaType1_8.Byte) {
entry.setValue(((Byte) value).intValue());
if (metaIndex == MetaIndex1_7_6_10To1_8.ENTITY_AGEABLE_AGE) {
if ((Integer) entry.getValue() < 0) {
entry.setValue(-25000);
}
}
}
if (metaIndex.getNewType() == MetaType1_8.Short) {
entry.setValue(((Short) value).intValue());
}
if (metaIndex.getNewType() == MetaType1_8.Int) {
entry.setValue(value);
}
break;
case Byte:
if (metaIndex.getNewType() == MetaType1_8.Int) {
entry.setValue(((Integer) value).byteValue());
}
if (metaIndex.getNewType() == MetaType1_8.Byte) {
if (metaIndex == MetaIndex1_7_6_10To1_8.ITEM_FRAME_ROTATION) {
entry.setValue(Integer.valueOf((Byte) value % 4).byteValue());
} else {
entry.setValue(value);
}
}
if (metaIndex == MetaIndex1_7_6_10To1_8.HUMAN_SKIN_FLAGS) {
byte flags = (byte) value;
boolean cape = (flags & 0x01) != 0;
flags = (byte) (cape ? 0x00 : 0x02);
entry.setValue(flags);
}
break;
case Slot:
entry.setValue(protocol.getItemRewriter().handleItemToClient((Item) value));
break;
case Float:
case String:
case Short:
case Position:
break;
default:
ViaRewind.getPlatform().getLogger().warning("Could not transform metadata for " + type + " with index " + entry.id() + " and type " + metaIndex.getOldType());
list.remove(entry);
break;
}
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Unable to transform metadata", e);
list.remove(entry);
}
}
}
}
@@ -1,230 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_7_6_10to1_8.rewriter;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import java.util.ArrayList;
import java.util.List;
public class ReplacementItemRewriter1_7_6_10 extends ReplacementItemRewriter<Protocol1_7_6_10To1_8> {
private final static String VIA_REWIND_TAG_KEY = "ViaRewind1_7_6_10to1_8";
public ReplacementItemRewriter1_7_6_10(Protocol1_7_6_10To1_8 protocol) {
super(protocol, ProtocolVersion.v1_8);
}
@Override
public void register() {
registerBlock(176, new Replacement(63));
registerBlock(177, new Replacement(68));
registerBlock(193, new Replacement(64));
registerBlock(194, new Replacement(64));
registerBlock(195, new Replacement(64));
registerBlock(196, new Replacement(64));
registerBlock(197, new Replacement(64));
registerBlock(77, 5, new Replacement(69, 6));
registerBlock(77, 13, new Replacement(69, 14));
registerBlock(77, 0, new Replacement(69, 0));
registerBlock(77, 8, new Replacement(69, 8));
registerBlock(143, 5, new Replacement(69, 6));
registerBlock(143, 13, new Replacement(69, 14));
registerBlock(143, 0, new Replacement(69, 0));
registerBlock(143, 8, new Replacement(69, 8));
registerBlock(178, new Replacement(151));
registerBlock(182, 0, new Replacement(44, 1));
registerBlock(182, 8, new Replacement(44, 9));
registerItem(425, new Replacement(323, "Banner"));
registerItem(409, new Replacement(406, "Prismarine Shard"));
registerItem(410, new Replacement(406, "Prismarine Crystal"));
registerItem(416, new Replacement(280, "Armor Stand"));
registerItem(423, new Replacement(363, "Raw Mutton"));
registerItem(424, new Replacement(364, "Cooked Mutton"));
registerItem(411, new Replacement(365, "Raw Rabbit"));
registerItem(412, new Replacement(366, "Cooked Rabbit"));
registerItem(413, new Replacement(282, "Rabbit Stew"));
registerItem(414, new Replacement(375, "Rabbit's Foot"));
registerItem(415, new Replacement(334, "Rabbit Hide"));
registerItem(373, 8203, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 8235, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 8267, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 16395, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(373, 16427, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(373, 16459, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(383, 30, new Replacement(383, "Spawn ArmorStand"));
registerItem(383, 67, new Replacement(383, "Spawn Endermite"));
registerItem(383, 68, new Replacement(383, "Spawn Guardian"));
registerItem(383, 101, new Replacement(383, "Spawn Rabbit"));
registerItem(19, 1, new Replacement(19, 0, "Wet Sponge"));
registerItem(182, new Replacement(44, 1, "Red Sandstone Slab"));
registerItemBlock(166, new Replacement(20, "Barrier"));
registerItemBlock(167, new Replacement(96, "Iron Trapdoor"));
registerItemBlock(1, 1, new Replacement(1, 0, "Granite"));
registerItemBlock(1, 2, new Replacement(1, 0, "Polished Granite"));
registerItemBlock(1, 3, new Replacement(1, 0, "Diorite"));
registerItemBlock(1, 4, new Replacement(1, 0, "Polished Diorite"));
registerItemBlock(1, 5, new Replacement(1, 0, "Andesite"));
registerItemBlock(1, 6, new Replacement(1, 0, "Polished Andesite"));
registerItemBlock(168, 0, new Replacement(1, 0, "Prismarine"));
registerItemBlock(168, 1, new Replacement(98, 0, "Prismarine Bricks"));
registerItemBlock(168, 2, new Replacement(98, 1, "Dark Prismarine"));
registerItemBlock(169, new Replacement(89, "Sea Lantern"));
registerItemBlock(165, new Replacement(95, 5, "Slime Block"));
registerItemBlock(179, 0, new Replacement(24, "Red Sandstone"));
registerItemBlock(179, 1, new Replacement(24, "Chiseled Red Sandstone"));
registerItemBlock(179, 2, new Replacement(24, "Smooth Sandstone"));
registerItemBlock(181, new Replacement(43, 1, "Double Red Sandstone Slab"));
registerItemBlock(180, new Replacement(128, "Red Sandstone Stairs"));
registerItemBlock(188, new Replacement(85, "Spruce Fence"));
registerItemBlock(189, new Replacement(85, "Birch Fence"));
registerItemBlock(190, new Replacement(85, "Jungle Fence"));
registerItemBlock(191, new Replacement(85, "Dark Oak Fence"));
registerItemBlock(192, new Replacement(85, "Acacia Fence"));
registerItemBlock(183, new Replacement(107, "Spruce Fence Gate"));
registerItemBlock(184, new Replacement(107, "Birch Fence Gate"));
registerItemBlock(185, new Replacement(107, "Jungle Fence Gate"));
registerItemBlock(186, new Replacement(107, "Dark Oak Fence Gate"));
registerItemBlock(187, new Replacement(107, "Acacia Fence Gate"));
registerItemBlock(427, new Replacement(324, "Spruce Door"));
registerItemBlock(428, new Replacement(324, "Birch Door"));
registerItemBlock(429, new Replacement(324, "Jungle Door"));
registerItemBlock(430, new Replacement(324, "Dark Oak Door"));
registerItemBlock(431, new Replacement(324, "Acacia Door"));
registerItemBlock(157, new Replacement(28, "Activator Rail"));
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
CompoundTag viaRewindTag = new CompoundTag();
tag.put(VIA_REWIND_TAG_KEY, viaRewindTag);
viaRewindTag.put("id", new ShortTag((short) item.identifier()));
viaRewindTag.put("data", new ShortTag(item.data()));
CompoundTag display = tag.get("display");
if (display != null && display.contains("Name")) {
viaRewindTag.put("displayName", new StringTag((String) display.get("Name").getValue()));
}
if (display != null && display.contains("Lore")) {
viaRewindTag.put("lore", new ListTag(((ListTag) display.get("Lore")).getValue()));
}
if (tag.contains("ench") || tag.contains("StoredEnchantments")) {
ListTag enchTag = tag.contains("ench") ? tag.get("ench") : tag.get("StoredEnchantments");
List<Tag> lore = new ArrayList<>();
for (Tag ench : new ArrayList<>(enchTag.getValue())) {
short id = ((NumberTag) ((CompoundTag) ench).get("id")).asShort();
short lvl = ((NumberTag) ((CompoundTag) ench).get("lvl")).asShort();
String s;
if (id == 8) {
s = "§r§7Depth Strider ";
} else {
continue;
}
enchTag.remove(ench);
s += Enchantments.ENCHANTMENTS.getOrDefault(lvl, "enchantment.level." + lvl);
lore.add(new StringTag(s));
}
if (!lore.isEmpty()) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaRewindTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
lore.addAll(loreTag.getValue());
loreTag.setValue(lore);
}
}
if (item.identifier() == 387 && tag.contains("pages")) {
ListTag pages = tag.get("pages");
ListTag oldPages = new ListTag(StringTag.class);
viaRewindTag.put("pages", oldPages);
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
oldPages.add(new StringTag(value));
value = ChatUtil.jsonToLegacy(value);
page.setValue(value);
}
}
replace(item);
if (viaRewindTag.size() == 2 && (short) viaRewindTag.get("id").getValue() == item.identifier() && (short) viaRewindTag.get("data").getValue() == item.data()) {
item.tag().remove(VIA_REWIND_TAG_KEY);
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null || !item.tag().contains(VIA_REWIND_TAG_KEY)) return item;
CompoundTag viaVersionTag = tag.remove(VIA_REWIND_TAG_KEY);
item.setIdentifier((short) viaVersionTag.get("id").getValue());
item.setData((Short) viaVersionTag.get("data").getValue());
if (viaVersionTag.contains("noDisplay")) tag.remove("display");
if (viaVersionTag.contains("displayName")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
StringTag name = display.get("Name");
if (name == null) display.put("Name", new StringTag((String) viaVersionTag.get("displayName").getValue()));
else name.setValue((String) viaVersionTag.get("displayName").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Name");
}
if (item.identifier() == 387) {
ListTag oldPages = viaVersionTag.get("pages");
tag.remove("pages");
tag.put("pages", oldPages);
}
return item;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
@@ -1,174 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.ReplacementEntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.MetadataRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
public class EntityTracker1_7_6_10 extends ReplacementEntityTracker {
protected final MetadataRewriter metadataRewriter;
private final Map<Integer, Integer> vehicleMap = new ConcurrentHashMap<>();
private final Map<Integer, VirtualHologramEntity> virtualHologramMap = new HashMap<>();
private final Map<Integer, UUID> playersByEntityId = new HashMap<>();
private final Map<UUID, Integer> playersByUniqueId = new HashMap<>();
public int spectatingPlayerId = -1;
public EntityTracker1_7_6_10(UserConnection user, final MetadataRewriter metadataRewriter) {
super(user, ProtocolVersion.v1_8);
this.metadataRewriter = metadataRewriter;
registerEntity(EntityTypes1_10.EntityType.GUARDIAN, EntityTypes1_10.EntityType.SQUID, "Guardian");
registerEntity(EntityTypes1_10.EntityType.ENDERMITE, EntityTypes1_10.EntityType.SQUID, "Endermite");
registerEntity(EntityTypes1_10.EntityType.RABBIT, EntityTypes1_10.EntityType.CHICKEN, "Rabbit");
}
public void trackHologram(final int entityId, final VirtualHologramEntity hologram) {
addEntity(entityId, EntityTypes1_10.EntityType.ARMOR_STAND);
getEntityReplacementMap().put(entityId, EntityTypes1_10.EntityType.ARMOR_STAND);
virtualHologramMap.put(entityId, hologram);
}
@Override
public void updateMetadata(int entityId, List<Metadata> metadata) throws Exception {
if (virtualHologramMap.containsKey(entityId)) {
virtualHologramMap.get(entityId).updateMetadata(metadata);
return;
}
super.updateMetadata(entityId, metadata);
}
@Override
public void removeEntity(int entityId) {
super.removeEntity(entityId);
if (playersByEntityId.containsKey(entityId)) {
final UUID playerId = playersByEntityId.remove(entityId);
playersByUniqueId.remove(playerId);
getUser().get(PlayerSessionStorage.class).getPlayerEquipment().remove(playerId);
}
}
@Override
public void clear() {
super.clear();
vehicleMap.clear();
}
@Override
public void setClientEntityId(int entityId) {
if (this.spectatingPlayerId == this.getPlayerId()) {
this.spectatingPlayerId = entityId;
}
super.setClientEntityId(entityId);
}
public void addPlayer(final Integer entityId, final UUID uuid) {
playersByUniqueId.put(uuid, entityId);
playersByEntityId.put(entityId, uuid);
}
public UUID getPlayerUUID(final int entityId) {
return playersByEntityId.get(entityId);
}
public int getPlayerEntityId(final UUID uuid) {
return playersByUniqueId.getOrDefault(uuid, -1);
}
public int getVehicle(final int passengerId) {
for (Map.Entry<Integer, Integer> vehicle : vehicleMap.entrySet()) {
if (vehicle.getValue() == passengerId) {
return vehicle.getValue();
}
}
return -1;
}
public int getPassenger(int vehicleId) {
return vehicleMap.getOrDefault(vehicleId, -1);
}
protected void startSneaking() {
try {
final PacketWrapper entityAction = PacketWrapper.create(ServerboundPackets1_7_2_5.ENTITY_ACTION, getUser());
entityAction.write(Type.VAR_INT, this.getPlayerId()); // entity id
entityAction.write(Type.VAR_INT, 0); // action id, start sneaking
entityAction.write(Type.VAR_INT, 0); // jump boost
entityAction.sendToServer(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send sneak packet", e);
}
}
public void setPassenger(int vehicleId, int passengerId) {
if (vehicleId == this.spectatingPlayerId && this.spectatingPlayerId != this.getPlayerId()) {
startSneaking();
setSpectating(this.getPlayerId());
}
if (vehicleId == -1) {
vehicleMap.remove(getVehicle(passengerId));
} else if (passengerId == -1) {
vehicleMap.remove(vehicleId);
} else {
vehicleMap.put(vehicleId, passengerId);
}
}
protected void attachEntity(final int target) {
try {
final PacketWrapper attachEntity = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, getUser());
attachEntity.write(Type.INT, this.getPlayerId()); // vehicle id
attachEntity.write(Type.INT, target); // passenger id
attachEntity.write(Type.BOOLEAN, false); // leash
attachEntity.scheduleSend(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send attach packet", e);
}
}
public void setSpectating(int spectating) {
if (spectating != this.getPlayerId() && getPassenger(spectating) != -1) {
startSneaking();
setSpectating(this.getPlayerId());
return;
}
if (this.spectatingPlayerId != spectating && this.spectatingPlayerId != this.getPlayerId()) {
attachEntity(-1);
}
this.spectatingPlayerId = spectating;
if (spectating != this.getPlayerId()) {
attachEntity(this.spectatingPlayerId);
}
}
public Map<Integer, VirtualHologramEntity> getVirtualHologramMap() {
return virtualHologramMap;
}
}
@@ -0,0 +1,183 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.emulation.VirtualHologramEntity;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntArrayMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectArrayMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntOpenHashMap;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
public class EntityTracker1_8 extends EntityTrackerBase {
private final Int2ObjectMap<VirtualHologramEntity> holograms = new Int2ObjectArrayMap<>();
private final Int2IntMap vehicles = new Int2IntArrayMap();
private final Int2ObjectMap<UUID> entityIdToUUID = new Int2ObjectArrayMap<>();
private final Object2IntMap<UUID> entityUUIDToId = new Object2IntOpenHashMap<>();
public int spectatingClientEntityId = -1;
private int clientEntityGameMode;
public EntityTracker1_8(UserConnection connection) {
super(connection, EntityTypes1_10.EntityType.ENTITY_HUMAN);
}
@Override
public void addEntity(int id, EntityType type) {
super.addEntity(id, type);
if (type == EntityTypes1_10.EntityType.ARMOR_STAND) {
holograms.put(id, new VirtualHologramEntity(user(), id));
}
}
@Override
public void removeEntity(int entityId) {
super.removeEntity(entityId);
if (entityIdToUUID.containsKey(entityId)) {
final UUID playerId = entityIdToUUID.remove(entityId);
entityUUIDToId.removeInt(playerId);
user().get(PlayerSessionStorage.class).getPlayerEquipment().remove(playerId);
}
}
@Override
public void clearEntities() {
super.clearEntities();
vehicles.clear();
}
@Override
public void setClientEntityId(int entityId) {
if (this.spectatingClientEntityId == this.clientEntityId()) {
this.spectatingClientEntityId = entityId;
}
super.setClientEntityId(entityId);
}
public void addPlayer(final int entityId, final UUID uuid) {
entityUUIDToId.put(uuid, entityId);
entityIdToUUID.put(entityId, uuid);
}
public UUID getPlayerUUID(final int entityId) {
return entityIdToUUID.get(entityId);
}
public int getPlayerEntityId(final UUID uuid) {
return entityUUIDToId.getOrDefault(uuid, -1);
}
public int getVehicle(final int passengerId) {
for (Map.Entry<Integer, Integer> vehicle : vehicles.entrySet()) {
if (vehicle.getValue() == passengerId) {
return vehicle.getValue();
}
}
return -1;
}
public int getPassenger(int vehicleId) {
return vehicles.getOrDefault(vehicleId, -1);
}
protected void startSneaking() {
try {
final PacketWrapper entityAction = PacketWrapper.create(ServerboundPackets1_7_2_5.ENTITY_ACTION, user());
entityAction.write(Type.VAR_INT, this.clientEntityId()); // Entity id
entityAction.write(Type.VAR_INT, 0); // Action id
entityAction.write(Type.VAR_INT, 0); // Jump boost
entityAction.sendToServer(Protocol1_7_6_10To1_8.class);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send sneak packet", e);
}
}
public void setPassenger(final int vehicleId, final int passengerId) {
if (vehicleId == this.spectatingClientEntityId && this.spectatingClientEntityId != this.clientEntityId()) {
startSneaking();
setSpectating(this.clientEntityId());
}
if (vehicleId == -1) {
vehicles.remove(getVehicle(passengerId));
} else if (passengerId == -1) {
vehicles.remove(vehicleId);
} else {
vehicles.put(vehicleId, passengerId);
}
}
protected void attachEntity(final int target) {
try {
final PacketWrapper attachEntity = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, user());
attachEntity.write(Type.INT, this.clientEntityId()); // vehicle id
attachEntity.write(Type.INT, target); // passenger id
attachEntity.write(Type.BOOLEAN, false); // leash
attachEntity.scheduleSend(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send attach packet", e);
}
}
public void setSpectating(int spectating) {
if (spectating != this.clientEntityId() && getPassenger(spectating) != -1) {
startSneaking();
setSpectating(this.clientEntityId());
return;
}
if (this.spectatingClientEntityId != spectating && this.spectatingClientEntityId != this.clientEntityId()) {
attachEntity(-1);
}
this.spectatingClientEntityId = spectating;
if (spectating != this.clientEntityId()) {
attachEntity(this.spectatingClientEntityId);
}
}
public Int2ObjectMap<VirtualHologramEntity> getHolograms() {
return holograms;
}
public boolean isSpectator() {
return clientEntityGameMode == 3;
}
public void setClientEntityGameMode(int clientEntityGameMode) {
this.clientEntityGameMode = clientEntityGameMode;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.utils.ChatUtil;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,20 +15,16 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.FurnaceData;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class InventoryTracker extends StoredObject {
public final static Map<String, Integer> WINDOW_TYPE_REGISTRY = new HashMap<>();
public static final Map<String, Integer> WINDOW_TYPE_REGISTRY = new HashMap<>();
static {
WINDOW_TYPE_REGISTRY.put("minecraft:container", 0);
@@ -76,4 +72,13 @@ public class InventoryTracker extends StoredObject {
public HashMap<Short, FurnaceData> getFurnaceData() {
return furnaceData;
}
public static class FurnaceData {
public short fuelLeft = 0;
public short maxFuel = 0;
public short progress = 0;
public short maxProgress = 200;
}
}
@@ -1,3 +1,20 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
@@ -10,9 +27,6 @@ import java.util.UUID;
public class PlayerSessionStorage extends StoredObject {
// Player info
public int gameMode;
// Player abilities
public boolean sprinting, allowFly, flying, invincible, creative;
public float flySpeed, walkSpeed;
@@ -77,10 +91,6 @@ public class PlayerSessionStorage extends StoredObject {
items[slot] = equipment;
}
public boolean isSpectator() {
return gameMode == 3;
}
public Map<UUID, Item[]> getPlayerEquipment() {
return playerEquipment;
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,12 +15,10 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -112,7 +110,7 @@ public class Scoreboard extends StoredObject {
return objectives.contains(name);
}
public String sendTeamForScore(String score) {
public String sendTeamForScore(String score) throws Exception {
if (score.length() <= 16) return score;
if (scoreTeams.containsKey(score)) return scoreTeams.get(score).name;
int l = 16;
@@ -143,12 +141,12 @@ public class Scoreboard extends StoredObject {
teamPacket.write(Type.BYTE, (byte) 0);
teamPacket.write(Type.SHORT, (short) 1);
teamPacket.write(Type.STRING, name);
PacketUtil.sendPacket(teamPacket, Protocol1_7_6_10To1_8.class, true, true);
teamPacket.send(Protocol1_7_6_10To1_8.class);
return name;
}
public String removeTeamForScore(String score) {
public String removeTeamForScore(String score) throws Exception {
ScoreTeam scoreTeam = scoreTeams.remove(score);
if (scoreTeam == null) return score;
scoreTeamNames.remove(scoreTeam.name);
@@ -156,7 +154,7 @@ public class Scoreboard extends StoredObject {
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.TEAMS, getUser());
teamPacket.write(Type.STRING, scoreTeam.name);
teamPacket.write(Type.BYTE, (byte) 1);
PacketUtil.sendPacket(teamPacket, Protocol1_7_6_10To1_8.class, true, true);
teamPacket.send(Protocol1_7_6_10To1_8.class);
return scoreTeam.name;
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
* 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.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
@@ -1,3 +1,20 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.task;
import com.viaversion.viarewind.ViaRewind;
@@ -13,7 +30,7 @@ import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.logging.Level;
public class WorldBorderUpdateTask implements Runnable {
public final static int VIEW_DISTANCE = 16;
public static final int VIEW_DISTANCE = 16;
@Override
public void run() {
@@ -1,60 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_7_6_10to1_8.types;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.CompressedNBTType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.ItemArrayType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.ItemType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.NBTType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetadataListType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetadataType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive.ByteIntArrayType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive.PositionUYType;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import java.util.List;
public class Types1_7_6_10 {
// Primitives
public final static Type<int[]> BYTE_INT_ARRAY = new ByteIntArrayType(); // Integer array with byte as length indicator
// Positions /shrug
public final static Type<Position> SHORT_POSITION = new PositionUYType<>(Type.SHORT, value -> (short) value);
public final static Type<Position> INT_POSITION = new PositionUYType<>(Type.INT, value -> value);
public final static Type<Position> BYTE_POSITION = new PositionUYType<>(Type.BYTE, value -> (byte) value);
public final static Type<Position> U_BYTE_POSITION = new PositionUYType<>(Type.UNSIGNED_BYTE, value -> (short) value);
// Uncompressed Items
public final static Type<CompoundTag> NBT = new NBTType();
public final static Type<Item> ITEM = new ItemType(false);
// Compressed Items
public final static Type<CompoundTag> COMPRESSED_NBT = new CompressedNBTType();
public final static Type<Item> COMPRESSED_NBT_ITEM = new ItemType(true);
public final static Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType(true);
// Metadata
public final static Type<Metadata> METADATA = new MetadataType();
public final static Type<List<Metadata>> METADATA_LIST = new MetadataListType();
}
@@ -1,72 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.NBTIO;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import java.io.*;
public class NBTType extends Type<CompoundTag> {
public NBTType() {
super(CompoundTag.class);
}
@Override
public CompoundTag read(ByteBuf buffer) {
short length = buffer.readShort();
if (length < 0) {
return null;
}
ByteBufInputStream byteBufInputStream = new ByteBufInputStream(buffer);
DataInputStream dataInputStream = new DataInputStream(byteBufInputStream);
try {
return NBTIO.readTag((DataInput) dataInputStream);
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Override
public void write(ByteBuf buffer, CompoundTag nbt) throws Exception {
if (nbt == null) {
buffer.writeShort(-1);
} else {
ByteBuf buf = buffer.alloc().buffer();
ByteBufOutputStream byteBufStream = new ByteBufOutputStream(buf);
DataOutputStream dataOutputStream = new DataOutputStream(byteBufStream);
NBTIO.writeTag((DataOutput) dataOutputStream, nbt);
dataOutputStream.close();
buffer.writeShort(buf.readableBytes());
buffer.writeBytes(buf);
buf.release();
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,17 +15,18 @@
* 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.viarewind.protocol.protocol1_8to1_9;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.rewriter.ReplacementItemRewriter1_8;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.data.RewindMappings;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata.MetadataRewriter1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.packets.*;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.utils.Ticker;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.task.CooldownIndicatorTask;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.task.LevitationUpdateTask;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.type.Type;
@@ -35,40 +36,27 @@ import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, ClientboundPackets1_8, ServerboundPackets1_9, ServerboundPackets1_8> {
private final ReplacementItemRewriter<Protocol1_8To1_9> itemRewriter = new ReplacementItemRewriter1_8(this);
private final MetadataRewriter metadataRewriter = new MetadataRewriter(this);
public class Protocol1_8To1_9 extends BackwardsProtocol<ClientboundPackets1_9, ClientboundPackets1_8, ServerboundPackets1_9, ServerboundPackets1_8> {
public Queue<PacketWrapper> animationsToSend = new ConcurrentLinkedQueue<>();
public final static Set<String> VALID_ATTRIBUTES = new HashSet<>();
public final static ValueTransformer<Double, Integer> TO_OLD_INT = new ValueTransformer<Double, Integer>(Type.INT) {
public static final ValueTransformer<Double, Integer> DOUBLE_TO_INT_TIMES_32 = new ValueTransformer<Double, Integer>(Type.INT) {
@Override
public Integer transform(PacketWrapper wrapper, Double inputValue) {
return (int) (inputValue * 32.0D);
}
};
public final static ValueTransformer<Float, Byte> DEGREES_TO_ANGLE = new ValueTransformer<Float, Byte>(Type.BYTE) {
public static final ValueTransformer<Float, Byte> DEGREES_TO_ANGLE = new ValueTransformer<Float, Byte>(Type.BYTE) {
@Override
public Byte transform(PacketWrapper packetWrapper, Float degrees) throws Exception {
public Byte transform(PacketWrapper packetWrapper, Float degrees) {
return (byte) ((degrees / 360F) * 256);
}
};
static {
VALID_ATTRIBUTES.add("generic.maxHealth");
VALID_ATTRIBUTES.add("generic.followRange");
VALID_ATTRIBUTES.add("generic.knockbackResistance");
VALID_ATTRIBUTES.add("generic.movementSpeed");
VALID_ATTRIBUTES.add("generic.attackDamage");
VALID_ATTRIBUTES.add("horse.jumpStrength");
VALID_ATTRIBUTES.add("zombie.spawnReinforcements");
}
public static final RewindMappings MAPPINGS = new RewindMappings();
private final BlockItemPackets1_9 itemRewriter = new BlockItemPackets1_9(this);
private final MetadataRewriter1_8To1_9 metadataRewriter = new MetadataRewriter1_8To1_9(this);
public Protocol1_8To1_9() {
super(ClientboundPackets1_9.class, ClientboundPackets1_8.class, ServerboundPackets1_9.class, ServerboundPackets1_8.class);
@@ -76,36 +64,53 @@ public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, Cl
@Override
protected void registerPackets() {
metadataRewriter.register();
itemRewriter.register();
EntityPackets.register(this);
InventoryPackets.register(this);
PlayerPackets.register(this);
ScoreboardPackets.register(this);
SpawnPackets.register(this);
WorldPackets.register(this);
EntityPackets1_9.register(this);
PlayerPackets1_9.register(this);
WorldPackets1_9.register(this);
}
@Override
public void init(UserConnection userConnection) {
Ticker.init();
public void init(UserConnection connection) {
connection.addEntityTracker(this.getClass(), new EntityTracker1_9(connection));
userConnection.put(new Windows(userConnection));
userConnection.put(new EntityTracker(userConnection, this));
userConnection.put(new Levitation(userConnection));
userConnection.put(new PlayerPosition(userConnection));
userConnection.put(new Cooldown(userConnection));
userConnection.put(new BlockPlaceDestroyTracker(userConnection));
userConnection.put(new BossBarStorage(userConnection));
userConnection.put(new ClientWorld(userConnection));
connection.put(new WindowTracker(connection));
connection.put(new LevitationStorage());
connection.put(new PlayerPositionTracker());
connection.put(new CooldownStorage());
connection.put(new BlockPlaceDestroyTracker());
connection.put(new BossBarStorage(connection));
if (!connection.has(ClientWorld.class)) {
connection.put(new ClientWorld());
}
}
@Override
public ReplacementItemRewriter<Protocol1_8To1_9> getItemRewriter() {
public void register(ViaProviders providers) {
Via.getManager().getScheduler().scheduleRepeating(new LevitationUpdateTask(), 0L, 50L, TimeUnit.MILLISECONDS);
Via.getManager().getScheduler().scheduleRepeating(new CooldownIndicatorTask(), 0L, 50L, TimeUnit.MILLISECONDS);
}
@Override
public RewindMappings getMappingData() {
return MAPPINGS;
}
@Override
public BlockItemPackets1_9 getItemRewriter() {
return itemRewriter;
}
public MetadataRewriter getMetadataRewriter() {
@Override
public MetadataRewriter1_8To1_9 getEntityRewriter() {
return metadataRewriter;
}
@Override
public boolean hasMappingDataToLoad() {
return true;
}
}
@@ -1,13 +0,0 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
public class DisabledCooldownVisualization implements CooldownVisualization {
@Override
public void show(double progress) {
}
@Override
public void hide() {
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,17 +15,13 @@
* 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.viarewind.protocol.protocol1_8to1_9.sound;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.data;
import java.util.HashMap;
public class Effect {
private final static HashMap<Integer, Integer> effects = new HashMap<>();
public class EffectMappings {
public static int getOldId(int id) {
return effects.getOrDefault(id, id);
}
private static final HashMap<Integer, Integer> effects = new HashMap<>();
static {
effects.put(1003, 1002);
@@ -66,4 +62,8 @@ public class Effect {
effects.put(3000, -1);
effects.put(3001, -1);
}
public static int getOldId(int id) {
return effects.getOrDefault(id, id);
}
}
@@ -1,13 +1,31 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.rewriter;
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.data;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
import java.util.HashMap;
import java.util.Map;
// TODO | Check if this is correct???
public class PotionMappings {
public final static Map<String, String> POTION_NAME_INDEX = new HashMap<>();
public final static Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
public static final Map<String, String> POTION_NAME_INDEX = new HashMap<>();
public static final Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
static {
POTION_NAME_TO_ID.putAll(ItemRewriter.POTION_NAME_TO_ID);
@@ -0,0 +1,48 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.data;
import com.viaversion.viarewind.api.data.VRMappingDataLoader;
import com.viaversion.viaversion.libs.fastutil.objects.ObjectArrayList;
import com.viaversion.viaversion.libs.fastutil.objects.ObjectList;
import com.viaversion.viaversion.libs.gson.JsonArray;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
public final class RewindMappings extends com.viaversion.viarewind.api.data.RewindMappings {
private final ObjectList<String> sounds = new ObjectArrayList<>();
public RewindMappings() {
super("1.9.4", "1.8");
}
@Override
protected void loadExtras(CompoundTag data) {
super.loadExtras(data);
final JsonArray sounds = VRMappingDataLoader.INSTANCE.loadData("sounds-1.9.4.json").getAsJsonArray("sounds");
for (final JsonElement sound : sounds) {
this.sounds.add(sound.getAsString());
}
}
public String soundName(final int soundId) {
return sounds.get(soundId);
}
}
@@ -1,4 +1,21 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -1,4 +1,21 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -1,4 +1,21 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.ViaRewindConfig.CooldownIndicator;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,9 +15,16 @@
* 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.viarewind.protocol.protocol1_8to1_9.emulation;
package com.viaversion.viarewind.utils;
public class DisabledCooldownVisualization implements CooldownVisualization {
@Override
public void show(double progress) {
public interface Tickable {
void tick();
}
@Override
public void hide() {
}
}
@@ -1,4 +1,21 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,9 +15,9 @@
* 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.viarewind.protocol.protocol1_8to1_9.emulation;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.bossbar;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.legacy.bossbar.BossBar;
@@ -29,9 +29,9 @@ import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viarewind.utils.PacketUtil;
import java.util.*;
import java.util.logging.Level;
public class WitherBossBar implements BossBar {
private static int highestId = Integer.MAX_VALUE - 10000;
@@ -61,7 +61,13 @@ public class WitherBossBar implements BossBar {
@Override
public BossBar setTitle(String title) {
this.title = title;
if (this.visible) updateMetadata();
if (this.visible) {
try {
updateMetadata();
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to update wither boss bar title", e);
}
}
return this;
}
@@ -73,8 +79,16 @@ public class WitherBossBar implements BossBar {
@Override
public BossBar setHealth(float health) {
this.health = health;
if (this.health <= 0) this.health = 0.0001f;
if (this.visible) updateMetadata();
if (this.health <= 0) {
this.health = 0.0001f;
}
if (this.visible) {
try {
updateMetadata();
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to update wither boss bar health", e);
}
}
return this;
}
@@ -147,7 +161,11 @@ public class WitherBossBar implements BossBar {
public BossBar show() {
if (!this.visible) {
this.visible = true;
spawnWither();
try {
spawnWither();
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to spawn wither boss bar", e);
}
}
return this;
}
@@ -156,7 +174,11 @@ public class WitherBossBar implements BossBar {
public BossBar hide() {
if (this.visible) {
this.visible = false;
despawnWither();
try {
despawnWither();
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to despawn wither boss bar", e);
}
}
return this;
}
@@ -171,26 +193,26 @@ public class WitherBossBar implements BossBar {
return this.uuid;
}
public void setLocation(double x, double y, double z) {
public void setLocation(double x, double y, double z) throws Exception {
locX = x;
locY = y;
locZ = z;
updateLocation();
}
private void spawnWither() {
PacketWrapper packetWrapper = PacketWrapper.create(0x0F, null, this.connection);
packetWrapper.write(Type.VAR_INT, entityId);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) 64);
packetWrapper.write(Type.INT, (int) (locX * 32d));
packetWrapper.write(Type.INT, (int) (locY * 32d));
packetWrapper.write(Type.INT, (int) (locZ * 32d));
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.SHORT, (short) 0);
packetWrapper.write(Type.SHORT, (short) 0);
packetWrapper.write(Type.SHORT, (short) 0);
private void spawnWither() throws Exception {
PacketWrapper wrapper = PacketWrapper.create(0x0F, null, this.connection);
wrapper.write(Type.VAR_INT, entityId);
wrapper.write(Type.UNSIGNED_BYTE, (short) 64);
wrapper.write(Type.INT, (int) (locX * 32d));
wrapper.write(Type.INT, (int) (locY * 32d));
wrapper.write(Type.INT, (int) (locZ * 32d));
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.SHORT, (short) 0);
wrapper.write(Type.SHORT, (short) 0);
wrapper.write(Type.SHORT, (short) 0);
List<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(0, MetaType1_8.Byte, (byte) 0x20));
@@ -198,45 +220,45 @@ public class WitherBossBar implements BossBar {
metadata.add(new Metadata(3, MetaType1_8.Byte, (byte) 1));
metadata.add(new Metadata(6, MetaType1_8.Float, health * 300f));
packetWrapper.write(Types1_8.METADATA_LIST, metadata);
wrapper.write(Types1_8.METADATA_LIST, metadata);
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
wrapper.scheduleSend(Protocol1_8To1_9.class);
}
private void updateLocation() {
PacketWrapper packetWrapper = PacketWrapper.create(0x18, null, this.connection);
packetWrapper.write(Type.VAR_INT, entityId);
packetWrapper.write(Type.INT, (int) (locX * 32d));
packetWrapper.write(Type.INT, (int) (locY * 32d));
packetWrapper.write(Type.INT, (int) (locZ * 32d));
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BOOLEAN, false);
private void updateLocation() throws Exception {
PacketWrapper wrapper = PacketWrapper.create(0x18, null, this.connection);
wrapper.write(Type.VAR_INT, entityId);
wrapper.write(Type.INT, (int) (locX * 32d));
wrapper.write(Type.INT, (int) (locY * 32d));
wrapper.write(Type.INT, (int) (locZ * 32d));
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
wrapper.scheduleSend(Protocol1_8To1_9.class);
}
private void updateMetadata() {
PacketWrapper packetWrapper = PacketWrapper.create(0x1C, null, this.connection);
packetWrapper.write(Type.VAR_INT, entityId);
private void updateMetadata() throws Exception {
PacketWrapper wrapper = PacketWrapper.create(0x1C, null, this.connection);
wrapper.write(Type.VAR_INT, entityId);
List<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(2, MetaType1_8.String, title));
metadata.add(new Metadata(6, MetaType1_8.Float, health * 300f));
packetWrapper.write(Types1_8.METADATA_LIST, metadata);
wrapper.write(Types1_8.METADATA_LIST, metadata);
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
wrapper.scheduleSend(Protocol1_8To1_9.class);
}
private void despawnWither() {
PacketWrapper packetWrapper = PacketWrapper.create(0x13, null, this.connection);
packetWrapper.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
private void despawnWither() throws Exception {
PacketWrapper wrapper = PacketWrapper.create(0x13, null, this.connection);
wrapper.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
wrapper.scheduleSend(Protocol1_8To1_9.class);
}
public void setPlayerLocation(double posX, double posY, double posZ, float yaw, float pitch) {
public void setPlayerLocation(double posX, double posY, double posZ, float yaw, float pitch) throws Exception {
double yawR = Math.toRadians(yaw);
double pitchR = Math.toRadians(pitch);
@@ -1,98 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.entityreplacement;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public abstract class EntityModel1_8To1_9 extends EntityModel<Protocol1_8To1_9> {
public EntityModel1_8To1_9(UserConnection user, Protocol1_8To1_9 protocol) {
super(user, protocol);
}
protected void sendTeleportWithHead(int entityId, double locX, double locY, double locZ, float yaw, float pitch, float headYaw) {
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
sendHeadYaw(entityId, headYaw);
}
protected void teleportEntity(int entityId, double locX, double locY, double locZ, float yaw, float pitch) {
PacketWrapper teleport = PacketWrapper.create(ClientboundPackets1_8.ENTITY_TELEPORT, null, user);
teleport.write(Type.VAR_INT, entityId);
teleport.write(Type.INT, (int) (locX * 32.0));
teleport.write(Type.INT, (int) (locY * 32.0));
teleport.write(Type.INT, (int) (locZ * 32.0));
teleport.write(Type.BYTE, (byte) ((yaw / 360f) * 256));
teleport.write(Type.BYTE, (byte) ((pitch / 360f) * 256));
teleport.write(Type.BOOLEAN, true);
PacketUtil.sendPacket(teleport, Protocol1_8To1_9.class, true, true);
}
protected void sendHeadYaw(int entityId, float headYaw) {
PacketWrapper head = PacketWrapper.create(ClientboundPackets1_8.ENTITY_HEAD_LOOK, null, user);
head.write(Type.VAR_INT, entityId);
head.write(Type.BYTE, (byte) ((headYaw / 360f) * 256));
PacketUtil.sendPacket(head, Protocol1_8To1_9.class, true, true);
}
protected void sendSpawn(int entityId, int type) {
PacketWrapper spawn = PacketWrapper.create(ClientboundPackets1_8.SPAWN_MOB, null, user);
spawn.write(Type.VAR_INT, entityId);
spawn.write(Type.UNSIGNED_BYTE, (short) type);
spawn.write(Type.INT, 0);
spawn.write(Type.INT, 0);
spawn.write(Type.INT, 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.SHORT, (short) 0);
spawn.write(Type.SHORT, (short) 0);
spawn.write(Type.SHORT, (short) 0);
List<Metadata> list = new ArrayList<>();
spawn.write(Types1_8.METADATA_LIST, list);
PacketUtil.sendPacket(spawn, Protocol1_8To1_9.class, true, true);
}
protected void sendSpawnEntity(int entityId, int type) {
PacketWrapper spawn = PacketWrapper.create(ClientboundPackets1_8.SPAWN_ENTITY, null, user);
spawn.write(Type.VAR_INT, entityId);
spawn.write(Type.BYTE, (byte) type);
spawn.write(Type.INT, 0);
spawn.write(Type.INT, 0);
spawn.write(Type.INT, 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.INT, 0);
PacketUtil.sendPacket(spawn, Protocol1_8To1_9.class, true, true);
}
}
@@ -1,103 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.entityreplacement;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public class ShulkerBulletModel extends EntityModel1_8To1_9 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
private float yaw, pitch;
private float headYaw;
public ShulkerBulletModel(UserConnection user, Protocol1_8To1_9 protocol, int entityId) {
super(user, protocol);
this.entityId = entityId;
sendSpawnPacket();
}
@Override
public void updateReplacementPosition(double x, double y, double z) {
if (x != this.locX || y != this.locY || z != this.locZ) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
}
@Override
public void handleOriginalMovementPacket(double x, double y, double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) return;
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
@Override
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw && this.pitch != pitch) {
this.yaw = yaw;
this.pitch = pitch;
updateLocation();
}
}
@Override
public void setHeadYaw(float yaw) {
this.headYaw = yaw;
}
@Override
public void updateMetadata(List<Metadata> metadataList) {
}
public void updateLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
@Override
public void sendSpawnPacket() {
sendSpawnEntity(entityId, 66);
}
@Override
public void deleteEntity() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_8.DESTROY_ENTITIES, null, user);
despawn.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_8To1_9.class, true, true);
}
@Override
public int getEntityId() {
return this.entityId;
}
}
@@ -1,120 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.entityreplacement;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_9;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public class ShulkerModel extends EntityModel1_8To1_9 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
public ShulkerModel(UserConnection user, Protocol1_8To1_9 protocol, int entityId) {
super(user, protocol);
this.entityId = entityId;
sendSpawnPacket();
}
@Override
public void updateReplacementPosition(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
@Override
public void handleOriginalMovementPacket(double x, double y, double z) {
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
@Override
public void setYawPitch(float yaw, float pitch) {
}
@Override
public void setHeadYaw(float yaw) {
}
@Override
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateMetadata();
}
public void updateLocation() {
teleportEntity(entityId, locX, locY, locZ, 0, 0);
}
public void updateMetadata() {
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_METADATA, null, user);
metadataPacket.write(Type.VAR_INT, entityId);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
if (metadata.id() == 11 || metadata.id() == 12 || metadata.id() == 13) continue;
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
metadataList.add(new Metadata(11, MetaType1_9.VarInt, 2));
getProtocol().getMetadataRewriter().transform(EntityTypes1_10.EntityType.MAGMA_CUBE, metadataList);
metadataPacket.write(Types1_8.METADATA_LIST, metadataList);
PacketUtil.sendPacket(metadataPacket, Protocol1_8To1_9.class);
}
@Override
public void sendSpawnPacket() {
sendSpawn(entityId, 62);
// Old clients don't like empty metadata
}
@Override
public void deleteEntity() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.DESTROY_ENTITIES, null, user);
despawn.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_8To1_9.class, true, true);
}
@Override
public int getEntityId() {
return this.entityId;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,9 +15,9 @@
* 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.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetaIndex;
import com.viaversion.viaversion.util.Pair;
@@ -27,34 +27,32 @@ import java.util.Optional;
public class MetaIndex1_8to1_9 {
private final static HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
private static final HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
static {
for (MetaIndex index : MetaIndex.values())
for (MetaIndex index : MetaIndex.values()) {
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
}
private static Optional<MetaIndex> getIndex(EntityTypes1_10.EntityType type, int index) {
Pair<EntityTypes1_10.EntityType, Integer> pair = new Pair<>(type, index);
private static Optional<MetaIndex> getIndex(final EntityType type, final int index) {
final Pair<EntityType, Integer> pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
} else {
return Optional.empty();
}
return Optional.empty();
}
public static MetaIndex searchIndex(EntityTypes1_10.EntityType type, int index) {
EntityTypes1_10.EntityType currentType = type;
public static MetaIndex searchIndex(final EntityType type, final int index) {
EntityType currentType = type;
do {
Optional<MetaIndex> optMeta = getIndex(currentType, index);
final Optional<MetaIndex> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
}
currentType = currentType.getParent();
} while (currentType != null);
return null;
}
}
@@ -1,130 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.minecraft.EulerAngle;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetaIndex;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MetadataRewriter {
private final Protocol1_8To1_9 protocol;
public MetadataRewriter(Protocol1_8To1_9 protocol) {
this.protocol = protocol;
}
public void transform(EntityTypes1_10.EntityType type, List<Metadata> list) {
for (Metadata entry : new ArrayList<>(list)) {
MetaIndex metaIndex = MetaIndex1_8to1_9.searchIndex(type, entry.id());
try {
if (metaIndex != null) {
if (metaIndex.getOldType() == MetaType1_8.NonExistent || metaIndex.getNewType() == null) {
list.remove(entry);
continue;
}
Object value = entry.getValue();
entry.setMetaTypeUnsafe(metaIndex.getOldType());
entry.setId(metaIndex.getIndex());
switch (metaIndex.getNewType()) {
case Byte:
if (metaIndex.getOldType() == MetaType1_8.Byte) {
entry.setValue(value);
}
if (metaIndex.getOldType() == MetaType1_8.Int) {
entry.setValue(((Byte) value).intValue());
}
break;
case OptUUID:
if (metaIndex.getOldType() != MetaType1_8.String) {
list.remove(entry);
break;
}
UUID owner = (UUID) value;
if (owner == null) entry.setValue("");
else entry.setValue(owner.toString());
break;
case BlockID:
list.remove(entry);
list.add(new Metadata(metaIndex.getIndex(), MetaType1_8.Short, ((Integer) value).shortValue()));
break;
case VarInt:
if (metaIndex.getOldType() == MetaType1_8.Byte) {
entry.setValue(((Integer) value).byteValue());
}
if (metaIndex.getOldType() == MetaType1_8.Short) {
entry.setValue(((Integer) value).shortValue());
}
if (metaIndex.getOldType() == MetaType1_8.Int) {
entry.setValue(value);
}
break;
case Float:
entry.setValue(value);
break;
case String:
entry.setValue(value);
break;
case Boolean:
if (metaIndex == MetaIndex.AGEABLE_AGE) entry.setValue((byte) ((Boolean) value ? -1 : 0));
else entry.setValue((byte) ((Boolean) value ? 1 : 0));
break;
case Slot:
entry.setValue(protocol.getItemRewriter().handleItemToClient((Item) value));
break;
case Position:
Vector vector = (Vector) value;
entry.setValue(vector);
break;
case Vector3F:
EulerAngle angle = (EulerAngle) value;
entry.setValue(angle);
break;
case Chat:
entry.setValue(value);
break;
default:
ViaRewind.getPlatform().getLogger().warning("[Out] Unhandled MetaDataType: " + metaIndex.getNewType());
list.remove(entry);
break;
}
if (!metaIndex.getOldType().type().getOutputClass().isAssignableFrom(entry.getValue().getClass())) {
list.remove(entry);
}
} else {
throw new Exception("Could not find valid metadata");
}
} catch (Exception e) {
list.remove(entry);
}
}
}
}
@@ -0,0 +1,338 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.VREntityRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker1_9;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.EulerAngle;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
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_8;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetaIndex;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent;
import com.viaversion.viaversion.util.IdAndData;
import java.util.UUID;
import java.util.logging.Level;
public class MetadataRewriter1_8To1_9 extends VREntityRewriter<ClientboundPackets1_9, Protocol1_8To1_9> {
private static final byte HAND_ACTIVE_BIT = 0;
private static final byte STATUS_USE_BIT = 4;
public MetadataRewriter1_8To1_9(Protocol1_8To1_9 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
registerJoinGame1_8(ClientboundPackets1_9.JOIN_GAME);
registerRemoveEntities(ClientboundPackets1_9.DESTROY_ENTITIES);
registerMetadataRewriter(ClientboundPackets1_9.ENTITY_METADATA, Types1_9.METADATA_LIST, Types1_8.METADATA_LIST);
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
read(Type.UUID); // Entity UUID
map(Type.BYTE); // Entity type
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.BYTE); // Pitch
map(Type.BYTE); // Yaw
map(Type.INT); // Data
// Track entity
handler(getObjectTrackerHandler());
handler(getObjectRewriter(id -> EntityTypes1_10.ObjectType.findById(id).orElse(null)));
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final int entityType = wrapper.get(Type.BYTE, 0);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(entityType, true);
// Cancel new entities which can't be handled properly
if (type == EntityTypes1_10.EntityType.AREA_EFFECT_CLOUD || type == EntityTypes1_10.EntityType.SPECTRAL_ARROW || type == EntityTypes1_10.EntityType.DRAGON_FIREBALL) {
wrapper.cancel();
return;
}
if (type.is(EntityTypes1_10.EntityType.BOAT)) {
byte yaw = wrapper.get(Type.BYTE, 1);
yaw -= 64;
wrapper.set(Type.BYTE, 1, yaw);
int y = wrapper.get(Type.INT, 1);
y += 10;
wrapper.set(Type.INT, 1, y);
}
int data = wrapper.get(Type.INT, 3);
if (type.isOrHasParent(EntityTypes1_10.EntityType.ARROW) && data != 0) {
wrapper.set(Type.INT, 3, --data);
}
if (type.is(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
IdAndData replace = protocol.getItemRewriter().handleBlock(blockId, blockData);
if (replace != null) {
wrapper.set(Type.INT, 3, replace.getId() | replace.getData() << 12);
}
}
if (data > 0) {
wrapper.passthrough(Type.SHORT); // Velocity x
wrapper.passthrough(Type.SHORT); // Velocity y
wrapper.passthrough(Type.SHORT); // Velocity z
} else {
final short velocityX = wrapper.read(Type.SHORT);
final short velocityY = wrapper.read(Type.SHORT);
final short velocityZ = wrapper.read(Type.SHORT);
final PacketWrapper velocityPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_VELOCITY, wrapper.user());
velocityPacket.write(Type.VAR_INT, entityId);
velocityPacket.write(Type.SHORT, velocityX);
velocityPacket.write(Type.SHORT, velocityY);
velocityPacket.write(Type.SHORT, velocityZ);
velocityPacket.scheduleSend(Protocol1_8To1_9.class);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_EXPERIENCE_ORB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.SHORT); // Count
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
wrapper.user().getEntityTracker(Protocol1_8To1_9.class).addEntity(entityId, EntityTypes1_10.EntityType.EXPERIENCE_ORB);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_GLOBAL_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.BYTE); // Type
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
wrapper.user().getEntityTracker(Protocol1_8To1_9.class).addEntity(entityId, EntityTypes1_10.EntityType.LIGHTNING);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
read(Type.UUID); // Entity UUID
map(Type.UNSIGNED_BYTE); // Entity type
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
map(Type.BYTE); // Head pitch
map(Type.SHORT); // Velocity x
map(Type.SHORT); // Velocity y
map(Type.SHORT); // Velocity z
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST); // Metadata
handler(getTrackerHandler(Type.UNSIGNED_BYTE, 0));
handler(getMobSpawnRewriter(Types1_8.METADATA_LIST));
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
read(Type.UUID); // Entity UUID
map(Type.STRING); // Title
map(Type.POSITION1_8); // Position
map(Type.BYTE, Type.UNSIGNED_BYTE); // Direction
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
wrapper.user().getEntityTracker(Protocol1_8To1_9.class).addEntity(entityId, EntityTypes1_10.EntityType.PAINTING);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.UUID); // Player UUID
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
create(Type.SHORT, (short) 0); // Current item
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST); // Metadata
handler(getTrackerAndMetaHandler(Types1_8.METADATA_LIST, EntityTypes1_10.EntityType.PLAYER));
}
});
}
@Override
protected void registerRewrites() {
// Handle new entities
mapEntityTypeWithData(EntityType.SHULKER, EntityType.MAGMA_CUBE).plainName();
mapEntityTypeWithData(EntityType.SHULKER_BULLET, EntityType.WITCH).plainName();
// Metadata rewrite
filter().handler((event, meta) -> {
try {
handleMetadata(event, meta);
} catch (Exception e) {
if (Via.getManager().isDebug()) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "An error occurred with entity metadata: " + meta, e);
}
event.cancel();
}
});
}
private void handleMetadata(MetaHandlerEvent event, Metadata metadata) {
final EntityTracker1_9 tracker = tracker(event.user());
if (metadata.id() == MetaIndex.ENTITY_STATUS.getIndex()) {
tracker.getStatus().put(event.entityId(), (Byte) metadata.value());
}
final MetaIndex metaIndex = MetaIndex1_8to1_9.searchIndex(event.entityType(), metadata.id());
if (metaIndex == null) {
// Almost certainly bad data, remove it
event.cancel();
return;
}
if (metaIndex.getOldType() == null || metaIndex.getNewType() == null) {
if (metaIndex == MetaIndex.PLAYER_HAND) { // Player eating/aiming/drinking
int status = tracker.getStatus().getOrDefault(event.entityId(), 0);
if ((((byte) metadata.value()) & 1 << HAND_ACTIVE_BIT) != 0) {
status = (byte) (status | 1 << STATUS_USE_BIT);
} else {
status = (byte) (status & ~(1 << STATUS_USE_BIT));
}
event.createExtraMeta(new Metadata(MetaIndex.ENTITY_STATUS.getIndex(), MetaType1_8.Byte, status));
return;
}
event.cancel();
return;
}
metadata.setId(metaIndex.getIndex());
metadata.setMetaTypeUnsafe(metaIndex.getOldType());
final Object value = metadata.getValue();
switch (metaIndex.getNewType()) {
case Byte:
if (metaIndex.getOldType() == MetaType1_8.Byte) {
metadata.setValue(value);
}
if (metaIndex.getOldType() == MetaType1_8.Int) {
metadata.setValue(((Byte) value).intValue());
}
break;
case OptUUID:
if (metaIndex.getOldType() != MetaType1_8.String) {
event.cancel();
break;
}
final UUID owner = (UUID) value;
metadata.setValue(owner != null ? owner.toString() : "");
break;
case BlockID:
event.cancel();
event.createExtraMeta(new Metadata(metaIndex.getIndex(), MetaType1_8.Short, ((Integer) value).shortValue()));
break;
case VarInt:
if (metaIndex.getOldType() == MetaType1_8.Byte) {
metadata.setValue(((Integer) value).byteValue());
}
if (metaIndex.getOldType() == MetaType1_8.Short) {
metadata.setValue(((Integer) value).shortValue());
}
if (metaIndex.getOldType() == MetaType1_8.Int) {
metadata.setValue(value);
}
break;
case Float:
case String:
case Chat:
metadata.setValue(value);
break;
case Boolean:
final boolean bool = (Boolean) value;
if (metaIndex == MetaIndex.AGEABLE_CREATURE_AGE) {
metadata.setValue((byte) (bool ? -1 : 0));
} else {
metadata.setValue((byte) (bool ? 1 : 0));
}
break;
case Slot:
metadata.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), (Item) value));
break;
case Position:
final Vector vector = (Vector) value;
metadata.setValue(vector);
break;
case Vector3F:
final EulerAngle angle = (EulerAngle) value;
metadata.setValue(angle);
break;
default:
event.cancel();
break;
}
}
@Override
public EntityType typeFromId(int type) {
return EntityTypes1_10.getTypeFromId(type, false);
}
@Override
public EntityType objectTypeFromId(int type) {
return EntityTypes1_10.getTypeFromId(type, true);
}
}
@@ -0,0 +1,316 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
import com.viaversion.viarewind.api.rewriter.VRBlockItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.data.PotionMappings;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.WindowTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
import com.viaversion.viaversion.util.Key;
import java.util.HashSet;
import java.util.Set;
import static com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter.potionNameFromDamage;
public class BlockItemPackets1_9 extends VRBlockItemRewriter<ClientboundPackets1_9, ServerboundPackets1_8, Protocol1_8To1_9> {
public final Set<String> VALID_ATTRIBUTES = new HashSet<>();
private LegacyEnchantmentRewriter enchantmentRewriter;
public BlockItemPackets1_9(Protocol1_8To1_9 protocol) {
super(protocol, "1.9");
VALID_ATTRIBUTES.add("generic.maxHealth");
VALID_ATTRIBUTES.add("generic.followRange");
VALID_ATTRIBUTES.add("generic.knockbackResistance");
VALID_ATTRIBUTES.add("generic.movementSpeed");
VALID_ATTRIBUTES.add("generic.attackDamage");
VALID_ATTRIBUTES.add("horse.jumpStrength");
VALID_ATTRIBUTES.add("zombie.spawnReinforcements");
}
@Override
protected void registerPackets() {
registerBlockChange(ClientboundPackets1_9.BLOCK_CHANGE);
registerMultiBlockChange(ClientboundPackets1_9.MULTI_BLOCK_CHANGE);
registerCreativeInvAction(ServerboundPackets1_8.CREATIVE_INVENTORY_ACTION);
protocol.registerClientbound(ClientboundPackets1_9.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
wrapper.user().get(WindowTracker.class).remove(windowId);
});
protocol.registerClientbound(ClientboundPackets1_9.OPEN_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
final String windowType = wrapper.passthrough(Type.STRING);
final JsonElement windowTitle = wrapper.passthrough(Type.COMPONENT);
wrapper.user().get(WindowTracker.class).put(windowId, windowType);
// TODO check
if (windowType.equalsIgnoreCase("minecraft:shulker_box")) {
wrapper.set(Type.STRING, 0, "minecraft:container");
}
if (windowTitle.toString().equalsIgnoreCase("{\"translate\":\"container.shulkerBox\"}")) {
wrapper.set(Type.COMPONENT, 0, JsonParser.parseString("{\"text\":\"Shulker Box\"}"));
}
});
protocol.registerClientbound(ClientboundPackets1_9.WINDOW_ITEMS, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
Item[] items = wrapper.passthrough(Type.ITEM1_8_SHORT_ARRAY);
for (int i = 0; i < items.length; i++) {
items[i] = handleItemToClient(wrapper.user(), items[i]);
}
if (windowId == 0 && items.length == 46) {
Item[] old = items;
items = new Item[45];
System.arraycopy(old, 0, items, 0, 45);
} else {
final String type = wrapper.user().get(WindowTracker.class).get(windowId);
if (type != null && type.equalsIgnoreCase("minecraft:brewing_stand")) {
System.arraycopy(items, 0, wrapper.user().get(WindowTracker.class).getBrewingItems(windowId), 0, 4);
WindowTracker.updateBrewingStand(wrapper.user(), items[4], windowId);
Item[] old = items;
items = new Item[old.length - 1];
System.arraycopy(old, 0, items, 0, 4);
System.arraycopy(old, 5, items, 4, old.length - 5);
}
}
});
protocol.registerClientbound(ClientboundPackets1_9.SET_SLOT, wrapper -> {
final byte windowId = wrapper.passthrough(Type.UNSIGNED_BYTE).byteValue();
final short slot = wrapper.passthrough(Type.SHORT);
final Item item = wrapper.passthrough(Type.ITEM1_8);
handleItemToClient(wrapper.user(), item);
if (windowId == 0 && slot == 45) {
wrapper.cancel();
return;
}
final WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
final String windowType = windowTracker.get(windowId);
if (windowType != null && windowType.equalsIgnoreCase("minecraft:brewing_stand")) {
if (slot > 4) {
wrapper.set(Type.SHORT, 0, (short) (slot - 1));
} else if (slot == 4) {
wrapper.cancel();
WindowTracker.updateBrewingStand(wrapper.user(), wrapper.get(Type.ITEM1_8, 0), windowId);
} else {
windowTracker.getBrewingItems(windowId)[slot] = wrapper.get(Type.ITEM1_8, 0);
}
}
});
protocol.registerServerbound(ServerboundPackets1_8.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
wrapper.user().get(WindowTracker.class).remove(windowId);
});
protocol.registerServerbound(ServerboundPackets1_8.CLICK_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // Window id
map(Type.SHORT); // Slot
map(Type.BYTE); // Button
map(Type.SHORT); // Action number
map(Type.BYTE, Type.VAR_INT); // Mode
map(Type.ITEM1_8); // Clicked item
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Type.ITEM1_8, 0)));
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
final String windowType = wrapper.user().get(WindowTracker.class).get(windowId);
if (windowType != null && windowType.equalsIgnoreCase("minecraft:brewing_stand")) {
final short slot = wrapper.get(Type.SHORT, 0);
if (slot > 3) {
wrapper.set(Type.SHORT, 0, (short) (slot + 1));
}
}
});
}
});
}
@Override
protected void registerRewrites() {
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName());
enchantmentRewriter.registerEnchantment(9, "§7Frost Walker");
enchantmentRewriter.registerEnchantment(70, "§7Mending");
}
@Override
public Item handleItemToClient(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToClient(connection, item);
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
enchantmentRewriter.handleToClient(item);
CompoundTag displayTag = tag.get("display");
if (item.data() != 0 && tag.contains("Unbreakable")) {
final ByteTag unbreakableTag = tag.get("Unbreakable");
if (unbreakableTag != null && unbreakableTag.asByte() != 0) {
tag.put(nbtTagName() + "|Unbreakable", new ByteTag(unbreakableTag.asByte()));
tag.remove("Unbreakable");
if (displayTag == null) { // Remove the display tag again if it was only added to emulate unbreakable
tag.put("display", displayTag = new CompoundTag());
tag.put(nbtTagName() + "|noDisplay", new ByteTag());
}
ListTag<StringTag> loreTag = displayTag.getListTag("Lore", StringTag.class);
if (loreTag == null) {
displayTag.put("Lore", loreTag = new ListTag<>(StringTag.class));
}
loreTag.add(new StringTag("§9Unbreakable"));
}
}
if (item.identifier() == 383 && item.data() == 0) { // Spawn eggs
int data = 0;
final CompoundTag entityTag = tag.getCompoundTag("EntityTag");
if (entityTag != null) {
final StringTag idTag = entityTag.getStringTag("id");
if (idTag != null) {
final String id = idTag.getValue();
if (ItemRewriter.ENTITY_NAME_TO_ID.containsKey(id)) {
data = ItemRewriter.ENTITY_NAME_TO_ID.get(id);
} else if (displayTag == null) {
tag.put("display", displayTag = new CompoundTag());
tag.put(nbtTagName() + "|noDisplay", new ByteTag());
displayTag.put("Name", new StringTag("§rSpawn " + id));
}
}
}
item.setData((short) data);
}
// Potion, splash potion, lingering potion
final boolean potion = item.identifier() == 373;
final boolean splashPotion = item.identifier() == 438;
final boolean lingeringPotion = item.identifier() == 441;
if (potion || splashPotion || lingeringPotion) {
int data = 0;
final StringTag potionTag = tag.getStringTag("Potion");
if (potionTag != null) {
String potionName = Key.stripMinecraftNamespace(potionTag.getValue());
if (PotionMappings.POTION_NAME_TO_ID.containsKey(potionName)) {
data = PotionMappings.POTION_NAME_TO_ID.get(potionName);
}
if (splashPotion) {
potionName += "_splash";
} else if (lingeringPotion) {
potionName += "_lingering";
}
// Don't override custom name
if ((displayTag == null || !displayTag.contains("Name")) && PotionMappings.POTION_NAME_INDEX.containsKey(potionName)) {
tag.put("display", displayTag = new CompoundTag());
tag.put(nbtTagName() + "|noDisplay", new ByteTag());
displayTag.put("Name", new StringTag(PotionMappings.POTION_NAME_INDEX.get(potionName)));
}
}
if (splashPotion || lingeringPotion) { // Convert splash and lingering potions to normal potions
item.setIdentifier(373);
data += 8192;
}
item.setData((short) data);
}
final ListTag<CompoundTag> attributeModifiers = tag.getListTag("AttributeModifiers", CompoundTag.class);
if (attributeModifiers != null) {
tag.put(nbtTagName() + "|AttributeModifiers", attributeModifiers.copy());
attributeModifiers.getValue().removeIf(entries -> {
final StringTag nameTag = entries.getStringTag("AttributeName");
return nameTag != null && !VALID_ATTRIBUTES.contains(nameTag.getValue());
});
}
return item;
}
@Override
public Item handleItemToServer(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
enchantmentRewriter.handleToServer(item);
if (item.identifier() == 383 && item.data() != 0) { // Spawn eggs
if (!tag.contains("EntityTag") && ItemRewriter.ENTITY_ID_TO_NAME.containsKey((int) item.data())) {
final CompoundTag entityTag = new CompoundTag();
entityTag.put("id", new StringTag(ItemRewriter.ENTITY_ID_TO_NAME.get((int) item.data())));
tag.put("EntityTag", entityTag);
}
item.setData((short) 0);
}
if (item.identifier() == 373 && !tag.contains("Potion")) { // Potions
if (item.data() >= 16384) {
item.setIdentifier(438);
item.setData((short) (item.data() - 8192));
}
final String name = item.data() == 8192 ? "water" : potionNameFromDamage(item.data());
tag.put("Potion", new StringTag("minecraft:" + name));
item.setData((short) 0);
}
final Tag noDisplayTag = tag.remove(nbtTagName() + "|noDisplay");
if (noDisplayTag != null) {
tag.remove("display");
}
final Tag unbreakableTag = tag.remove(nbtTagName() + "|Unbreakable");
if (unbreakableTag != null) {
tag.put("Unbreakable", unbreakableTag);
}
final Tag attributeModifiersTag = tag.remove(nbtTagName() + "|AttributeModifiers");
if (attributeModifiersTag != null) {
tag.put("AttributeModifiers", attributeModifiersTag);
}
return item;
}
}
@@ -1,481 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.Cooldown;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.Levitation;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.PlayerPosition;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.util.RelativeMoveUtil;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
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_8;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class EntityPackets {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_STATUS, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
handler(packetWrapper -> {
byte status = packetWrapper.read(Type.BYTE);
if (status > 23) {
packetWrapper.cancel();
return;
}
packetWrapper.write(Type.BYTE, status);
});
}
});
//Entity Relative Move
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int relX = packetWrapper.read(Type.SHORT);
int relY = packetWrapper.read(Type.SHORT);
int relZ = packetWrapper.read(Type.SHORT);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
replacement.handleOriginalMovementPacket(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
return;
}
Vector[] moves = RelativeMoveUtil.calculateRelativeMoves(packetWrapper.user(), entityId, relX, relY, relZ);
packetWrapper.write(Type.BYTE, (byte) moves[0].blockX());
packetWrapper.write(Type.BYTE, (byte) moves[0].blockY());
packetWrapper.write(Type.BYTE, (byte) moves[0].blockZ());
boolean onGround = packetWrapper.passthrough(Type.BOOLEAN);
if (moves.length > 1) {
PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION, null, packetWrapper.user());
secondPacket.write(Type.VAR_INT, packetWrapper.get(Type.VAR_INT, 0));
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
secondPacket.write(Type.BYTE, (byte) moves[1].blockZ());
secondPacket.write(Type.BOOLEAN, onGround);
PacketUtil.sendPacket(secondPacket, Protocol1_8To1_9.class);
}
});
}
});
//Entity Relative Move And Look
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int relX = packetWrapper.read(Type.SHORT);
int relY = packetWrapper.read(Type.SHORT);
int relZ = packetWrapper.read(Type.SHORT);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
replacement.handleOriginalMovementPacket(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
replacement.setYawPitch(packetWrapper.read(Type.BYTE) * 360f / 256, packetWrapper.read(Type.BYTE) * 360f / 256);
return;
}
Vector[] moves = RelativeMoveUtil.calculateRelativeMoves(packetWrapper.user(), entityId, relX, relY, relZ);
packetWrapper.write(Type.BYTE, (byte) moves[0].blockX());
packetWrapper.write(Type.BYTE, (byte) moves[0].blockY());
packetWrapper.write(Type.BYTE, (byte) moves[0].blockZ());
byte yaw = packetWrapper.passthrough(Type.BYTE);
byte pitch = packetWrapper.passthrough(Type.BYTE);
boolean onGround = packetWrapper.passthrough(Type.BOOLEAN);
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
yaw -= 64;
packetWrapper.set(Type.BYTE, 3, yaw);
}
if (moves.length > 1) {
PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION_AND_ROTATION, null, packetWrapper.user());
secondPacket.write(Type.VAR_INT, packetWrapper.get(Type.VAR_INT, 0));
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
secondPacket.write(Type.BYTE, (byte) moves[1].blockZ());
secondPacket.write(Type.BYTE, yaw);
secondPacket.write(Type.BYTE, pitch);
secondPacket.write(Type.BOOLEAN, onGround);
PacketUtil.sendPacket(secondPacket, Protocol1_8To1_9.class);
}
});
}
});
//Entity Look
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BOOLEAN);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
int pitch = packetWrapper.get(Type.BYTE, 1);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = packetWrapper.get(Type.BYTE, 0);
yaw -= 64;
packetWrapper.set(Type.BYTE, 0, yaw);
}
});
}
});
//Entity
//Vehicle Move -> Entity Teleport
protocol.registerClientbound(ClientboundPackets1_9.VEHICLE_MOVE, ClientboundPackets1_8.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int vehicle = tracker.getVehicle(tracker.getPlayerId());
if (vehicle == -1) packetWrapper.cancel();
packetWrapper.write(Type.VAR_INT, vehicle);
});
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.FLOAT, Protocol1_8To1_9.DEGREES_TO_ANGLE);
map(Type.FLOAT, Protocol1_8To1_9.DEGREES_TO_ANGLE);
handler(packetWrapper -> {
if (packetWrapper.isCancelled()) return;
PlayerPosition position = packetWrapper.user().get(PlayerPosition.class);
double x = packetWrapper.get(Type.INT, 0) / 32d;
double y = packetWrapper.get(Type.INT, 1) / 32d;
double z = packetWrapper.get(Type.INT, 2) / 32d;
position.setPos(x, y, z);
});
create(Type.BOOLEAN, true);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = packetWrapper.get(Type.BYTE, 1);
yaw -= 64;
packetWrapper.set(Type.BYTE, 0, yaw);
int y = packetWrapper.get(Type.INT, 1);
y += 10;
packetWrapper.set(Type.INT, 1, y);
}
});
}
});
//Use Bed
//Destroy Entities
protocol.registerClientbound(ClientboundPackets1_9.DESTROY_ENTITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT_ARRAY_PRIMITIVE);
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
for (int entityId : packetWrapper.get(Type.VAR_INT_ARRAY_PRIMITIVE, 0))
tracker.removeEntity(entityId);
});
}
});
//Remove Entity Effect
protocol.registerClientbound(ClientboundPackets1_9.REMOVE_ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
handler(packetWrapper -> {
int id = packetWrapper.get(Type.BYTE, 0);
if (id > 23) packetWrapper.cancel();
if (id == 25) {
if (packetWrapper.get(Type.VAR_INT, 0) != packetWrapper.user().get(EntityTracker.class).getPlayerId())
return;
Levitation levitation = packetWrapper.user().get(Levitation.class);
levitation.setActive(false);
}
});
}
});
//Entity Head Look
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_HEAD_LOOK, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
replacement.setHeadYaw(yaw * 360f / 256);
}
});
}
});
//Entity Metadata
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_METADATA, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST);
handler(wrapper -> {
List<Metadata> metadataList = wrapper.get(Types1_8.METADATA_LIST, 0);
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (tracker.getClientEntityTypes().containsKey(entityId)) {
protocol.getMetadataRewriter().transform(tracker.getClientEntityTypes().get(entityId), metadataList);
if (metadataList.isEmpty()) wrapper.cancel();
} else {
tracker.addMetadataToBuffer(entityId, metadataList);
wrapper.cancel();
}
});
}
});
//Attach Entity
protocol.registerClientbound(ClientboundPackets1_9.ATTACH_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.INT);
create(Type.BOOLEAN, true);
}
});
//Entity Velocity
//Entity Equipment
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_EQUIPMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
handler(packetWrapper -> {
// todo check if this is correct for the own player
int slot = packetWrapper.read(Type.VAR_INT);
if (slot == 1) {
packetWrapper.cancel();
} else if (slot > 1) {
slot -= 1;
}
packetWrapper.write(Type.SHORT, (short) slot);
});
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToClient(packetWrapper.get(Type.ITEM1_8, 0))));
}
});
//Set Passengers
protocol.registerClientbound(ClientboundPackets1_9.SET_PASSENGERS, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
EntityTracker entityTracker = packetWrapper.user().get(EntityTracker.class);
int vehicle = packetWrapper.read(Type.VAR_INT);
int count = packetWrapper.read(Type.VAR_INT);
ArrayList<Integer> passengers = new ArrayList<>();
for (int i = 0; i < count; i++) passengers.add(packetWrapper.read(Type.VAR_INT));
List<Integer> oldPassengers = entityTracker.getPassengers(vehicle);
entityTracker.setPassengers(vehicle, passengers);
if (!oldPassengers.isEmpty()) {
for (Integer passenger : oldPassengers) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, null, packetWrapper.user());
detach.write(Type.INT, passenger);
detach.write(Type.INT, -1);
detach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(detach, Protocol1_8To1_9.class);
}
}
for (int i = 0; i < count; i++) {
int v = i == 0 ? vehicle : passengers.get(i - 1);
int p = passengers.get(i);
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, null, packetWrapper.user());
attach.write(Type.INT, p);
attach.write(Type.INT, v);
attach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(attach, Protocol1_8To1_9.class);
}
});
}
});
//Collect Item
//Entity Teleport
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BOOLEAN);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = packetWrapper.get(Type.BYTE, 1);
yaw -= 64;
packetWrapper.set(Type.BYTE, 0, yaw);
int y = packetWrapper.get(Type.INT, 1);
y += 10;
packetWrapper.set(Type.INT, 1, y);
}
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
packetWrapper.user().get(EntityTracker.class).resetEntityOffset(entityId);
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.INT, 0);
int y = packetWrapper.get(Type.INT, 1);
int z = packetWrapper.get(Type.INT, 2);
int yaw = packetWrapper.get(Type.BYTE, 0);
int pitch = packetWrapper.get(Type.BYTE, 1);
replacement.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
});
//Entity Properties
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_PROPERTIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.INT);
handler(packetWrapper -> {
boolean player = packetWrapper.get(Type.VAR_INT, 0) == packetWrapper.user().get(EntityTracker.class).getPlayerId();
int size = packetWrapper.get(Type.INT, 0);
int removed = 0;
for (int i = 0; i < size; i++) {
String key = packetWrapper.read(Type.STRING);
boolean skip = !Protocol1_8To1_9.VALID_ATTRIBUTES.contains(key);
double value = packetWrapper.read(Type.DOUBLE);
int modifierSize = packetWrapper.read(Type.VAR_INT);
if (!skip) {
packetWrapper.write(Type.STRING, key);
packetWrapper.write(Type.DOUBLE, value);
packetWrapper.write(Type.VAR_INT, modifierSize);
} else {
removed++;
}
ArrayList<Pair<Byte, Double>> modifiers = new ArrayList<>();
for (int j = 0; j < modifierSize; j++) {
UUID uuid = packetWrapper.read(Type.UUID);
double amount = packetWrapper.read(Type.DOUBLE);
byte operation = packetWrapper.read(Type.BYTE);
modifiers.add(new Pair<>(operation, amount));
if (skip) continue;
packetWrapper.write(Type.UUID, uuid);
packetWrapper.write(Type.DOUBLE, amount);
packetWrapper.write(Type.BYTE, operation);
}
if (player && key.equals("generic.attackSpeed")) {
packetWrapper.user().get(Cooldown.class).setAttackSpeed(value, modifiers);
}
}
packetWrapper.set(Type.INT, 0, size - removed);
});
}
});
//Entity Effect
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.VAR_INT);
map(Type.BYTE);
handler(packetWrapper -> {
int id = packetWrapper.get(Type.BYTE, 0);
if (id > 23) packetWrapper.cancel();
if (id == 25) {
if (packetWrapper.get(Type.VAR_INT, 0) != packetWrapper.user().get(EntityTracker.class).getPlayerId())
return;
Levitation levitation = packetWrapper.user().get(Levitation.class);
levitation.setActive(true);
levitation.setAmplifier(packetWrapper.get(Type.BYTE, 1));
}
});
}
});
}
}
@@ -0,0 +1,333 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.CooldownStorage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.LevitationStorage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.PlayerPositionTracker;
import com.viaversion.viarewind.utils.math.RelativeMoveUtil;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.fastutil.ints.IntArrayList;
import com.viaversion.viaversion.libs.fastutil.ints.IntList;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class EntityPackets1_9 {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_STATUS, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // Entity id
handler(wrapper -> {
final byte status = wrapper.read(Type.BYTE);
if (status > 23) { // Remove op permission level 0-4 (24-28)
wrapper.cancel();
return;
}
wrapper.write(Type.BYTE, status);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_POSITION, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final int deltaX = wrapper.read(Type.SHORT);
final int deltaY = wrapper.read(Type.SHORT);
final int deltaZ = wrapper.read(Type.SHORT);
final Vector[] moves = RelativeMoveUtil.calculateRelativeMoves(wrapper.user(), entityId, deltaX, deltaY, deltaZ);
wrapper.write(Type.BYTE, (byte) moves[0].blockX());
wrapper.write(Type.BYTE, (byte) moves[0].blockY());
wrapper.write(Type.BYTE, (byte) moves[0].blockZ());
final boolean onGround = wrapper.passthrough(Type.BOOLEAN);
if (moves.length > 1) {
final PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION, wrapper.user());
secondPacket.write(Type.VAR_INT, entityId);
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
secondPacket.write(Type.BYTE, (byte) moves[1].blockZ());
secondPacket.write(Type.BOOLEAN, onGround);
secondPacket.scheduleSend(Protocol1_8To1_9.class);
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_POSITION_AND_ROTATION, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final int deltaX = wrapper.read(Type.SHORT);
final int deltaY = wrapper.read(Type.SHORT);
final int deltaZ = wrapper.read(Type.SHORT);
final Vector[] moves = RelativeMoveUtil.calculateRelativeMoves(wrapper.user(), entityId, deltaX, deltaY, deltaZ);
wrapper.write(Type.BYTE, (byte) moves[0].blockX());
wrapper.write(Type.BYTE, (byte) moves[0].blockY());
wrapper.write(Type.BYTE, (byte) moves[0].blockZ());
byte yaw = wrapper.passthrough(Type.BYTE);
final byte pitch = wrapper.passthrough(Type.BYTE);
final boolean onGround = wrapper.passthrough(Type.BOOLEAN);
EntityType type = wrapper.user().getEntityTracker(Protocol1_8To1_9.class).entityType(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
yaw -= 64;
wrapper.set(Type.BYTE, 3, yaw);
}
if (moves.length > 1) {
final PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION_AND_ROTATION, wrapper.user());
secondPacket.write(Type.VAR_INT, entityId);
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
secondPacket.write(Type.BYTE, (byte) moves[1].blockZ());
secondPacket.write(Type.BYTE, yaw);
secondPacket.write(Type.BYTE, pitch);
secondPacket.write(Type.BOOLEAN, onGround);
secondPacket.scheduleSend(Protocol1_8To1_9.class);
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_ROTATION, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final EntityType type = wrapper.user().getEntityTracker(Protocol1_8To1_9.class).entityType(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = wrapper.read(Type.BYTE);
yaw -= 64;
wrapper.write(Type.BYTE, yaw);
}
});
protocol.registerClientbound(ClientboundPackets1_9.VEHICLE_MOVE, ClientboundPackets1_8.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
final int vehicle = tracker.getVehicle(tracker.clientEntityId());
if (vehicle == -1) {
wrapper.cancel();
}
wrapper.write(Type.VAR_INT, vehicle);
});
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.FLOAT, Protocol1_8To1_9.DEGREES_TO_ANGLE); // Yaw
map(Type.FLOAT, Protocol1_8To1_9.DEGREES_TO_ANGLE); // Pitch
handler(wrapper -> {
if (wrapper.isCancelled()) return;
final PlayerPositionTracker position = wrapper.user().get(PlayerPositionTracker.class);
double x = wrapper.get(Type.INT, 0) / 32d;
double y = wrapper.get(Type.INT, 1) / 32d;
double z = wrapper.get(Type.INT, 2) / 32d;
position.setPos(x, y, z);
});
create(Type.BOOLEAN, true);
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityType type = wrapper.user().getEntityTracker(Protocol1_8To1_9.class).entityType(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = wrapper.get(Type.BYTE, 1);
yaw -= 64;
wrapper.set(Type.BYTE, 0, yaw);
int y = wrapper.get(Type.INT, 1);
y += 10;
wrapper.set(Type.INT, 1, y);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.REMOVE_ENTITY_EFFECT, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final int effectId = wrapper.passthrough(Type.BYTE);
if (effectId > 23) { // Throw away new effects
wrapper.cancel();
}
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
if (effectId == 25 && entityId == tracker.clientEntityId()) {
wrapper.user().get(LevitationStorage.class).setActive(false);
}
});
protocol.registerClientbound(ClientboundPackets1_9.ATTACH_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // Attached entity id
map(Type.INT); // Holding entity id
create(Type.BOOLEAN, true); // Leash
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_EQUIPMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
handler(wrapper -> {
// todo check if this is correct for the own player
int slot = wrapper.read(Type.VAR_INT);
if (slot == 1) {
wrapper.cancel();
} else if (slot > 1) {
slot -= 1;
}
wrapper.write(Type.SHORT, (short) slot);
});
map(Type.ITEM1_8); // Item
handler(wrapper -> protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.get(Type.ITEM1_8, 0)));
}
});
protocol.registerClientbound(ClientboundPackets1_9.SET_PASSENGERS, null, wrapper -> {
wrapper.cancel();
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
final int vehicle = wrapper.read(Type.VAR_INT);
final IntList oldPassengers = tracker.getPassengers(vehicle);
final int count = wrapper.read(Type.VAR_INT);
final IntList passengers = new IntArrayList();
for (int i = 0; i < count; i++) {
passengers.add(wrapper.read(Type.VAR_INT));
}
tracker.setPassengers(vehicle, passengers);
if (!oldPassengers.isEmpty()) {
for (Integer passenger : oldPassengers) {
final PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, wrapper.user());
detach.write(Type.INT, passenger); // Attached entity id
detach.write(Type.INT, -1); // Holding entity id
detach.write(Type.BOOLEAN, false); // Leash
detach.scheduleSend(Protocol1_8To1_9.class);
}
}
for (int i = 0; i < count; i++) {
final int attachedEntityId = passengers.getInt(i);
final int holdingEntityId = i == 0 ? vehicle : passengers.getInt(i - 1);
final PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, wrapper.user());
attach.write(Type.INT, attachedEntityId);
attach.write(Type.INT, holdingEntityId);
attach.write(Type.BOOLEAN, false); // Leash
attach.scheduleSend(Protocol1_8To1_9.class);
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
map(Type.BOOLEAN); // On ground
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
if (tracker.entityType(entityId) == EntityTypes1_10.EntityType.BOAT) {
byte yaw = wrapper.get(Type.BYTE, 1);
yaw -= 64;
wrapper.set(Type.BYTE, 0, yaw);
int y = wrapper.get(Type.INT, 1);
y += 10;
wrapper.set(Type.INT, 1, y);
}
tracker.resetEntityOffset(entityId);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_PROPERTIES, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
final boolean player = entityId == tracker.clientEntityId();
// Throw away new attributes and track attack speed
int removed = 0;
final int size = wrapper.passthrough(Type.INT);
for (int i = 0; i < size; i++) {
final String key = wrapper.read(Type.STRING);
final double value = wrapper.read(Type.DOUBLE);
final int modifierSize = wrapper.read(Type.VAR_INT);
final boolean valid = protocol.getItemRewriter().VALID_ATTRIBUTES.contains(key);
if (valid) {
wrapper.write(Type.STRING, key);
wrapper.write(Type.DOUBLE, value);
wrapper.write(Type.VAR_INT, modifierSize);
}
final List<Pair<Byte, Double>> modifiers = new ArrayList<>();
for (int j = 0; j < modifierSize; j++) {
final UUID modifierId = wrapper.read(Type.UUID); // UUID
final double amount = wrapper.read(Type.DOUBLE); // Amount
final byte operation = wrapper.read(Type.BYTE); // Operation
if (valid) {
wrapper.write(Type.UUID, modifierId);
wrapper.write(Type.DOUBLE, amount);
wrapper.write(Type.BYTE, operation);
}
modifiers.add(new Pair<>(operation, amount));
}
if (!valid) {
if (player && key.equals("generic.attackSpeed")) {
wrapper.user().get(CooldownStorage.class).setAttackSpeed(value, modifiers);
}
removed++;
}
}
wrapper.set(Type.INT, 0, size - removed);
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_EFFECT, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final int effectId = wrapper.passthrough(Type.BYTE);
final byte amplifier = wrapper.passthrough(Type.BYTE);
if (effectId > 23) { // Throw away new effects
wrapper.cancel();
}
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
if (effectId == 25 && entityId == tracker.clientEntityId()) {
final LevitationStorage levitation = wrapper.user().get(LevitationStorage.class);
levitation.setActive(true);
levitation.setAmplifier(amplifier);
}
});
}
}
@@ -1,187 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.Windows;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
public class InventoryPackets {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.CLOSE_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowsId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
packetWrapper.user().get(Windows.class).remove(windowsId);
});
}
});
//Open Window
protocol.registerClientbound(ClientboundPackets1_9.OPEN_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.STRING);
map(Type.COMPONENT);
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
String type = packetWrapper.get(Type.STRING, 0);
if (type.equals("EntityHorse")) packetWrapper.passthrough(Type.INT);
});
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
String windowType = packetWrapper.get(Type.STRING, 0);
packetWrapper.user().get(Windows.class).put(windowId, windowType);
});
handler(packetWrapper -> {
String type = packetWrapper.get(Type.STRING, 0);
if (type.equalsIgnoreCase("minecraft:shulker_box")) {
packetWrapper.set(Type.STRING, 0, type = "minecraft:container");
}
String name = packetWrapper.get(Type.COMPONENT, 0).toString();
if (name.equalsIgnoreCase("{\"translate\":\"container.shulkerBox\"}")) {
packetWrapper.set(Type.COMPONENT, 0, JsonParser.parseString("{\"text\":\"Shulker Box\"}"));
}
});
}
});
//Window Items
protocol.registerClientbound(ClientboundPackets1_9.WINDOW_ITEMS, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
Item[] items = packetWrapper.read(Type.ITEM1_8_SHORT_ARRAY);
for (int i = 0; i < items.length; i++) {
items[i] = protocol.getItemRewriter().handleItemToClient(items[i]);
}
if (windowId == 0 && items.length == 46) {
Item[] old = items;
items = new Item[45];
System.arraycopy(old, 0, items, 0, 45);
} else {
String type = packetWrapper.user().get(Windows.class).get(windowId);
if (type != null && type.equalsIgnoreCase("minecraft:brewing_stand")) {
System.arraycopy(items, 0, packetWrapper.user().get(Windows.class).getBrewingItems(windowId), 0, 4);
Windows.updateBrewingStand(packetWrapper.user(), items[4], windowId);
Item[] old = items;
items = new Item[old.length - 1];
System.arraycopy(old, 0, items, 0, 4);
System.arraycopy(old, 5, items, 4, old.length - 5);
}
}
packetWrapper.write(Type.ITEM1_8_SHORT_ARRAY, items);
});
}
});
//Window Property
//Set Slot
protocol.registerClientbound(ClientboundPackets1_9.SET_SLOT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.SHORT);
map(Type.ITEM1_8);
handler(packetWrapper -> {
packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToClient(packetWrapper.get(Type.ITEM1_8, 0)));
byte windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0).byteValue();
short slot = packetWrapper.get(Type.SHORT, 0);
if (windowId == 0 && slot == 45) {
packetWrapper.cancel();
return;
}
String type = packetWrapper.user().get(Windows.class).get(windowId);
if (type == null) return;
if (type.equalsIgnoreCase("minecraft:brewing_stand")) {
if (slot > 4) {
packetWrapper.set(Type.SHORT, 0, slot -= 1);
} else if (slot == 4) {
packetWrapper.cancel();
Windows.updateBrewingStand(packetWrapper.user(), packetWrapper.get(Type.ITEM1_8, 0), windowId);
} else {
packetWrapper.user().get(Windows.class).getBrewingItems(windowId)[slot] = packetWrapper.get(Type.ITEM1_8, 0);
}
}
});
}
});
/* INCOMING */
//Close Window
protocol.registerServerbound(ServerboundPackets1_8.CLOSE_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowsId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
packetWrapper.user().get(Windows.class).remove(windowsId);
});
}
});
//Click Window
protocol.registerServerbound(ServerboundPackets1_8.CLICK_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.SHORT);
map(Type.BYTE);
map(Type.SHORT);
map(Type.BYTE, Type.VAR_INT);
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToServer(packetWrapper.get(Type.ITEM1_8, 0))));
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
Windows windows = packetWrapper.user().get(Windows.class);
String type = windows.get(windowId);
if (type == null) return;
if (type.equalsIgnoreCase("minecraft:brewing_stand")) {
short slot = packetWrapper.get(Type.SHORT, 0);
if (slot > 3) {
packetWrapper.set(Type.SHORT, 0, slot += 1);
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT);
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToServer(packetWrapper.get(Type.ITEM1_8, 0))));
}
});
}
}
@@ -1,635 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import java.util.ArrayList;
import java.util.UUID;
public class PlayerPackets {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.BOSSBAR, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
UUID uuid = packetWrapper.read(Type.UUID);
int action = packetWrapper.read(Type.VAR_INT);
BossBarStorage bossBarStorage = packetWrapper.user().get(BossBarStorage.class);
if (action == 0) {
bossBarStorage.add(uuid, ChatUtil.jsonToLegacy(packetWrapper.read(Type.COMPONENT)), packetWrapper.read(Type.FLOAT));
packetWrapper.read(Type.VAR_INT);
packetWrapper.read(Type.VAR_INT);
packetWrapper.read(Type.UNSIGNED_BYTE);
} else if (action == 1) {
bossBarStorage.remove(uuid);
} else if (action == 2) {
bossBarStorage.updateHealth(uuid, packetWrapper.read(Type.FLOAT));
} else if (action == 3) {
String title = ChatUtil.jsonToLegacy(packetWrapper.read(Type.COMPONENT));
bossBarStorage.updateTitle(uuid, title);
}
});
}
});
//Tab-Complete
//Chat Message
//Set Cooldown
protocol.cancelClientbound(ClientboundPackets1_9.COOLDOWN);
//Custom Payload
protocol.registerClientbound(ClientboundPackets1_9.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
if (channel.equalsIgnoreCase("MC|TrList")) {
packetWrapper.passthrough(Type.INT); //Window Id
int size;
if (packetWrapper.isReadable(Type.BYTE, 0)) {
size = packetWrapper.passthrough(Type.BYTE);
} else {
size = packetWrapper.passthrough(Type.UNSIGNED_BYTE);
}
final ItemRewriter<?> itemRewriter = protocol.getItemRewriter();
for (int i = 0; i < size; i++) {
packetWrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(packetWrapper.read(Type.ITEM1_8))); //Buy Item 1
packetWrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(packetWrapper.read(Type.ITEM1_8))); //Buy Item 3
boolean has3Items = packetWrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
packetWrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(packetWrapper.read(Type.ITEM1_8))); //Buy Item 2
}
packetWrapper.passthrough(Type.BOOLEAN); //Unavailable
packetWrapper.passthrough(Type.INT); //Uses
packetWrapper.passthrough(Type.INT); //Max Uses
}
} else if (channel.equalsIgnoreCase("MC|BOpen")) {
packetWrapper.read(Type.VAR_INT);
}
});
}
});
//Disconnect
//Change Game State
protocol.registerClientbound(ClientboundPackets1_9.GAME_EVENT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.FLOAT);
handler(packetWrapper -> {
int reason = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
if (reason == 3)
packetWrapper.user().get(EntityTracker.class).setPlayerGamemode(packetWrapper.get(Type.FLOAT, 0).intValue());
});
}
});
//Join Game
protocol.registerClientbound(ClientboundPackets1_9.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.UNSIGNED_BYTE);
map(Type.BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.STRING);
map(Type.BOOLEAN);
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.setPlayerId(packetWrapper.get(Type.INT, 0));
tracker.setPlayerGamemode(packetWrapper.get(Type.UNSIGNED_BYTE, 0));
tracker.getClientEntityTypes().put(tracker.getPlayerId(), EntityTypes1_10.EntityType.ENTITY_HUMAN);
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
world.setEnvironment(packetWrapper.get(Type.BYTE, 0));
});
}
});
//Open Sign Editor
//Player Abilities
//Player List Item
//Player Position And Look
protocol.registerClientbound(ClientboundPackets1_9.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BYTE);
handler(packetWrapper -> {
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
int teleportId = packetWrapper.read(Type.VAR_INT);
pos.setConfirmId(teleportId);
byte flags = packetWrapper.get(Type.BYTE, 0);
double x = packetWrapper.get(Type.DOUBLE, 0);
double y = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
float yaw = packetWrapper.get(Type.FLOAT, 0);
float pitch = packetWrapper.get(Type.FLOAT, 1);
packetWrapper.set(Type.BYTE, 0, (byte) 0);
if (flags != 0) {
if ((flags & 0x01) != 0) {
x += pos.getPosX();
packetWrapper.set(Type.DOUBLE, 0, x);
}
if ((flags & 0x02) != 0) {
y += pos.getPosY();
packetWrapper.set(Type.DOUBLE, 1, y);
}
if ((flags & 0x04) != 0) {
z += pos.getPosZ();
packetWrapper.set(Type.DOUBLE, 2, z);
}
if ((flags & 0x08) != 0) {
yaw += pos.getYaw();
packetWrapper.set(Type.FLOAT, 0, yaw);
}
if ((flags & 0x10) != 0) {
pitch += pos.getPitch();
packetWrapper.set(Type.FLOAT, 1, pitch);
}
}
pos.setPos(x, y, z);
pos.setYaw(yaw);
pos.setPitch(pitch);
});
}
});
//Resource Pack Send
//Respawn
protocol.registerClientbound(ClientboundPackets1_9.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.STRING);
handler(packetWrapper -> packetWrapper.user().get(EntityTracker.class).setPlayerGamemode(packetWrapper.get(Type.UNSIGNED_BYTE, 1)));
handler(packetWrapper -> {
packetWrapper.user().get(BossBarStorage.class).updateLocation();
packetWrapper.user().get(BossBarStorage.class).changeWorld();
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
world.setEnvironment(packetWrapper.get(Type.INT, 0));
});
}
});
//Camera
//Held Item Change
//Set Experience
//Update Health
//Spawn Position
//Title
//Player List Header And Footer
/* INCOMING */
//Chat Message
protocol.registerServerbound(ServerboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
if (msg.toLowerCase().startsWith("/offhand")) {
packetWrapper.cancel();
PacketWrapper swapItems = PacketWrapper.create(0x13, null, packetWrapper.user());
swapItems.write(Type.VAR_INT, 6);
swapItems.write(Type.POSITION1_8, new Position(0, 0, 0));
swapItems.write(Type.BYTE, (byte) 255);
PacketUtil.sendToServer(swapItems, Protocol1_8To1_9.class, true, true);
}
});
}
});
//Confirm Transaction
//Use Entity
protocol.registerServerbound(ServerboundPackets1_8.INTERACT_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.VAR_INT);
handler(packetWrapper -> {
int type = packetWrapper.get(Type.VAR_INT, 1);
if (type == 2) {
packetWrapper.passthrough(Type.FLOAT);
packetWrapper.passthrough(Type.FLOAT);
packetWrapper.passthrough(Type.FLOAT);
}
if (type == 2 || type == 0) {
packetWrapper.write(Type.VAR_INT, 0);
}
});
}
});
//Player
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.BOOLEAN);
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int playerId = tracker.getPlayerId();
if (tracker.isInsideVehicle(playerId)) packetWrapper.cancel();
});
}
});
//Player Position
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.BOOLEAN);
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
if (pos.getConfirmId() != -1) return;
pos.setPos(packetWrapper.get(Type.DOUBLE, 0), packetWrapper.get(Type.DOUBLE, 1),
packetWrapper.get(Type.DOUBLE, 2));
pos.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
});
handler(packetWrapper -> packetWrapper.user().get(BossBarStorage.class).updateLocation());
}
});
//Player Look
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
if (pos.getConfirmId() != -1) return;
pos.setYaw(packetWrapper.get(Type.FLOAT, 0));
pos.setPitch(packetWrapper.get(Type.FLOAT, 1));
pos.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
});
handler(packetWrapper -> packetWrapper.user().get(BossBarStorage.class).updateLocation());
}
});
//Player Position And Look
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
double x = packetWrapper.get(Type.DOUBLE, 0);
double y = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
float yaw = packetWrapper.get(Type.FLOAT, 0);
float pitch = packetWrapper.get(Type.FLOAT, 1);
boolean onGround = packetWrapper.get(Type.BOOLEAN, 0);
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
if (pos.getConfirmId() != -1) {
if (pos.getPosX() == x && pos.getPosY() == y && pos.getPosZ() == z
&& pos.getYaw() == yaw && pos.getPitch() == pitch) {
PacketWrapper confirmTeleport = packetWrapper.create(0x00);
confirmTeleport.write(Type.VAR_INT, pos.getConfirmId());
PacketUtil.sendToServer(confirmTeleport,
Protocol1_8To1_9.class, true, true);
pos.setConfirmId(-1);
}
} else {
pos.setPos(x, y, z);
pos.setYaw(yaw);
pos.setPitch(pitch);
pos.setOnGround(onGround);
packetWrapper.user().get(BossBarStorage.class).updateLocation();
}
});
}
});
//Player Digging
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_DIGGING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.POSITION1_8);
handler(packetWrapper -> {
int state = packetWrapper.get(Type.VAR_INT, 0);
if (state == 0) {
packetWrapper.user().get(BlockPlaceDestroyTracker.class).setMining(true);
} else if (state == 2) {
BlockPlaceDestroyTracker tracker = packetWrapper.user().get(BlockPlaceDestroyTracker.class);
tracker.setMining(false);
tracker.setLastMining(System.currentTimeMillis() + 100);
packetWrapper.user().get(Cooldown.class).setLastHit(0);
} else if (state == 1) {
BlockPlaceDestroyTracker tracker = packetWrapper.user().get(BlockPlaceDestroyTracker.class);
tracker.setMining(false);
tracker.setLastMining(0);
packetWrapper.user().get(Cooldown.class).hit();
}
});
}
});
//Player Block Placement
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
map(Type.BYTE, Type.VAR_INT);
read(Type.ITEM1_8);
create(Type.VAR_INT, 0); //Main Hand
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
if (packetWrapper.get(Type.VAR_INT, 0) == -1) {
packetWrapper.cancel();
PacketWrapper useItem = PacketWrapper.create(0x1D, null, packetWrapper.user());
useItem.write(Type.VAR_INT, 0);
PacketUtil.sendToServer(useItem, Protocol1_8To1_9.class, true, true);
}
});
handler(packetWrapper -> {
if (packetWrapper.get(Type.VAR_INT, 0) != -1) {
packetWrapper.user().get(BlockPlaceDestroyTracker.class).place();
}
});
}
});
//Held Item Change
protocol.registerServerbound(ServerboundPackets1_8.HELD_ITEM_CHANGE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> packetWrapper.user().get(Cooldown.class).hit());
}
});
//Animation
protocol.registerServerbound(ServerboundPackets1_8.ANIMATION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
/* We have to add ArmAnimation to a queue to be sent on PacketPlayInFlying. In 1.9,
* PacketPlayInArmAnimation is sent after PacketPlayInUseEntity, not before like it used to be.
* However, all packets are sent before PacketPlayInFlying. We'd just do a normal delay, but
* it would cause the packet to be sent after PacketPlayInFlying, potentially false flagging
* anticheats that check for this behavior from clients. Since all packets are sent before
* PacketPlayInFlying, if we queue it to be sent right before PacketPlayInFlying is processed,
* we can be certain it will be sent after PacketPlayInUseEntity */
packetWrapper.cancel();
final PacketWrapper delayedPacket = PacketWrapper.create(0x1A,
null, packetWrapper.user());
delayedPacket.write(Type.VAR_INT, 0); //Main Hand
((Protocol1_8To1_9) protocol).animationsToSend.add(delayedPacket);
});
handler(packetWrapper -> {
packetWrapper.user().get(BlockPlaceDestroyTracker.class).updateMining();
packetWrapper.user().get(Cooldown.class).hit();
});
}
});
//Entity Action
protocol.registerServerbound(ServerboundPackets1_8.ENTITY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.VAR_INT);
map(Type.VAR_INT);
handler(packetWrapper -> {
int action = packetWrapper.get(Type.VAR_INT, 1);
if (action == 6) {
packetWrapper.set(Type.VAR_INT, 1, 7);
} else if (action == 0) {
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
if (!pos.isOnGround()) {
PacketWrapper elytra = PacketWrapper.create(0x14, null, packetWrapper.user());
elytra.write(Type.VAR_INT, packetWrapper.get(Type.VAR_INT, 0));
elytra.write(Type.VAR_INT, 8);
elytra.write(Type.VAR_INT, 0);
PacketUtil.sendToServer(elytra, Protocol1_8To1_9.class, true, false);
}
}
});
}
});
//Steer Vehicle
protocol.registerServerbound(ServerboundPackets1_8.STEER_VEHICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int playerId = tracker.getPlayerId();
int vehicle = tracker.getVehicle(playerId);
if (vehicle != -1 && tracker.getClientEntityTypes().get(vehicle) == EntityTypes1_10.EntityType.BOAT) {
PacketWrapper steerBoat = PacketWrapper.create(0x11, null, packetWrapper.user());
float left = packetWrapper.get(Type.FLOAT, 0);
float forward = packetWrapper.get(Type.FLOAT, 1);
steerBoat.write(Type.BOOLEAN, forward != 0.0f || left < 0.0f);
steerBoat.write(Type.BOOLEAN, forward != 0.0f || left > 0.0f);
PacketUtil.sendToServer(steerBoat, Protocol1_8To1_9.class);
}
});
}
});
//Update Sign
protocol.registerServerbound(ServerboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
handler(packetWrapper -> {
for (int i = 0; i < 4; i++) {
packetWrapper.write(Type.STRING, ChatUtil.jsonToLegacy(packetWrapper.read(Type.COMPONENT)));
}
});
}
});
//Player Abilities
//Tab Complete
protocol.registerServerbound(ServerboundPackets1_8.TAB_COMPLETE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> packetWrapper.write(Type.BOOLEAN, false));
map(Type.OPTIONAL_POSITION1_8);
}
});
//Client Settings
protocol.registerServerbound(ServerboundPackets1_8.CLIENT_SETTINGS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
map(Type.BYTE, Type.VAR_INT);
map(Type.BOOLEAN);
map(Type.UNSIGNED_BYTE);
create(Type.VAR_INT, 1);
handler(packetWrapper -> {
short flags = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
PacketWrapper updateSkin = PacketWrapper.create(0x1C, null, packetWrapper.user());
updateSkin.write(Type.VAR_INT, packetWrapper.user().get(EntityTracker.class).getPlayerId());
ArrayList<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(10, MetaType1_8.Byte, (byte) flags));
updateSkin.write(Types1_8.METADATA_LIST, metadata);
PacketUtil.sendPacket(updateSkin, Protocol1_8To1_9.class);
});
}
});
//Client Status
//Custom Payload
protocol.registerServerbound(ServerboundPackets1_8.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
if (channel.equalsIgnoreCase("MC|BEdit") || channel.equalsIgnoreCase("MC|BSign")) {
Item book = packetWrapper.passthrough(Type.ITEM);
book.setIdentifier(386);
CompoundTag tag = book.tag();
if (tag.contains("pages")) {
ListTag pages = tag.get("pages");
if (pages.size() > ViaRewind.getConfig().getMaxBookPages()) {
packetWrapper.user().disconnect("Too many book pages");
return;
}
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
if (value.length() > ViaRewind.getConfig().getMaxBookPageSize()) {
packetWrapper.user().disconnect("Book page too large");
return;
}
value = ChatUtil.jsonToLegacy(value);
page.setValue(value);
}
}
} else if (channel.equalsIgnoreCase("MC|AdvCdm")) {
packetWrapper.set(Type.STRING, 0, channel = "MC|AdvCmd");
}
});
}
});
//Spectate
//Resource Pack Status
}
}
@@ -0,0 +1,537 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import java.util.ArrayList;
import java.util.UUID;
public class PlayerPackets1_9 {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.BOSSBAR, null, wrapper -> {
wrapper.cancel();
final BossBarStorage bossbar = wrapper.user().get(BossBarStorage.class);
final UUID uuid = wrapper.read(Type.UUID);
final int action = wrapper.read(Type.VAR_INT);
if (action == 0 /* add */) {
final JsonElement title = wrapper.read(Type.COMPONENT);
final float health = wrapper.read(Type.FLOAT);
wrapper.read(Type.VAR_INT); // Color
wrapper.read(Type.VAR_INT); // Division
wrapper.read(Type.UNSIGNED_BYTE); // Flags
bossbar.add(uuid, ChatUtil.jsonToLegacy(wrapper.user(), title), health);
} else if (action == 1 /* remove */) {
bossbar.remove(uuid);
} else if (action == 2 /* update health */) {
final float health = wrapper.read(Type.FLOAT);
bossbar.updateHealth(uuid, health);
} else if (action == 3 /* update title */) {
final JsonElement title = wrapper.read(Type.COMPONENT);
bossbar.updateTitle(uuid, ChatUtil.jsonToLegacy(wrapper.user(), title));
}
});
protocol.registerClientbound(ClientboundPackets1_9.TEAMS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // Team name
map(Type.BYTE); // Mode
handler(wrapper -> {
final byte mode = wrapper.get(Type.BYTE, 0);
if (mode == 0 /* create team */ || mode == 2 /* update team info */) {
wrapper.passthrough(Type.STRING); // Display name
wrapper.passthrough(Type.STRING); // Prefix
wrapper.passthrough(Type.STRING); // Suffix
wrapper.passthrough(Type.BYTE); // Friendly fire
wrapper.passthrough(Type.STRING); // Name tag visibility
wrapper.read(Type.STRING); // Collision rule
}
});
}
});
protocol.cancelClientbound(ClientboundPackets1_9.COOLDOWN);
protocol.registerClientbound(ClientboundPackets1_9.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // Channel
handlerSoftFail(wrapper -> {
final String channel = wrapper.get(Type.STRING, 0);
if (channel.equals("MC|TrList")) {
wrapper.passthrough(Type.INT); // Window id
int size;
if (wrapper.isReadable(Type.BYTE, 0)) {
size = wrapper.passthrough(Type.BYTE);
} else {
size = wrapper.passthrough(Type.UNSIGNED_BYTE);
}
final ItemRewriter<?> itemRewriter = protocol.getItemRewriter();
for (int i = 0; i < size; i++) {
wrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8))); // Buy item 1
wrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8))); // Buy item 3
boolean has3Items = wrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
wrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8))); // Buy item 2
}
wrapper.passthrough(Type.BOOLEAN); //Unavailable
wrapper.passthrough(Type.INT); //Uses
wrapper.passthrough(Type.INT); //Max Uses
}
} else if (channel.equals("MC|BOpen")) {
wrapper.read(Type.VAR_INT);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); // X
map(Type.DOUBLE); // Feet y
map(Type.DOUBLE); // Z
map(Type.FLOAT); // Yaw
map(Type.FLOAT); // Pitch
map(Type.BYTE); // Relative arguments
handler(wrapper -> {
final PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
pos.setConfirmId(wrapper.read(Type.VAR_INT));
byte flags = wrapper.get(Type.BYTE, 0);
double x = wrapper.get(Type.DOUBLE, 0);
double y = wrapper.get(Type.DOUBLE, 1);
double z = wrapper.get(Type.DOUBLE, 2);
float yaw = wrapper.get(Type.FLOAT, 0);
float pitch = wrapper.get(Type.FLOAT, 1);
wrapper.set(Type.BYTE, 0, (byte) 0);
if (flags != 0) {
if ((flags & 0x01) != 0) {
x += pos.getPosX();
wrapper.set(Type.DOUBLE, 0, x);
}
if ((flags & 0x02) != 0) {
y += pos.getPosY();
wrapper.set(Type.DOUBLE, 1, y);
}
if ((flags & 0x04) != 0) {
z += pos.getPosZ();
wrapper.set(Type.DOUBLE, 2, z);
}
if ((flags & 0x08) != 0) {
yaw += pos.getYaw();
wrapper.set(Type.FLOAT, 0, yaw);
}
if ((flags & 0x10) != 0) {
pitch += pos.getPitch();
wrapper.set(Type.FLOAT, 1, pitch);
}
}
pos.setPos(x, y, z);
pos.setYaw(yaw);
pos.setPitch(pitch);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // Dimension
handler(wrapper -> wrapper.user().get(BossBarStorage.class).reset());
handler(wrapper -> {
final ClientWorld world = wrapper.user().get(ClientWorld.class);
world.setEnvironment(wrapper.get(Type.INT, 0));
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // Message
handler(wrapper -> {
if (!ViaRewind.getConfig().isEnableOffhand()) {
return;
}
final String msg = wrapper.get(Type.STRING, 0);
if (msg.toLowerCase().trim().startsWith(ViaRewind.getConfig().getOffhandCommand())) {
wrapper.cancel();
final PacketWrapper swapItems = PacketWrapper.create(ServerboundPackets1_9.PLAYER_DIGGING, wrapper.user());
swapItems.write(Type.VAR_INT, 6);
swapItems.write(Type.POSITION1_8, new Position(0, 0, 0));
swapItems.write(Type.BYTE, (byte) 255);
swapItems.sendToServer(Protocol1_8To1_9.class);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.INTERACT_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Target
map(Type.VAR_INT); // Type
handler(wrapper -> {
final int type = wrapper.get(Type.VAR_INT, 1);
if (type == 2 /* attack */) {
wrapper.passthrough(Type.FLOAT); // Target x
wrapper.passthrough(Type.FLOAT); // Target y
wrapper.passthrough(Type.FLOAT); // Target z
}
if (type == 2 /* attack */ || type == 0 /* interact */) {
wrapper.write(Type.VAR_INT, 0); // Hand
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.BOOLEAN); // On ground
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
if (tracker.isInsideVehicle(tracker.clientEntityId())) {
wrapper.cancel();
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); // X
map(Type.DOUBLE); // Feet y
map(Type.DOUBLE); // Z
map(Type.BOOLEAN); // On ground
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
final PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (pos.getConfirmId() != -1) {
return;
}
pos.setPos(wrapper.get(Type.DOUBLE, 0), wrapper.get(Type.DOUBLE, 1), wrapper.get(Type.DOUBLE, 2));
pos.setOnGround(wrapper.get(Type.BOOLEAN, 0));
});
handler(wrapper -> wrapper.user().get(BossBarStorage.class).updateLocation());
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (pos.getConfirmId() != -1) return;
pos.setYaw(wrapper.get(Type.FLOAT, 0));
pos.setPitch(wrapper.get(Type.FLOAT, 1));
pos.setOnGround(wrapper.get(Type.BOOLEAN, 0));
});
handler(wrapper -> wrapper.user().get(BossBarStorage.class).updateLocation());
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
double x = wrapper.get(Type.DOUBLE, 0);
double y = wrapper.get(Type.DOUBLE, 1);
double z = wrapper.get(Type.DOUBLE, 2);
float yaw = wrapper.get(Type.FLOAT, 0);
float pitch = wrapper.get(Type.FLOAT, 1);
boolean onGround = wrapper.get(Type.BOOLEAN, 0);
PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (pos.getConfirmId() != -1) {
if (pos.getPosX() == x && pos.getPosY() == y && pos.getPosZ() == z
&& pos.getYaw() == yaw && pos.getPitch() == pitch) {
PacketWrapper confirmTeleport = wrapper.create(0x00);
confirmTeleport.write(Type.VAR_INT, pos.getConfirmId());
confirmTeleport.sendToServer(Protocol1_8To1_9.class);
pos.setConfirmId(-1);
}
} else {
pos.setPos(x, y, z);
pos.setYaw(yaw);
pos.setPitch(pitch);
pos.setOnGround(onGround);
wrapper.user().get(BossBarStorage.class).updateLocation();
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_DIGGING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.POSITION1_8);
handler(wrapper -> {
int state = wrapper.get(Type.VAR_INT, 0);
if (state == 0) {
wrapper.user().get(BlockPlaceDestroyTracker.class).setMining();
} else if (state == 2) {
BlockPlaceDestroyTracker tracker = wrapper.user().get(BlockPlaceDestroyTracker.class);
tracker.setMining();
tracker.setLastMining(System.currentTimeMillis() + 100);
wrapper.user().get(CooldownStorage.class).setLastHit(0);
} else if (state == 1) {
BlockPlaceDestroyTracker tracker = wrapper.user().get(BlockPlaceDestroyTracker.class);
tracker.setMining();
tracker.setLastMining(0);
wrapper.user().get(CooldownStorage.class).hit();
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
map(Type.BYTE, Type.VAR_INT);
read(Type.ITEM1_8);
create(Type.VAR_INT, 0); //Main Hand
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
handler(wrapper -> {
if (wrapper.get(Type.VAR_INT, 0) == -1) {
wrapper.cancel();
PacketWrapper useItem = PacketWrapper.create(0x1D, null, wrapper.user());
useItem.write(Type.VAR_INT, 0);
useItem.sendToServer(Protocol1_8To1_9.class);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.HELD_ITEM_CHANGE, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> wrapper.user().get(CooldownStorage.class).hit());
}
});
protocol.registerServerbound(ServerboundPackets1_8.ANIMATION, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
wrapper.cancel();
/* We have to add ArmAnimation to a queue to be sent on PacketPlayInFlying. In 1.9,
* PacketPlayInArmAnimation is sent after PacketPlayInUseEntity, not before like it used to be.
* However, all packets are sent before PacketPlayInFlying. We'd just do a normal delay, but
* it would cause the packet to be sent after PacketPlayInFlying, potentially false flagging
* anticheats that check for this behavior from clients. Since all packets are sent before
* PacketPlayInFlying, if we queue it to be sent right before PacketPlayInFlying is processed,
* we can be certain it will be sent after PacketPlayInUseEntity */
wrapper.cancel();
final PacketWrapper delayedPacket = PacketWrapper.create(0x1A, null, wrapper.user());
delayedPacket.write(Type.VAR_INT, 0); //Main Hand
wrapper.user().get(PlayerPositionTracker.class).queueAnimation(delayedPacket);
});
handler(wrapper -> {
wrapper.user().get(BlockPlaceDestroyTracker.class).updateMining();
wrapper.user().get(CooldownStorage.class).hit();
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.ENTITY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.VAR_INT);
map(Type.VAR_INT);
handler(wrapper -> {
int action = wrapper.get(Type.VAR_INT, 1);
if (action == 6) {
wrapper.set(Type.VAR_INT, 1, 7);
} else if (action == 0) {
PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (!pos.isOnGround()) {
PacketWrapper elytra = PacketWrapper.create(0x14, null, wrapper.user());
elytra.write(Type.VAR_INT, wrapper.get(Type.VAR_INT, 0));
elytra.write(Type.VAR_INT, 8);
elytra.write(Type.VAR_INT, 0);
elytra.scheduleSendToServer(Protocol1_8To1_9.class);
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.STEER_VEHICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.UNSIGNED_BYTE);
handler(wrapper -> {
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
final int vehicle = tracker.getVehicle(tracker.clientEntityId());
if (vehicle != -1 && tracker.entityType(vehicle) == EntityTypes1_10.EntityType.BOAT) {
PacketWrapper steerBoat = PacketWrapper.create(0x11, null, wrapper.user());
float left = wrapper.get(Type.FLOAT, 0);
float forward = wrapper.get(Type.FLOAT, 1);
steerBoat.write(Type.BOOLEAN, forward != 0.0f || left < 0.0f);
steerBoat.write(Type.BOOLEAN, forward != 0.0f || left > 0.0f);
steerBoat.scheduleSendToServer(Protocol1_8To1_9.class);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
wrapper.write(Type.STRING, ChatUtil.jsonToLegacy(wrapper.user(), wrapper.read(Type.COMPONENT)));
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.TAB_COMPLETE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
create(Type.BOOLEAN, false);
map(Type.OPTIONAL_POSITION1_8);
}
});
protocol.registerServerbound(ServerboundPackets1_8.CLIENT_SETTINGS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
map(Type.BYTE, Type.VAR_INT);
map(Type.BOOLEAN);
map(Type.UNSIGNED_BYTE);
create(Type.VAR_INT, 1);
handler(wrapper -> {
short flags = wrapper.get(Type.UNSIGNED_BYTE, 0);
PacketWrapper updateSkin = PacketWrapper.create(0x1C, null, wrapper.user());
updateSkin.write(Type.VAR_INT, wrapper.user().getEntityTracker(Protocol1_8To1_9.class).clientEntityId());
ArrayList<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(10, MetaType1_8.Byte, (byte) flags));
updateSkin.write(Types1_8.METADATA_LIST, metadata);
updateSkin.scheduleSend(Protocol1_8To1_9.class);
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(wrapper -> {
String channel = wrapper.get(Type.STRING, 0);
if (channel.equals("MC|BEdit") || channel.equals("MC|BSign")) {
Item book = wrapper.passthrough(Type.ITEM);
book.setIdentifier(386);
CompoundTag tag = book.tag();
if (tag.contains("pages")) {
ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
if (pages.size() > ViaRewind.getConfig().getMaxBookPages()) {
wrapper.user().disconnect("Too many book pages");
return;
}
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
if (value.length() > ViaRewind.getConfig().getMaxBookPageSize()) {
wrapper.user().disconnect("Book page too large");
return;
}
value = ChatUtil.jsonToLegacy(wrapper.user(), value);
page.setValue(value);
}
}
} else if (channel.equals("MC|AdvCdm")) {
wrapper.set(Type.STRING, 0, "MC|AdvCmd");
}
});
}
});
}
}
@@ -1,65 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
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_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
public class ScoreboardPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
//Display Scoreboard
//Scoreboard Objective
//Scoreboard Team
protocol.registerClientbound(ClientboundPackets1_9.TEAMS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
handler(packetWrapper -> {
byte mode = packetWrapper.get(Type.BYTE, 0);
if (mode == 0 || mode == 2) {
packetWrapper.passthrough(Type.STRING); //Display Name
packetWrapper.passthrough(Type.STRING); //Prefix
packetWrapper.passthrough(Type.STRING); //Suffix
packetWrapper.passthrough(Type.BYTE); //Friendly Flags
packetWrapper.passthrough(Type.STRING); //Name Tag Visibility
packetWrapper.read(Type.STRING); //Skip Collision Rule
packetWrapper.passthrough(Type.BYTE); //Friendly Flags
}
if (mode == 0 || mode == 3 || mode == 4) {
packetWrapper.passthrough(Type.STRING_ARRAY);
}
});
}
});
//Update Score
}
}
@@ -1,271 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement.ShulkerBulletModel;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement.ShulkerModel;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
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_8;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import java.util.List;
public class SpawnPackets {
public static void register(Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
read(Type.UUID);
map(Type.BYTE);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.INT);
handler(packetWrapper -> {
final int entityId = packetWrapper.get(Type.VAR_INT, 0);
final int typeId = packetWrapper.get(Type.BYTE, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(typeId, true);
//cancel AREA_EFFECT_CLOUD = 3, SPECTRAL_ARROW = 91, DRAGON_FIREBALL = 93
if (typeId == 3 || typeId == 91 || typeId == 92 || typeId == 93) {
packetWrapper.cancel();
return;
}
if (type == null) {
ViaRewind.getPlatform().getLogger().warning("[ViaRewind] Unhandled Spawn Object Type: " + typeId);
packetWrapper.cancel();
return;
}
int x = packetWrapper.get(Type.INT, 0);
int y = packetWrapper.get(Type.INT, 1);
int z = packetWrapper.get(Type.INT, 2);
if (type.is(EntityTypes1_10.EntityType.BOAT)) {
byte yaw = packetWrapper.get(Type.BYTE, 1);
yaw -= 64;
packetWrapper.set(Type.BYTE, 1, yaw);
y += 10;
packetWrapper.set(Type.INT, 1, y);
} else if (type.is(EntityTypes1_10.EntityType.SHULKER_BULLET)) {
packetWrapper.cancel();
ShulkerBulletModel shulkerBulletReplacement = new ShulkerBulletModel(packetWrapper.user(), protocol, entityId);
shulkerBulletReplacement.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
tracker.addEntityReplacement(shulkerBulletReplacement);
return;
}
int data = packetWrapper.get(Type.INT, 3);
//Rewrite Object Data
if (type.isOrHasParent(EntityTypes1_10.EntityType.ARROW) && data != 0) {
packetWrapper.set(Type.INT, 3, --data);
}
if (type.is(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
Replacement replace = protocol.getItemRewriter().replace(blockId, blockData);
if (replace != null) {
packetWrapper.set(Type.INT, 3, replace.getId() | replace.replaceData(data) << 12);
}
}
if (data > 0) {
packetWrapper.passthrough(Type.SHORT);
packetWrapper.passthrough(Type.SHORT);
packetWrapper.passthrough(Type.SHORT);
} else {
short vX = packetWrapper.read(Type.SHORT);
short vY = packetWrapper.read(Type.SHORT);
short vZ = packetWrapper.read(Type.SHORT);
PacketWrapper velocityPacket = PacketWrapper.create(0x12, null, packetWrapper.user());
velocityPacket.write(Type.VAR_INT, entityId);
velocityPacket.write(Type.SHORT, vX);
velocityPacket.write(Type.SHORT, vY);
velocityPacket.write(Type.SHORT, vZ);
PacketUtil.sendPacket(velocityPacket, Protocol1_8To1_9.class);
}
tracker.getClientEntityTypes().put(entityId, type);
tracker.sendMetadataBuffer(entityId);
});
}
});
//Spawn Experience Orb
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_EXPERIENCE_ORB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.SHORT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.EXPERIENCE_ORB);
tracker.sendMetadataBuffer(entityId);
});
}
});
//Spawn Global Entity
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_GLOBAL_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.LIGHTNING);
tracker.sendMetadataBuffer(entityId);
});
}
});
//Spawn Mob
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
read(Type.UUID);
map(Type.UNSIGNED_BYTE);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BYTE);
map(Type.SHORT);
map(Type.SHORT);
map(Type.SHORT);
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int typeId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
int x = packetWrapper.get(Type.INT, 0);
int y = packetWrapper.get(Type.INT, 1);
int z = packetWrapper.get(Type.INT, 2);
byte pitch = packetWrapper.get(Type.BYTE, 1);
byte yaw = packetWrapper.get(Type.BYTE, 0);
byte headYaw = packetWrapper.get(Type.BYTE, 2);
if (typeId == 69) {
packetWrapper.cancel();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
ShulkerModel shulkerReplacement = new ShulkerModel(packetWrapper.user(), protocol, entityId);
shulkerReplacement.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
shulkerReplacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
shulkerReplacement.setHeadYaw(headYaw * 360f / 256);
tracker.addEntityReplacement(shulkerReplacement);
} else if (typeId == -1 || typeId == 255) {
packetWrapper.cancel();
}
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int typeId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.getTypeFromId(typeId, false));
tracker.sendMetadataBuffer(entityId);
});
handler(wrapper -> {
List<Metadata> metadataList = wrapper.get(Types1_8.METADATA_LIST, 0);
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
EntityModel replacement;
if ((replacement = tracker.getEntityReplacement(entityId)) != null) {
replacement.updateMetadata(metadataList);
} else if (tracker.getClientEntityTypes().containsKey(entityId)) {
protocol.getMetadataRewriter().transform(tracker.getClientEntityTypes().get(entityId), metadataList);
} else {
wrapper.cancel();
}
});
}
});
//Spawn Painting
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
read(Type.UUID);
map(Type.STRING);
map(Type.POSITION1_8);
map(Type.BYTE, Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.PAINTING);
tracker.sendMetadataBuffer(entityId);
});
}
});
//Spawn Player
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.UUID);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.BYTE);
map(Type.BYTE);
handler(packetWrapper -> packetWrapper.write(Type.SHORT, (short) 0));
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST);
this.handler(wrapper -> {
List<Metadata> metadataList = wrapper.get(Types1_8.METADATA_LIST, 0);
protocol.getMetadataRewriter().transform(EntityTypes1_10.EntityType.PLAYER, metadataList);
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.PLAYER);
tracker.sendMetadataBuffer(entityId);
});
}
});
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,16 +15,12 @@
* 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.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.sound.Effect;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.sound.SoundRemapper;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.data.EffectMappings;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.chunks.BaseChunk;
@@ -46,7 +42,7 @@ import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_
import java.util.ArrayList;
public class WorldPackets {
public class WorldPackets1_9 {
public static void register(Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_ENTITY_DATA, new PacketHandlers() {
@@ -55,8 +51,8 @@ public class WorldPackets {
map(Type.POSITION1_8);
map(Type.UNSIGNED_BYTE);
map(Type.NAMED_COMPOUND_TAG);
handler(packetWrapper -> {
CompoundTag tag = packetWrapper.get(Type.NAMED_COMPOUND_TAG, 0);
handler(wrapper -> {
CompoundTag tag = wrapper.get(Type.NAMED_COMPOUND_TAG, 0);
if (tag != null && tag.contains("SpawnData")) {
CompoundTag spawnData = tag.get("SpawnData");
if (spawnData.contains("id")) {
@@ -69,7 +65,6 @@ public class WorldPackets {
}
});
//Block Action
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_ACTION, new PacketHandlers() {
@Override
public void register() {
@@ -77,59 +72,26 @@ public class WorldPackets {
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.VAR_INT);
handler(packetWrapper -> {
int block = packetWrapper.get(Type.VAR_INT, 0);
handler(wrapper -> {
int block = wrapper.get(Type.VAR_INT, 0);
if (block >= 219 && block <= 234) {
packetWrapper.set(Type.VAR_INT, 0, block = 130);
wrapper.set(Type.VAR_INT, 0, 130);
}
});
}
});
//Block Change
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
map(Type.VAR_INT);
handler(packetWrapper -> {
int combined = packetWrapper.get(Type.VAR_INT, 0);
int replacedCombined = protocol.getItemRewriter().replace(combined);
packetWrapper.set(Type.VAR_INT, 0, replacedCombined);
});
}
});
//Server Difficulty
//Multi Block Change
protocol.registerClientbound(ClientboundPackets1_9.MULTI_BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.INT);
map(Type.BLOCK_CHANGE_RECORD_ARRAY);
handler(packetWrapper -> {
for (BlockChangeRecord record : packetWrapper.get(Type.BLOCK_CHANGE_RECORD_ARRAY, 0)) {
int replacedCombined = protocol.getItemRewriter().replace(record.getBlockId());
record.setBlockId(replacedCombined);
}
});
}
});
//Named Sound Effect
protocol.registerClientbound(ClientboundPackets1_9.NAMED_SOUND, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String name = packetWrapper.get(Type.STRING, 0);
name = SoundRemapper.getOldName(name);
handler(wrapper -> {
String name = wrapper.get(Type.STRING, 0);
name = protocol.getMappingData().getMappedNamedSound(name);
if (name == null) {
packetWrapper.cancel();
wrapper.cancel();
} else {
packetWrapper.set(Type.STRING, 0, name);
wrapper.set(Type.STRING, 0, name);
}
});
read(Type.VAR_INT);
@@ -141,59 +103,34 @@ public class WorldPackets {
}
});
//Explosion
protocol.registerClientbound(ClientboundPackets1_9.EXPLOSION, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
handler(packetWrapper -> {
int count = packetWrapper.read(Type.INT);
packetWrapper.write(Type.INT, count);
for (int i = 0; i < count; i++) {
packetWrapper.passthrough(Type.UNSIGNED_BYTE);
packetWrapper.passthrough(Type.UNSIGNED_BYTE);
packetWrapper.passthrough(Type.UNSIGNED_BYTE);
}
});
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
}
});
//Unload Chunk
protocol.registerClientbound(ClientboundPackets1_9.UNLOAD_CHUNK, ClientboundPackets1_8.CHUNK_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
final Environment environment = packetWrapper.user().get(ClientWorld.class).getEnvironment();
handler(wrapper -> {
final Environment environment = wrapper.user().get(ClientWorld.class).getEnvironment();
final int chunkX = packetWrapper.read(Type.INT);
final int chunkZ = packetWrapper.read(Type.INT);
final int chunkX = wrapper.read(Type.INT);
final int chunkZ = wrapper.read(Type.INT);
packetWrapper.write(ChunkType1_8.forEnvironment(environment), new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], null, new ArrayList<>()));
wrapper.write(ChunkType1_8.forEnvironment(environment), new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], null, new ArrayList<>()));
});
}
});
//Chunk Data
protocol.registerClientbound(ClientboundPackets1_9.CHUNK_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
final Environment environment = packetWrapper.user().get(ClientWorld.class).getEnvironment();
handler(wrapper -> {
final Environment environment = wrapper.user().get(ClientWorld.class).getEnvironment();
Chunk chunk = packetWrapper.read(ChunkType1_9_1.forEnvironment(environment));
Chunk chunk = wrapper.read(ChunkType1_9_1.forEnvironment(environment));
for (ChunkSection section : chunk.getSections()) {
if (section == null) continue;
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < palette.size(); i++) {
int block = palette.idByIndex(i);
int replacedBlock = protocol.getItemRewriter().replace(block);
int replacedBlock = protocol.getItemRewriter().handleBlockId(block);
palette.setIdByIndex(i, replacedBlock);
}
}
@@ -208,9 +145,9 @@ public class WorldPackets {
chunk = new BaseChunk(chunk.getX(), chunk.getZ(), true, false, 1, sections, chunk.getBiomeData(), chunk.getBlockEntities());
}
packetWrapper.write(ChunkType1_8.forEnvironment(environment), chunk);
wrapper.write(ChunkType1_8.forEnvironment(environment), chunk);
final UserConnection user = packetWrapper.user();
final UserConnection user = wrapper.user();
chunk.getBlockEntities().forEach(nbt -> {
if (!nbt.contains("x") || !nbt.contains("y") || !nbt.contains("z") || !nbt.contains("id"))
return;
@@ -246,13 +183,16 @@ public class WorldPackets {
updateTileEntity.write(Type.UNSIGNED_BYTE, action);
updateTileEntity.write(Type.NBT, nbt);
PacketUtil.sendPacket(updateTileEntity, Protocol1_8To1_9.class, false, false);
try {
updateTileEntity.scheduleSend(Protocol1_8To1_9.class, false);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().warning("Error sending tile entity update packet: " + e.getMessage());
}
});
});
}
});
//Effect
protocol.registerClientbound(ClientboundPackets1_9.EFFECT, new PacketHandlers() {
@Override
public void register() {
@@ -260,47 +200,45 @@ public class WorldPackets {
map(Type.POSITION1_8);
map(Type.INT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
int id = packetWrapper.get(Type.INT, 0);
id = Effect.getOldId(id);
handler(wrapper -> {
int id = wrapper.get(Type.INT, 0);
id = EffectMappings.getOldId(id);
if (id == -1) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
packetWrapper.set(Type.INT, 0, id);
wrapper.set(Type.INT, 0, id);
if (id == 2001) {
int replacedBlock = protocol.getItemRewriter().replace(packetWrapper.get(Type.INT, 1));
packetWrapper.set(Type.INT, 1, replacedBlock);
int replacedBlock = protocol.getItemRewriter().handleBlockId(wrapper.get(Type.INT, 1));
wrapper.set(Type.INT, 1, replacedBlock);
}
});
}
});
//Particle
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PARTICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
handler(packetWrapper -> {
int type = packetWrapper.get(Type.INT, 0);
handler(wrapper -> {
int type = wrapper.get(Type.INT, 0);
if (type > 41 && !ViaRewind.getConfig().isReplaceParticles()) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
if (type == 42) { // Dragon Breath
packetWrapper.set(Type.INT, 0, 24); // Portal
wrapper.set(Type.INT, 0, 24); // Portal
} else if (type == 43) { // End Rod
packetWrapper.set(Type.INT, 0, 3); // Firework Spark
wrapper.set(Type.INT, 0, 3); // Firework Spark
} else if (type == 44) { // Damage Indicator
packetWrapper.set(Type.INT, 0, 34); // Heart
wrapper.set(Type.INT, 0, 34); // Heart
} else if (type == 45) { // Sweep Attack
packetWrapper.set(Type.INT, 0, 1); // Large Explosion
wrapper.set(Type.INT, 0, 1); // Large Explosion
}
});
}
});
//Map
protocol.registerClientbound(ClientboundPackets1_9.MAP_DATA, new PacketHandlers() {
@Override
public void register() {
@@ -310,25 +248,19 @@ public class WorldPackets {
}
});
//Combat Event
//World Border
//Update Time
//Update Sign
//Sound Effects
protocol.registerClientbound(ClientboundPackets1_9.SOUND, ClientboundPackets1_8.NAMED_SOUND, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int soundId = packetWrapper.read(Type.VAR_INT);
String sound = SoundRemapper.oldNameFromId(soundId);
if (sound == null) {
packetWrapper.cancel();
handler(wrapper -> {
final int soundId = wrapper.read(Type.VAR_INT);
final String soundName = protocol.getMappingData().soundName(soundId);
if (soundName == null) {
wrapper.cancel();
} else {
packetWrapper.write(Type.STRING, sound);
wrapper.write(Type.STRING, protocol.getMappingData().getMappedNamedSound(soundName));
}
});
handler(packetWrapper -> packetWrapper.read(Type.VAR_INT));
read(Type.VAR_INT);
map(Type.INT);
map(Type.INT);
map(Type.INT);
@@ -1,314 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.rewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.utils.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
import java.util.ArrayList;
import java.util.List;
import static com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter.potionNameFromDamage;
public class ReplacementItemRewriter1_8 extends ReplacementItemRewriter<Protocol1_8To1_9> {
public final static String VIA_REWIND_TAG_KEY = "ViaRewind1_8to1_9";
public ReplacementItemRewriter1_8(Protocol1_8To1_9 protocol) {
super(protocol, ProtocolVersion.v1_9);
}
@Override
public void register() {
registerItem(198, new Replacement(50, 0, "End Rod"));
registerItem(434, new Replacement(391, "Beetroot"));
registerItem(435, new Replacement(361, "Beetroot Seeds"));
registerItem(436, new Replacement(282, "Beetroot Soup"));
registerItem(432, new Replacement(322, "Chorus Fruit"));
registerItem(433, new Replacement(393, "Popped Chorus Fruit"));
registerItem(437, new Replacement(373, "Dragons Breath"));
registerItem(443, new Replacement(299, "Elytra"));
registerItem(426, new Replacement(410, "End Crystal"));
registerItem(442, new Replacement(425, "Shield"));
registerItem(439, new Replacement(262, "Spectral Arrow"));
registerItem(440, new Replacement(262, "Tipped Arrow"));
registerItem(444, new Replacement(333, "Spruce Boat"));
registerItem(445, new Replacement(333, "Birch Boat"));
registerItem(446, new Replacement(333, "Jungle Boat"));
registerItem(447, new Replacement(333, "Acacia Boat"));
registerItem(448, new Replacement(333, "Dark Oak Boat"));
registerItem(204, new Replacement(43, 7, "Purpur Double Slab"));
registerItem(205, new Replacement(44, 7, "Purpur Slab"));
registerBlock(209, new Replacement(119));
registerBlock(198, 0, new Replacement(50, 5));
registerBlock(198, 1, new Replacement(50, 5));
registerBlock(198, 2, new Replacement(50, 4));
registerBlock(198, 3, new Replacement(50, 3));
registerBlock(198, 4, new Replacement(50, 2));
registerBlock(198, 5, new Replacement(50, 1));
registerBlock(204, new Replacement(43, 7));
registerBlock(205, 0, new Replacement(44, 7));
registerBlock(205, 8, new Replacement(44, 15));
registerBlock(207, new Replacement(141));
registerBlock(137, new Replacement(137, 0));
registerItemBlock(199, new Replacement(35, 10, "Chorus Plant"));
registerItemBlock(200, new Replacement(35, 2, "Chorus Flower"));
registerItemBlock(201, new Replacement(155, 0, "Purpur Block"));
registerItemBlock(202, new Replacement(155, 2, "Purpur Pillar"));
registerItemBlock(203, 0, new Replacement(156, 0, "Purpur Stairs"));
registerItemBlock(203, 1, new Replacement(156, 1, "Purpur Stairs"));
registerItemBlock(203, 2, new Replacement(156, 2, "Purpur Stairs"));
registerItemBlock(203, 3, new Replacement(156, 3, "Purpur Stairs"));
registerItemBlock(203, 4, new Replacement(156, 4, "Purpur Stairs"));
registerItemBlock(203, 5, new Replacement(156, 5, "Purpur Stairs"));
registerItemBlock(203, 6, new Replacement(156, 6, "Purpur Stairs"));
registerItemBlock(203, 7, new Replacement(156, 7, "Purpur Stairs"));
registerItemBlock(203, 8, new Replacement(156, 8, "Purpur Stairs"));
registerItemBlock(206, new Replacement(121, 0, "Endstone Bricks"));
registerItemBlock(207, new Replacement(141, "Beetroot Block"));
registerItemBlock(208, new Replacement(2, 0, "Grass Path"));
registerItemBlock(209, new Replacement(90, "End Gateway"));
registerItemBlock(210, new Replacement(137, 0, "Repeating Command Block"));
registerItemBlock(211, new Replacement(137, 0, "Chain Command Block"));
registerItemBlock(212, new Replacement(79, 0, "Frosted Ice"));
registerItemBlock(214, new Replacement(87, 0, "Nether Wart Block"));
registerItemBlock(215, new Replacement(112, 0, "Red Nether Brick"));
registerItemBlock(217, new Replacement(166, 0, "Structure Void"));
registerItemBlock(255, new Replacement(137, 0, "Structure Block"));
registerItemBlock(397, 5, new Replacement(397, 0, "Dragon Head"));
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null) item.setTag(tag = new CompoundTag());
CompoundTag viaVersionTag = new CompoundTag();
tag.put(VIA_REWIND_TAG_KEY, viaVersionTag);
viaVersionTag.put("id", new ShortTag((short) item.identifier()));
viaVersionTag.put("data", new ShortTag(item.data()));
CompoundTag display = tag.get("display");
if (display != null && display.contains("Name")) {
viaVersionTag.put("displayName", new StringTag((String) display.get("Name").getValue()));
}
if (display != null && display.contains("Lore")) {
viaVersionTag.put("lore", new ListTag(((ListTag) display.get("Lore")).getValue()));
}
if (tag.contains("ench") || tag.contains("StoredEnchantments")) {
ListTag enchTag = tag.contains("ench") ? tag.get("ench") : tag.get("StoredEnchantments");
List<Tag> lore = new ArrayList<>();
for (Tag ench : new ArrayList<>(enchTag.getValue())) {
short id = ((NumberTag) ((CompoundTag) ench).get("id")).asShort();
short lvl = ((NumberTag) ((CompoundTag) ench).get("lvl")).asShort();
String s;
if (id == 70) {
s = "§r§7Mending ";
} else if (id == 9) {
s = "§r§7Frost Walker ";
} else {
continue;
}
enchTag.remove(ench);
s += Enchantments.ENCHANTMENTS.getOrDefault(lvl, "enchantment.level." + lvl);
lore.add(new StringTag(s));
}
if (!lore.isEmpty()) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
lore.addAll(loreTag.getValue());
loreTag.setValue(lore);
}
}
if (item.data() != 0 && tag.contains("Unbreakable")) {
ByteTag unbreakable = tag.get("Unbreakable");
if (unbreakable.asByte() != 0) {
viaVersionTag.put("Unbreakable", new ByteTag(unbreakable.asByte()));
tag.remove("Unbreakable");
if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
loreTag.add(new StringTag("§9Unbreakable"));
}
}
if (tag.contains("AttributeModifiers")) {
viaVersionTag.put("AttributeModifiers", tag.get("AttributeModifiers").clone());
}
if (item.identifier() == 383 && item.data() == 0) {
int data = 0;
if (tag.contains("EntityTag")) {
CompoundTag entityTag = tag.get("EntityTag");
if (entityTag.contains("id")) {
StringTag id = entityTag.get("id");
if (ItemRewriter.ENTITY_NAME_TO_ID.containsKey(id.getValue())) {
data = ItemRewriter.ENTITY_NAME_TO_ID.get(id.getValue());
} else if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
display.put("Name", new StringTag("§rSpawn " + id.getValue()));
}
}
}
item.setData((short) data);
}
replace(item);
if (item.identifier() == 373 || item.identifier() == 438 || item.identifier() == 441) {
int data = 0;
if (tag.contains("Potion")) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (PotionMappings.POTION_NAME_TO_ID.containsKey(potionName)) {
data = PotionMappings.POTION_NAME_TO_ID.get(potionName);
}
if (item.identifier() == 438) potionName += "_splash";
else if (item.identifier() == 441) potionName += "_lingering";
if ((display == null || !display.contains("Name")) && PotionMappings.POTION_NAME_INDEX.containsKey(potionName)) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
display.put("Name", new StringTag(PotionMappings.POTION_NAME_INDEX.get(potionName)));
}
}
if (item.identifier() == 438 || item.identifier() == 441) {
item.setIdentifier(373);
data += 8192;
}
item.setData((short) data);
}
if (tag.contains("AttributeModifiers")) {
ListTag attributes = tag.get("AttributeModifiers");
for (int i = 0; i < attributes.size(); i++) {
CompoundTag attribute = attributes.get(i);
String name = (String) attribute.get("AttributeName").getValue();
if (!Protocol1_8To1_9.VALID_ATTRIBUTES.contains(name)) {
attributes.remove(attribute);
i--;
}
}
}
if (viaVersionTag.size() == 2 && (short) viaVersionTag.get("id").getValue() == item.identifier() && (short) viaVersionTag.get("data").getValue() == item.data()) {
item.tag().remove(VIA_REWIND_TAG_KEY);
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (item.identifier() == 383 && item.data() != 0) {
if (tag == null) item.setTag(tag = new CompoundTag());
if (!tag.contains("EntityTag") && ItemRewriter.ENTITY_ID_TO_NAME.containsKey((int) item.data())) {
CompoundTag entityTag = new CompoundTag();
entityTag.put("id", new StringTag(ItemRewriter.ENTITY_ID_TO_NAME.get((int) item.data())));
tag.put("EntityTag", entityTag);
}
item.setData((short) 0);
}
if (item.identifier() == 373 && (tag == null || !tag.contains("Potion"))) {
if (tag == null) item.setTag(tag = new CompoundTag());
if (item.data() >= 16384) {
item.setIdentifier(438);
item.setData((short) (item.data() - 8192));
}
String name = item.data() == 8192 ? "water" : potionNameFromDamage(item.data());
tag.put("Potion", new StringTag("minecraft:" + name));
item.setData((short) 0);
}
if (tag == null || !item.tag().contains("ViaRewind1_8to1_9")) return item;
CompoundTag viaVersionTag = tag.remove("ViaRewind1_8to1_9");
item.setIdentifier((short) viaVersionTag.get("id").getValue());
item.setData((Short) viaVersionTag.get("data").getValue());
if (viaVersionTag.contains("noDisplay")) tag.remove("display");
if (viaVersionTag.contains("Unbreakable")) {
tag.put("Unbreakable", viaVersionTag.get("Unbreakable").clone());
}
if (viaVersionTag.contains("displayName")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
StringTag name = display.get("Name");
if (name == null) display.put("Name", new StringTag((String) viaVersionTag.get("displayName").getValue()));
else name.setValue((String) viaVersionTag.get("displayName").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Name");
}
if (viaVersionTag.contains("lore")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
ListTag lore = display.get("Lore");
if (lore == null) display.put("Lore", new ListTag((List<Tag>) viaVersionTag.get("lore").getValue()));
else lore.setValue((List<Tag>) viaVersionTag.get("lore").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Lore");
}
tag.remove("AttributeModifiers");
if (viaVersionTag.contains("AttributeModifiers")) {
tag.put("AttributeModifiers", viaVersionTag.get("AttributeModifiers"));
}
return item;
}
}
@@ -1,885 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* 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.viarewind.protocol.protocol1_8to1_9.sound;
import java.util.HashMap;
public class SoundRemapper {
private final static HashMap<Integer, String> sounds1_9 = new HashMap<>();
private final static HashMap<String, String> sound1_9to1_8 = new HashMap<>();
private static int id;
private static void register1_9Sound(String sound1_9) {
sounds1_9.put(id++, sound1_9);
}
private static void registerSoundRemapping(String sound1_9, String sound1_8) {
sound1_9to1_8.put(sound1_9, sound1_8);
}
public static String oldNameFromId(int id) {
String sound1_9 = sounds1_9.get(id);
if (sound1_9 == null) return null;
return getOldName(sound1_9);
}
public static String getOldName(String sound1_9) {
return sound1_9to1_8.getOrDefault(sound1_9, sound1_9);
}
static {
registerSoundRemapping("entity.zombie_horse.ambient", "mob.horse.zombie.idle");
registerSoundRemapping("block.note.snare", "note.snare");
registerSoundRemapping("block.wood_button.click_off", "random.wood_click");
registerSoundRemapping("block.wood_button.click_on", "random.wood_click");
registerSoundRemapping("block.gravel.break", "dig.gravel");
registerSoundRemapping("block.gravel.place", "dig.gravel");
registerSoundRemapping("entity.arrow.hit", "random.bowhit");
registerSoundRemapping("block.tripwire.detach", "random.bowhit");
registerSoundRemapping("entity.splash_potion.break", "dig.glass");
registerSoundRemapping("block.glass.break", "dig.glass");
registerSoundRemapping("entity.zombie.ambient", "mob.zombie.say");
registerSoundRemapping("entity.zombie_villager.ambient", "mob.zombie.say");
registerSoundRemapping("entity.pig.death", "mob.pig.death");
registerSoundRemapping("entity.mule.hurt", "mob.horse.donkey.hit");
registerSoundRemapping("entity.donkey.hurt", "mob.horse.donkey.hit");
registerSoundRemapping("entity.endermen.ambient", "mob.endermen.idle");
registerSoundRemapping("block.portal.ambient", "portal.portal");
registerSoundRemapping("entity.generic.burn", "random.fizz");
registerSoundRemapping("block.fire.extinguish", "random.fizz");
registerSoundRemapping("block.redstone_torch.burnout", "random.fizz");
registerSoundRemapping("block.lava.extinguish", "random.fizz");
registerSoundRemapping("entity.generic.extinguish_fire", "random.fizz");
registerSoundRemapping("block.note.harp", "note.harp");
registerSoundRemapping("block.snow.hit", "step.snow");
registerSoundRemapping("block.snow.fall", "step.snow");
registerSoundRemapping("block.snow.step", "step.snow");
registerSoundRemapping("entity.arrow.hit_player", "random.successful_hit");
registerSoundRemapping("entity.zombie_pig.hurt", "mob.zombiepig.zpighurt");
registerSoundRemapping("entity.wolf.howl", "mob.wolf.howl");
registerSoundRemapping("entity.firework.launch", "fireworks.launch");
registerSoundRemapping("entity.cow.hurt", "mob.cow.hurt");
registerSoundRemapping("entity.cow.death", "mob.cow.hurt");
registerSoundRemapping("entity.firework.large_blast", "fireworks.largeBlast");
registerSoundRemapping("entity.blaze.hurt", "mob.blaze.hit");
registerSoundRemapping("entity.villager.death", "mob.villager.death");
registerSoundRemapping("entity.blaze.death", "mob.blaze.death");
registerSoundRemapping("entity.zombie_horse.death", "mob.horse.zombie.death");
registerSoundRemapping("entity.silverfish.death", "mob.silverfish.kill");
registerSoundRemapping("entity.endermite.death", "mob.silverfish.kill");
registerSoundRemapping("record.ward", "records.ward");
registerSoundRemapping("entity.wolf.pant", "mob.wolf.panting");
registerSoundRemapping("block.metal.break", "dig.stone");
registerSoundRemapping("block.metal.place", "dig.stone");
registerSoundRemapping("entity.armorstand.place", "dig.stone");
registerSoundRemapping("block.stone.break", "dig.stone");
registerSoundRemapping("block.stone.place", "dig.stone");
registerSoundRemapping("block.anvil.break", "dig.stone");
registerSoundRemapping("block.glass.place", "dig.stone");
registerSoundRemapping("entity.endermen.stare", "mob.endermen.stare");
registerSoundRemapping("entity.small_magmacube.hurt", "mob.slime.small");
registerSoundRemapping("block.slime.fall", "mob.slime.small");
registerSoundRemapping("entity.small_slime.death", "mob.slime.small");
registerSoundRemapping("block.slime.step", "mob.slime.small");
registerSoundRemapping("entity.small_magmacube.death", "mob.slime.small");
registerSoundRemapping("entity.small_slime.hurt", "mob.slime.small");
registerSoundRemapping("block.slime.hit", "mob.slime.small");
registerSoundRemapping("music.nether", "music.game.nether");
registerSoundRemapping("entity.ghast.death", "mob.ghast.death");
registerSoundRemapping("entity.guardian.attack", "mob.guardian.attack");
registerSoundRemapping("block.dispenser.fail", "random.click");
registerSoundRemapping("block.comparator.click", "random.click");
registerSoundRemapping("block.stone_button.click_on", "random.click");
registerSoundRemapping("block.stone_button.click_off", "random.click");
registerSoundRemapping("block.tripwire.click_on", "random.click");
registerSoundRemapping("block.dispenser.dispense", "random.click");
registerSoundRemapping("ui.button.click", "random.click");
registerSoundRemapping("block.lever.click", "random.click");
registerSoundRemapping("block.tripwire.attach", "random.click");
registerSoundRemapping("block.stone_pressureplate.click_on", "random.click");
registerSoundRemapping("block.wood_pressureplate.click_off", "random.click");
registerSoundRemapping("block.stone_pressureplate.click_off", "random.click");
registerSoundRemapping("block.metal_pressureplate.click_off", "random.click");
registerSoundRemapping("block.tripwire.click_off", "random.click");
registerSoundRemapping("block.metal_pressureplate.click_on", "random.click");
registerSoundRemapping("block.wood_pressureplate.click_on", "random.click");
registerSoundRemapping("entity.zombie_pig.ambient", "mob.zombiepig.zpig");
registerSoundRemapping("music.dragon", "music.game.end.dragon");
registerSoundRemapping("entity.firework.twinkle_far", "fireworks.twinkle_far");
registerSoundRemapping("entity.elder_guardian.ambient_land", "mob.guardian.land.idle");
registerSoundRemapping("entity.guardian.ambient_land", "mob.guardian.land.idle");
registerSoundRemapping("block.grass.break", "dig.grass");
registerSoundRemapping("block.grass.place", "dig.grass");
registerSoundRemapping("entity.skeleton.step", "mob.skeleton.step");
registerSoundRemapping("entity.wither.death", "mob.wither.death");
registerSoundRemapping("entity.wolf.hurt", "mob.wolf.hurt");
registerSoundRemapping("entity.pig.saddle", "mob.horse.leather");
registerSoundRemapping("entity.horse.saddle", "mob.horse.leather");
registerSoundRemapping("entity.bat.loop", "mob.bat.loop");
registerSoundRemapping("entity.ghast.hurt", "mob.ghast.scream");
registerSoundRemapping("entity.creeper.death", "mob.creeper.death");
registerSoundRemapping("entity.horse.gallop", "mob.horse.gallop");
registerSoundRemapping("entity.wither.spawn", "mob.wither.spawn");
registerSoundRemapping("entity.endermen.hurt", "mob.endermen.hit");
registerSoundRemapping("entity.creeper.hurt", "mob.creeper.say");
registerSoundRemapping("entity.horse.step_wood", "mob.horse.wood");
registerSoundRemapping("entity.rabbit.death", "mob.rabbit.death");
registerSoundRemapping("entity.zombie_villager.converted", "mob.zombie.unfect");
registerSoundRemapping("block.anvil.use", "random.anvil_use");
registerSoundRemapping("block.enderchest.close", "random.chestclosed");
registerSoundRemapping("entity.mooshroom.shear", "mob.sheep.shear");
registerSoundRemapping("entity.sheep.shear", "mob.sheep.shear");
registerSoundRemapping("entity.item.pickup", "random.pop");
registerSoundRemapping("entity.bat.death", "mob.bat.death");
registerSoundRemapping("block.wood.place", "dig.wood");
registerSoundRemapping("block.wood.break", "dig.wood");
registerSoundRemapping("block.ladder.place", "dig.wood");
registerSoundRemapping("entity.armorstand.fall", "dig.wood");
registerSoundRemapping("block.ladder.break", "dig.wood");
registerSoundRemapping("record.chirp", "records.chirp");
registerSoundRemapping("entity.mule.death", "mob.horse.donkey.death");
registerSoundRemapping("entity.donkey.death", "mob.horse.donkey.death");
registerSoundRemapping("entity.firework.blast", "fireworks.blast");
registerSoundRemapping("entity.zombie_pig.angry", "mob.zombiepig.zpigangry");
registerSoundRemapping("entity.guardian.flop", "mob.guardian.flop");
registerSoundRemapping("entity.villager.yes", "mob.villager.yes");
registerSoundRemapping("entity.ghast.warn", "mob.ghast.charge");
registerSoundRemapping("entity.tnt.primed", "creeper.primed");
registerSoundRemapping("entity.creeper.primed", "creeper.primed");
registerSoundRemapping("block.sand.place", "dig.sand");
registerSoundRemapping("block.sand.break", "dig.sand");
registerSoundRemapping("entity.chicken.ambient", "mob.chicken.say");
registerSoundRemapping("record.13", "records.13");
registerSoundRemapping("record.11", "records.11");
registerSoundRemapping("entity.elder_guardian.death", "mob.guardian.elder.death");
registerSoundRemapping("entity.firework.twinkle", "fireworks.twinkle");
registerSoundRemapping("entity.skeleton_horse.death", "mob.horse.skeleton.death");
registerSoundRemapping("weather.rain", "ambient.weather.rain");
registerSoundRemapping("weather.rain.above", "ambient.weather.rain");
registerSoundRemapping("block.portal.trigger", "portal.trigger");
registerSoundRemapping("block.enderchest.open", "random.chestopen");
registerSoundRemapping("entity.horse.land", "mob.horse.land");
registerSoundRemapping("entity.endermite.step", "mob.silverfish.step");
registerSoundRemapping("entity.silverfish.step", "mob.silverfish.step");
registerSoundRemapping("entity.bat.takeoff", "mob.bat.takeoff");
registerSoundRemapping("entity.villager.no", "mob.villager.no");
registerSoundRemapping("entity.irongolem.step", "mob.irongolem.walk");
registerSoundRemapping("block.note.hat", "note.hat");
registerSoundRemapping("entity.zombie.attack_iron_door", "mob.zombie.metal");
registerSoundRemapping("entity.villager.trading", "mob.villager.haggle");
registerSoundRemapping("item.firecharge.use", "mob.ghast.fireball");
registerSoundRemapping("entity.ghast.shoot", "mob.ghast.fireball");
registerSoundRemapping("entity.enderdragon.shoot", "mob.ghast.fireball");
registerSoundRemapping("entity.blaze.shoot", "mob.ghast.fireball");
registerSoundRemapping("music.credits", "music.game.end.credits");
registerSoundRemapping("entity.irongolem.death", "mob.irongolem.death");
registerSoundRemapping("entity.item.break", "random.break");
registerSoundRemapping("item.shield.break", "random.break");
registerSoundRemapping("record.mellohi", "records.mellohi");
registerSoundRemapping("entity.zombie_villager.cure", "mob.zombie.remedy");
registerSoundRemapping("entity.enderpearl.throw", "random.bow");
registerSoundRemapping("block.dispenser.launch", "random.bow");
registerSoundRemapping("entity.skeleton.shoot", "random.bow");
registerSoundRemapping("entity.endereye.launch", "random.bow");
registerSoundRemapping("entity.firework.shoot", "random.bow");
registerSoundRemapping("entity.experience_bottle.throw", "random.bow");
registerSoundRemapping("entity.snowman.shoot", "random.bow");
registerSoundRemapping("entity.arrow.shoot", "random.bow");
registerSoundRemapping("entity.egg.throw", "random.bow");
registerSoundRemapping("entity.snowball.throw", "random.bow");
registerSoundRemapping("entity.bobber.throw", "random.bow");
registerSoundRemapping("entity.lingeringpotion.throw", "random.bow");
registerSoundRemapping("entity.splash_potion.throw", "random.bow");
registerSoundRemapping("entity.villager.ambient", "mob.villager.idle");
registerSoundRemapping("block.cloth.hit", "step.cloth");
registerSoundRemapping("block.cloth.step", "step.cloth");
registerSoundRemapping("block.cloth.fall", "step.cloth");
registerSoundRemapping("entity.silverfish.hurt", "mob.silverfish.hit");
registerSoundRemapping("entity.endermite.hurt", "mob.silverfish.hit");
registerSoundRemapping("music.game", "music.game");
registerSoundRemapping("block.lava.ambient", "liquid.lava");
registerSoundRemapping("record.mall", "records.mall");
registerSoundRemapping("entity.blaze.burn", "fire.fire");
registerSoundRemapping("block.fire.ambient", "fire.fire");
registerSoundRemapping("entity.zombie.attack_door_wood", "mob.zombie.wood");
registerSoundRemapping("entity.chicken.step", "mob.chicken.step");
registerSoundRemapping("record.stal", "records.stal");
registerSoundRemapping("entity.elder_guardian.hurt_land", "mob.guardian.land.hit");
registerSoundRemapping("entity.guardian.hurt_land", "mob.guardian.land.hit");
registerSoundRemapping("entity.chicken.egg", "mob.chicken.plop");
registerSoundRemapping("entity.donkey.chest", "mob.chicken.plop");
registerSoundRemapping("entity.enderdragon.flap", "mob.enderdragon.wings");
registerSoundRemapping("block.grass.step", "step.grass");
registerSoundRemapping("block.grass.fall", "step.grass");
registerSoundRemapping("block.grass.hit", "step.grass");
registerSoundRemapping("entity.horse.breathe", "mob.horse.breathe");
registerSoundRemapping("entity.mule.ambient", "mob.horse.donkey.idle");
registerSoundRemapping("entity.donkey.ambient", "mob.horse.donkey.idle");
registerSoundRemapping("record.far", "records.far");
registerSoundRemapping("entity.spider.step", "mob.spider.step");
registerSoundRemapping("entity.cow.ambient", "mob.cow.say");
registerSoundRemapping("entity.horse.jump", "mob.horse.jump");
registerSoundRemapping("entity.horse.step", "mob.horse.soft");
registerSoundRemapping("entity.guardian.hurt", "mob.guardian.hit");
registerSoundRemapping("entity.enderdragon.death", "mob.enderdragon.end");
registerSoundRemapping("entity.zombie_villager.step", "mob.zombie.step");
registerSoundRemapping("entity.zombie.step", "mob.zombie.step");
registerSoundRemapping("entity.enderdragon.ambient", "mob.enderdragon.growl");
registerSoundRemapping("entity.enderdragon.growl", "mob.enderdragon.growl");
registerSoundRemapping("entity.wolf.shake", "mob.wolf.shake");
registerSoundRemapping("entity.endermen.death", "mob.endermen.death");
registerSoundRemapping("block.anvil.place", "random.anvil_land");
registerSoundRemapping("block.anvil.land", "random.anvil_land");
registerSoundRemapping("entity.minecart.inside", "minecart.inside");
registerSoundRemapping("entity.slime.squish", "mob.slime.big");
registerSoundRemapping("entity.magmacube.hurt", "mob.slime.big");
registerSoundRemapping("entity.magmacube.death", "mob.slime.big");
registerSoundRemapping("block.slime.break", "mob.slime.big");
registerSoundRemapping("block.slime.place", "mob.slime.big");
registerSoundRemapping("entity.slime.jump", "mob.slime.big");
registerSoundRemapping("entity.slime.hurt", "mob.slime.big");
registerSoundRemapping("entity.slime.death", "mob.slime.big");
registerSoundRemapping("block.water.ambient", "liquid.water");
registerSoundRemapping("entity.pig.hurt", "mob.pig.say");
registerSoundRemapping("entity.pig.ambient", "mob.pig.say");
registerSoundRemapping("entity.wither.shoot", "mob.wither.shoot");
registerSoundRemapping("record.blocks", "records.blocks");
registerSoundRemapping("item.firecharge.use", "item.fireCharge.use");
registerSoundRemapping("entity.ghast.shoot", "item.fireCharge.use");
registerSoundRemapping("entity.enderdragon.shoot", "item.fireCharge.use");
registerSoundRemapping("entity.blaze.shoot", "item.fireCharge.use");
registerSoundRemapping("block.sand.hit", "step.sand");
registerSoundRemapping("block.sand.step", "step.sand");
registerSoundRemapping("block.sand.fall", "step.sand");
registerSoundRemapping("music.creative", "music.game.creative");
registerSoundRemapping("entity.irongolem.hurt", "mob.irongolem.hit");
registerSoundRemapping("entity.horse.death", "mob.horse.death");
registerSoundRemapping("entity.bat.hurt", "mob.bat.hurt");
registerSoundRemapping("entity.ghast.scream", "mob.ghast.affectionate_scream");
registerSoundRemapping("entity.elder_guardian.ambient", "mob.guardian.elder.idle");
registerSoundRemapping("entity.zombie_pig.death", "mob.zombiepig.zpigdeath");
registerSoundRemapping("entity.lightning.thunder", "ambient.weather.thunder");
registerSoundRemapping("entity.minecart.riding", "minecart.base");
registerSoundRemapping("block.ladder.step", "step.ladder");
registerSoundRemapping("block.ladder.fall", "step.ladder");
registerSoundRemapping("block.ladder.hit", "step.ladder");
registerSoundRemapping("entity.donkey.angry", "mob.horse.donkey.angry");
registerSoundRemapping("ambient.cave", "ambient.cave.cave");
registerSoundRemapping("record.wait", "records.wait");
registerSoundRemapping("entity.firework.blast_far", "fireworks.blast_far");
registerSoundRemapping("entity.generic.drink", "random.drink");
registerSoundRemapping("music.menu", "music.menu");
registerSoundRemapping("entity.cat.hiss", "mob.cat.hiss");
registerSoundRemapping("block.note.basedrum", "note.bd");
registerSoundRemapping("entity.spider.ambient", "mob.spider.say");
registerSoundRemapping("entity.spider.hurt", "mob.spider.say");
registerSoundRemapping("block.stone.fall", "step.stone");
registerSoundRemapping("block.anvil.fall", "step.stone");
registerSoundRemapping("block.metal.step", "step.stone");
registerSoundRemapping("block.stone.hit", "step.stone");
registerSoundRemapping("block.glass.fall", "step.stone");
registerSoundRemapping("block.stone.step", "step.stone");
registerSoundRemapping("block.anvil.step", "step.stone");
registerSoundRemapping("block.metal.hit", "step.stone");
registerSoundRemapping("block.glass.step", "step.stone");
registerSoundRemapping("block.metal.fall", "step.stone");
registerSoundRemapping("block.glass.hit", "step.stone");
registerSoundRemapping("block.anvil.hit", "step.stone");
registerSoundRemapping("entity.player.levelup", "random.levelup");
registerSoundRemapping("block.lava.pop", "liquid.lavapop");
registerSoundRemapping("entity.sheep.hurt", "mob.sheep.say");
registerSoundRemapping("entity.sheep.death", "mob.sheep.say");
registerSoundRemapping("entity.sheep.ambient", "mob.sheep.say");
registerSoundRemapping("entity.skeleton.ambient", "mob.skeleton.say");
registerSoundRemapping("entity.blaze.ambient", "mob.blaze.breathe");
registerSoundRemapping("entity.bat.ambient", "mob.bat.idle");
registerSoundRemapping("entity.magmacube.squish", "mob.magmacube.big");
registerSoundRemapping("entity.horse.ambient", "mob.horse.idle");
registerSoundRemapping("entity.zombie_horse.hurt", "mob.horse.zombie.hit");
registerSoundRemapping("entity.irongolem.attack", "mob.irongolem.throw");
registerSoundRemapping("block.cloth.break", "dig.cloth");
registerSoundRemapping("block.cloth.place", "dig.cloth");
registerSoundRemapping("block.gravel.fall", "step.gravel");
registerSoundRemapping("block.gravel.step", "step.gravel");
registerSoundRemapping("block.gravel.hit", "step.gravel");
registerSoundRemapping("entity.endermite.ambient", "mob.silverfish.say");
registerSoundRemapping("entity.silverfish.ambient", "mob.silverfish.say");
registerSoundRemapping("entity.cat.purr", "mob.cat.purr");
registerSoundRemapping("entity.zombie.infect", "mob.zombie.infect");
registerSoundRemapping("entity.generic.eat", "random.eat");
registerSoundRemapping("entity.wolf.ambient", "mob.wolf.bark");
registerSoundRemapping("entity.tnt.primed", "game.tnt.primed");
registerSoundRemapping("entity.creeper.primed", "game.tnt.primed");
registerSoundRemapping("entity.sheep.step", "mob.sheep.step");
registerSoundRemapping("entity.zombie_villager.death", "mob.zombie.death");
registerSoundRemapping("entity.zombie.death", "mob.zombie.death");
registerSoundRemapping("entity.shulker.teleport", "mob.endermen.portal");
registerSoundRemapping("item.chorus_fruit.teleport", "mob.endermen.portal");
registerSoundRemapping("entity.endermen.teleport", "mob.endermen.portal");
registerSoundRemapping("entity.horse.angry", "mob.horse.angry");
registerSoundRemapping("entity.wolf.growl", "mob.wolf.growl");
registerSoundRemapping("block.snow.break", "dig.snow");
registerSoundRemapping("block.snow.place", "dig.snow");
registerSoundRemapping("block.piston.extend", "tile.piston.out");
registerSoundRemapping("entity.player.burp", "random.burp");
registerSoundRemapping("entity.cow.step", "mob.cow.step");
registerSoundRemapping("entity.wither.hurt", "mob.wither.hurt");
registerSoundRemapping("entity.guardian.death_land", "mob.guardian.land.death");
registerSoundRemapping("entity.elder_guardian.death_land", "mob.guardian.land.death");
registerSoundRemapping("music.end", "music.game.end");
registerSoundRemapping("entity.chicken.hurt", "mob.chicken.hurt");
registerSoundRemapping("entity.chicken.death", "mob.chicken.hurt");
registerSoundRemapping("entity.wolf.step", "mob.wolf.step");
registerSoundRemapping("entity.wolf.death", "mob.wolf.death");
registerSoundRemapping("entity.wolf.whine", "mob.wolf.whine");
registerSoundRemapping("block.note.pling", "note.pling");
registerSoundRemapping("entity.rabbit.hurt", "mob.rabbit.hurt");
registerSoundRemapping("entity.cat.purreow", "mob.cat.purreow");
registerSoundRemapping("entity.firework.large_blast_far", "fireworks.largeBlast_far");
registerSoundRemapping("entity.skeleton.hurt", "mob.skeleton.hurt");
registerSoundRemapping("entity.spider.death", "mob.spider.death");
registerSoundRemapping("block.anvil.destroy", "random.anvil_break");
registerSoundRemapping("record.cat", "records.cat");
registerSoundRemapping("entity.wither.ambient", "mob.wither.idle");
registerSoundRemapping("entity.elder_guardian.hurt", "mob.guardian.elder.hit");
registerSoundRemapping("entity.endermen.scream", "mob.endermen.scream");
registerSoundRemapping("entity.cat.death", "mob.cat.hitt");
registerSoundRemapping("entity.cat.hurt", "mob.cat.hitt");
registerSoundRemapping("entity.small_magmacube.squish", "mob.magmacube.small");
registerSoundRemapping("item.flintandsteel.use", "fire.ignite");
registerSoundRemapping("entity.enderdragon.hurt", "mob.enderdragon.hit");
registerSoundRemapping("entity.zombie.hurt", "mob.zombie.hurt");
registerSoundRemapping("entity.zombie_villager.hurt", "mob.zombie.hurt");
registerSoundRemapping("entity.enderdragon_fireball.explode", "random.explode");
registerSoundRemapping("entity.generic.explode", "random.explode");
registerSoundRemapping("entity.lightning.impact", "random.explode");
registerSoundRemapping("block.end_gateway.spawn", "random.explode");
registerSoundRemapping("entity.slime.attack", "mob.slime.attack");
registerSoundRemapping("entity.magmacube.jump", "mob.magmacube.jump");
registerSoundRemapping("entity.bobber.splash", "random.splash");
registerSoundRemapping("entity.skeleton_horse.hurt", "mob.horse.skeleton.hit");
registerSoundRemapping("entity.rabbit.jump", "mob.rabbit.hop");
registerSoundRemapping("entity.ghast.ambient", "mob.ghast.moan");
registerSoundRemapping("entity.elder_guardian.curse", "mob.guardian.curse");
registerSoundRemapping("entity.splash_potion.break", "game.potion.smash");
registerSoundRemapping("block.glass.break", "game.potion.smash");
registerSoundRemapping("block.note.bass", "note.bassattack");
registerSoundRemapping("block.dispenser.fail", "gui.button.press");
registerSoundRemapping("block.comparator.click", "gui.button.press");
registerSoundRemapping("block.stone_button.click_on", "gui.button.press");
registerSoundRemapping("block.stone_button.click_off", "gui.button.press");
registerSoundRemapping("block.tripwire.click_on", "gui.button.press");
registerSoundRemapping("block.dispenser.dispense", "gui.button.press");
registerSoundRemapping("ui.button.click", "gui.button.press");
registerSoundRemapping("block.lever.click", "gui.button.press");
registerSoundRemapping("block.tripwire.attach", "gui.button.press");
registerSoundRemapping("block.stone_pressureplate.click_on", "gui.button.press");
registerSoundRemapping("block.wood_pressureplate.click_off", "gui.button.press");
registerSoundRemapping("block.stone_pressureplate.click_off", "gui.button.press");
registerSoundRemapping("block.metal_pressureplate.click_off", "gui.button.press");
registerSoundRemapping("block.tripwire.click_off", "gui.button.press");
registerSoundRemapping("block.metal_pressureplate.click_on", "gui.button.press");
registerSoundRemapping("block.wood_pressureplate.click_on", "gui.button.press");
registerSoundRemapping("entity.experience_orb.touch", "random.orb");
registerSoundRemapping("entity.experience_orb.pickup", "random.orb");
registerSoundRemapping("entity.wither.break_block", "mob.zombie.woodbreak");
registerSoundRemapping("entity.zombie.break_door_wood", "mob.zombie.woodbreak");
registerSoundRemapping("entity.horse.armor", "mob.horse.armor");
registerSoundRemapping("entity.rabbit.ambient", "mob.rabbit.idle");
registerSoundRemapping("block.piston.contract", "tile.piston.in");
registerSoundRemapping("entity.cat.ambient", "mob.cat.meow");
registerSoundRemapping("entity.pig.step", "mob.pig.step");
registerSoundRemapping("record.strad", "records.strad");
registerSoundRemapping("block.wood.hit", "step.wood");
registerSoundRemapping("block.wood.fall", "step.wood");
registerSoundRemapping("block.wood.step", "step.wood");
registerSoundRemapping("block.portal.travel", "portal.travel");
registerSoundRemapping("entity.guardian.death", "mob.guardian.death");
registerSoundRemapping("entity.skeleton.death", "mob.skeleton.death");
registerSoundRemapping("entity.horse.hurt", "mob.horse.hit");
registerSoundRemapping("entity.villager.hurt", "mob.villager.hit");
registerSoundRemapping("entity.skeleton_horse.ambient", "mob.horse.skeleton.idle");
registerSoundRemapping("block.chest.open", "random.chestopen");
registerSoundRemapping("block.chest.close", "random.chestclosed");
registerSoundRemapping("entity.player.hurt_on_fire", "game.player.hurt");
registerSoundRemapping("entity.player.hurt_drown", "game.player.hurt");
registerSoundRemapping("entity.generic.swim", "game.neutral.swim");
registerSoundRemapping("entity.hostile.swim", "game.hostile.swim");
registerSoundRemapping("entity.player.swim", "game.player.swim");
registerSoundRemapping("entity.player.splash", "game.player.swim.splash");
registerSoundRemapping("entity.hostile.splash", "game.hostile.swim.splash");
registerSoundRemapping("entity.generic.splash", "game.neutral.swim.splash");
registerSoundRemapping("entity.generic.death", "game.neutral.die");
registerSoundRemapping("entity.hostile.hurt", "game.hostile.hurt");
registerSoundRemapping("entity.player.hurt", "game.player.hurt");
registerSoundRemapping("entity.hostile.death", "game.hostile.die");
registerSoundRemapping("entity.generic.hurt", "game.neutral.hurt");
registerSoundRemapping("entity.player.death", "game.player.die");
registerSoundRemapping("entity.player.big_fall", "game.player.hurt.fall.big");
registerSoundRemapping("entity.generic.big_fall", "game.neutral.hurt.fall.big");
registerSoundRemapping("entity.hostile.big_fall", "game.hostile.hurt.fall.big");
registerSoundRemapping("entity.hostile.small_fall", "game.hostile.hurt.fall.small");
registerSoundRemapping("entity.player.small_fall", "game.player.hurt.fall.small");
registerSoundRemapping("entity.generic.small_fall", "game.neutral.hurt.fall.small");
register1_9Sound("ambient.cave");
register1_9Sound("block.anvil.break");
register1_9Sound("block.anvil.destroy");
register1_9Sound("block.anvil.fall");
register1_9Sound("block.anvil.hit");
register1_9Sound("block.anvil.land");
register1_9Sound("block.anvil.place");
register1_9Sound("block.anvil.step");
register1_9Sound("block.anvil.use");
register1_9Sound("block.brewing_stand.brew");
register1_9Sound("block.chest.close");
register1_9Sound("block.chest.locked");
register1_9Sound("block.chest.open");
register1_9Sound("block.chorus_flower.death");
register1_9Sound("block.chorus_flower.grow");
register1_9Sound("block.cloth.break");
register1_9Sound("block.cloth.fall");
register1_9Sound("block.cloth.hit");
register1_9Sound("block.cloth.place");
register1_9Sound("block.cloth.step");
register1_9Sound("block.comparator.click");
register1_9Sound("block.dispenser.dispense");
register1_9Sound("block.dispenser.fail");
register1_9Sound("block.dispenser.launch");
register1_9Sound("block.end_gateway.spawn");
register1_9Sound("block.enderchest.close");
register1_9Sound("block.enderchest.open");
register1_9Sound("block.fence_gate.close");
register1_9Sound("block.fence_gate.open");
register1_9Sound("block.fire.ambient");
register1_9Sound("block.fire.extinguish");
register1_9Sound("block.furnace.fire_crackle");
register1_9Sound("block.glass.break");
register1_9Sound("block.glass.fall");
register1_9Sound("block.glass.hit");
register1_9Sound("block.glass.place");
register1_9Sound("block.glass.step");
register1_9Sound("block.grass.break");
register1_9Sound("block.grass.fall");
register1_9Sound("block.grass.hit");
register1_9Sound("block.grass.place");
register1_9Sound("block.grass.step");
register1_9Sound("block.gravel.break");
register1_9Sound("block.gravel.fall");
register1_9Sound("block.gravel.hit");
register1_9Sound("block.gravel.place");
register1_9Sound("block.gravel.step");
register1_9Sound("block.iron_door.close");
register1_9Sound("block.iron_door.open");
register1_9Sound("block.iron_trapdoor.close");
register1_9Sound("block.iron_trapdoor.open");
register1_9Sound("block.ladder.break");
register1_9Sound("block.ladder.fall");
register1_9Sound("block.ladder.hit");
register1_9Sound("block.ladder.place");
register1_9Sound("block.ladder.step");
register1_9Sound("block.lava.ambient");
register1_9Sound("block.lava.extinguish");
register1_9Sound("block.lava.pop");
register1_9Sound("block.lever.click");
register1_9Sound("block.metal.break");
register1_9Sound("block.metal.fall");
register1_9Sound("block.metal.hit");
register1_9Sound("block.metal.place");
register1_9Sound("block.metal.step");
register1_9Sound("block.metal_pressureplate.click_off");
register1_9Sound("block.metal_pressureplate.click_on");
register1_9Sound("block.note.basedrum");
register1_9Sound("block.note.bass");
register1_9Sound("block.note.harp");
register1_9Sound("block.note.hat");
register1_9Sound("block.note.pling");
register1_9Sound("block.note.snare");
register1_9Sound("block.piston.contract");
register1_9Sound("block.piston.extend");
register1_9Sound("block.portal.ambient");
register1_9Sound("block.portal.travel");
register1_9Sound("block.portal.trigger");
register1_9Sound("block.redstone_torch.burnout");
register1_9Sound("block.sand.break");
register1_9Sound("block.sand.fall");
register1_9Sound("block.sand.hit");
register1_9Sound("block.sand.place");
register1_9Sound("block.sand.step");
register1_9Sound("block.slime.break");
register1_9Sound("block.slime.fall");
register1_9Sound("block.slime.hit");
register1_9Sound("block.slime.place");
register1_9Sound("block.slime.step");
register1_9Sound("block.snow.break");
register1_9Sound("block.snow.fall");
register1_9Sound("block.snow.hit");
register1_9Sound("block.snow.place");
register1_9Sound("block.snow.step");
register1_9Sound("block.stone.break");
register1_9Sound("block.stone.fall");
register1_9Sound("block.stone.hit");
register1_9Sound("block.stone.place");
register1_9Sound("block.stone.step");
register1_9Sound("block.stone_button.click_off");
register1_9Sound("block.stone_button.click_on");
register1_9Sound("block.stone_pressureplate.click_off");
register1_9Sound("block.stone_pressureplate.click_on");
register1_9Sound("block.tripwire.attach");
register1_9Sound("block.tripwire.click_off");
register1_9Sound("block.tripwire.click_on");
register1_9Sound("block.tripwire.detach");
register1_9Sound("block.water.ambient");
register1_9Sound("block.waterlily.place");
register1_9Sound("block.wood.break");
register1_9Sound("block.wood.fall");
register1_9Sound("block.wood.hit");
register1_9Sound("block.wood.place");
register1_9Sound("block.wood.step");
register1_9Sound("block.wood_button.click_off");
register1_9Sound("block.wood_button.click_on");
register1_9Sound("block.wood_pressureplate.click_off");
register1_9Sound("block.wood_pressureplate.click_on");
register1_9Sound("block.wooden_door.close");
register1_9Sound("block.wooden_door.open");
register1_9Sound("block.wooden_trapdoor.close");
register1_9Sound("block.wooden_trapdoor.open");
register1_9Sound("enchant.thorns.hit");
register1_9Sound("entity.armorstand.break");
register1_9Sound("entity.armorstand.fall");
register1_9Sound("entity.armorstand.hit");
register1_9Sound("entity.armorstand.place");
register1_9Sound("entity.arrow.hit");
register1_9Sound("entity.arrow.hit_player");
register1_9Sound("entity.arrow.shoot");
register1_9Sound("entity.bat.ambient");
register1_9Sound("entity.bat.death");
register1_9Sound("entity.bat.hurt");
register1_9Sound("entity.bat.loop");
register1_9Sound("entity.bat.takeoff");
register1_9Sound("entity.blaze.ambient");
register1_9Sound("entity.blaze.burn");
register1_9Sound("entity.blaze.death");
register1_9Sound("entity.blaze.hurt");
register1_9Sound("entity.blaze.shoot");
register1_9Sound("entity.bobber.splash");
register1_9Sound("entity.bobber.throw");
register1_9Sound("entity.cat.ambient");
register1_9Sound("entity.cat.death");
register1_9Sound("entity.cat.hiss");
register1_9Sound("entity.cat.hurt");
register1_9Sound("entity.cat.purr");
register1_9Sound("entity.cat.purreow");
register1_9Sound("entity.chicken.ambient");
register1_9Sound("entity.chicken.death");
register1_9Sound("entity.chicken.egg");
register1_9Sound("entity.chicken.hurt");
register1_9Sound("entity.chicken.step");
register1_9Sound("entity.cow.ambient");
register1_9Sound("entity.cow.death");
register1_9Sound("entity.cow.hurt");
register1_9Sound("entity.cow.milk");
register1_9Sound("entity.cow.step");
register1_9Sound("entity.creeper.death");
register1_9Sound("entity.creeper.hurt");
register1_9Sound("entity.creeper.primed");
register1_9Sound("entity.donkey.ambient");
register1_9Sound("entity.donkey.angry");
register1_9Sound("entity.donkey.chest");
register1_9Sound("entity.donkey.death");
register1_9Sound("entity.donkey.hurt");
register1_9Sound("entity.egg.throw");
register1_9Sound("entity.elder_guardian.ambient");
register1_9Sound("entity.elder_guardian.ambient_land");
register1_9Sound("entity.elder_guardian.curse");
register1_9Sound("entity.elder_guardian.death");
register1_9Sound("entity.elder_guardian.death_land");
register1_9Sound("entity.elder_guardian.hurt");
register1_9Sound("entity.elder_guardian.hurt_land");
register1_9Sound("entity.enderdragon.ambient");
register1_9Sound("entity.enderdragon.death");
register1_9Sound("entity.enderdragon.flap");
register1_9Sound("entity.enderdragon.growl");
register1_9Sound("entity.enderdragon.hurt");
register1_9Sound("entity.enderdragon.shoot");
register1_9Sound("entity.enderdragon_fireball.explode");
register1_9Sound("entity.endereye.launch");
register1_9Sound("entity.endermen.ambient");
register1_9Sound("entity.endermen.death");
register1_9Sound("entity.endermen.hurt");
register1_9Sound("entity.endermen.scream");
register1_9Sound("entity.endermen.stare");
register1_9Sound("entity.endermen.teleport");
register1_9Sound("entity.endermite.ambient");
register1_9Sound("entity.endermite.death");
register1_9Sound("entity.endermite.hurt");
register1_9Sound("entity.endermite.step");
register1_9Sound("entity.enderpearl.throw");
register1_9Sound("entity.experience_bottle.throw");
register1_9Sound("entity.experience_orb.pickup");
register1_9Sound("entity.experience_orb.touch");
register1_9Sound("entity.firework.blast");
register1_9Sound("entity.firework.blast_far");
register1_9Sound("entity.firework.large_blast");
register1_9Sound("entity.firework.large_blast_far");
register1_9Sound("entity.firework.launch");
register1_9Sound("entity.firework.shoot");
register1_9Sound("entity.firework.twinkle");
register1_9Sound("entity.firework.twinkle_far");
register1_9Sound("entity.generic.big_fall");
register1_9Sound("entity.generic.burn");
register1_9Sound("entity.generic.death");
register1_9Sound("entity.generic.drink");
register1_9Sound("entity.generic.eat");
register1_9Sound("entity.generic.explode");
register1_9Sound("entity.generic.extinguish_fire");
register1_9Sound("entity.generic.hurt");
register1_9Sound("entity.generic.small_fall");
register1_9Sound("entity.generic.splash");
register1_9Sound("entity.generic.swim");
register1_9Sound("entity.ghast.ambient");
register1_9Sound("entity.ghast.death");
register1_9Sound("entity.ghast.hurt");
register1_9Sound("entity.ghast.scream");
register1_9Sound("entity.ghast.shoot");
register1_9Sound("entity.ghast.warn");
register1_9Sound("entity.guardian.ambient");
register1_9Sound("entity.guardian.ambient_land");
register1_9Sound("entity.guardian.attack");
register1_9Sound("entity.guardian.death");
register1_9Sound("entity.guardian.death_land");
register1_9Sound("entity.guardian.flop");
register1_9Sound("entity.guardian.hurt");
register1_9Sound("entity.guardian.hurt_land");
register1_9Sound("entity.horse.ambient");
register1_9Sound("entity.horse.angry");
register1_9Sound("entity.horse.armor");
register1_9Sound("entity.horse.breathe");
register1_9Sound("entity.horse.death");
register1_9Sound("entity.horse.eat");
register1_9Sound("entity.horse.gallop");
register1_9Sound("entity.horse.hurt");
register1_9Sound("entity.horse.jump");
register1_9Sound("entity.horse.land");
register1_9Sound("entity.horse.saddle");
register1_9Sound("entity.horse.step");
register1_9Sound("entity.horse.step_wood");
register1_9Sound("entity.hostile.big_fall");
register1_9Sound("entity.hostile.death");
register1_9Sound("entity.hostile.hurt");
register1_9Sound("entity.hostile.small_fall");
register1_9Sound("entity.hostile.splash");
register1_9Sound("entity.hostile.swim");
register1_9Sound("entity.irongolem.attack");
register1_9Sound("entity.irongolem.death");
register1_9Sound("entity.irongolem.hurt");
register1_9Sound("entity.irongolem.step");
register1_9Sound("entity.item.break");
register1_9Sound("entity.item.pickup");
register1_9Sound("entity.itemframe.add_item");
register1_9Sound("entity.itemframe.break");
register1_9Sound("entity.itemframe.place");
register1_9Sound("entity.itemframe.remove_item");
register1_9Sound("entity.itemframe.rotate_item");
register1_9Sound("entity.leashknot.break");
register1_9Sound("entity.leashknot.place");
register1_9Sound("entity.lightning.impact");
register1_9Sound("entity.lightning.thunder");
register1_9Sound("entity.lingeringpotion.throw");
register1_9Sound("entity.magmacube.death");
register1_9Sound("entity.magmacube.hurt");
register1_9Sound("entity.magmacube.jump");
register1_9Sound("entity.magmacube.squish");
register1_9Sound("entity.minecart.inside");
register1_9Sound("entity.minecart.riding");
register1_9Sound("entity.mooshroom.shear");
register1_9Sound("entity.mule.ambient");
register1_9Sound("entity.mule.death");
register1_9Sound("entity.mule.hurt");
register1_9Sound("entity.painting.break");
register1_9Sound("entity.painting.place");
register1_9Sound("entity.pig.ambient");
register1_9Sound("entity.pig.death");
register1_9Sound("entity.pig.hurt");
register1_9Sound("entity.pig.saddle");
register1_9Sound("entity.pig.step");
register1_9Sound("entity.player.attack.crit");
register1_9Sound("entity.player.attack.knockback");
register1_9Sound("entity.player.attack.nodamage");
register1_9Sound("entity.player.attack.strong");
register1_9Sound("entity.player.attack.sweep");
register1_9Sound("entity.player.attack.weak");
register1_9Sound("entity.player.big_fall");
register1_9Sound("entity.player.breath");
register1_9Sound("entity.player.burp");
register1_9Sound("entity.player.death");
register1_9Sound("entity.player.hurt");
register1_9Sound("entity.player.levelup");
register1_9Sound("entity.player.small_fall");
register1_9Sound("entity.player.splash");
register1_9Sound("entity.player.swim");
register1_9Sound("entity.rabbit.ambient");
register1_9Sound("entity.rabbit.attack");
register1_9Sound("entity.rabbit.death");
register1_9Sound("entity.rabbit.hurt");
register1_9Sound("entity.rabbit.jump");
register1_9Sound("entity.sheep.ambient");
register1_9Sound("entity.sheep.death");
register1_9Sound("entity.sheep.hurt");
register1_9Sound("entity.sheep.shear");
register1_9Sound("entity.sheep.step");
register1_9Sound("entity.shulker.ambient");
register1_9Sound("entity.shulker.close");
register1_9Sound("entity.shulker.death");
register1_9Sound("entity.shulker.hurt");
register1_9Sound("entity.shulker.hurt_closed");
register1_9Sound("entity.shulker.open");
register1_9Sound("entity.shulker.shoot");
register1_9Sound("entity.shulker.teleport");
register1_9Sound("entity.shulker_bullet.hit");
register1_9Sound("entity.shulker_bullet.hurt");
register1_9Sound("entity.silverfish.ambient");
register1_9Sound("entity.silverfish.death");
register1_9Sound("entity.silverfish.hurt");
register1_9Sound("entity.silverfish.step");
register1_9Sound("entity.skeleton.ambient");
register1_9Sound("entity.skeleton.death");
register1_9Sound("entity.skeleton.hurt");
register1_9Sound("entity.skeleton.shoot");
register1_9Sound("entity.skeleton.step");
register1_9Sound("entity.skeleton_horse.ambient");
register1_9Sound("entity.skeleton_horse.death");
register1_9Sound("entity.skeleton_horse.hurt");
register1_9Sound("entity.slime.attack");
register1_9Sound("entity.slime.death");
register1_9Sound("entity.slime.hurt");
register1_9Sound("entity.slime.jump");
register1_9Sound("entity.slime.squish");
register1_9Sound("entity.small_magmacube.death");
register1_9Sound("entity.small_magmacube.hurt");
register1_9Sound("entity.small_magmacube.squish");
register1_9Sound("entity.small_slime.death");
register1_9Sound("entity.small_slime.hurt");
register1_9Sound("entity.small_slime.jump");
register1_9Sound("entity.small_slime.squish");
register1_9Sound("entity.snowball.throw");
register1_9Sound("entity.snowman.ambient");
register1_9Sound("entity.snowman.death");
register1_9Sound("entity.snowman.hurt");
register1_9Sound("entity.snowman.shoot");
register1_9Sound("entity.spider.ambient");
register1_9Sound("entity.spider.death");
register1_9Sound("entity.spider.hurt");
register1_9Sound("entity.spider.step");
register1_9Sound("entity.splash_potion.break");
register1_9Sound("entity.splash_potion.throw");
register1_9Sound("entity.squid.ambient");
register1_9Sound("entity.squid.death");
register1_9Sound("entity.squid.hurt");
register1_9Sound("entity.tnt.primed");
register1_9Sound("entity.villager.ambient");
register1_9Sound("entity.villager.death");
register1_9Sound("entity.villager.hurt");
register1_9Sound("entity.villager.no");
register1_9Sound("entity.villager.trading");
register1_9Sound("entity.villager.yes");
register1_9Sound("entity.witch.ambient");
register1_9Sound("entity.witch.death");
register1_9Sound("entity.witch.drink");
register1_9Sound("entity.witch.hurt");
register1_9Sound("entity.witch.throw");
register1_9Sound("entity.wither.ambient");
register1_9Sound("entity.wither.break_block");
register1_9Sound("entity.wither.death");
register1_9Sound("entity.wither.hurt");
register1_9Sound("entity.wither.shoot");
register1_9Sound("entity.wither.spawn");
register1_9Sound("entity.wolf.ambient");
register1_9Sound("entity.wolf.death");
register1_9Sound("entity.wolf.growl");
register1_9Sound("entity.wolf.howl");
register1_9Sound("entity.wolf.hurt");
register1_9Sound("entity.wolf.pant");
register1_9Sound("entity.wolf.shake");
register1_9Sound("entity.wolf.step");
register1_9Sound("entity.wolf.whine");
register1_9Sound("entity.zombie.ambient");
register1_9Sound("entity.zombie.attack_door_wood");
register1_9Sound("entity.zombie.attack_iron_door");
register1_9Sound("entity.zombie.break_door_wood");
register1_9Sound("entity.zombie.death");
register1_9Sound("entity.zombie.hurt");
register1_9Sound("entity.zombie.infect");
register1_9Sound("entity.zombie.step");
register1_9Sound("entity.zombie_horse.ambient");
register1_9Sound("entity.zombie_horse.death");
register1_9Sound("entity.zombie_horse.hurt");
register1_9Sound("entity.zombie_pig.ambient");
register1_9Sound("entity.zombie_pig.angry");
register1_9Sound("entity.zombie_pig.death");
register1_9Sound("entity.zombie_pig.hurt");
register1_9Sound("entity.zombie_villager.ambient");
register1_9Sound("entity.zombie_villager.converted");
register1_9Sound("entity.zombie_villager.cure");
register1_9Sound("entity.zombie_villager.death");
register1_9Sound("entity.zombie_villager.hurt");
register1_9Sound("entity.zombie_villager.step");
register1_9Sound("item.armor.equip_chain");
register1_9Sound("item.armor.equip_diamond");
register1_9Sound("item.armor.equip_generic");
register1_9Sound("item.armor.equip_gold");
register1_9Sound("item.armor.equip_iron");
register1_9Sound("item.armor.equip_leather");
register1_9Sound("item.bottle.fill");
register1_9Sound("item.bottle.fill_dragonbreath");
register1_9Sound("item.bucket.empty");
register1_9Sound("item.bucket.empty_lava");
register1_9Sound("item.bucket.fill");
register1_9Sound("item.bucket.fill_lava");
register1_9Sound("item.chorus_fruit.teleport");
register1_9Sound("item.firecharge.use");
register1_9Sound("item.flintandsteel.use");
register1_9Sound("item.hoe.till");
register1_9Sound("item.shield.block");
register1_9Sound("item.shield.break");
register1_9Sound("item.shovel.flatten");
register1_9Sound("music.creative");
register1_9Sound("music.credits");
register1_9Sound("music.dragon");
register1_9Sound("music.end");
register1_9Sound("music.game");
register1_9Sound("music.menu");
register1_9Sound("music.nether");
register1_9Sound("record.11");
register1_9Sound("record.13");
register1_9Sound("record.blocks");
register1_9Sound("record.cat");
register1_9Sound("record.chirp");
register1_9Sound("record.far");
register1_9Sound("record.mall");
register1_9Sound("record.mellohi");
register1_9Sound("record.stal");
register1_9Sound("record.strad");
register1_9Sound("record.wait");
register1_9Sound("record.ward");
register1_9Sound("ui.button.click");
register1_9Sound("weather.rain");
register1_9Sound("weather.rain.above");
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,42 +15,22 @@
* 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.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.connection.StorableObject;
public class BlockPlaceDestroyTracker extends StoredObject {
private long blockPlaced, lastMining;
private boolean mining;
public BlockPlaceDestroyTracker(UserConnection user) {
super(user);
}
public long getBlockPlaced() {
return blockPlaced;
}
public void place() {
blockPlaced = System.currentTimeMillis();
}
public class BlockPlaceDestroyTracker implements StorableObject {
private long lastMining;
public boolean isMining() {
long time = System.currentTimeMillis() - lastMining;
return time < 75;
}
public void setMining(boolean mining) {
this.mining = mining && getUser().get(EntityTracker.class).getPlayerGamemode() != 1;
public void setMining() {
lastMining = System.currentTimeMillis();
}
public long getLastMining() {
return lastMining;
}
public void updateMining() {
if (this.isMining()) {
lastMining = System.currentTimeMillis();
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,10 +15,9 @@
* 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.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.bossbar.WitherBossBar;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation.WitherBossBar;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -27,16 +26,22 @@ import java.util.Map;
import java.util.UUID;
public class BossBarStorage extends StoredObject {
private final Map<UUID, WitherBossBar> bossBars = new HashMap<>();
public BossBarStorage(UserConnection user) {
super(user);
}
public void add(UUID uuid, String title, float health) {
public void reset() {
updateLocation();
changeWorld();
}
public void add(UUID uuid, String title, float health) throws Exception {
WitherBossBar bossBar = new WitherBossBar(this.getUser(), uuid, title, health);
PlayerPosition playerPosition = this.getUser().get(PlayerPosition.class);
bossBar.setPlayerLocation(playerPosition.getPosX(), playerPosition.getPosY(), playerPosition.getPosZ(), playerPosition.getYaw(), playerPosition.getPitch());
PlayerPositionTracker playerPositionTracker = this.getUser().get(PlayerPositionTracker.class);
bossBar.setPlayerLocation(playerPositionTracker.getPosX(), playerPositionTracker.getPosY(), playerPositionTracker.getPosZ(), playerPositionTracker.getYaw(), playerPositionTracker.getPitch());
bossBar.show();
bossBars.put(uuid, bossBar);
}
@@ -48,8 +53,14 @@ public class BossBarStorage extends StoredObject {
}
public void updateLocation() {
PlayerPosition playerPosition = this.getUser().get(PlayerPosition.class);
bossBars.values().forEach(bossBar -> bossBar.setPlayerLocation(playerPosition.getPosX(), playerPosition.getPosY(), playerPosition.getPosZ(), playerPosition.getYaw(), playerPosition.getPitch()));
PlayerPositionTracker playerPositionTracker = this.getUser().get(PlayerPositionTracker.class);
bossBars.values().forEach(bossBar -> {
try {
bossBar.setPlayerLocation(playerPositionTracker.getPosX(), playerPositionTracker.getPosY(), playerPositionTracker.getPosZ(), playerPositionTracker.getYaw(), playerPositionTracker.getPitch());
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
public void changeWorld() {
Loaded 100 of 135 files, more files were not shown because too many files have changed in this diff. Show more