110 Commits
Author SHA1 Message Date
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
FlorianMichael 8892110810 3.0.5 Release 2023-12-05 19:26:15 +01:00
EnZaXD c1cd560b06 1.20.3-pre1 2023-11-20 19:43:14 +01:00
EnZaXD cd74482278 23w46a 2023-11-20 14:04:17 +01:00
FlorianMichael 7cb97dcfd1 Fixed Bulk Chunk 1.7 <-> 1.8 skylight reading 2023-11-07 21:02:56 +01:00
FlorianMichael 69363c8bd5 Merge remote-tracking branch 'origin/dev' into dev 2023-11-05 19:40:01 +01:00
FlorianMichael b1c9616364 Added armor stand interaction rewriting 2023-11-05 19:39:48 +01:00
EnZaXD 5c4d928426 23w44a Via 2023-11-03 20:16:04 +01:00
SplotyCode dfebb916bb Added cooldown api in 1.7 -> 1.8 (#463)
* Cooldown api

* Small cleanup

* Remove unnecessary method
2023-11-01 05:16:04 +01:00
FlorianMichael ab4b9277e4 Hotfix for NPE in spectator emulation
Fixed https://github.com/ViaVersion/ViaRewind/issues/462
2023-10-30 20:27:44 +01:00
FlorianMichael d8b36666d5 Cleaned entity tracker code 2023-10-29 02:29:19 +02:00
FlorianMichael 784a444283 Track player ids correctly 2023-10-27 00:00:43 +02:00
FlorianMichael b1f153ea0a fixed yStance 2023-10-26 23:01:11 +02:00
FlorianMichael 8f48781268 Bump version to 3.0.4-SNAPSHOT 2023-10-26 22:12:46 +02:00
FlorianMichael c2f19c6528 Replaced deprecated API usage 2023-10-26 22:12:23 +02:00
FlorianMichael b0e7a20c86 Implemented hologram rewriting
Fixed https://github.com/ViaVersion/ViaRewind/issues/97
Probably fixed https://github.com/ViaVersion/ViaRewind/issues/458
Probably fixed https://github.com/ViaVersion/ViaRewind/issues/457
2023-10-26 22:05:27 +02:00
FlorianMichael ebed6dd715 Merge branch 'dev' into abstraction 2023-10-26 16:05:24 +02:00
FlorianMichael 21c0a4e304 23w43a 2023-10-26 16:01:04 +02:00
FlorianMichael 2650e7ae44 Updated chunk reading and writing to work with Via again 2023-10-20 12:05:42 +02:00
FlorianMichael 15c434cb42 Removed unused field and fixed player id tracking 2023-10-19 22:22:29 +02:00
FlorianMichael 7bd0a0b85d Apply API changes to new abstraction 2023-10-19 18:33:07 +02:00
FlorianMichael 2c8f431377 Merge remote-tracking branch 'origin/dev' into abstraction
# Conflicts:
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/Protocol1_7_6_10To1_8.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/emulator/EndermiteModel.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/emulator/GuardianModel.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/emulator/RabbitModel.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/model/VirtualHologramEntity.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/packets/EntityPackets.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/packets/PlayerPackets.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/packets/SpawnPackets.java
#	common/src/main/java/com/viaversion/viarewind/protocol/protocol1_7_6_10to1_8/storage/EntityTracker.java
2023-10-19 18:30:21 +02:00
FlorianMichael 5ed1d3a4d3 Updated Via API usage 2023-10-19 18:20:46 +02:00
FlorianMichael b85d305fe1 It compiles ™️ 2023-10-19 18:11:03 +02:00
FlorianMichael 0a55b0a35b Correctly rewrite block ids in chunk packets 2023-10-11 04:05:12 +02:00
FlorianMichael 3650a08752 Show version in Item replacements 2023-10-11 01:08:35 +02:00
FlorianMichael 14a314d167 Added abstraction types for position rewriting in 1.7 -> 1.8, cleanup of SpawnPackets, added groups for Via types. 2023-10-10 13:34:18 +02:00
FlorianMichael dc2babd173 Merge remote-tracking branch 'origin/dev' into dev 2023-10-10 06:13:58 +02:00
FlorianMichael 9bb731037b Fixed https://github.com/ViaVersion/ViaRewind/issues/283 2023-10-10 06:13:34 +02:00
Kichura 68bc76cfba Depend on newer fabric loader, Recommend newer ViaFabric (#459)
* Depend on newer fabric loader.

Fabric loader 0.4.0 is too ancient and very likely will not work properly with the current viarewind build.

* Recommend atleast viafabric 0.4.10 or higher.

Having "*" for viafabric included is not a great idea as then all copies are accepted including unsupported ones.
2023-10-09 01:42:30 +02:00
FlorianMichael 1f651a67c7 Bump version to 3.0.3-SNAPSHOT 2023-10-09 01:35:26 +02:00
FlorianMichael 2d3e495f85 Fixed metadata issues, added new config options to emulate world border, cleaned protocol code. 2023-10-09 01:28:58 +02:00
FlorianMichael 7689769e26 Fixed merge conflict. 2023-10-08 22:56:38 +02:00
FlorianMichael 990a5bafe1 Merge remote-tracking branch 'origin/1.7-particle-data-fix' into dev
# Conflicts:
#	core/src/main/java/de/gerrygames/viarewind/protocol/protocol1_7_6_10to1_8/packets/WorldPackets.java
2023-10-08 22:53:24 +02:00
FlorianMichael bdef039008 Fixed loading on Bukkit 2023-10-08 20:49:40 +02:00
FlorianMichael f516528e77 Rewrote entity packet translations 2023-10-08 12:42:21 +02:00
FlorianMichael ad85d1c4fd 1.7 -> 1.8: deleted Ticker system 2023-10-08 12:21:20 +02:00
FlorianMichael 15769e5ee3 Initial rewrite of entity emulation system
Don't buffer Entity Metadata
2023-10-08 12:08:40 +02:00
FlorianMichael a7e865ee6d Allow platform implementation to define config path 2023-10-08 08:59:52 +02:00
FlorianMichael 4a0a4bb40c Fabric is also a thing! 2023-10-08 07:18:10 +02:00
FlorianMichael 16d308610e Updated all platform implementations 2023-10-08 07:15:58 +02:00
FlorianMichael b5825462bf Fixed 1.7 -> 1.8 metadata rewriting not working 2023-10-08 06:22:42 +02:00
FlorianMichael fe123b13b7 Load 1.8 -> 1.9 item replacements 2023-10-08 06:16:56 +02:00
FlorianMichael 3fa305f637 Refactor ItemRewriter and replacement system 2023-10-08 06:15:51 +02:00
FlorianMichael 5a0e57a4a0 Added more exception handling to Metadata rewriter (1.7 -> 1.8) 2023-10-08 03:35:24 +02:00
FlorianMichael 76dcad78ce Start with rewriting Replacement system 2023-10-08 03:13:49 +02:00
FlorianMichael bff3a99f2d Rewrote chunk handling (1.7 -> 1.8) completely. 2023-10-08 02:22:54 +02:00
FlorianMichael f95a2db7f5 Small code cleanup. 2023-10-08 01:38:39 +02:00
FlorianMichael 5a126695c3 Bump version to 3.0.2-SNAPSHOT 2023-10-07 23:02:10 +02:00
FlorianMichael e84a9b619f Cleaned up Compression handling 2023-10-07 21:39:20 +02:00
FlorianMichael 684e6d1377 Cleaned up Protocol 1.7.2 -> 1.7.6 2023-10-07 20:59:53 +02:00
FlorianMichael f1988765ba Don't allow platform to be initialized twice. 2023-10-07 20:33:12 +02:00
FlorianMichael df28363692 Mention ViaProxy instead of ViaFabricPlus in README file. 2023-10-07 20:29:36 +02:00
FlorianMichael eb6e7b17b8 Merge remote-tracking branch 'origin/master' into dev 2023-10-07 20:22:20 +02:00
Nassim Jahnke 85c2816808 Fix branch check on headless ci 2023-09-26 10:51:32 +10:00
Nassim Jahnke f7a2f22bed [ci skip] Fix branch check in publishing 2023-09-26 00:27:47 +10:00
FlorianMichael 1cce662f36 Move util to correct package 2023-09-23 03:29:59 +02:00
FlorianMichael bf359bb81e Improved Hologram detection method in ArmorStandReplacement 2023-09-23 03:20:44 +02:00
FlorianMichael 925484c45e Apply checkstyle, build javadoc and source jar file 2023-09-22 23:09:33 +02:00
FlorianMichael 916cb9bae0 Fixed compile error 2023-09-21 20:24:18 +02:00
Terrence S 3892a02ce3 Make overall formatting more consistent plus a few spelling fixes and minor changes (#455) 2023-09-21 20:18:53 +02:00
FlorianMichael c2bf1a6231 Bump version to 3.0.1-SNAPSHOT 2023-09-21 20:11:42 +02:00
ShinyDialga 2b791879d3 Fix data values for BLOCK_CRACK and BLOCK_DUST particles for 1.7 players 2021-03-22 22:22:25 -05:00
138 changed files with 4922 additions and 5297 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>
+2 -2
View File
@@ -5,9 +5,9 @@
**ViaVersion 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.
**On Fabric, use either [ViaFabric](https://modrinth.com/mod/viafabric) or [ViaFabricPlus](https://modrinth.com/mod/viafabricplus). To override the included version**
**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 **ViaFabricPlus**, put ViaRewind into the `ViaFabricPlus/jars` 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).**
@@ -40,20 +40,24 @@ dependencies {
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
@@ -19,16 +19,14 @@
package com.viaversion.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
import com.viaversion.viaversion.api.Via;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
public class BukkitPlugin extends JavaPlugin implements ViaRewindPlatform {
@Override
public void onEnable() {
ViaRewindConfig conf = new ViaRewindConfig(new File(getDataFolder(), "config.yml"));
conf.reloadConfig();
this.init(conf);
public BukkitPlugin() {
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
}
}
+4 -5
View File
@@ -1,12 +1,11 @@
name: ViaRewind
version: ${version}
main: com.viaversion.viarewind.BukkitPlugin
authors: [Gerrygames, FlorianMichael/EnZaXD, 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]
+1 -1
View File
@@ -5,5 +5,5 @@ plugins {
dependencies {
api project(":viarewind-common")
compileOnly(annotationProcessor("net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT"))
compileOnly(annotationProcessor("net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT"))
}
@@ -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
@@ -19,16 +19,15 @@
package com.viaversion.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
import com.viaversion.viaversion.api.Via;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
public class BungeePlugin extends Plugin implements ViaRewindPlatform {
@Override
public void onEnable() {
ViaRewindConfig conf = new ViaRewindConfig(new File(getDataFolder(), "config.yml"));
conf.reloadConfig();
this.init(conf);
}
@Override
public void onLoad() {
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
}
}
@@ -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
@@ -18,6 +18,7 @@
package com.viaversion.viarewind;
import com.google.common.base.Preconditions;
import com.viaversion.viarewind.api.ViaRewindConfig;
import com.viaversion.viarewind.api.ViaRewindPlatform;
@@ -27,6 +28,8 @@ public class ViaRewind {
private static ViaRewindConfig config;
public static void init(ViaRewindPlatform platform, ViaRewindConfig config) {
Preconditions.checkArgument(ViaRewind.platform == null, "ViaRewind is already initialized");
ViaRewind.platform = platform;
ViaRewind.config = config;
}
@@ -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
@@ -27,9 +27,10 @@ import java.util.List;
import java.util.Map;
public class ViaRewindConfig extends Config implements com.viaversion.viarewind.api.ViaRewindConfig {
public ViaRewindConfig(File configFile) {
super(configFile);
reloadConfig();
reload();
}
@Override
@@ -57,7 +58,17 @@ public class ViaRewindConfig extends Config implements com.viaversion.viarewind.
return getInt("max-book-page-length", 5000);
}
@Override
@Override
public boolean isEmulateWorldBorder() {
return getBoolean("emulate-world-border", true);
}
@Override
public String getWorldBorderParticle() {
return getString("world-border-particle", "fireworksSpark");
}
@Override
public URL getDefaultConfigURL() {
return getClass().getClassLoader().getResource("assets/viarewind/config.yml");
}
@@ -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
@@ -18,10 +18,12 @@
package com.viaversion.viarewind.api;
import com.viaversion.viaversion.api.configuration.Config;
/**
* This class is used to get the platform specific config
*/
public interface ViaRewindConfig {
public interface ViaRewindConfig extends Config {
enum CooldownIndicator {
TITLE, ACTION_BAR, BOSS_BAR, DISABLED
@@ -67,4 +69,18 @@ public interface ViaRewindConfig {
* @return the max amount of characters
*/
int getMaxBookPageSize();
/**
* Whether to emulate the 1.8+ world border for 1.7.x clients
*
* @return true if enabled
*/
boolean isEmulateWorldBorder();
/**
* 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();
}
@@ -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
@@ -18,14 +18,16 @@
package com.viaversion.viarewind.api;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.ViaRewindConfig;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.Protocol1_7_2_5To1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.ProtocolManager;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import java.io.File;
import java.util.logging.Logger;
/**
@@ -39,16 +41,20 @@ public interface ViaRewindPlatform {
/**
* Initialize ViaRewind
*/
default void init(ViaRewindConfig config) {
default void init(final File configFile) {
ViaRewindConfig config = new ViaRewindConfig(configFile);
config.reload();
Via.getManager().getConfigurationProvider().register(config);
ViaRewind.init(this, config);
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.registerProtocol(new Protocol1_8To1_9(), ProtocolVersion.v1_8, ProtocolVersion.v1_9);
protocolManager.registerProtocol(new Protocol1_7_6_10To1_8(), ProtocolVersion.v1_7_6, ProtocolVersion.v1_8);
protocolManager.registerProtocol(new Protocol1_7_2_5To1_7_6_10(), ProtocolVersion.v1_7_1, 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);
}
/**
@@ -57,4 +63,11 @@ public interface ViaRewindPlatform {
* @return the logger
*/
Logger getLogger();
/**
* Returns ViaRewind's data folder.
*
* @return data folder
*/
File getDataFolder();
}
@@ -0,0 +1,102 @@
/*
* 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.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;
}
}
@@ -0,0 +1,78 @@
/*
* 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.minecraft;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.NibbleArray;
public class ExtendedBlockStorage {
private final byte[] blockLSBArray = new byte[4096];
private final NibbleArray blockMetadataArray = new NibbleArray(this.blockLSBArray.length);
private final NibbleArray blockLightArray = new NibbleArray(this.blockLSBArray.length);
private NibbleArray blockMSBArray;
private NibbleArray skyLightArray;
public ExtendedBlockStorage(final boolean skylight) {
if (skylight) {
this.skyLightArray = new NibbleArray(this.blockLSBArray.length);
}
}
public void setBlockId(final int x, final int y, final int z, final int value) {
this.blockLSBArray[ChunkSection.index(x, y, z)] = (byte) (value & 255);
if (value > 255) {
this.getOrCreateBlockMSBArray().set(x, y, z, (value & 0xF00) >> 8);
} else if (this.blockMSBArray != null) {
this.blockMSBArray.set(x, y, z, 0);
}
}
public void setBlockMetadata(final int x, final int y, final int z, final int value) {
this.blockMetadataArray.set(x, y, z, value);
}
public boolean hasBlockMSBArray() {
return this.blockMSBArray != null;
}
public byte[] getBlockLSBArray() {
return this.blockLSBArray;
}
public NibbleArray getOrCreateBlockMSBArray() {
if (this.blockMSBArray == null) {
return this.blockMSBArray = new NibbleArray(this.blockLSBArray.length);
}
return this.blockMSBArray;
}
public NibbleArray getBlockMetadataArray() {
return this.blockMetadataArray;
}
public NibbleArray getBlockLightArray() {
return this.blockLightArray;
}
public NibbleArray getSkyLightArray() {
return this.skyLightArray;
}
}
@@ -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
@@ -16,27 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.replacement;
package com.viaversion.viarewind.api.minecraft;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
public class IdDataCombine {
import java.util.List;
public static int idFromCombined(final int combined) {
return combined >> 4;
}
public interface EntityReplacement {
public static int dataFromCombined(final int combined) {
return combined & 0xF;
}
int getEntityId();
void setLocation(double x, double y, double z);
void relMove(double x, double y, double z);
void setYawPitch(float yaw, float pitch);
void setHeadYaw(float yaw);
void spawn();
void despawn();
void updateMetadata(List<Metadata> metadataList);
public static int toCombined(final int id, final int data) {
return (id << 4) | (data & 0xF);
}
}
@@ -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
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.netty;
package com.viaversion.viarewind.api.netty;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
@@ -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
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.netty;
package com.viaversion.viarewind.api.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
@@ -0,0 +1,106 @@
/*
* 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.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;
}
}
@@ -0,0 +1,116 @@
/*
* 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.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.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
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 abstract class ReplacementEntityTracker extends StoredObject implements ClientEntityIdChangeListener {
private final Map<EntityType, Pair<EntityType, String>> ENTITY_REPLACEMENTS = new HashMap<>();
private final Map<Integer, EntityType> entityMap = new HashMap<>();
private final Map<Integer, EntityType> entityReplacementMap = new HashMap<>();
private int playerId = -1;
private final ProtocolVersion version;
private final int displayNameVisibilityIndex;
private final MetaType displayNameVisibilityType;
private final int displayNameIndex;
private final MetaType displayNameType;
public ReplacementEntityTracker(UserConnection user, ProtocolVersion version, MetaType displayNameVisibilityType, MetaType displayNameType) {
this(user, version, 3, displayNameVisibilityType, 2, displayNameType);
}
public ReplacementEntityTracker(UserConnection user, ProtocolVersion version, int displayNameVisibilityIndex, MetaType displayNameVisibilityType, int displayNameIndex, MetaType displayNameType) {
super(user);
this.version = version;
this.displayNameVisibilityIndex = displayNameVisibilityIndex;
this.displayNameVisibilityType = displayNameVisibilityType;
this.displayNameIndex = displayNameIndex;
this.displayNameType = displayNameType;
}
public void registerEntity(final EntityType oldType, final 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(this.displayNameVisibilityIndex, this.displayNameVisibilityType, (byte) 1));
metadata.add(new Metadata(this.displayNameIndex, this.displayNameType, name));
}
@Override
public void setClientEntityId(int entityId) {
removeEntity(this.playerId);
addEntity(entityId, EntityTypes1_10.EntityType.ENTITY_HUMAN);
this.playerId = entityId;
}
public Map<Integer, EntityType> getEntityMap() {
return entityMap;
}
public Map<Integer, EntityType> getEntityReplacementMap() {
return entityReplacementMap;
}
public int getPlayerId() {
return playerId;
}
}
@@ -0,0 +1,115 @@
/*
* 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.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;
}
}
@@ -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
@@ -16,11 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8;
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
public enum ClientboundPackets1_7 implements ClientboundPacketType {
public enum ClientboundPackets1_7_2_5 implements ClientboundPacketType {
KEEP_ALIVE, // 0x00
JOIN_GAME, // 0x01
CHAT_MESSAGE, // 0x02
@@ -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
@@ -18,23 +18,21 @@
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.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;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ServerboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPackets1_7, ClientboundPackets1_7, ServerboundPackets1_7, ServerboundPackets1_7> {
public static final ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<String, String>(Type.STRING) {
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) {
@Override
public String transform(PacketWrapper packetWrapper, String s) {
return s.replace("-", "");
@@ -42,65 +40,66 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
};
public Protocol1_7_2_5To1_7_6_10() {
super(ClientboundPackets1_7.class, ClientboundPackets1_7.class, ServerboundPackets1_7.class, ServerboundPackets1_7.class);
super(ClientboundPackets1_7_2_5.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class);
}
@Override
protected void registerPackets() {
//Login Success
this.registerClientbound(State.LOGIN, 0x02, 0x02, new PacketHandlers() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.STRING, REMOVE_DASHES);
map(Type.STRING);
map(Type.STRING, REMOVE_DASHES); // uuid
map(Type.STRING); // name
}
});
//Spawn Player
this.registerClientbound(ClientboundPackets1_7.SPAWN_PLAYER, new PacketHandlers() {
this.registerClientbound(ClientboundPackets1_7_2_5.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.STRING, REMOVE_DASHES);
map(Type.STRING);
handler(packetWrapper -> {
int size = packetWrapper.read(Type.VAR_INT);
for (int i = 0; i < size * 3; i++) packetWrapper.read(Type.STRING);
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
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
}
});
map(Type.INT);
map(Type.INT);
map(Type.INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.SHORT);
map(Types1_7_6_10.METADATA_LIST);
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
map(Types1_7_6_10.METADATA_LIST); // metadata
}
});
//Teams
this.registerClientbound(ClientboundPackets1_7.TEAMS, new PacketHandlers() {
this.registerClientbound(ClientboundPackets1_7_2_5.TEAMS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
map(Type.STRING); // team name
map(Type.BYTE); // mode
handler(packetWrapper -> {
byte mode = packetWrapper.get(Type.BYTE, 0);
if (mode == 0 || mode == 2) {
packetWrapper.passthrough(Type.STRING);
packetWrapper.passthrough(Type.STRING);
packetWrapper.passthrough(Type.STRING);
packetWrapper.passthrough(Type.BYTE);
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
}
if (mode == 0 || mode == 3 || mode == 4) {
if (mode == 0 || mode == 3 || mode == 4) { // team is created, player is added or player is removed
List<String> entryList = new ArrayList<>();
int size = packetWrapper.read(Type.SHORT);
final int size = packetWrapper.read(Type.SHORT);
for (int i = 0; i < size; i++) {
entryList.add(packetWrapper.read(Type.STRING));
}
entryList = entryList.stream()
.map(it -> it.length() > 16 ? it.substring(0, 16) : it)
.distinct()
.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());
@@ -112,9 +111,4 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
}
});
}
@Override
public void init(UserConnection 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
@@ -16,11 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8;
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
public enum ServerboundPackets1_7 implements ServerboundPacketType {
public enum ServerboundPackets1_7_2_5 implements ServerboundPacketType {
KEEP_ALIVE, // 0x00
CHAT_MESSAGE, // 0x01
INTERACT_ENTITY, // 0x02
@@ -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
@@ -18,12 +18,20 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.ReplacementItemRewriter;
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.metadata.MetadataRewriter;
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.utils.Ticker;
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;
@@ -31,19 +39,26 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_8, ClientboundPackets1_7,
ServerboundPackets1_8, ServerboundPackets1_7> {
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> {
private final ReplacementItemRewriter<Protocol1_7_6_10To1_8> itemRewriter = new ReplacementItemRewriter1_7_6_10(this);
private final MetadataRewriter metadataRewriter = new MetadataRewriter(this);
public Protocol1_7_6_10To1_8() {
super(ClientboundPackets1_8.class, ClientboundPackets1_7.class, ServerboundPackets1_8.class, ServerboundPackets1_7.class);
super(ClientboundPackets1_8.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_8.class, ServerboundPackets1_7_2_5.class);
}
@Override
protected void registerPackets() {
itemRewriter.register();
EntityPackets.register(this);
InventoryPackets.register(this);
PlayerPackets.register(this);
@@ -51,79 +66,86 @@ public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_
SpawnPackets.register(this);
WorldPackets.register(this);
this.registerClientbound(ClientboundPackets1_8.KEEP_ALIVE, new PacketHandlers() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT);
map(Type.STRING); // server hash
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // public key
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // verification token
}
});
this.cancelClientbound(ClientboundPackets1_8.SET_COMPRESSION); // unused
this.registerServerbound(ServerboundPackets1_7.KEEP_ALIVE, new PacketHandlers() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_COMPRESSION.getId(), ClientboundLoginPackets.LOGIN_COMPRESSION.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT);
}
});
handler(wrapper -> {
final int threshold = wrapper.read(Type.VAR_INT);
//Encryption Request
this.registerClientbound(State.LOGIN, 0x01, 0x01, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); //Server ID
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // Public key
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // Verification token
}
});
//Set Compression
this.registerClientbound(State.LOGIN, 0x03, 0x03, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Via.getManager().getProviders().get(CompressionHandlerProvider.class)
.handleSetCompression(packetWrapper.user(), packetWrapper.read(Type.VAR_INT));
packetWrapper.cancel();
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onHandleLoginCompressionPacket(wrapper.user(), threshold);
wrapper.cancel();
});
}
});
//Encryption Response
this.registerServerbound(State.LOGIN, 0x01, 0x01, new PacketHandlers() {
this.cancelClientbound(ClientboundPackets1_8.SET_COMPRESSION); // unused
this.registerClientbound(ClientboundPackets1_8.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // Shared secret
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // Verification token
map(Type.VAR_INT, Type.INT); // id
}
});
this.registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // shared secret
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // verification token
}
});
this.registerServerbound(ServerboundPackets1_7_2_5.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT); // id
}
});
}
@Override
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
Via.getManager().getProviders().get(CompressionHandlerProvider.class)
.handleTransform(packetWrapper.user());
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onTransformPacket(packetWrapper.user());
super.transform(direction, state, packetWrapper);
}
@Override
public void init(UserConnection userConnection) {
Ticker.init();
userConnection.put(new Windows(userConnection));
userConnection.put(new EntityTracker(userConnection));
userConnection.put(new PlayerPosition(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 CompressionSendStorage(userConnection));
userConnection.put(new WorldBorder(userConnection));
userConnection.put(new PlayerAbilities(userConnection));
userConnection.put(new ClientWorld(userConnection));
userConnection.put(new CompressionStatusTracker(userConnection));
userConnection.put(new WorldBorderEmulator(userConnection));
if (!userConnection.has(ClientWorld.class)) {
userConnection.put(new ClientWorld());
}
}
@Override
public void register(ViaProviders providers) {
providers.register(CompressionHandlerProvider.class, new CompressionHandlerProvider());
providers.register(CompressionHandlerProvider.class, new TrackingCompressionHandlerProvider());
if (ViaRewind.getConfig().isEmulateWorldBorder()) {
Via.getManager().getScheduler().scheduleRepeating(new WorldBorderUpdateTask(), 0L, 50L, TimeUnit.MILLISECONDS);
}
}
@Override
public ReplacementItemRewriter<Protocol1_7_6_10To1_8> getItemRewriter() {
return itemRewriter;
}
public MetadataRewriter getMetadataRewriter() {
return metadataRewriter;
}
}
@@ -1,155 +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.chunks;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ReplacementRegistry1_7_6_10to1_8;
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.type.Type;
import com.viaversion.viaversion.api.type.types.CustomByteType;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import java.io.ByteArrayOutputStream;
import java.util.zip.DeflaterOutputStream;
public class ChunkPacketTransformer {
private static byte[] transformChunkData(byte[] data, int primaryBitMask, boolean skyLight, boolean groundUp) throws Exception {
ByteBuf inputData = Unpooled.wrappedBuffer(data);
ByteBuf finalBuf = ByteBufAllocator.DEFAULT.buffer();
try {
ChunkSection[] sections = new ChunkSection[16];
for (int i = 0; i < 16; i++) {
if ((primaryBitMask & 1 << i) == 0) continue;
sections[i] = Types1_8.CHUNK_SECTION.read(inputData);
}
for (int i = 0; i < 16; i++) {
if ((primaryBitMask & 1 << i) == 0) continue;
ChunkSection section = sections[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int k = 0; k < palette.size(); k++) {
int blockData = palette.idByIndex(k);
blockData = ReplacementRegistry1_7_6_10to1_8.replace(blockData);
palette.setIdByIndex(k, blockData);
}
}
for (int i = 0; i < 16; i++) {
if ((primaryBitMask & 1 << i) == 0) continue;
ChunkSection section = sections[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < 4096; j++) {
int raw = palette.idAt(j);
finalBuf.writeByte(raw >> 4);
}
}
for (int i = 0; i < 16; i++) {
if ((primaryBitMask & 1 << i) == 0) continue;
ChunkSection section = sections[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < 4096; j += 2) {
int meta0 = palette.idAt(j) & 0xF;
int meta1 = palette.idAt(j + 1) & 0xF;
finalBuf.writeByte(meta1 << 4 | meta0);
}
}
int columnCount = Integer.bitCount(primaryBitMask);
// Block light
finalBuf.writeBytes(inputData, 2048 * columnCount);
// Skylight
if (skyLight) {
finalBuf.writeBytes(inputData, 2048 * columnCount);
}
if (groundUp && inputData.isReadable(256)) {
finalBuf.writeBytes(inputData, 256);
}
return Type.REMAINING_BYTES.read(finalBuf);
} finally {
finalBuf.release();
}
}
private static int calcSize(int i, boolean hasSkyLight, boolean hasBiome) {
int blocks = i * 2 * 16 * 16 * 16;
int blockLight = i * 16 * 16 * 16 / 2;
int skyLight = hasSkyLight ? i * 16 * 16 * 16 / 2 : 0;
int biome = hasBiome ? 256 : 0;
return blocks + blockLight + skyLight + biome;
}
public static void transformChunkBulk(PacketWrapper packetWrapper) throws Exception {
boolean skyLightSent = packetWrapper.read(Type.BOOLEAN);
int columnCount = packetWrapper.read(Type.VAR_INT);
int[] chunkX = new int[columnCount];
int[] chunkZ = new int[columnCount];
int[] primaryBitMask = new int[columnCount];
byte[][] data = new byte[columnCount][];
for (int i = 0; i < columnCount; i++) {
chunkX[i] = packetWrapper.read(Type.INT);
chunkZ[i] = packetWrapper.read(Type.INT);
primaryBitMask[i] = packetWrapper.read(Type.UNSIGNED_SHORT);
}
for (int i = 0; i < columnCount; i++) {
int size = calcSize(Integer.bitCount(primaryBitMask[i]), skyLightSent, true);
CustomByteType customByteType = new CustomByteType(size);
data[i] = transformChunkData(packetWrapper.read(customByteType), primaryBitMask[i], skyLightSent, true);
}
ByteArrayOutputStream compressedData = new ByteArrayOutputStream();
// todo compression level config
try (DeflaterOutputStream deflaterStream = new DeflaterOutputStream(compressedData)) {
for (int i = 0; i < columnCount; ++i) {
deflaterStream.write(data[i]);
}
}
packetWrapper.write(Type.SHORT, (short) columnCount);
packetWrapper.write(Type.INT, compressedData.size());
packetWrapper.write(Type.BOOLEAN, skyLightSent);
CustomByteType customByteType = new CustomByteType(compressedData.size());
packetWrapper.write(customByteType, compressedData.toByteArray());
for (int i = 0; i < columnCount; i++) {
packetWrapper.write(Type.INT, chunkX[i]);
packetWrapper.write(Type.INT, chunkZ[i]);
packetWrapper.write(Type.SHORT, (short) primaryBitMask[i]);
packetWrapper.write(Type.SHORT, (short) 0);
}
}
}
@@ -1,121 +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.chunks;
import com.viaversion.viaversion.api.minecraft.chunks.NibbleArray;
public class ExtendedBlockStorage {
private final int yBase;
private byte[] blockLSBArray;
private NibbleArray blockMSBArray;
private NibbleArray blockMetadataArray;
private NibbleArray blocklightArray;
private NibbleArray skylightArray;
public ExtendedBlockStorage(int paramInt, boolean paramBoolean) {
this.yBase = paramInt;
this.blockLSBArray = new byte[4096];
this.blockMetadataArray = new NibbleArray(this.blockLSBArray.length);
this.blocklightArray = new NibbleArray(this.blockLSBArray.length);
if (paramBoolean) {
this.skylightArray = new NibbleArray(this.blockLSBArray.length);
}
}
public int getExtBlockMetadata(int paramInt1, int paramInt2, int paramInt3) {
return this.blockMetadataArray.get(paramInt1, paramInt2, paramInt3);
}
public void setExtBlockMetadata(int paramInt1, int paramInt2, int paramInt3, int paramInt4) {
this.blockMetadataArray.set(paramInt1, paramInt2, paramInt3, paramInt4);
}
public int getYLocation() {
return this.yBase;
}
public void setExtSkylightValue(int paramInt1, int paramInt2, int paramInt3, int paramInt4) {
this.skylightArray.set(paramInt1, paramInt2, paramInt3, paramInt4);
}
public int getExtSkylightValue(int paramInt1, int paramInt2, int paramInt3) {
return this.skylightArray.get(paramInt1, paramInt2, paramInt3);
}
public void setExtBlocklightValue(int paramInt1, int paramInt2, int paramInt3, int paramInt4) {
this.blocklightArray.set(paramInt1, paramInt2, paramInt3, paramInt4);
}
public int getExtBlocklightValue(int paramInt1, int paramInt2, int paramInt3) {
return this.blocklightArray.get(paramInt1, paramInt2, paramInt3);
}
public byte[] getBlockLSBArray() {
return this.blockLSBArray;
}
public boolean isEmpty() {
return this.blockMSBArray==null;
}
public void clearMSBArray() {
this.blockMSBArray = null;
}
public NibbleArray getBlockMSBArray() {
return this.blockMSBArray;
}
public NibbleArray getMetadataArray() {
return this.blockMetadataArray;
}
public NibbleArray getBlocklightArray() {
return this.blocklightArray;
}
public NibbleArray getSkylightArray() {
return this.skylightArray;
}
public void setBlockLSBArray(byte[] paramArrayOfByte) {
this.blockLSBArray = paramArrayOfByte;
}
public void setBlockMSBArray(NibbleArray paramNibbleArray) {
this.blockMSBArray = paramNibbleArray;
}
public void setBlockMetadataArray(NibbleArray paramNibbleArray) {
this.blockMetadataArray = paramNibbleArray;
}
public void setBlocklightArray(NibbleArray paramNibbleArray) {
this.blocklightArray = paramNibbleArray;
}
public void setSkylightArray(NibbleArray paramNibbleArray) {
this.skylightArray = paramNibbleArray;
}
public NibbleArray createBlockMSBArray() {
this.blockMSBArray = new NibbleArray(this.blockLSBArray.length);
return this.blockMSBArray;
}
}
@@ -1,280 +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.entityreplacements;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Vector3d;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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.viarewind.protocol.protocol1_7_6_10to1_8.types.MetaType1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.ArrayList;
import java.util.List;
public class ArmorStandReplacement extends EntityReplacement1_7to1_8 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private int[] entityIds = null;
private double locX, locY, locZ;
private State currentState = null;
private boolean invisible = false;
private boolean nameTagVisible = false;
private String name = null;
private float yaw, pitch;
private float headYaw;
private boolean small = false;
private boolean marker = false;
public int getEntityId() {
return this.entityId;
}
private enum State {
HOLOGRAM, ZOMBIE
}
public ArmorStandReplacement(int entityId, UserConnection user) {
super(user);
this.entityId = entityId;
}
public void setLocation(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(false);
}
}
public void relMove(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(false);
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw && this.pitch != pitch || this.headYaw != yaw) {
this.yaw = yaw;
this.headYaw = yaw;
this.pitch = pitch;
updateLocation(false);
}
}
public void setHeadYaw(float yaw) {
if (this.headYaw != yaw) {
this.headYaw = yaw;
updateLocation(false);
}
}
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateState();
}
public void updateState() {
byte flags = 0;
byte armorStandFlags = 0;
for (Metadata metadata : datawatcher) {
if (metadata.id() == 0 && metadata.metaType() == MetaType1_8.Byte) {
flags = ((Number) metadata.getValue()).byteValue();
} else if (metadata.id() == 2 && metadata.metaType() == MetaType1_8.String) {
name = metadata.getValue().toString();
if (name != null && name.equals("")) name = null;
} else if (metadata.id() == 10 && metadata.metaType() == MetaType1_8.Byte) {
armorStandFlags = ((Number) metadata.getValue()).byteValue();
} else if (metadata.id() == 3 && metadata.metaType() == MetaType1_8.Byte) {
nameTagVisible = ((Number) metadata.getValue()).byteValue() != 0;
}
}
invisible = (flags & 0x20) != 0;
small = (armorStandFlags & 0x01) != 0;
marker = (armorStandFlags & 0x10) != 0;
State prevState = currentState;
if (invisible && marker) {
currentState = State.HOLOGRAM;
} else {
currentState = State.ZOMBIE;
}
if (currentState != prevState) {
despawn();
spawn();
} else {
updateMetadata();
updateLocation(false);
}
}
public void updateLocation(boolean remount) {
if (entityIds == null) return;
if (currentState == State.ZOMBIE) {
updateZombieLocation();
} else if (currentState == State.HOLOGRAM) {
updateHologramLocation(remount);
}
}
private void updateZombieLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
private void updateHologramLocation(boolean remount) {
if(remount) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7.ATTACH_ENTITY, null, 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);
}
// Don't ask me where this offset is coming from
sendTeleport(entityIds[0], locX, (locY + (marker ? 54.85 : small ? 56 : 57)), locZ, 0, 0); // Skull
if(remount) {
sendTeleport(entityIds[1], locX, locY + 56.75, locZ, 0, 0); // Horse
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7.ATTACH_ENTITY, null, user);
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);
}
}
public void updateMetadata() {
if (entityIds == null) return;
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_METADATA, null, user);
if (currentState == State.ZOMBIE) {
writeZombieMeta(metadataPacket);
} else if (currentState == State.HOLOGRAM) {
writeHologramMeta(metadataPacket);
} else {
return;
}
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class, true, true);
}
private void writeZombieMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[0]);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
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(Entity1_10Types.EntityType.ZOMBIE, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
private void writeHologramMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[1]);
List<Metadata> metadataList = new ArrayList<>();
metadataList.add(new Metadata(12, MetaType1_7_6_10.Int, -1700000));
metadataList.add(new Metadata(10, MetaType1_7_6_10.String, name));
metadataList.add(new Metadata(11, MetaType1_7_6_10.Byte, (byte) 1));
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
public void spawn() {
if (entityIds != null) despawn();
if (currentState == State.ZOMBIE) {
spawnZombie();
} else if (currentState == State.HOLOGRAM) {
spawnHologram();
}
updateMetadata();
updateLocation(true);
}
private void spawnZombie() {
sendSpawn(entityId, 54, locX, locY, locZ);
entityIds = new int[] {entityId};
}
private void spawnHologram() {
int[] entityIds = {entityId, additionalEntityId()};
PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7.SPAWN_ENTITY, null, user);
spawnSkull.write(Type.VAR_INT, entityIds[0]);
spawnSkull.write(Type.BYTE, (byte) 66);
spawnSkull.write(Type.INT, (int) (locX * 32.0));
spawnSkull.write(Type.INT, (int) (locY * 32.0));
spawnSkull.write(Type.INT, (int) (locZ * 32.0));
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);
sendSpawn(entityIds[1], 100, locX, locY, locZ); // Horse
this.entityIds = entityIds;
}
private int additionalEntityId() {
return Integer.MAX_VALUE - 16000 - entityId;
}
public AABB getBoundingBox() {
double w = this.small ? 0.25 : 0.5;
double h = this.small ? 0.9875 : 1.975;
Vector3d min = new Vector3d(this.locX - w / 2, this.locY, this.locZ - w / 2);
Vector3d max = new Vector3d(this.locX + w / 2, this.locY + h, this.locZ + w / 2);
return new AABB(min, max);
}
public void despawn() {
if (entityIds == null) return;
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, 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);
}
}
@@ -1,121 +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.entityreplacements;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
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.types.Types1_7_6_10;
import java.util.ArrayList;
import java.util.List;
public class EndermiteReplacement extends EntityReplacement1_7to1_8 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
private float yaw, pitch;
private float headYaw;
public EndermiteReplacement(int entityId, UserConnection user) {
super(user);
this.entityId = entityId;
spawn();
}
public void setLocation(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
public void relMove(double x, double y, double z) {
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw || this.pitch != pitch) {
this.yaw = yaw;
this.pitch = pitch;
updateLocation();
}
}
public void setHeadYaw(float yaw) {
if (this.headYaw != yaw) {
this.headYaw = yaw;
updateLocation();
}
}
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateMetadata();
}
public void updateLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
public void updateMetadata() {
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_METADATA, user);
metadataPacket.write(Type.INT, entityId);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
MetadataRewriter.transform(Entity1_10Types.EntityType.SQUID, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class);
}
@Override
public void spawn() {
sendSpawn(entityId, 60, locX, locY, locZ);
}
@Override
public void despawn() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, user);
despawn.write(Types1_7_6_10.INT_ARRAY, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
}
public int getEntityId() {
return this.entityId;
}
}
@@ -1,80 +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.entityreplacements;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.ArrayList;
public abstract class EntityReplacement1_7to1_8 implements EntityReplacement {
protected final UserConnection user;
public EntityReplacement1_7to1_8(UserConnection user) {
this.user = user;
}
protected void sendTeleportWithHead(int entityId, double locX, double locY, double locZ, float yaw, float pitch, float headYaw) {
sendTeleport(entityId, locX, locY, locZ, yaw, pitch);
sendHeadYaw(entityId, headYaw);
}
protected void sendTeleport(int entityId, double locX, double locY, double locZ, float yaw, float pitch) {
PacketWrapper teleport = PacketWrapper.create(ClientboundPackets1_7.ENTITY_TELEPORT, null, user);
teleport.write(Type.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));
PacketUtil.sendPacket(teleport, Protocol1_7_6_10To1_8.class, true, true);
}
protected void sendHeadYaw(int entityId, float headYaw) {
PacketWrapper head = PacketWrapper.create(ClientboundPackets1_7.ENTITY_HEAD_LOOK, null, user);
head.write(Type.INT, entityId);
head.write(Type.BYTE, (byte) ((headYaw / 360f) * 256));
PacketUtil.sendPacket(head, Protocol1_7_6_10To1_8.class, true, true);
}
protected void sendSpawn(int entityId, int type, double locX, double locY, double locZ) {
PacketWrapper spawn = PacketWrapper.create(ClientboundPackets1_7.SPAWN_MOB, null, user);
spawn.write(Type.VAR_INT, entityId);
spawn.write(Type.UNSIGNED_BYTE, (short) type); // type
spawn.write(Type.INT, (int) (locX * 32.0));
spawn.write(Type.INT, (int) (locY * 32.0));
spawn.write(Type.INT, (int) (locZ * 32.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);
spawn.write(Types1_7_6_10.METADATA_LIST, new ArrayList<>());
PacketUtil.sendPacket(spawn, Protocol1_7_6_10To1_8.class, true, true);
}
}
@@ -1,122 +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.entityreplacements;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
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.types.Types1_7_6_10;
import java.util.ArrayList;
import java.util.List;
public class GuardianReplacement extends EntityReplacement1_7to1_8 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
private float yaw, pitch;
private float headYaw;
public GuardianReplacement(int entityId, UserConnection user) {
super(user);
this.entityId = entityId;
spawn();
}
public void setLocation(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
public void relMove(double x, double y, double z) {
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw || this.pitch != pitch) {
this.yaw = yaw;
this.pitch = pitch;
updateLocation();
}
}
public void setHeadYaw(float yaw) {
if (this.headYaw != yaw) {
this.headYaw = yaw;
updateLocation();
}
}
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateMetadata();
}
public void updateLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
public void updateMetadata() {
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_METADATA, null, user);
metadataPacket.write(Type.INT, entityId);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
if (metadata.id() == 16 || metadata.id() == 17) continue;
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
MetadataRewriter.transform(Entity1_10Types.EntityType.SQUID, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class);
}
@Override
public void spawn() {
sendSpawn(entityId, 94, locX, locY, locZ);
}
@Override
public void despawn() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, user);
despawn.write(Types1_7_6_10.INT_ARRAY, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
}
public int getEntityId() {
return this.entityId;
}
}
@@ -1,121 +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.entityreplacements;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
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.types.Types1_7_6_10;
import java.util.ArrayList;
import java.util.List;
public class RabbitReplacement extends EntityReplacement1_7to1_8 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
private float yaw, pitch;
private float headYaw;
public RabbitReplacement(int entityId, UserConnection user) {
super(user);
this.entityId = entityId;
spawn();
}
public void setLocation(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
public void relMove(double x, double y, double z) {
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw || this.pitch != pitch) {
this.yaw = yaw;
this.pitch = pitch;
updateLocation();
}
}
public void setHeadYaw(float yaw) {
if (this.headYaw != yaw) {
this.headYaw = yaw;
updateLocation();
}
}
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateMetadata();
}
public void updateLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
public void updateMetadata() {
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_METADATA, null, user);
metadataPacket.write(Type.INT, entityId);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
MetadataRewriter.transform(Entity1_10Types.EntityType.CHICKEN, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class, true, true);
}
@Override
public void spawn() {
sendSpawn(entityId, 93, locX, locY, locZ); // Chicken
}
@Override
public void despawn() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, user);
despawn.write(Types1_7_6_10.INT_ARRAY, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
}
public int getEntityId() {
return this.entityId;
}
}
@@ -1,136 +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.items;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import java.util.ArrayList;
import java.util.List;
public class ItemRewriter {
public static Item toClient(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("ViaRewind1_7_6_10to1_8", 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==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());
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.identifier()==387 && tag.contains("pages")) {
ListTag pages = tag.get("pages");
ListTag oldPages = new ListTag(StringTag.class);
viaVersionTag.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);
}
}
ReplacementRegistry1_7_6_10to1_8.replace(item);
if (viaVersionTag.size()==2 && (short)viaVersionTag.get("id").getValue()==item.identifier() && (short)viaVersionTag.get("data").getValue()==item.data()) {
item.tag().remove("ViaRewind1_7_6_10to1_8");
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
public static Item toServer(Item item) {
if (item==null) return null;
CompoundTag tag = item.tag();
if (tag==null || !item.tag().contains("ViaRewind1_7_6_10to1_8")) return item;
CompoundTag viaVersionTag = tag.remove("ViaRewind1_7_6_10to1_8");
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,123 +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.items;
import com.viaversion.viarewind.replacement.Replacement;
import com.viaversion.viarewind.storage.BlockState;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viarewind.replacement.ReplacementRegistry;
public class ReplacementRegistry1_7_6_10to1_8 {
private static final ReplacementRegistry registry = new ReplacementRegistry();
static {
registry.registerBlock(176, new Replacement(63));
registry.registerBlock(177, new Replacement(68));
registry.registerBlock(193, new Replacement(64));
registry.registerBlock(194, new Replacement(64));
registry.registerBlock(195, new Replacement(64));
registry.registerBlock(196, new Replacement(64));
registry.registerBlock(197, new Replacement(64));
registry.registerBlock(77, 5, new Replacement(69, 6));
registry.registerBlock(77, 13, new Replacement(69, 14));
registry.registerBlock(77, 0, new Replacement(69, 0));
registry.registerBlock(77, 8, new Replacement(69, 8));
registry.registerBlock(143, 5, new Replacement(69, 6));
registry.registerBlock(143, 13, new Replacement(69, 14));
registry.registerBlock(143, 0, new Replacement(69, 0));
registry.registerBlock(143, 8, new Replacement(69, 8));
registry.registerBlock(178, new Replacement(151));
registry.registerBlock(182, 0, new Replacement(44, 1));
registry.registerBlock(182, 8, new Replacement(44, 9));
registry.registerItem(425, new Replacement(323, "Banner"));
registry.registerItem(409, new Replacement(406, "Prismarine Shard"));
registry.registerItem(410, new Replacement(406, "Prismarine Crystal"));
registry.registerItem(416, new Replacement(280, "Armor Stand"));
registry.registerItem(423, new Replacement(363, "Raw Mutton"));
registry.registerItem(424, new Replacement(364, "Cooked Mutton"));
registry.registerItem(411, new Replacement(365, "Raw Rabbit"));
registry.registerItem(412, new Replacement(366, "Cooked Rabbit"));
registry.registerItem(413, new Replacement(282, "Rabbit Stew"));
registry.registerItem(414, new Replacement(375, "Rabbit's Foot"));
registry.registerItem(415, new Replacement(334, "Rabbit Hide"));
registry.registerItem(373, 8203, new Replacement(373, 0, "Potion of Leaping"));
registry.registerItem(373, 8235, new Replacement(373, 0, "Potion of Leaping"));
registry.registerItem(373, 8267, new Replacement(373, 0, "Potion of Leaping"));
registry.registerItem(373, 16395, new Replacement(373, 0, "Splash Potion of Leaping"));
registry.registerItem(373, 16427, new Replacement(373, 0, "Splash Potion of Leaping"));
registry.registerItem(373, 16459, new Replacement(373, 0, "Splash Potion of Leaping"));
registry.registerItem(383, 30, new Replacement(383, "Spawn ArmorStand"));
registry.registerItem(383, 67, new Replacement(383, "Spawn Endermite"));
registry.registerItem(383, 68, new Replacement(383, "Spawn Guardian"));
registry.registerItem(383, 101, new Replacement(383, "Spawn Rabbit"));
registry.registerItem(19, 1, new Replacement(19, 0, "Wet Sponge"));
registry.registerItem(182, new Replacement(44, 1, "Red Sandstone Slab"));
registry.registerItemBlock(166, new Replacement(20, "Barrier"));
registry.registerItemBlock(167, new Replacement(96, "Iron Trapdoor"));
registry.registerItemBlock(1, 1, new Replacement(1, 0, "Granite"));
registry.registerItemBlock(1, 2, new Replacement(1, 0, "Polished Granite"));
registry.registerItemBlock(1, 3, new Replacement(1, 0, "Diorite"));
registry.registerItemBlock(1, 4, new Replacement(1, 0, "Polished Diorite"));
registry.registerItemBlock(1, 5, new Replacement(1, 0, "Andesite"));
registry.registerItemBlock(1, 6, new Replacement(1, 0, "Polished Andesite"));
registry.registerItemBlock(168, 0, new Replacement(1, 0, "Prismarine"));
registry.registerItemBlock(168, 1, new Replacement(98, 0, "Prismarine Bricks"));
registry.registerItemBlock(168, 2, new Replacement(98, 1, "Dark Prismarine"));
registry.registerItemBlock(169, new Replacement(89, "Sea Lantern"));
registry.registerItemBlock(165, new Replacement(95, 5, "Slime Block"));
registry.registerItemBlock(179, 0, new Replacement(24, "Red Sandstone"));
registry.registerItemBlock(179, 1, new Replacement(24, "Chiseled Red Sandstone"));
registry.registerItemBlock(179, 2, new Replacement(24, "Smooth Sandstone"));
registry.registerItemBlock(181, new Replacement(43, 1, "Double Red Sandstone Slab"));
registry.registerItemBlock(180, new Replacement(128, "Red Sandstone Stairs"));
registry.registerItemBlock(188, new Replacement(85, "Spruce Fence"));
registry.registerItemBlock(189, new Replacement(85, "Birch Fence"));
registry.registerItemBlock(190, new Replacement(85, "Jungle Fence"));
registry.registerItemBlock(191, new Replacement(85, "Dark Oak Fence"));
registry.registerItemBlock(192, new Replacement(85, "Acacia Fence"));
registry.registerItemBlock(183, new Replacement(107, "Spruce Fence Gate"));
registry.registerItemBlock(184, new Replacement(107, "Birch Fence Gate"));
registry.registerItemBlock(185, new Replacement(107, "Jungle Fence Gate"));
registry.registerItemBlock(186, new Replacement(107, "Dark Oak Fence Gate"));
registry.registerItemBlock(187, new Replacement(107, "Acacia Fence Gate"));
registry.registerItemBlock(427, new Replacement(324, "Spruce Door"));
registry.registerItemBlock(428, new Replacement(324, "Birch Door"));
registry.registerItemBlock(429, new Replacement(324, "Jungle Door"));
registry.registerItemBlock(430, new Replacement(324, "Dark Oak Door"));
registry.registerItemBlock(431, new Replacement(324, "Acacia Door"));
registry.registerItemBlock(157, new Replacement(28, "Activator Rail"));
}
public static Item replace(Item item) {
return registry.replace(item);
}
public static int replace(int raw) {
int data = BlockState.extractData(raw);
Replacement replace = registry.replace(BlockState.extractId(raw), data);
return replace != null ? BlockState.stateToRaw(replace.getId(), replace.replaceData(data)) : raw;
}
public static Replacement getReplacement(int id, int data) {
return registry.replace(id, data);
}
}
@@ -0,0 +1,186 @@
/*
* 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.protocol.protocol1_7_6_10to1_8.types.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;
import java.util.HashMap;
import java.util.Optional;
public enum MetaIndex1_7_6_10To1_8 {
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_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_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),
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_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_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),
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),
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<>();
static {
for (MetaIndex1_7_6_10To1_8 index : MetaIndex1_7_6_10To1_8.values()) {
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
}
private final EntityTypes1_10.EntityType clazz;
private final int newIndex;
private final MetaType1_8 newType;
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) {
this.clazz = type;
this.index = index;
this.newIndex = index;
this.oldType = oldType;
this.newType = newType;
}
MetaIndex1_7_6_10To1_8(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;
this.newIndex = newIndex;
this.newType = newType;
}
private static Optional<MetaIndex1_7_6_10To1_8> getIndex(EntityType type, int index) {
Pair<EntityType, Integer> pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
return Optional.empty();
}
public EntityTypes1_10.EntityType getClazz() {
return clazz;
}
public int getNewIndex() {
return newIndex;
}
public MetaType1_8 getNewType() {
return newType;
}
public MetaType1_7_6_10 getOldType() {
return oldType;
}
public int getIndex() {
return index;
}
public static MetaIndex1_7_6_10To1_8 searchIndex(EntityType type, int index) {
EntityType currentType = type;
do {
Optional<MetaIndex1_7_6_10To1_8> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
}
currentType = currentType.getParent();
} while (currentType != null);
return null;
}
}
@@ -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.metadata;
import com.viaversion.viarewind.protocol.protocol1_8to1_7_6_10.metadata.MetaIndex1_8To1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.Optional;
public class MetaIndex1_7_6_10to1_8 {
private static final HashMap<Pair<Entity1_10Types.EntityType, Integer>, MetaIndex1_8To1_7_6_10> metadataRewrites = new HashMap<>();
static {
for (MetaIndex1_8To1_7_6_10 index : MetaIndex1_8To1_7_6_10.values())
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
private static Optional<MetaIndex1_8To1_7_6_10> getIndex(Entity1_10Types.EntityType type, int index) {
Pair pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
return Optional.empty();
}
public static MetaIndex1_8To1_7_6_10 searchIndex(Entity1_10Types.EntityType type, int index) {
Entity1_10Types.EntityType currentType = type;
do {
Optional<MetaIndex1_8To1_7_6_10> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
}
currentType = currentType.getParent();
} while (currentType != null);
return null;
}
}
@@ -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
@@ -19,40 +19,49 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_7_6_10.metadata.MetaIndex1_8To1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.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.viarewind.protocol.protocol1_7_6_10to1_8.types.MetaType1_7_6_10;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
@SuppressWarnings({"deprecation"})
public class MetadataRewriter {
public static void transform(Entity1_10Types.EntityType type, List<Metadata> list) {
private final Protocol1_7_6_10To1_8 protocol;
public MetadataRewriter(Protocol1_7_6_10To1_8 protocol) {
this.protocol = protocol;
}
public void transform(EntityType type, List<Metadata> list) {
for (Metadata entry : new ArrayList<>(list)) {
MetaIndex1_8To1_7_6_10 metaIndex = MetaIndex1_7_6_10to1_8.searchIndex(type, entry.id());
final MetaIndex1_7_6_10To1_8 metaIndex = MetaIndex1_7_6_10To1_8.searchIndex(type, entry.id());
try {
if (metaIndex == null) throw new Exception("Could not find valid metadata");
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;
}
Object value = entry.getValue();
if (!metaIndex.getNewType().type().getOutputClass().isAssignableFrom(value.getClass())) {
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_8To1_7_6_10.ENTITY_AGEABLE_AGE) {
if (metaIndex == MetaIndex1_7_6_10To1_8.ENTITY_AGEABLE_AGE) {
if ((Integer) entry.getValue() < 0) {
entry.setValue(-25000);
}
@@ -70,12 +79,13 @@ public class MetadataRewriter {
entry.setValue(((Integer) value).byteValue());
}
if (metaIndex.getNewType() == MetaType1_8.Byte) {
if (metaIndex == MetaIndex1_8To1_7_6_10.ITEM_FRAME_ROTATION) {
value = ((Integer) ((Byte) value / 2)).byteValue();
if (metaIndex == MetaIndex1_7_6_10To1_8.ITEM_FRAME_ROTATION) {
entry.setValue(Integer.valueOf((Byte) value % 4).byteValue());
} else {
entry.setValue(value);
}
entry.setValue(value);
}
if (metaIndex == MetaIndex1_8To1_7_6_10.HUMAN_SKIN_FLAGS) {
if (metaIndex == MetaIndex1_7_6_10To1_8.HUMAN_SKIN_FLAGS) {
byte flags = (byte) value;
boolean cape = (flags & 0x01) != 0;
flags = (byte) (cape ? 0x00 : 0x02);
@@ -83,26 +93,20 @@ public class MetadataRewriter {
}
break;
case Slot:
entry.setValue(ItemRewriter.toClient((Item) value));
entry.setValue(protocol.getItemRewriter().handleItemToClient((Item) value));
break;
case Float:
entry.setValue(value);
break;
case Short:
entry.setValue(value);
break;
case String:
entry.setValue(value);
break;
case Short:
case Position:
entry.setValue(value);
break;
default:
ViaRewind.getPlatform().getLogger().warning("[Out] Unhandled MetaDataType: " + metaIndex.getNewType());
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);
}
}
@@ -0,0 +1,27 @@
/*
* 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.model;
public class FurnaceData {
public short fuelLeft = 0;
public short maxFuel = 0;
public short progress = 0;
public short maxProgress = 200;
}
@@ -0,0 +1,319 @@
/*
* 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.model;
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.metadata.MetaIndex1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.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.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Vector3d;
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_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import java.util.ArrayList;
import java.util.List;
// Close this class file while you still can, because it's about to get ugly
public class VirtualHologramEntity {
private final List<Metadata> metadataTracker = new ArrayList<>();
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 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) {
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;
}
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;
}
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;
}
this.yaw = yaw;
this.headYaw = yaw;
this.pitch = pitch;
updateLocation(false);
}
public void setHeadYaw(float yaw) {
if (this.headYaw == yaw) {
return;
}
this.headYaw = yaw;
updateLocation(false);
}
public void updateMetadata(final List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
metadataTracker.removeIf(m -> m.id() == metadata.id());
metadataTracker.add(metadata);
}
updateState();
}
public void updateState() {
byte flags = 0;
byte armorStandFlags = 0;
for (Metadata metadata : metadataTracker) {
if (metadata.id() == 0 && metadata.metaType() == MetaType1_8.Byte) {
flags = ((Number) metadata.getValue()).byteValue();
} else if (metadata.id() == 2 && metadata.metaType() == MetaType1_8.String) {
name = metadata.getValue().toString();
if (name != null && name.isEmpty()) name = null;
} else if (metadata.id() == 10 && metadata.metaType() == MetaType1_8.Byte) {
armorStandFlags = ((Number) metadata.getValue()).byteValue();
}
}
final boolean invisible = (flags & 0x20) != 0;
small = (armorStandFlags & 0x01) != 0;
marker = (armorStandFlags & 0x10) != 0;
State prevState = currentState;
if (invisible && name != null) {
currentState = State.HOLOGRAM;
} else {
currentState = State.ZOMBIE;
}
if (currentState != prevState) {
deleteEntity();
sendSpawnPacket();
} else {
updateMetadata();
updateLocation(false);
}
}
public void updateLocation(boolean remount) {
if (entityIds == null) return;
if (currentState == State.ZOMBIE) {
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
final PacketWrapper entityHeadLook = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_HEAD_LOOK, user);
entityHeadLook.write(Type.INT, entityId);
entityHeadLook.write(Type.BYTE, (byte) ((headYaw / 360f) * 256));
PacketUtil.sendPacket(entityHeadLook, Protocol1_7_6_10To1_8.class, true, true);
} else if (currentState == State.HOLOGRAM) {
if (remount) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, null, 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);
}
// Don't ask me where this offset is coming from
teleportEntity(entityIds[0], locX, (locY + (marker ? 54.85 : small ? 56 : 57) - 0.16), locZ, 0, 0); // Skull
if (remount) {
teleportEntity(entityIds[1], locX, locY + 56.75, locZ, 0, 0); // Horse
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, null, user);
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);
}
}
}
protected void teleportEntity(final int entityId, final double x, final double y, final double z, final float yaw, final float pitch) {
final PacketWrapper entityTeleport = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_TELEPORT, user);
entityTeleport.write(Type.INT, entityId); // entity id
entityTeleport.write(Type.INT, (int) (x * 32.0)); // x
entityTeleport.write(Type.INT, (int) (y * 32.0)); // y
entityTeleport.write(Type.INT, (int) (z * 32.0)); // z
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);
}
protected void spawnEntity(final int entityId, final int type, final double locX, final double locY, final double locZ) {
final PacketWrapper spawnMob = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_MOB, null, user);
spawnMob.write(Type.VAR_INT, entityId); // entity id
spawnMob.write(Type.UNSIGNED_BYTE, (short) type); // type
spawnMob.write(Type.INT, (int) (locX * 32.0)); // x
spawnMob.write(Type.INT, (int) (locY * 32.0)); // y
spawnMob.write(Type.INT, (int) (locZ * 32.0)); // z
spawnMob.write(Type.BYTE, (byte) 0); // yaw
spawnMob.write(Type.BYTE, (byte) 0); // pitch
spawnMob.write(Type.BYTE, (byte) 0); // head pitch
spawnMob.write(Type.SHORT, (short) 0); // velocity x
spawnMob.write(Type.SHORT, (short) 0); // velocity y
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);
}
public void updateMetadata() {
if (entityIds == null) return;
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_METADATA, null, user);
if (currentState == State.ZOMBIE) {
writeZombieMeta(metadataPacket);
} else if (currentState == State.HOLOGRAM) {
writeHologramMeta(metadataPacket);
} else {
return;
}
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class, true, true);
}
private void writeZombieMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[0]);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : metadataTracker) {
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);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
private void writeHologramMeta(PacketWrapper metadataPacket) {
metadataPacket.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));
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
public void sendSpawnPacket() {
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()};
PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_ENTITY, null, user);
spawnSkull.write(Type.VAR_INT, entityIds[0]);
spawnSkull.write(Type.BYTE, (byte) 66);
spawnSkull.write(Type.INT, (int) (locX * 32.0));
spawnSkull.write(Type.INT, (int) (locY * 32.0));
spawnSkull.write(Type.INT, (int) (locZ * 32.0));
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);
spawnEntity(entityIds[1], 100, locX, locY, locZ); // Horse
this.entityIds = entityIds;
}
updateMetadata();
updateLocation(true);
}
public AABB getBoundingBox() {
final double width = this.small ? 0.25 : 0.5;
final double height = this.small ? 0.9875 : 1.975;
final Vector3d min = new Vector3d(this.locX - width / 2, this.locY, this.locZ - width / 2);
final Vector3d max = new Vector3d(this.locX + width / 2, this.locY + height, this.locZ + width / 2);
return new AABB(min, max);
}
private int additionalEntityId() {
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);
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);
}
private enum State {
HOLOGRAM, ZOMBIE
}
public int getEntityId() {
return 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
@@ -18,26 +18,20 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
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.items.ItemRewriter;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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.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.viaversion.api.minecraft.entities.EntityType;
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.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.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.List;
import java.util.UUID;
@@ -45,39 +39,33 @@ import java.util.UUID;
public class EntityPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
/* OUTGOING */
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EQUIPMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.SHORT); //Slot
map(Type.ITEM, Types1_7_6_10.COMPRESSED_NBT_ITEM); //Item
handler(packetWrapper -> {
Item item = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
ItemRewriter.toClient(item);
packetWrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.SHORT); // slot
map(Type.ITEM1_8, Types1_7_6_10.COMPRESSED_NBT_ITEM); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int id = packetWrapper.get(Type.INT, 0);
int limit = tracker.getPlayerId() == id ? 3 : 4;
if (packetWrapper.get(Type.SHORT, 0) > limit) packetWrapper.cancel();
});
handler(packetWrapper -> {
short slot = packetWrapper.get(Type.SHORT, 0);
if (packetWrapper.isCancelled()) return;
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
UUID uuid = tracker.getPlayerUUID(packetWrapper.get(Type.INT, 0));
handler(wrapper -> {
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));
if (uuid == null) return;
Item item = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
tracker.setPlayerEquipment(uuid, item, slot);
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
wrapper.user().get(PlayerSessionStorage.class).setPlayerEquipment(uuid, item, slot);
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
final GameProfileStorage storage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile profile = storage.get(uuid);
if (profile != null && profile.gamemode == 3) packetWrapper.cancel();
if (profile != null && profile.gamemode == 3) { // spectator mode didn't exist in 1.7.10
wrapper.cancel();
}
});
}
});
@@ -85,84 +73,74 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.USE_BED, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.UNSIGNED_BYTE, (short) position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.VAR_INT, Type.INT); // entity id
map(Type.POSITION1_8, Types1_7_6_10.U_BYTE_POSITION); // position
}
});
protocol.registerClientbound(ClientboundPackets1_8.COLLECT_ITEM, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Collected Entity ID
map(Type.VAR_INT, Type.INT); //Collector Entity ID
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)));
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_VELOCITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.SHORT); //velX
map(Type.SHORT); //velY
map(Type.SHORT); //velZ
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() {
handler(packetWrapper -> {
int[] entityIds = packetWrapper.read(Type.VAR_INT_ARRAY_PRIMITIVE);
map(Type.VAR_INT_ARRAY_PRIMITIVE, Types1_7_6_10.BYTE_INT_ARRAY); // entity ids
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
for (int entityId : entityIds) tracker.removeEntity(entityId);
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
List<List<Integer>> parts = Lists.partition(Ints.asList(entityIds), Byte.MAX_VALUE);
for (int i = 0; i < parts.size() - 1; i++) {
PacketWrapper destroy = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES,
packetWrapper.user());
destroy.write(Types1_7_6_10.INT_ARRAY, parts.get(i).stream()
.mapToInt(Integer::intValue).toArray());
PacketUtil.sendPacket(destroy, Protocol1_7_6_10To1_8.class);
for (int entityId : wrapper.get(Types1_7_6_10.BYTE_INT_ARRAY, 0)) {
tracker.removeEntity(entityId);
}
packetWrapper.write(Types1_7_6_10.INT_ARRAY, parts.get(parts.size() - 1).stream()
.mapToInt(Integer::intValue).toArray());
}); //Entity Id Array
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.VAR_INT, Type.INT); // entity id
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //x
map(Type.BYTE); //y
map(Type.BYTE); //z
map(Type.BOOLEAN, Type.NOTHING);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.BYTE, 0);
int y = packetWrapper.get(Type.BYTE, 1);
int z = packetWrapper.get(Type.BYTE, 2);
replacement.relMove(x / 32.0, y / 32.0, z / 32.0);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // x
map(Type.BYTE); // y
map(Type.BYTE); // z
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().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);
}
});
}
@@ -171,19 +149,21 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //yaw
map(Type.BYTE); //pitch
map(Type.BOOLEAN, Type.NOTHING);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement 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);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // yaw
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 VirtualHologramEntity hologram = tracker.getVirtualHologramMap().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);
}
});
}
@@ -192,26 +172,29 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //x
map(Type.BYTE); //y
map(Type.BYTE); //z
map(Type.BYTE); //yaw
map(Type.BYTE); //pitch
map(Type.BOOLEAN, Type.NOTHING);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.BYTE, 0);
int y = packetWrapper.get(Type.BYTE, 1);
int z = packetWrapper.get(Type.BYTE, 2);
int yaw = packetWrapper.get(Type.BYTE, 3);
int pitch = packetWrapper.get(Type.BYTE, 4);
replacement.relMove(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // x
map(Type.BYTE); // y
map(Type.BYTE); // z
map(Type.BYTE); // yaw
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 VirtualHologramEntity hologram = tracker.getVirtualHologramMap().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);
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);
}
});
}
@@ -220,36 +203,37 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.INT); //x
map(Type.INT); //y
map(Type.INT); //z
map(Type.BYTE); //yaw
map(Type.BYTE); //pitch
map(Type.BOOLEAN, Type.NOTHING);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
Entity1_10Types.EntityType type = tracker.getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.MINECART_ABSTRACT) {
int y = packetWrapper.get(Type.INT, 2);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
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 EntityType type = tracker.getEntityMap().get(entityId);
if (type == EntityTypes1_10.EntityType.MINECART_ABSTRACT) { // TODO | Realign all entities?
int y = wrapper.get(Type.INT, 2);
y += 12;
packetWrapper.set(Type.INT, 2, y);
wrapper.set(Type.INT, 2, y);
}
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.INT, 1);
int y = packetWrapper.get(Type.INT, 2);
int z = packetWrapper.get(Type.INT, 3);
int yaw = packetWrapper.get(Type.BYTE, 0);
int pitch = packetWrapper.get(Type.BYTE, 1);
replacement.setLocation(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(entityId);
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.INT, 1);
final int y = wrapper.get(Type.INT, 2);
final int z = wrapper.get(Type.INT, 3);
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);
}
});
}
@@ -258,16 +242,18 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_HEAD_LOOK, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //Head yaw
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
replacement.setHeadYaw(yaw * 360f / 256);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // head yaw
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int yaw = wrapper.get(Type.BYTE, 0);
hologram.setHeadYaw(yaw * 360f / 256);
}
});
}
@@ -276,16 +262,19 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ATTACH_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.INT);
map(Type.BOOLEAN);
map(Type.INT); // riding entity id
map(Type.INT); // vehicle entity id
map(Type.BOOLEAN); // leash state
handler(packetWrapper -> {
boolean leash = packetWrapper.get(Type.BOOLEAN, 0);
if (leash) return;
int passenger = packetWrapper.get(Type.INT, 0);
int vehicle = packetWrapper.get(Type.INT, 1);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.setPassenger(vehicle, passenger);
final boolean leash = packetWrapper.get(Type.BOOLEAN, 0);
if (!leash) {
final EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
final int passenger = packetWrapper.get(Type.INT, 0);
final int vehicle = packetWrapper.get(Type.INT, 1);
tracker.setPassenger(vehicle, passenger);
}
});
}
});
@@ -293,23 +282,24 @@ 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
map(Type.VAR_INT, Type.INT); // entity id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
int entityId = wrapper.get(Type.INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (tracker.getClientEntityTypes().containsKey(entityId)) {
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
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();
replacement.updateMetadata(metadataList);
} else {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityId), metadataList);
if (metadataList.isEmpty()) wrapper.cancel();
}
} else {
tracker.addMetadataToBuffer(entityId, metadataList);
wrapper.cancel();
}
});
@@ -319,43 +309,44 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //Effect Id
map(Type.BYTE); //Amplifier
map(Type.VAR_INT, Type.SHORT); //Duration
map(Type.BYTE, Type.NOTHING); //Hide Particles
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // effect id
map(Type.BYTE); // amplifier
map(Type.VAR_INT, Type.SHORT); // duration
read(Type.BYTE); // hide particles
}
});
protocol.registerClientbound(ClientboundPackets1_8.REMOVE_ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //Effect Id
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // effect id
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_PROPERTIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (tracker.getEntityReplacement(entityId) != null) {
packetWrapper.cancel();
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;
}
int amount = packetWrapper.passthrough(Type.INT);
final int amount = wrapper.passthrough(Type.INT);
for (int i = 0; i < amount; i++) {
packetWrapper.passthrough(Type.STRING);
packetWrapper.passthrough(Type.DOUBLE);
int modifierlength = packetWrapper.read(Type.VAR_INT);
packetWrapper.write(Type.SHORT, (short) modifierlength);
for (int j = 0; j < modifierlength; j++) {
packetWrapper.passthrough(Type.UUID);
packetWrapper.passthrough(Type.DOUBLE);
packetWrapper.passthrough(Type.BYTE);
wrapper.passthrough(Type.STRING); // id
wrapper.passthrough(Type.DOUBLE); // value
int modifierLength = wrapper.read(Type.VAR_INT);
wrapper.write(Type.SHORT, (short) modifierLength);
for (int j = 0; j < modifierLength; j++) {
wrapper.passthrough(Type.UUID); // modifier uuid
wrapper.passthrough(Type.DOUBLE); // modifier amount
wrapper.passthrough(Type.BYTE); // modifier operation
}
}
});
@@ -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
@@ -18,98 +18,98 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.Windows;
import com.viaversion.viarewind.utils.ChatUtil;
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.ServerboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ItemRewriter;
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.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.utils.ChatUtil;
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.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.UUID;
public class InventoryPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.OPEN_WINDOW, wrapper -> {
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
/* OUTGOING */
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE); // window id
final short windowTypeId = InventoryTracker.getInventoryType(wrapper.read(Type.STRING)); // window type
protocol.registerClientbound(ClientboundPackets1_8.OPEN_WINDOW, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
short windowId = packetWrapper.passthrough(Type.UNSIGNED_BYTE);
String windowType = packetWrapper.read(Type.STRING);
short windowtypeId = (short) Windows.getInventoryType(windowType);
packetWrapper.user().get(Windows.class).types.put(windowId, windowtypeId);
packetWrapper.write(Type.UNSIGNED_BYTE, windowtypeId);
windowTracker.getWindowTypeMap().put(windowId, windowTypeId);
wrapper.write(Type.UNSIGNED_BYTE, windowTypeId); // window type id
JsonElement titleComponent = packetWrapper.read(Type.COMPONENT); //Title
String title = ChatUtil.jsonToLegacy(titleComponent);
title = ChatUtil.removeUnusedColor(title, '8');
if (title.length() > 32) {
title = title.substring(0, 32);
}
packetWrapper.write(Type.STRING, title); //Window title
final JsonElement titleComponent = wrapper.read(Type.COMPONENT); // Title
String title = ChatUtil.jsonToLegacy(titleComponent);
title = ChatUtil.removeUnusedColor(title, '8');
if (title.length() > 32) {
title = title.substring(0, 32);
}
wrapper.write(Type.STRING, title); // window title
packetWrapper.passthrough(Type.UNSIGNED_BYTE);
packetWrapper.write(Type.BOOLEAN, true);
if (windowtypeId == 11) packetWrapper.passthrough(Type.INT); //Entity Id
});
wrapper.passthrough(Type.UNSIGNED_BYTE); // slots count
wrapper.write(Type.BOOLEAN, true); // use provided window title
if (windowTypeId == 11) { // Horse
wrapper.passthrough(Type.INT); // entity id
}
});
protocol.registerClientbound(ClientboundPackets1_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);
});
}
protocol.registerClientbound(ClientboundPackets1_8.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE); // window id
wrapper.user().get(InventoryTracker.class).remove(windowId);
});
protocol.registerClientbound(ClientboundPackets1_8.SET_SLOT, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
short windowId = packetWrapper.read(Type.UNSIGNED_BYTE); //Window Id
short windowType = packetWrapper.user().get(Windows.class).get(windowId);
packetWrapper.write(Type.UNSIGNED_BYTE, windowId);
short slot = packetWrapper.read(Type.SHORT);
if (windowType == 4) {
map(Type.UNSIGNED_BYTE); // window id
map(Type.SHORT); // slot
handler(wrapper -> {
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Type.UNSIGNED_BYTE, 0));
final short slot = wrapper.get(Type.SHORT, 0);
if (windowType == 4) { // Enchantment Table
if (slot == 1) {
packetWrapper.cancel();
return;
wrapper.cancel();
} else if (slot >= 2) {
slot -= 1;
wrapper.set(Type.SHORT, 0, (short) (slot - 1));
}
}
packetWrapper.write(Type.SHORT, slot); //Slot
});
map(Type.ITEM, Types1_7_6_10.COMPRESSED_NBT_ITEM); //Item
handler(packetWrapper -> {
Item item = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
ItemRewriter.toClient(item);
packetWrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
map(Type.ITEM1_8, Types1_7_6_10.COMPRESSED_NBT_ITEM); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
short slot = packetWrapper.get(Type.SHORT, 0);
final short slot = wrapper.get(Type.SHORT, 0);
if (slot < 5 || slot > 8) return;
Item item = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
UUID myId = packetWrapper.user().getProtocolInfo().getUuid();
tracker.setPlayerEquipment(myId, item, 8 - slot);
if (tracker.getGamemode() == 3) packetWrapper.cancel();
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
wrapper.cancel();
}
});
}
});
@@ -117,33 +117,44 @@ public class InventoryPackets {
protocol.registerClientbound(ClientboundPackets1_8.WINDOW_ITEMS, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
short windowId = packetWrapper.read(Type.UNSIGNED_BYTE); //Window Id
short windowType = packetWrapper.user().get(Windows.class).get(windowId);
packetWrapper.write(Type.UNSIGNED_BYTE, windowId);
Item[] items = packetWrapper.read(Type.ITEM_ARRAY);
if (windowType == 4) {
map(Type.UNSIGNED_BYTE); // window id
// remap enchantment table items
handler(wrapper -> {
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Type.UNSIGNED_BYTE, 0));
Item[] items = wrapper.read(Type.ITEM1_8_SHORT_ARRAY);
if (windowType == 4) { // Enchantment Table
Item[] old = items;
items = new Item[old.length - 1];
items[0] = old[0];
System.arraycopy(old, 2, items, 1, old.length - 3);
}
for (int i = 0; i < items.length; i++) items[i] = ItemRewriter.toClient(items[i]);
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, items); //Items
});
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
Item[] items = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
UUID myId = packetWrapper.user().getProtocolInfo().getUuid();
for (int i = 5; i < 9; i++) {
tracker.setPlayerEquipment(myId, items[i], 8 - i);
if (tracker.getGamemode() == 3) items[i] = null;
for (int i = 0; i < items.length; i++) {
items[i] = protocol.getItemRewriter().handleItemToClient(items[i]);
}
if (tracker.getGamemode() == 3) {
GameProfileStorage.GameProfile profile = packetWrapper.user().get(GameProfileStorage.class).get(myId);
if (profile != null) items[5] = profile.getSkull();
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, items); // items
});
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
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()) {
items[i] = null;
}
}
if (playerSession.isSpectator()) {
final GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(userId);
if (profile != null) {
items[5] = profile.getSkull();
}
}
});
}
@@ -152,112 +163,107 @@ public class InventoryPackets {
protocol.registerClientbound(ClientboundPackets1_8.WINDOW_PROPERTY, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.SHORT);
map(Type.SHORT);
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
Windows windows = packetWrapper.user().get(Windows.class);
short windowType = windows.get(windowId);
map(Type.UNSIGNED_BYTE); // window id
map(Type.SHORT); // progress bar id
map(Type.SHORT); // progress bar value
short property = packetWrapper.get(Type.SHORT, 0);
short value = packetWrapper.get(Type.SHORT, 1);
handler(wrapper -> {
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
if (windowType == -1) return;
if (windowType == 2) { //Furnace
Windows.Furnace furnace = windows.furnace.computeIfAbsent(windowId, x -> new Windows.Furnace());
if (property == 0 || property == 1) {
if (property == 0) {
furnace.setFuelLeft(value);
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
final short windowType = windowTracker.get(windowId);
final short progressBarId = wrapper.get(Type.SHORT, 0);
short progress = wrapper.get(Type.SHORT, 1);
if (windowType == 2) { // Furnace
final FurnaceData furnace = windowTracker.getFurnaceData().computeIfAbsent(windowId, x -> new FurnaceData());
if (progressBarId == 0 || progressBarId == 1) {
if (progressBarId == 0) {
furnace.fuelLeft = progress;
} else {
furnace.setMaxFuel(value);
furnace.maxFuel = progress;
}
if (furnace.getMaxFuel() == 0) {
packetWrapper.cancel();
if (furnace.maxFuel == 0) {
wrapper.cancel();
return;
}
value = (short) (200 * furnace.getFuelLeft() / furnace.getMaxFuel());
packetWrapper.set(Type.SHORT, 0, (short) 1);
packetWrapper.set(Type.SHORT, 1, value);
} else if (property == 2 || property == 3) {
if (property == 2) {
furnace.setProgress(value);
progress = (short) (200 * furnace.fuelLeft / furnace.maxFuel);
wrapper.set(Type.SHORT, 0, (short) 1);
wrapper.set(Type.SHORT, 1, progress);
} else if (progressBarId == 2 || progressBarId == 3) {
if (progressBarId == 2) {
furnace.progress = progress;
} else {
furnace.setMaxProgress(value);
furnace.maxProgress = progress;
}
if (furnace.getMaxProgress() == 0) {
packetWrapper.cancel();
if (furnace.maxProgress == 0) {
wrapper.cancel();
return;
}
value = (short) (200 * furnace.getProgress() / furnace.getMaxProgress());
packetWrapper.set(Type.SHORT, 0, (short) 0);
packetWrapper.set(Type.SHORT, 1, value);
progress = (short) (200 * furnace.progress / furnace.maxProgress);
wrapper.set(Type.SHORT, 0, (short) 0);
wrapper.set(Type.SHORT, 1, progress);
}
} else if (windowType == 4) { //Enchanting Table
if (property > 2) {
packetWrapper.cancel();
}
} else if (windowType == 8) {
windows.levelCost = value;
windows.anvilId = windowId;
} else if (windowType == 4 && progressBarId > 2) { // Enchanting Table
wrapper.cancel();
} else if (windowType == 8) { // Anvil
windowTracker.levelCost = progress;
windowTracker.anvilId = windowId;
}
});
}
});
/* INCOMING */
protocol.registerServerbound(ServerboundPackets1_7_2_5.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
protocol.registerServerbound(ServerboundPackets1_7.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);
});
}
wrapper.user().get(InventoryTracker.class).remove(windowId);
});
protocol.registerServerbound(ServerboundPackets1_7.CLICK_WINDOW, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.CLICK_WINDOW, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
short windowId = packetWrapper.read(Type.BYTE); //Window Id
packetWrapper.write(Type.UNSIGNED_BYTE, windowId);
short windowType = packetWrapper.user().get(Windows.class).get(windowId);
short slot = packetWrapper.read(Type.SHORT);
if (windowType == 4) {
map(Type.BYTE, Type.UNSIGNED_BYTE); // window id
map(Type.SHORT); // slot
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0); //Window Id
final short slot = wrapper.get(Type.SHORT, 0);
final short windowType = wrapper.user().get(InventoryTracker.class).get(windowId);
if (windowType == 4) { // Enchantment Table
if (slot > 0) {
slot += 1;
wrapper.set(Type.SHORT, 0, (short) (slot + 1));
}
}
packetWrapper.write(Type.SHORT, slot);
});
map(Type.BYTE); //Button
map(Type.SHORT); //Action Number
map(Type.BYTE); //Mode
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM);
handler(packetWrapper -> {
Item item = packetWrapper.get(Type.ITEM, 0);
ItemRewriter.toServer(item);
packetWrapper.set(Type.ITEM, 0, item);
map(Type.BYTE); // button
map(Type.SHORT); // action number
map(Type.BYTE); // mode
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM1_8); // clicked 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);
});
}
});
//Creative Inventory Action
protocol.registerServerbound(ServerboundPackets1_7.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT); //Slot
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM); //Item
handler(packetWrapper -> {
Item item = packetWrapper.get(Type.ITEM, 0);
ItemRewriter.toServer(item);
packetWrapper.set(Type.ITEM, 0, item);
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);
});
}
});
}
}
@@ -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
@@ -18,36 +18,34 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.ArmorStandReplacement;
import com.viaversion.viarewind.ViaRewind;
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_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.replacement.EntityReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.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;
import com.viaversion.viarewind.utils.math.Vector3d;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
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.ServerboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ItemRewriter;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.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.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
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;
@@ -59,38 +57,31 @@ import java.util.UUID;
public class PlayerPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
/* OUTGOING */
protocol.registerClientbound(ClientboundPackets1_8.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); //Entiy Id
map(Type.UNSIGNED_BYTE); //Gamemode
map(Type.BYTE); //Dimension
map(Type.UNSIGNED_BYTE); //Difficulty
map(Type.UNSIGNED_BYTE); //Max players
map(Type.STRING); //Level Type
map(Type.BOOLEAN, Type.NOTHING);//Reduced Debug Info
handler(packetWrapper -> {
if (!ViaRewind.getConfig().isReplaceAdventureMode()) return;
if (packetWrapper.get(Type.UNSIGNED_BYTE, 0) == 2) {
packetWrapper.set(Type.UNSIGNED_BYTE, 0, (short) 0);
}
});
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.setGamemode(packetWrapper.get(Type.UNSIGNED_BYTE, 0));
tracker.setPlayerId(packetWrapper.get(Type.INT, 0));
tracker.getClientEntityTypes().put(tracker.getPlayerId(), Entity1_10Types.EntityType.ENTITY_HUMAN);
tracker.setDimension(packetWrapper.get(Type.BYTE, 0));
tracker.addPlayer(tracker.getPlayerId(), packetWrapper.user().getProtocolInfo().getUuid());
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
world.setEnvironment(packetWrapper.get(Type.BYTE, 0));
});
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()));
});
@@ -100,10 +91,12 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.COMPONENT); //Chat Message
handler(packetWrapper -> {
int position = packetWrapper.read(Type.BYTE);
if (position == 2) packetWrapper.cancel();
map(Type.COMPONENT); // chat message
handler(wrapper -> {
final int position = wrapper.read(Type.BYTE);
if (position == 2) { // above hotbar
wrapper.cancel();
}
});
}
});
@@ -111,102 +104,87 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_POSITION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.INT, position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // spawn position
}
});
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_HEALTH, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT); //Health
map(Type.VAR_INT, Type.SHORT); //Food
map(Type.FLOAT); //Food Saturation
map(Type.FLOAT); // health
map(Type.VAR_INT, Type.SHORT); // food
map(Type.FLOAT); // food saturation
}
});
protocol.registerClientbound(ClientboundPackets1_8.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.STRING);
handler(packetWrapper -> {
if (!ViaRewind.getConfig().isReplaceAdventureMode()) return;
if (packetWrapper.get(Type.UNSIGNED_BYTE, 1) == 2) {
packetWrapper.set(Type.UNSIGNED_BYTE, 1, (short) 0);
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) {
wrapper.set(Type.UNSIGNED_BYTE, 1, (short) 0);
}
}
});
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.setGamemode(packetWrapper.get(Type.UNSIGNED_BYTE, 1));
if (tracker.getDimension() != packetWrapper.get(Type.INT, 0)) {
tracker.setDimension(packetWrapper.get(Type.INT, 0));
tracker.clearEntities();
tracker.getClientEntityTypes().put(tracker.getPlayerId(), Entity1_10Types.EntityType.ENTITY_HUMAN);
wrapper.user().get(PlayerSessionStorage.class).gameMode = 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);
if (world.getEnvironment() != dimension) {
world.setEnvironment(dimension.id());
// Reset on dimension change
tracker.clear();
tracker.getEntityMap().put(tracker.getPlayerId(), EntityTypes1_10.EntityType.ENTITY_HUMAN);
}
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
world.setEnvironment(packetWrapper.get(Type.INT, 0));
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); //x
map(Type.DOUBLE); //y
map(Type.DOUBLE); //z
map(Type.FLOAT); //yaw
map(Type.FLOAT); //pitch
handler(packetWrapper -> {
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
playerPosition.setPositionPacketReceived(true);
map(Type.DOUBLE); // x
map(Type.DOUBLE); // y
map(Type.DOUBLE); // z
map(Type.FLOAT); // yaw
map(Type.FLOAT); // pitch
handler(wrapper -> {
final double x = wrapper.get(Type.DOUBLE, 0);
double y = wrapper.get(Type.DOUBLE, 1);
final double z = wrapper.get(Type.DOUBLE, 2);
int flags = packetWrapper.read(Type.BYTE);
if ((flags & 0x01) == 0x01) {
double x = packetWrapper.get(Type.DOUBLE, 0);
x += playerPosition.getPosX();
packetWrapper.set(Type.DOUBLE, 0, x);
}
double y = packetWrapper.get(Type.DOUBLE, 1);
if ((flags & 0x02) == 0x02) {
y += playerPosition.getPosY();
}
playerPosition.setReceivedPosY(y);
y += 1.62F;
packetWrapper.set(Type.DOUBLE, 1, y);
if ((flags & 0x04) == 0x04) {
double z = packetWrapper.get(Type.DOUBLE, 2);
z += playerPosition.getPosZ();
packetWrapper.set(Type.DOUBLE, 2, z);
}
if ((flags & 0x08) == 0x08) {
float yaw = packetWrapper.get(Type.FLOAT, 0);
yaw += playerPosition.getYaw();
packetWrapper.set(Type.FLOAT, 0, yaw);
}
if ((flags & 0x10) == 0x10) {
float pitch = packetWrapper.get(Type.FLOAT, 1);
pitch += playerPosition.getPitch();
packetWrapper.set(Type.FLOAT, 1, pitch);
}
});
handler(packetWrapper -> {
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
packetWrapper.write(Type.BOOLEAN, playerPosition.isOnGround());
});
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (tracker.getSpectating() != tracker.getPlayerId()) {
packetWrapper.cancel();
final float yaw = wrapper.get(Type.FLOAT, 0);
final float pitch = wrapper.get(Type.FLOAT, 1);
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final int flags = wrapper.read(Type.BYTE);
// x, y, and z
if ((flags & 0x01) == 0x01) wrapper.set(Type.DOUBLE, 0, x + playerSession.getPosX());
if ((flags & 0x02) == 0x02) y += playerSession.getPosY();
playerSession.receivedPosY = y;
wrapper.set(Type.DOUBLE, 1, y + 1.62F);
if ((flags & 0x04) == 0x04) wrapper.set(Type.DOUBLE, 2, z + playerSession.getPosZ());
// yaw and pitch
if ((flags & 0x08) == 0x08) wrapper.set(Type.FLOAT, 0, yaw + playerSession.yaw);
if ((flags & 0x10) == 0x10) wrapper.set(Type.FLOAT, 1, pitch + playerSession.pitch);
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()) {
wrapper.cancel();
}
});
}
@@ -215,53 +193,48 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.SET_EXPERIENCE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT); //Experience bar
map(Type.VAR_INT, Type.SHORT); //Level
map(Type.VAR_INT, Type.SHORT); //Total Experience
map(Type.FLOAT); // experience bar
map(Type.VAR_INT, Type.SHORT); // level
map(Type.VAR_INT, Type.SHORT); // total experience
}
});
protocol.registerClientbound(ClientboundPackets1_8.GAME_EVENT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.FLOAT);
handler(packetWrapper -> {
int mode = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
if (mode != 3) return;
int gamemode = packetWrapper.get(Type.FLOAT, 0).intValue();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (gamemode == 3 || tracker.getGamemode() == 3) {
UUID myId = packetWrapper.user().getProtocolInfo().getUuid();
map(Type.UNSIGNED_BYTE); // reason
map(Type.FLOAT); // value
handler(wrapper -> {
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) {
UUID myId = wrapper.user().getProtocolInfo().getUuid();
Item[] equipment = new Item[4];
if (gamemode == 3) {
GameProfileStorage.GameProfile profile = packetWrapper.user().get(GameProfileStorage.class).get(myId);
equipment[3] = profile.getSkull();
if (gameMode == 3) {
GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(myId);
equipment[3] = profile == null ? null : profile.getSkull();
} else {
for (int i = 0; i < equipment.length; i++) {
equipment[i] = tracker.getPlayerEquipment(myId, i);
equipment[i] = playerSession.getPlayerEquipment(myId, i);
}
}
for (int i = 0; i < equipment.length; i++) {
PacketWrapper setSlot = PacketWrapper.create(ClientboundPackets1_7.SET_SLOT, packetWrapper.user());
PacketWrapper setSlot = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_SLOT, wrapper.user());
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);
}
}
});
handler(packetWrapper -> {
int mode = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
if (mode == 3) {
int gamemode = packetWrapper.get(Type.FLOAT, 0).intValue();
if (gamemode == 2 && ViaRewind.getConfig().isReplaceAdventureMode()) {
gamemode = 0;
packetWrapper.set(Type.FLOAT, 0, 0.0f);
}
packetWrapper.user().get(EntityTracker.class).setGamemode(gamemode);
if (gameMode == 2 && ViaRewind.getConfig().isReplaceAdventureMode()) {
gameMode = 0;
wrapper.set(Type.FLOAT, 0, 0.0f);
}
wrapper.user().get(PlayerSessionStorage.class).gameMode = gameMode;
});
}
});
@@ -269,12 +242,7 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.OPEN_SIGN_EDITOR, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.INT, position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // position
}
});
@@ -311,7 +279,7 @@ public class PlayerPackets {
gameProfile.setDisplayName(ChatUtil.jsonToLegacy(displayName));
}
PacketWrapper packet = PacketWrapper.create(0x38, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
@@ -323,7 +291,7 @@ public class PlayerPackets {
if (gameProfile == null || gameProfile.gamemode == gamemode) continue;
if (gamemode == 3 || gameProfile.gamemode == 3) {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
int entityId = tracker.getPlayerEntityId(uuid);
boolean isOwnPlayer = entityId == tracker.getPlayerId();
if (entityId != -1) {
@@ -333,12 +301,12 @@ public class PlayerPackets {
equipment[isOwnPlayer ? 3 : 4] = gameProfile.getSkull();
} else {
for (int j = 0; j < equipment.length; j++) {
equipment[j] = tracker.getPlayerEquipment(uuid, j);
equipment[j] = packetWrapper.user().get(PlayerSessionStorage.class).getPlayerEquipment(uuid, j);
}
}
for (short slot = 0; slot < equipment.length; slot++) {
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_EQUIPMENT, packetWrapper.user());
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, packetWrapper.user());
equipmentPacket.write(Type.INT, entityId);
equipmentPacket.write(Type.SHORT, slot);
equipmentPacket.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, equipment[slot]);
@@ -353,16 +321,16 @@ public class PlayerPackets {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(0x38, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.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);
gameProfile.ping = ping;
packet = PacketWrapper.create(0x38, null, packetWrapper.user());
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
@@ -373,8 +341,8 @@ public class PlayerPackets {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null || gameProfile.displayName == null && displayName == null) continue;
PacketWrapper packet = PacketWrapper.create(0x38, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
@@ -383,8 +351,8 @@ public class PlayerPackets {
if (gameProfile.displayName == null && displayName != null || gameProfile.displayName != null && displayName == null || !gameProfile.displayName.equals(displayName)) {
gameProfile.setDisplayName(displayName);
}
packet = PacketWrapper.create(0x38, null, packetWrapper.user());
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) gameProfile.ping);
@@ -393,7 +361,7 @@ public class PlayerPackets {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.remove(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(0x38, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
@@ -414,15 +382,16 @@ public class PlayerPackets {
byte flags = packetWrapper.get(Type.BYTE, 0);
float flySpeed = packetWrapper.get(Type.FLOAT, 0);
float walkSpeed = packetWrapper.get(Type.FLOAT, 1);
PlayerAbilities abilities = packetWrapper.user().get(PlayerAbilities.class);
abilities.setInvincible((flags & 8) == 8);
abilities.setAllowFly((flags & 4) == 4);
abilities.setFlying((flags & 2) == 2);
abilities.setCreative((flags & 1) == 1);
abilities.setFlySpeed(flySpeed);
abilities.setWalkSpeed(walkSpeed);
if (abilities.isSprinting() && abilities.isFlying()) {
packetWrapper.set(Type.FLOAT, 0, abilities.getFlySpeed() * 2.0f);
PlayerSessionStorage abilities = packetWrapper.user().get(PlayerSessionStorage.class);
abilities.invincible = (flags & 8) == 8;
abilities.allowFly = (flags & 4) == 4;
abilities.flying = (flags & 2) == 2;
abilities.creative = (flags & 1) == 1;
abilities.flySpeed = flySpeed;
abilities.walkSpeed = walkSpeed;
if (abilities.sprinting && abilities.flying) {
packetWrapper.set(Type.FLOAT, 0, abilities.flySpeed * 2.0f);
}
});
}
@@ -434,7 +403,7 @@ public class PlayerPackets {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
if (channel.equalsIgnoreCase("MC|TrList")) {
if (channel.equals("MC|TrList")) {
packetWrapper.passthrough(Type.INT); //Window Id
int size;
@@ -445,15 +414,15 @@ public class PlayerPackets {
}
for (int i = 0; i < size; i++) {
Item item = ItemRewriter.toClient(packetWrapper.read(Type.ITEM));
Item item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 1
item = ItemRewriter.toClient(packetWrapper.read(Type.ITEM));
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 3
boolean has3Items = packetWrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
item = ItemRewriter.toClient(packetWrapper.read(Type.ITEM));
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 2
}
@@ -461,15 +430,15 @@ public class PlayerPackets {
packetWrapper.read(Type.INT); //Uses
packetWrapper.read(Type.INT); //Max Uses
}
} else if (channel.equalsIgnoreCase("MC|Brand")) {
} else if (channel.equals("MC|Brand")) {
packetWrapper.write(Type.REMAINING_BYTES, packetWrapper.read(Type.STRING).getBytes(StandardCharsets.UTF_8));
}
packetWrapper.cancel();
packetWrapper.setId(-1);
packetWrapper.setPacketType(null);
ByteBuf newPacketBuf = Unpooled.buffer();
packetWrapper.writeToBuffer(newPacketBuf);
PacketWrapper newWrapper = PacketWrapper.create(0x3F, newPacketBuf, packetWrapper.user());
PacketWrapper newWrapper = PacketWrapper.create(ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, newPacketBuf, packetWrapper.user());
newWrapper.passthrough(Type.STRING);
if (newPacketBuf.readableBytes() <= Short.MAX_VALUE) {
newWrapper.write(Type.SHORT, (short) newPacketBuf.readableBytes());
@@ -486,10 +455,10 @@ public class PlayerPackets {
handler(packetWrapper -> {
packetWrapper.cancel();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
int entityId = packetWrapper.read(Type.VAR_INT);
int spectating = tracker.getSpectating();
int spectating = tracker.spectatingPlayerId;
if (spectating != entityId) {
tracker.setSpectating(entityId);
@@ -533,7 +502,7 @@ public class PlayerPackets {
protocol.cancelClientbound(ClientboundPackets1_8.TAB_LIST);
//Resource Pack Send
protocol.registerClientbound(ClientboundPackets1_8.RESOURCE_PACK, ClientboundPackets1_7.PLUGIN_MESSAGE, new PacketHandlers() {
protocol.registerClientbound(ClientboundPackets1_8.RESOURCE_PACK, ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
create(Type.STRING, "MC|RPack");
@@ -548,19 +517,19 @@ public class PlayerPackets {
buf.release();
}
});
map(Type.STRING, Type.NOTHING); // Hash
read(Type.STRING); // Hash
}
});
/* INCOMING */
protocol.registerServerbound(ServerboundPackets1_7.CHAT_MESSAGE, new PacketHandlers() {
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(EntityTracker.class).getGamemode();
int gamemode = packetWrapper.user().get(PlayerSessionStorage.class).gameMode;
if (gamemode == 3 && msg.toLowerCase().startsWith("/stp ")) {
String username = msg.split(" ")[1];
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
@@ -578,55 +547,63 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.INTERACT_ENTITY, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.INTERACT_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT);
map(Type.BYTE, Type.VAR_INT);
handler(packetWrapper -> {
int mode = packetWrapper.get(Type.VAR_INT, 1);
if (mode != 0) return;
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (!(replacement instanceof ArmorStandReplacement)) return;
ArmorStandReplacement armorStand = (ArmorStandReplacement) replacement;
AABB boundingBox = armorStand.getBoundingBox();
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
Vector3d pos = new Vector3d(playerPosition.getPosX(), playerPosition.getPosY() + 1.8, playerPosition.getPosZ());
double yaw = Math.toRadians(playerPosition.getYaw());
double pitch = Math.toRadians(playerPosition.getPitch());
Vector3d dir = new Vector3d(-Math.cos(pitch) * Math.sin(yaw), -Math.sin(pitch), Math.cos(pitch) * Math.cos(yaw));
Ray3d ray = new Ray3d(pos, dir);
Vector3d intersection = RayTracing.trace(ray, boundingBox, 5.0);
if (intersection == null) return;
intersection.substract(boundingBox.getMin());
mode = 2;
packetWrapper.set(Type.VAR_INT, 1, mode);
packetWrapper.write(Type.FLOAT, (float) intersection.getX());
packetWrapper.write(Type.FLOAT, (float) intersection.getY());
packetWrapper.write(Type.FLOAT, (float) intersection.getZ());
handler(wrapper -> {
int mode = wrapper.get(Type.VAR_INT, 1);
if (mode != 0) {
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 PlayerSessionStorage position = wrapper.user().get(PlayerSessionStorage.class);
if (tracker.getVirtualHologramMap().containsKey(entityId)) {
final AABB boundingBox = tracker.getVirtualHologramMap().get(entityId).getBoundingBox();
Vector3d pos = new Vector3d(position.getPosX(), position.getPosY() + 1.8, position.getPosZ());
double yaw = Math.toRadians(position.yaw);
double pitch = Math.toRadians(position.pitch);
Vector3d dir = new Vector3d(-Math.cos(pitch) * Math.sin(yaw), -Math.sin(pitch), Math.cos(pitch) * Math.cos(yaw));
Ray3d ray = new Ray3d(pos, dir);
Vector3d intersection = RayTracing.trace(ray, boundingBox, 5.0);
if (intersection == null) {
return;
}
intersection.substract(boundingBox.getMin());
mode = 2;
wrapper.set(Type.VAR_INT, 1, mode);
wrapper.write(Type.FLOAT, (float) intersection.getX());
wrapper.write(Type.FLOAT, (float) intersection.getY());
wrapper.write(Type.FLOAT, (float) intersection.getZ());
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_MOVEMENT, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
playerPosition.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_POSITION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); //X
map(Type.DOUBLE); //Y
map(Type.DOUBLE, Type.NOTHING);
read(Type.DOUBLE);
map(Type.DOUBLE); //Z
map(Type.BOOLEAN); //OnGround
handler(packetWrapper -> {
@@ -634,35 +611,35 @@ public class PlayerPackets {
double feetY = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerPosition.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
playerPosition.setPos(x, feetY, z);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_ROTATION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
playerPosition.setYaw(packetWrapper.get(Type.FLOAT, 0));
playerPosition.setPitch(packetWrapper.get(Type.FLOAT, 1));
playerPosition.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
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);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_POSITION_AND_ROTATION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); //X
map(Type.DOUBLE); //Y
map(Type.DOUBLE, Type.NOTHING);
read(Type.DOUBLE);
map(Type.DOUBLE); //Z
map(Type.FLOAT); //Yaw
map(Type.FLOAT); //Pitch
@@ -675,17 +652,17 @@ public class PlayerPackets {
float yaw = packetWrapper.get(Type.FLOAT, 0);
float pitch = packetWrapper.get(Type.FLOAT, 1);
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerPosition.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
playerPosition.setPos(x, feetY, z);
playerPosition.setYaw(yaw);
playerPosition.setPitch(pitch);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
playerSession.yaw = yaw;
playerSession.pitch = pitch;
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_DIGGING, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_DIGGING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); //Status
@@ -693,24 +670,24 @@ public class PlayerPackets {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.UNSIGNED_BYTE);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION, new Position(x, y, z));
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
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.POSITION, new Position(x, y, z));
packetWrapper.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 = ItemRewriter.toServer(item);
packetWrapper.write(Type.ITEM, item);
item = protocol.getItemRewriter().handleItemToServer(item);
packetWrapper.write(Type.ITEM1_8, item);
for (int i = 0; i < 3; i++) {
packetWrapper.passthrough(Type.BYTE);
@@ -719,7 +696,7 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.ANIMATION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.ANIMATION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
@@ -750,28 +727,28 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.ENTITY_ACTION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.ENTITY_ACTION, new PacketHandlers() {
@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
map(Type.INT, Type.VAR_INT); //Action Paramter
map(Type.INT, Type.VAR_INT); //Action Parameter
handler(packetWrapper -> {
int action = packetWrapper.get(Type.VAR_INT, 1);
if (action == 3 || action == 4) {
PlayerAbilities abilities = packetWrapper.user().get(PlayerAbilities.class);
abilities.setSprinting(action == 3);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.sprinting = action == 3;
PacketWrapper abilitiesPacket = PacketWrapper.create(0x39, null, packetWrapper.user());
abilitiesPacket.write(Type.BYTE, abilities.getFlags());
abilitiesPacket.write(Type.FLOAT, abilities.isSprinting() ? abilities.getFlySpeed() * 2.0f : abilities.getFlySpeed());
abilitiesPacket.write(Type.FLOAT, abilities.getWalkSpeed());
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);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.STEER_VEHICLE, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.STEER_VEHICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT); //Sideways
@@ -785,8 +762,8 @@ public class PlayerPackets {
packetWrapper.write(Type.UNSIGNED_BYTE, flags);
if (unmount) {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (tracker.getSpectating() != tracker.getPlayerId()) {
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());
sneakPacket.write(Type.VAR_INT, 0); //Start sneaking
@@ -804,45 +781,45 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.UPDATE_SIGN, new PacketHandlers() {
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.POSITION, new Position(x, y, z));
packetWrapper.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 = packetWrapper.read(Type.STRING);
packetWrapper.write(Type.COMPONENT, ComponentUtil.legacyToJson(line));
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_ABILITIES, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_ABILITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.BYTE);
map(Type.FLOAT);
map(Type.FLOAT);
handler(packetWrapper -> {
PlayerAbilities abilities = packetWrapper.user().get(PlayerAbilities.class);
if (abilities.isAllowFly()) {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
if (playerSession.allowFly) {
byte flags = packetWrapper.get(Type.BYTE, 0);
abilities.setFlying((flags & 2) == 2);
playerSession.flying = (flags & 2) == 2;
}
packetWrapper.set(Type.FLOAT, 0, abilities.getFlySpeed());
packetWrapper.set(Type.FLOAT, 0, playerSession.flySpeed);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.TAB_COMPLETE, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.TAB_COMPLETE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
create(Type.OPTIONAL_POSITION, null);
create(Type.OPTIONAL_POSITION1_8, null);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
if (msg.toLowerCase().startsWith("/stp ")) {
@@ -867,14 +844,14 @@ public class PlayerPackets {
});
//Client Settings
protocol.registerServerbound(ServerboundPackets1_7.CLIENT_SETTINGS, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.CLIENT_SETTINGS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BOOLEAN);
map(Type.BYTE, Type.NOTHING);
read(Type.BYTE);
handler(packetWrapper -> {
boolean cape = packetWrapper.read(Type.BOOLEAN);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) (cape ? 127 : 126));
@@ -882,11 +859,11 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLUGIN_MESSAGE, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.SHORT, Type.NOTHING); // Length
read(Type.SHORT); // Length
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
@@ -902,11 +879,11 @@ public class PlayerPackets {
packetWrapper.write(Type.STRING, name);
Windows windows = packetWrapper.user().get(Windows.class);
InventoryTracker windowTracker = packetWrapper.user().get(InventoryTracker.class);
PacketWrapper updateCost = PacketWrapper.create(0x31, null, packetWrapper.user());
updateCost.write(Type.UNSIGNED_BYTE, windows.anvilId);
updateCost.write(Type.UNSIGNED_BYTE, windowTracker.anvilId);
updateCost.write(Type.SHORT, (short) 0);
updateCost.write(Type.SHORT, windows.levelCost);
updateCost.write(Type.SHORT, windowTracker.levelCost);
PacketUtil.sendPacket(updateCost, Protocol1_7_6_10To1_8.class, true, true);
break;
@@ -920,11 +897,11 @@ public class PlayerPackets {
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.ITEM, book);
packetWrapper.write(Type.ITEM1_8, book);
break;
}
case "MC|Brand": {
@@ -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
@@ -18,9 +18,9 @@
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.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
@@ -34,10 +34,6 @@ import java.util.Optional;
public class ScoreboardPackets {
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() {
@@ -95,7 +91,6 @@ public class ScoreboardPackets {
}
});
//Update Score
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_SCORE, new PacketHandlers() {
@Override
public void register() {
@@ -225,30 +220,29 @@ public class ScoreboardPackets {
String[] entries = packetWrapper.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 = packetWrapper.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 = 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);
}
packetWrapper.write(Type.SHORT, (short) entryList.size());
for (String entry : entryList) {
@@ -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
@@ -18,28 +18,21 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.ArmorStandReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.EndermiteReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.GuardianReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.RabbitReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.replacement.Replacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
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.items.ReplacementRegistry1_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.Replacement;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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 com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.List;
import java.util.UUID;
@@ -47,63 +40,64 @@ import java.util.UUID;
public class SpawnPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
/* OUTGOING */
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
handler(packetWrapper -> {
UUID uuid = packetWrapper.read(Type.UUID);
packetWrapper.write(Type.STRING, uuid.toString());
map(Type.VAR_INT); // entity id
handler(wrapper -> {
final UUID uuid = wrapper.read(Type.UUID);
wrapper.write(Type.STRING, uuid.toString()); // map to string
GameProfileStorage gameProfileStorage = packetWrapper.user().get(GameProfileStorage.class);
final GameProfileStorage gameProfileStorage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) {
packetWrapper.write(Type.STRING, "");
packetWrapper.write(Type.VAR_INT, 0);
wrapper.write(Type.STRING, ""); // name
wrapper.write(Type.VAR_INT, 0); // properties count
} else {
packetWrapper.write(Type.STRING, gameProfile.name.length() > 16 ? gameProfile.name.substring(0, 16) : gameProfile.name);
packetWrapper.write(Type.VAR_INT, gameProfile.properties.size());
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) {
packetWrapper.write(Type.STRING, property.name);
packetWrapper.write(Type.STRING, property.value);
packetWrapper.write(Type.STRING, property.signature == null ? "" : property.signature);
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
}
}
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (gameProfile != null && gameProfile.gamemode == 3) {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
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++) {
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_EQUIPMENT, packetWrapper.user());
equipmentPacket.write(Type.INT, entityId);
equipmentPacket.write(Type.SHORT, i);
equipmentPacket.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, i == 4 ? gameProfile.getSkull() :null);
PacketUtil.sendPacket(equipmentPacket, Protocol1_7_6_10To1_8.class);
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(packetWrapper.get(Type.VAR_INT, 0), uuid);
tracker.addPlayer(entityId, uuid);
});
map(Type.INT);
map(Type.INT);
map(Type.INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.SHORT);
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST);
handler(packetWrapper -> {
List<Metadata> metadata = packetWrapper.get(Types1_7_6_10.METADATA_LIST, 0); //Metadata
MetadataRewriter.transform(Entity1_10Types.EntityType.PLAYER, metadata);
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(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.PLAYER);
tracker.sendMetadataBuffer(entityId);
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);
});
}
});
@@ -111,25 +105,31 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.INT);
map(Type.INT);
map(Type.INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.INT);
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(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
byte typeId = packetWrapper.get(Type.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, 2);
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (typeId == 71) {
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;
@@ -148,47 +148,39 @@ public class SpawnPackets {
yaw = 64;
break;
}
} else if (typeId == 78) {
packetWrapper.cancel();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
ArmorStandReplacement armorStand = new ArmorStandReplacement(entityId, packetWrapper.user());
armorStand.setLocation(x / 32.0, y / 32.0, z / 32.0);
armorStand.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
armorStand.setHeadYaw(yaw * 360f / 256);
tracker.addEntityReplacement(armorStand);
} else if (typeId == 10) {
y += 12;
} 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
packetWrapper.set(Type.BYTE, 0, typeId);
packetWrapper.set(Type.INT, 0, x);
packetWrapper.set(Type.INT, 1, y);
packetWrapper.set(Type.INT, 2, z);
packetWrapper.set(Type.BYTE, 1, pitch);
packetWrapper.set(Type.BYTE, 2, yaw);
wrapper.set(Type.INT, 0, x);
wrapper.set(Type.INT, 1, y);
wrapper.set(Type.INT, 2, z);
wrapper.set(Type.BYTE, 2, yaw);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
Entity1_10Types.EntityType type = Entity1_10Types.getTypeFromId(typeId, true);
tracker.getClientEntityTypes().put(entityId, type);
tracker.sendMetadataBuffer(entityId);
tracker.addEntity(entityId, type);
int data = packetWrapper.get(Type.INT, 3);
if (type != null && type.isOrHasParent(Entity1_10Types.EntityType.FALLING_BLOCK)) {
if (type != null && type.isOrHasParent(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
Replacement replace = ReplacementRegistry1_7_6_10to1_8.getReplacement(blockId, blockData);
final Replacement replace = protocol.getItemRewriter().replace(blockId, blockData);
if (replace != null) {
blockId = replace.getId();
blockData = replace.replaceData(blockData);
}
packetWrapper.set(Type.INT, 3, data = (blockId | blockData << 16));
wrapper.set(Type.INT, 3, data = (blockId | blockData << 16));
}
if (data > 0) {
packetWrapper.passthrough(Type.SHORT);
packetWrapper.passthrough(Type.SHORT);
packetWrapper.passthrough(Type.SHORT);
wrapper.passthrough(Type.SHORT); // velocity x
wrapper.passthrough(Type.SHORT); // velocity y
wrapper.passthrough(Type.SHORT); // velocity z
}
});
}
@@ -197,68 +189,58 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.UNSIGNED_BYTE);
map(Type.INT);
map(Type.INT);
map(Type.INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BYTE);
map(Type.SHORT);
map(Type.SHORT);
map(Type.SHORT);
map(Types1_8.METADATA_LIST, Types1_7_6_10.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 == 30 || typeId == 68 || typeId == 67 || typeId == 101) {
packetWrapper.cancel();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = null;
if (typeId == 30) {
replacement = new ArmorStandReplacement(entityId, packetWrapper.user());
} else if (typeId == 68) {
replacement = new GuardianReplacement(entityId, packetWrapper.user());
} else if (typeId == 67) {
replacement = new EndermiteReplacement(entityId, packetWrapper.user());
} else if (typeId == 101){
replacement = new RabbitReplacement(entityId, packetWrapper.user());
}
replacement.setLocation(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
replacement.setHeadYaw(headYaw * 360f / 256);
tracker.addEntityReplacement(replacement);
} else if (typeId == 255 || typeId == -1) {
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, Entity1_10Types.getTypeFromId(typeId, false));
tracker.sendMetadataBuffer(entityId);
});
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 -> {
List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (tracker.getEntityReplacement(entityId) != null) {
tracker.getEntityReplacement(entityId).updateMetadata(metadataList);
} else if (tracker.getClientEntityTypes().containsKey(entityId)) {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityId), metadataList);
} else {
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);
}
}
});
}
});
@@ -266,20 +248,33 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); //Entity Id
map(Type.STRING); //Title
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.INT, position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.UNSIGNED_BYTE, Type.INT); //Rotation
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.PAINTING);
tracker.sendMetadataBuffer(entityId);
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 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));
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);
});
}
});
@@ -287,16 +282,15 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_EXPERIENCE_ORB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.INT);
map(Type.INT);
map(Type.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, Entity1_10Types.EntityType.EXPERIENCE_ORB);
tracker.sendMetadataBuffer(entityId);
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);
});
}
});
@@ -304,16 +298,15 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_GLOBAL_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.INT);
map(Type.INT);
map(Type.INT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.LIGHTNING);
tracker.sendMetadataBuffer(entityId);
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
@@ -18,14 +18,14 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.chunks.ChunkPacketTransformer;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.WorldBorder;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
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.items.ReplacementRegistry1_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.rewriter.ParticleIndex1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
@@ -33,55 +33,50 @@ 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;
import com.viaversion.viaversion.api.type.types.CustomByteType;
import com.viaversion.viaversion.api.type.types.FixedByteArrayType;
import com.viaversion.viaversion.api.type.types.chunk.BulkChunkType1_8;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.types.Chunk1_8Type;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.util.ChatColorUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Chunk1_7_10Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Particle;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
public class WorldPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
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);
/* OUTGOING */
protocol.registerClientbound(ClientboundPackets1_8.CHUNK_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
Chunk chunk = packetWrapper.read(new Chunk1_8Type(world));
packetWrapper.write(new Chunk1_7_10Type(world), chunk);
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 = ReplacementRegistry1_7_6_10to1_8.replace(block);
palette.setIdByIndex(i, replacedBlock);
}
}
});
for (int i = 0; i < palette.size(); i++) {
palette.setIdByIndex(i, protocol.getItemRewriter().replace(palette.idByIndex(i)));
}
}
}
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);
wrapper.write(ChunkType1_7_6.TYPE, chunk);
});
protocol.registerClientbound(ClientboundPackets1_8.MULTI_BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.INT);
handler(packetWrapper -> {
final BlockChangeRecord[] records = packetWrapper.read(Type.BLOCK_CHANGE_RECORD_ARRAY);
packetWrapper.write(Type.SHORT, (short) records.length);
packetWrapper.write(Type.INT, records.length * 4);
map(Type.INT); // chunk x
map(Type.INT); // chunk z
handler(wrapper -> {
final BlockChangeRecord[] records = wrapper.read(Type.BLOCK_CHANGE_RECORD_ARRAY);
wrapper.write(Type.SHORT, (short) records.length); // record count
wrapper.write(Type.INT, records.length * 4); // data array length (position + block id)
for (BlockChangeRecord record : records) {
short data = (short) (record.getSectionX() << 12 | record.getSectionZ() << 8 | record.getY());
packetWrapper.write(Type.SHORT, data);
int replacedBlock = ReplacementRegistry1_7_6_10to1_8.replace(record.getBlockId());
packetWrapper.write(Type.SHORT, (short) replacedBlock);
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
}
});
}
@@ -89,114 +84,96 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.UNSIGNED_BYTE, (short) position.y());
packetWrapper.write(Type.INT, position.z());
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
});
handler(packetWrapper -> {
int data = packetWrapper.read(Type.VAR_INT);
data = ReplacementRegistry1_7_6_10to1_8.replace(data);
packetWrapper.write(Type.VAR_INT, data >> 4);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) (data & 0xF));
}); //Block Data
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ACTION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.SHORT, (short) position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.VAR_INT);
map(Type.POSITION1_8, Types1_7_6_10.SHORT_POSITION); // position
map(Type.UNSIGNED_BYTE); // type
map(Type.UNSIGNED_BYTE); // data
map(Type.VAR_INT); // block id
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_BREAK_ANIMATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); //Entity Id
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.INT, position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.BYTE); //Progress
map(Type.VAR_INT); // entity id
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // position
map(Type.BYTE); // progress
}
});
protocol.registerClientbound(ClientboundPackets1_8.MAP_BULK_CHUNK, new PacketHandlers() {
@Override
public void register() {
handler(ChunkPacketTransformer::transformChunkBulk);
protocol.registerClientbound(ClientboundPackets1_8.MAP_BULK_CHUNK, wrapper -> {
final Chunk[] chunks = wrapper.read(BulkChunkType1_8.TYPE);
for (Chunk chunk : chunks) {
rewriteBlockIds(protocol, chunk);
}
wrapper.write(BulkChunkType1_7_6.TYPE, chunks);
});
//Effect
protocol.registerClientbound(ClientboundPackets1_8.EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.BYTE, (byte) position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.INT);
map(Type.BOOLEAN);
map(Type.INT); // effect id
map(Type.POSITION1_8, Types1_7_6_10.BYTE_POSITION); // position
map(Type.INT); // data
map(Type.BOOLEAN); // disable relative volume
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PARTICLE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int particleId = packetWrapper.read(Type.INT);
Particle particle = Particle.find(particleId);
if (particle == null) particle = Particle.CRIT;
packetWrapper.write(Type.STRING, particle.name);
handler(wrapper -> {
final int particleId = wrapper.read(Type.INT); // particle id
ParticleIndex1_7_6_10 particle = ParticleIndex1_7_6_10.find(particleId);
if (particle == null) particle = ParticleIndex1_7_6_10.CRIT;
wrapper.write(Type.STRING, particle.name); // particle name
packetWrapper.read(Type.BOOLEAN);
});
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.INT);
handler(packetWrapper -> {
String name = packetWrapper.get(Type.STRING, 0);
Particle particle = Particle.find(name);
read(Type.BOOLEAN); // long distance
map(Type.FLOAT); // x
map(Type.FLOAT); // y
map(Type.FLOAT); // z
map(Type.FLOAT); // offset x
map(Type.FLOAT); // offset y
map(Type.FLOAT); // offset z
map(Type.FLOAT); // particle data
map(Type.INT); // particle count
handler(wrapper -> {
String name = wrapper.get(Type.STRING, 0);
ParticleIndex1_7_6_10 particle = ParticleIndex1_7_6_10.find(name);
if (particle == Particle.ICON_CRACK || particle == Particle.BLOCK_CRACK || particle == Particle.BLOCK_DUST) {
int id = packetWrapper.read(Type.VAR_INT);
int data = particle == Particle.ICON_CRACK ? packetWrapper.read(Type.VAR_INT) : 0;
if (particle == ParticleIndex1_7_6_10.ICON_CRACK || particle == ParticleIndex1_7_6_10.BLOCK_CRACK || particle == ParticleIndex1_7_6_10.BLOCK_DUST) {
int id = wrapper.read(Type.VAR_INT);
int data = particle == ParticleIndex1_7_6_10.ICON_CRACK ? wrapper.read(Type.VAR_INT) : id / 4096;
id %= 4096;
if (id >= 256 && id <= 422 || id >= 2256 && id <= 2267) { //item
particle = Particle.ICON_CRACK;
particle = ParticleIndex1_7_6_10.ICON_CRACK;
} else if (id >= 0 && id <= 164 || id >= 170 && id <= 175) {
if (particle == Particle.ICON_CRACK) particle = Particle.BLOCK_CRACK;
if (particle == ParticleIndex1_7_6_10.ICON_CRACK)
particle = ParticleIndex1_7_6_10.BLOCK_CRACK;
} else {
packetWrapper.cancel();
wrapper.cancel();
return;
}
name = particle.name + "_" + id + "_" + data;
}
packetWrapper.set(Type.STRING, 0, name);
wrapper.set(Type.STRING, 0, name);
});
}
});
@@ -204,22 +181,18 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.SHORT, (short) position.y());
packetWrapper.write(Type.INT, position.z());
});
handler(packetWrapper -> {
map(Type.POSITION1_8, Types1_7_6_10.SHORT_POSITION); // position
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
String line = packetWrapper.read(Type.STRING);
String line = wrapper.read(Type.STRING);
line = ChatUtil.jsonToLegacy(line);
line = ChatUtil.removeUnusedColor(line, '0');
if (line.length() > 15) {
line = ChatColorUtil.stripColor(line);
if (line.length() > 15) line = line.substring(0, 15);
}
packetWrapper.write(Type.STRING, line);
wrapper.write(Type.STRING, line);
}
});
}
@@ -228,27 +201,28 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.MAP_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
int id = packetWrapper.read(Type.VAR_INT);
byte scale = packetWrapper.read(Type.BYTE);
handler(wrapper -> {
wrapper.cancel();
final int id = wrapper.read(Type.VAR_INT);
final byte scale = wrapper.read(Type.BYTE);
int count = packetWrapper.read(Type.VAR_INT);
byte[] icons = new byte[count * 4];
for (int i = 0; i < count; i++) {
int j = packetWrapper.read(Type.BYTE);
icons[i * 4] = (byte) (j >> 4 & 0xF);
icons[i * 4 + 1] = packetWrapper.read(Type.BYTE);
icons[i * 4 + 2] = packetWrapper.read(Type.BYTE);
icons[i * 4 + 3] = (byte) (j & 0xF);
final int iconCount = wrapper.read(Type.VAR_INT);
byte[] icons = new byte[iconCount * 4];
for (int i = 0; i < iconCount; i++) {
final int directionAndType = wrapper.read(Type.BYTE);
icons[i * 4] = (byte) (directionAndType >> 4 & 0xF);
icons[i * 4 + 1] = wrapper.read(Type.BYTE); // x
icons[i * 4 + 2] = wrapper.read(Type.BYTE); // z
icons[i * 4 + 3] = (byte) (directionAndType & 0xF);
}
short columns = packetWrapper.read(Type.UNSIGNED_BYTE);
final short columns = wrapper.read(Type.UNSIGNED_BYTE);
if (columns > 0) {
short rows = packetWrapper.read(Type.UNSIGNED_BYTE);
short x = packetWrapper.read(Type.UNSIGNED_BYTE);
short z = packetWrapper.read(Type.UNSIGNED_BYTE);
byte[] data = packetWrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
final short rows = wrapper.read(Type.UNSIGNED_BYTE);
final short x = wrapper.read(Type.UNSIGNED_BYTE);
final short z = wrapper.read(Type.UNSIGNED_BYTE);
final byte[] data = wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
for (int column = 0; column < columns; column++) {
byte[] columnData = new byte[rows + 3];
columnData[0] = 0;
@@ -259,36 +233,39 @@ public class WorldPackets {
columnData[i + 3] = data[column + i * columns];
}
PacketWrapper columnUpdate = PacketWrapper.create(0x34, null, packetWrapper.user());
columnUpdate.write(Type.VAR_INT, id);
columnUpdate.write(Type.SHORT, (short) columnData.length);
columnUpdate.write(new CustomByteType(columnData.length), columnData);
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_DATA, wrapper.user());
mapData.write(Type.VAR_INT, id); // map id
mapData.write(Type.SHORT, (short) columnData.length); // data length
mapData.write(new FixedByteArrayType(columnData.length), columnData); // data
PacketUtil.sendPacket(columnUpdate, Protocol1_7_6_10To1_8.class, true, true);
mapData.send(Protocol1_7_6_10To1_8.class, true);
}
}
if (count > 0) {
byte[] iconData = new byte[count * 3 + 1];
if (iconCount > 0) {
final byte[] iconData = new byte[iconCount * 3 + 1];
iconData[0] = 1;
for (int i = 0; i < count; i++) {
for (int i = 0; i < iconCount; i++) {
iconData[i * 3 + 1] = (byte) (icons[i * 4] << 4 | icons[i * 4 + 3] & 0xF);
iconData[i * 3 + 2] = icons[i * 4 + 1];
iconData[i * 3 + 3] = icons[i * 4 + 2];
}
PacketWrapper iconUpdate = PacketWrapper.create(0x34, null, packetWrapper.user());
iconUpdate.write(Type.VAR_INT, id);
iconUpdate.write(Type.SHORT, (short) iconData.length);
CustomByteType customByteType = new CustomByteType(iconData.length);
iconUpdate.write(customByteType, iconData);
PacketUtil.sendPacket(iconUpdate, Protocol1_7_6_10To1_8.class, true, true);
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_DATA, wrapper.user());
mapData.write(Type.VAR_INT, id); // map id
mapData.write(Type.SHORT, (short) iconData.length); // data length
mapData.write(new FixedByteArrayType(iconData.length), iconData); // data
mapData.send(Protocol1_7_6_10To1_8.class, true);
}
PacketWrapper scaleUpdate = PacketWrapper.create(0x34, null, packetWrapper.user());
scaleUpdate.write(Type.VAR_INT, id);
scaleUpdate.write(Type.SHORT, (short) 2);
scaleUpdate.write(new CustomByteType(2), new byte[]{2, scale});
PacketUtil.sendPacket(scaleUpdate, Protocol1_7_6_10To1_8.class, true, true);
// Update scale
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.send(Protocol1_7_6_10To1_8.class, true);
});
}
});
@@ -296,50 +273,33 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ENTITY_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.SHORT, (short) position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.UNSIGNED_BYTE); //Action
map(Type.NBT, Types1_7_6_10.COMPRESSED_NBT);
map(Type.POSITION1_8, Types1_7_6_10.SHORT_POSITION); // position
map(Type.UNSIGNED_BYTE); // action
map(Type.NAMED_COMPOUND_TAG, Types1_7_6_10.COMPRESSED_NBT); // nbt
}
});
protocol.cancelClientbound(ClientboundPackets1_8.SERVER_DIFFICULTY);
protocol.cancelClientbound(ClientboundPackets1_8.COMBAT_EVENT);
protocol.registerClientbound(ClientboundPackets1_8.WORLD_BORDER, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int action = packetWrapper.read(Type.VAR_INT);
WorldBorder worldBorder = packetWrapper.user().get(WorldBorder.class);
if (action == 0) {
worldBorder.setSize(packetWrapper.read(Type.DOUBLE));
} else if (action == 1) {
worldBorder.lerpSize(packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.VAR_LONG));
} else if (action == 2) {
worldBorder.setCenter(packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.DOUBLE));
} else if (action == 3) {
worldBorder.init(
packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.DOUBLE),
packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.DOUBLE),
packetWrapper.read(Type.VAR_LONG),
packetWrapper.read(Type.VAR_INT),
packetWrapper.read(Type.VAR_INT), packetWrapper.read(Type.VAR_INT)
);
} else if (action == 4) {
worldBorder.setWarningTime(packetWrapper.read(Type.VAR_INT));
} else if (action == 5) {
worldBorder.setWarningBlocks(packetWrapper.read(Type.VAR_INT));
}
protocol.registerClientbound(ClientboundPackets1_8.WORLD_BORDER, null, wrapper -> {
final WorldBorderEmulator emulator = wrapper.user().get(WorldBorderEmulator.class);
wrapper.cancel();
packetWrapper.cancel();
});
final int action = wrapper.read(Type.VAR_INT);
if (action == 0) { // set size
emulator.setSize(wrapper.read(Type.DOUBLE)); // radius
} else if (action == 1) { // lerp size
emulator.lerpSize(wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE), wrapper.read(Type.VAR_LONG)); // old radius, new radius, speed
} else if (action == 2) { // set center
emulator.setCenter(wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE)); // x, z
} else if (action == 3) { // initialize
emulator.init(
wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE), // x, z
wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE), // old radius, new radius
wrapper.read(Type.VAR_LONG) // speed
);
}
});
}
}
@@ -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
@@ -18,159 +18,24 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.CompressionSendStorage;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.CompressionStatusTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.platform.providers.Provider;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.netty.EmptyChannelHandler;
import com.viaversion.viarewind.netty.ForwardMessageToByteEncoder;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
public abstract class CompressionHandlerProvider implements Provider {
public class CompressionHandlerProvider implements Provider {
public void handleSetCompression(UserConnection user, int threshold) {
ChannelPipeline pipeline = user.getChannel().pipeline();
if (user.isClientSide()) {
pipeline.addBefore(Via.getManager().getInjector().getEncoderName(), "compress", getEncoder(threshold));
pipeline.addBefore(Via.getManager().getInjector().getDecoderName(), "decompress", getDecoder(threshold));
} else {
CompressionSendStorage storage = user.get(CompressionSendStorage.class);
storage.setRemoveCompression(true);
}
public abstract void onHandleLoginCompressionPacket(UserConnection user, int threshold);
public abstract void onTransformPacket(UserConnection user);
public abstract ChannelHandler getEncoder(int threshold);
public abstract ChannelHandler getDecoder(int threshold);
public boolean isCompressionEnabled(UserConnection user) {
return user.get(CompressionStatusTracker.class).removeCompression;
}
public void handleTransform(UserConnection user) {
CompressionSendStorage storage = user.get(CompressionSendStorage.class);
if (storage.isRemoveCompression()) {
ChannelPipeline pipeline = user.getChannel().pipeline();
String compressor = null;
String decompressor = null;
if (pipeline.get("compress") != null) {
compressor = "compress";
decompressor = "decompress";
} else if (pipeline.get("compression-encoder") != null) { // Velocity
compressor = "compression-encoder";
decompressor = "compression-decoder";
}
if (compressor != null) { // We can neutralize the effect of compressor to the client
pipeline.replace(decompressor, decompressor, new EmptyChannelHandler());
pipeline.replace(compressor, compressor, new ForwardMessageToByteEncoder());
} else {
throw new IllegalStateException("Couldn't remove compression for 1.7!");
}
storage.setRemoveCompression(false);
}
}
protected ChannelHandler getEncoder(int threshold) {
return new Compressor(threshold);
}
protected ChannelHandler getDecoder(int threshold) {
return new Decompressor(threshold);
}
private static class Decompressor extends MessageToMessageDecoder<ByteBuf> {
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
private final Inflater inflater;
private final int threshold;
public Decompressor(int var1) {
this.threshold = var1;
this.inflater = new Inflater();
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (!in.isReadable()) return;
int outLength = Type.VAR_INT.readPrimitive(in);
if (outLength == 0) {
out.add(in.readBytes(in.readableBytes()));
return;
}
if (outLength < this.threshold) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is below server threshold of " + this.threshold);
} else if (outLength > 2097152) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is larger than protocol maximum of " + 2097152);
}
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer(outLength, outLength);
try {
this.inflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
output.writerIndex(output.writerIndex() + this.inflater.inflate(
output.array(), output.arrayOffset(), outLength));
out.add(output.retain());
} finally {
output.release();
temp.release();
this.inflater.reset();
}
}
}
private static class Compressor extends MessageToByteEncoder<ByteBuf> {
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
private final Deflater deflater;
private final int threshold;
public Compressor(int var1) {
this.threshold = var1;
this.deflater = new Deflater();
}
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
int frameLength = in.readableBytes();
if (frameLength < this.threshold) {
out.writeByte(0); // varint
out.writeBytes(in);
return;
}
Type.VAR_INT.writePrimitive(out, frameLength);
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer();
try {
this.deflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
deflater.finish();
while (!deflater.finished()) {
output.ensureWritable(4096);
output.writerIndex(output.writerIndex() + this.deflater.deflate(output.array(),
output.arrayOffset() + output.writerIndex(), output.writableBytes()));
}
out.writeBytes(output);
} finally {
output.release();
temp.release();
this.deflater.reset();
}
}
public void setCompressionEnabled(UserConnection user, boolean enabled) {
user.get(CompressionStatusTracker.class).removeCompression = enabled;
}
}
@@ -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
@@ -39,7 +39,7 @@ public abstract class TitleRenderProvider implements Provider {
setFadeOut(uuid, fadeOut);
AtomicInteger time = getTime(uuid);
if (time.get()>0) time.set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
if (time.get() > 0) time.set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
}
public void reset(UUID uuid) {
@@ -83,17 +83,17 @@ public abstract class TitleRenderProvider implements Provider {
}
public void setFadeIn(UUID uuid, int fadeIn) {
if (fadeIn>=0) this.fadeIn.put(uuid, fadeIn);
if (fadeIn >= 0) this.fadeIn.put(uuid, fadeIn);
else this.fadeIn.remove(uuid);
}
public void setStay(UUID uuid, int stay) {
if (stay>=0) this.stay.put(uuid, stay);
if (stay >= 0) this.stay.put(uuid, stay);
else this.stay.remove(uuid);
}
public void setFadeOut(UUID uuid, int fadeOut) {
if (fadeOut>=0) this.fadeOut.put(uuid, fadeOut);
if (fadeOut >= 0) this.fadeOut.put(uuid, fadeOut);
else this.fadeOut.remove(uuid);
}
}
@@ -0,0 +1,74 @@
/*
* 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;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
import java.util.zip.Inflater;
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionDecoder.java
public class CompressionDecoder extends MessageToMessageDecoder<ByteBuf> {
private final Inflater inflater = new Inflater();
private final int threshold;
public CompressionDecoder(final int threshold) {
this.threshold = threshold;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (!in.isReadable()) return;
int outLength = Type.VAR_INT.readPrimitive(in);
if (outLength == 0) {
out.add(in.readBytes(in.readableBytes()));
return;
}
if (outLength < this.threshold) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is below server threshold of " + this.threshold);
} else if (outLength > 2097152) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is larger than protocol maximum of " + 2097152);
}
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer(outLength, outLength);
try {
this.inflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
output.writerIndex(output.writerIndex() + this.inflater.inflate(output.array(), output.arrayOffset(), outLength));
out.add(output.retain());
} finally {
output.release();
temp.release();
this.inflater.reset();
}
}
}
@@ -0,0 +1,72 @@
/*
* 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;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import java.util.zip.Deflater;
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
private final Deflater deflater = new Deflater();
private final int threshold;
public CompressionEncoder(final int threshold) {
this.threshold = threshold;
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
int frameLength = in.readableBytes();
if (frameLength < this.threshold) {
out.writeByte(0); // VarInt
out.writeBytes(in);
return;
}
Type.VAR_INT.writePrimitive(out, frameLength);
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer();
try {
this.deflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
deflater.finish();
while (!deflater.finished()) {
output.ensureWritable(4096);
output.writerIndex(output.writerIndex() + this.deflater.deflate(output.array(), output.arrayOffset() + output.writerIndex(), output.writableBytes()));
}
out.writeBytes(output);
} finally {
output.release();
temp.release();
this.deflater.reset();
}
}
}
@@ -0,0 +1,79 @@
/*
* 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;
import com.viaversion.viarewind.api.netty.ForwardMessageToByteEncoder;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.CompressionHandlerProvider;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
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";
@Override
public void onHandleLoginCompressionPacket(UserConnection user, int threshold) {
final ChannelPipeline pipeline = user.getChannel().pipeline();
if (user.isClientSide()) {
pipeline.addBefore(Via.getManager().getInjector().getEncoderName(), COMPRESS_HANDLER_NAME, getEncoder(threshold));
pipeline.addBefore(Via.getManager().getInjector().getDecoderName(), DECOMPRESS_HANDLER_NAME, getDecoder(threshold));
} else {
setCompressionEnabled(user, true); // We need to remove compression for 1.7 clients
}
}
@Override
public void onTransformPacket(UserConnection user) {
if (isCompressionEnabled(user)) {
final ChannelPipeline pipeline = user.getChannel().pipeline();
String compressor = null;
String decompressor = null;
if (pipeline.get(COMPRESS_HANDLER_NAME) != null) { // ViaVersion
compressor = COMPRESS_HANDLER_NAME;
decompressor = DECOMPRESS_HANDLER_NAME;
} else if (pipeline.get("compression-encoder") != null) { // Velocity
compressor = "compression-encoder";
decompressor = "compression-decoder";
}
if (compressor != null) { // We can neutralize the effect of compressor to the client
pipeline.replace(decompressor, decompressor, new EmptyChannelHandler());
pipeline.replace(compressor, compressor, new ForwardMessageToByteEncoder());
} else {
throw new IllegalStateException("Couldn't remove compression for 1.7!");
}
setCompressionEnabled(user, false);
}
}
@Override
public ChannelHandler getEncoder(int threshold) {
return new CompressionEncoder(threshold);
}
@Override
public ChannelHandler getDecoder(int threshold) {
return new CompressionDecoder(threshold);
}
}
@@ -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
@@ -16,11 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter;
import java.util.HashMap;
public enum Particle {
public enum ParticleIndex1_7_6_10 {
EXPLOSION_NORMAL("explode"),
EXPLOSION_LARGE("largeexplode"),
EXPLOSION_HUGE("hugeexplosion"),
@@ -66,33 +66,32 @@ public enum Particle {
public final String name;
public final int extra;
private static final HashMap<String, Particle> particleMap = new HashMap();
private final static HashMap<String, ParticleIndex1_7_6_10> particleMap = new HashMap<>();
Particle(String name) {
ParticleIndex1_7_6_10(String name) {
this(name, 0);
}
Particle(String name, int extra) {
ParticleIndex1_7_6_10(String name, int extra) {
this.name = name;
this.extra = extra;
}
public static Particle find(String part) {
public static ParticleIndex1_7_6_10 find(String part) {
return particleMap.get(part);
}
public static Particle find(int id) {
if (id<0) return null;
Particle[] values = Particle.values();
return id>=values.length ? null : values[id];
public static ParticleIndex1_7_6_10 find(int id) {
if (id < 0) return null;
ParticleIndex1_7_6_10[] values = ParticleIndex1_7_6_10.values();
return id >= values.length ? null : values[id];
}
static {
Particle[] particles = values();
ParticleIndex1_7_6_10[] particles = values();
for (Particle particle : particles) {
for (ParticleIndex1_7_6_10 particle : particles) {
particleMap.put(particle.name, particle);
}
}
}
@@ -0,0 +1,230 @@
/*
* 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.rewriter;
import com.viaversion.viarewind.api.rewriter.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.api.rewriter.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
@@ -21,18 +21,13 @@ package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class CompressionSendStorage extends StoredObject {
private boolean removeCompression = false;
/**
* @see com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.CompressionHandlerProvider
*/
public class CompressionStatusTracker extends StoredObject {
public boolean removeCompression = false;
public CompressionSendStorage(UserConnection user) {
public CompressionStatusTracker(UserConnection user) {
super(user);
}
public boolean isRemoveCompression() {
return removeCompression;
}
public void setRemoveCompression(boolean removeCompression) {
this.removeCompression = removeCompression;
}
}
@@ -1,258 +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.storage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
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.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.item.Item;
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.api.type.types.version.Types1_8;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class EntityTracker extends StoredObject implements ClientEntityIdChangeListener {
private final Map<Integer, Entity1_10Types.EntityType> clientEntityTypes = new ConcurrentHashMap();
private final Map<Integer, List<Metadata>> metadataBuffer = new ConcurrentHashMap();
private final Map<Integer, Integer> vehicles = new ConcurrentHashMap<>();
private final Map<Integer, EntityReplacement> entityReplacements = new ConcurrentHashMap<>();
private final Map<Integer, UUID> playersByEntityId = new HashMap<>();
private final Map<UUID, Integer> playersByUniqueId = new HashMap<>();
private final Map<UUID, Item[]> playerEquipment = new HashMap<>();
private int gamemode = 0;
private int playerId = -1;
private int spectating = -1;
private int dimension = 0;
public EntityTracker(UserConnection user) {
super(user);
}
public void removeEntity(int entityId) {
clientEntityTypes.remove(entityId);
if (entityReplacements.containsKey(entityId)) {
entityReplacements.remove(entityId).despawn();
}
if (playersByEntityId.containsKey(entityId)) {
UUID playerId = playersByEntityId.remove(entityId);
playersByUniqueId.remove(playerId);
playerEquipment.remove(playerId);
}
}
public void addPlayer(Integer entityId, UUID uuid) {
playersByUniqueId.put(uuid, entityId);
playersByEntityId.put(entityId, uuid);
}
public UUID getPlayerUUID(int entityId) {
return playersByEntityId.get(entityId);
}
public int getPlayerEntityId(UUID uuid) {
return playersByUniqueId.getOrDefault(uuid, -1);
}
public Item getPlayerEquipment(UUID uuid, int slot) {
Item[] items = playerEquipment.get(uuid);
if (items == null || slot < 0 || slot >= items.length) return null;
return items[slot];
}
public void setPlayerEquipment(UUID uuid, Item equipment, int slot) {
// Please note that when referring to the client player, it has an Item[4] array
Item[] items = playerEquipment.computeIfAbsent(uuid, it -> new Item[5]);
if (slot < 0 || slot >= items.length) return;
items[slot] = equipment;
}
public Map<Integer, Entity1_10Types.EntityType> getClientEntityTypes() {
return this.clientEntityTypes;
}
public void addMetadataToBuffer(int entityID, List<Metadata> metadataList) {
if (this.metadataBuffer.containsKey(entityID)) {
this.metadataBuffer.get(entityID).addAll(metadataList);
} else if (!metadataList.isEmpty()) {
this.metadataBuffer.put(entityID, metadataList);
}
}
public void addEntityReplacement(EntityReplacement entityReplacement) {
entityReplacements.put(entityReplacement.getEntityId(), entityReplacement);
}
public EntityReplacement getEntityReplacement(int entityId) {
return entityReplacements.get(entityId);
}
public List<Metadata> getBufferedMetadata(int entityId) {
return metadataBuffer.get(entityId);
}
public void sendMetadataBuffer(int entityId) {
if (!this.metadataBuffer.containsKey(entityId)) return;
if (entityReplacements.containsKey(entityId)) {
entityReplacements.get(entityId).updateMetadata(this.metadataBuffer.remove(entityId));
} else {
Entity1_10Types.EntityType type = this.getClientEntityTypes().get(entityId);
PacketWrapper wrapper = PacketWrapper.create(0x1C, null, this.getUser());
wrapper.write(Type.VAR_INT, entityId);
wrapper.write(Types1_8.METADATA_LIST, this.metadataBuffer.get(entityId));
MetadataRewriter.transform(type, this.metadataBuffer.get(entityId));
if (!this.metadataBuffer.get(entityId).isEmpty()) {
PacketUtil.sendPacket(wrapper, Protocol1_7_6_10To1_8.class);
}
this.metadataBuffer.remove(entityId);
}
}
public int getVehicle(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);
}
public void setPassenger(int vehicleId, int passengerId) {
if (vehicleId==this.spectating && this.spectating!=this.playerId) {
try {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, getUser());
sneakPacket.write(Type.VAR_INT, playerId);
sneakPacket.write(Type.VAR_INT, 0); //Start sneaking
sneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketWrapper unsneakPacket = PacketWrapper.create(0x0B, null, getUser());
unsneakPacket.write(Type.VAR_INT, playerId);
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, true, true);
setSpectating(playerId);
} catch (Exception ex) {ex.printStackTrace();}
}
if (vehicleId==-1) {
int oldVehicleId = getVehicle(passengerId);
vehicles.remove(oldVehicleId);
} else if (passengerId==-1) {
vehicles.remove(vehicleId);
} else {
vehicles.put(vehicleId, passengerId);
}
}
public int getSpectating() {
return spectating;
}
public boolean setSpectating(int spectating) {
if (spectating!=this.playerId && getPassenger(spectating)!=-1) {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, getUser());
sneakPacket.write(Type.VAR_INT, playerId);
sneakPacket.write(Type.VAR_INT, 0); //Start sneaking
sneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketWrapper unsneakPacket = PacketWrapper.create(0x0B, null, getUser());
unsneakPacket.write(Type.VAR_INT, playerId);
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, true, true);
setSpectating(this.playerId);
return false; //Entity has Passenger
}
if (this.spectating!=spectating && this.spectating!=this.playerId) {
PacketWrapper unmount = PacketWrapper.create(0x1B, null, this.getUser());
unmount.write(Type.INT, this.playerId);
unmount.write(Type.INT, -1);
unmount.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(unmount, Protocol1_7_6_10To1_8.class);
}
this.spectating = spectating;
if (spectating!=this.playerId) {
PacketWrapper mount = PacketWrapper.create(0x1B, null, this.getUser());
mount.write(Type.INT, this.playerId);
mount.write(Type.INT, this.spectating);
mount.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(mount, Protocol1_7_6_10To1_8.class);
}
return true;
}
public int getGamemode() {
return gamemode;
}
public void setGamemode(int gamemode) {
this.gamemode = gamemode;
}
public int getPlayerId() {
return playerId;
}
public void setPlayerId(int playerId) {
this.playerId = this.spectating = playerId;
}
public void clearEntities() {
clientEntityTypes.clear();
entityReplacements.clear();
vehicles.clear();
metadataBuffer.clear();
}
public int getDimension() {
return dimension;
}
public void setDimension(int dimension) {
this.dimension = dimension;
}
@Override
public void setClientEntityId(int playerEntityId) {
if (this.spectating == this.playerId) {
this.spectating = playerEntityId;
}
clientEntityTypes.remove(this.playerId);
this.playerId = playerEntityId;
clientEntityTypes.put(this.playerId, Entity1_10Types.EntityType.ENTITY_HUMAN);
}
}
@@ -0,0 +1,193 @@
/*
* 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.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.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
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, MetaType1_7_6_10.Byte, MetaType1_7_6_10.String);
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;
}
}
@@ -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
@@ -43,14 +43,6 @@ public class GameProfileStorage extends StoredObject {
return gameProfile;
}
public void putProperty(UUID uuid, Property property) {
properties.computeIfAbsent(uuid, profile -> new GameProfile(uuid, null)).properties.add(property);
}
public void putProperty(UUID uuid, String name, String value, String signature) {
putProperty(uuid, new Property(name, value, signature));
}
public GameProfile get(UUID uuid) {
return properties.get(uuid);
}
@@ -0,0 +1,79 @@
/*
* 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.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<>();
static {
WINDOW_TYPE_REGISTRY.put("minecraft:container", 0);
WINDOW_TYPE_REGISTRY.put("minecraft:chest", 0);
WINDOW_TYPE_REGISTRY.put("minecraft:crafting_table", 1);
WINDOW_TYPE_REGISTRY.put("minecraft:furnace", 2);
WINDOW_TYPE_REGISTRY.put("minecraft:dispenser", 3);
WINDOW_TYPE_REGISTRY.put("minecraft:enchanting_table", 4);
WINDOW_TYPE_REGISTRY.put("minecraft:brewing_stand", 5);
WINDOW_TYPE_REGISTRY.put("minecraft:villager", 6);
WINDOW_TYPE_REGISTRY.put("minecraft:beacon", 7);
WINDOW_TYPE_REGISTRY.put("minecraft:anvil", 8);
WINDOW_TYPE_REGISTRY.put("minecraft:hopper", 9);
WINDOW_TYPE_REGISTRY.put("minecraft:dropper", 10);
WINDOW_TYPE_REGISTRY.put("EntityHorse", 11);
}
private final HashMap<Short, Short> windowTypeMap = new HashMap<>();
private final HashMap<Short, FurnaceData> furnaceData = new HashMap<>();
public short levelCost = 0;
public short anvilId = -1;
public InventoryTracker(UserConnection user) {
super(user);
}
public short get(short windowId) {
return windowTypeMap.getOrDefault(windowId, (short) -1);
}
public void remove(short windowId) {
windowTypeMap.remove(windowId);
furnaceData.remove(windowId);
}
public static short getInventoryType(String name) {
return WINDOW_TYPE_REGISTRY.getOrDefault(name, -1).shortValue();
}
public HashMap<Short, Short> getWindowTypeMap() {
return windowTypeMap;
}
public HashMap<Short, FurnaceData> getFurnaceData() {
return furnaceData;
}
}
@@ -1,132 +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.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class PlayerAbilities extends StoredObject {
private boolean sprinting, allowFly, flying, invincible, creative;
private float flySpeed, walkSpeed;
public PlayerAbilities(UserConnection user) {
super(user);
}
public byte getFlags() {
byte flags = 0;
if (invincible) flags |= 8;
if (allowFly) flags |= 4;
if (flying) flags |= 2;
if (creative) flags |= 1;
return flags;
}
public boolean isSprinting() {
return this.sprinting;
}
public boolean isAllowFly() {
return this.allowFly;
}
public boolean isFlying() {
return this.flying;
}
public boolean isInvincible() {
return this.invincible;
}
public boolean isCreative() {
return this.creative;
}
public float getFlySpeed() {
return this.flySpeed;
}
public float getWalkSpeed() {
return this.walkSpeed;
}
public void setSprinting(boolean sprinting) {
this.sprinting = sprinting;
}
public void setAllowFly(boolean allowFly) {
this.allowFly = allowFly;
}
public void setFlying(boolean flying) {
this.flying = flying;
}
public void setInvincible(boolean invincible) {
this.invincible = invincible;
}
public void setCreative(boolean creative) {
this.creative = creative;
}
public void setFlySpeed(float flySpeed) {
this.flySpeed = flySpeed;
}
public void setWalkSpeed(float walkSpeed) {
this.walkSpeed = walkSpeed;
}
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof PlayerAbilities))
return false;
final PlayerAbilities other = (PlayerAbilities) o;
if (!other.canEqual(this)) return false;
if (this.isSprinting() != other.isSprinting()) return false;
if (this.isAllowFly() != other.isAllowFly()) return false;
if (this.isFlying() != other.isFlying()) return false;
if (this.isInvincible() != other.isInvincible()) return false;
if (this.isCreative() != other.isCreative()) return false;
if (Float.compare(this.getFlySpeed(), other.getFlySpeed()) != 0) return false;
return Float.compare(this.getWalkSpeed(), other.getWalkSpeed()) == 0;
}
protected boolean canEqual(final Object other) {
return other instanceof PlayerAbilities;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + (this.isSprinting() ? 79 : 97);
result = result * PRIME + (this.isAllowFly() ? 79 : 97);
result = result * PRIME + (this.isFlying() ? 79 : 97);
result = result * PRIME + (this.isInvincible() ? 79 : 97);
result = result * PRIME + (this.isCreative() ? 79 : 97);
result = result * PRIME + Float.floatToIntBits(this.getFlySpeed());
result = result * PRIME + Float.floatToIntBits(this.getWalkSpeed());
return result;
}
public String toString() {
return "PlayerAbilities(sprinting=" + this.isSprinting() + ", allowFly=" + this.isAllowFly() + ", flying=" + this.isFlying() + ", invincible=" + this.isInvincible() + ", creative=" + this.isCreative() + ", flySpeed=" + this.getFlySpeed() + ", walkSpeed=" + this.getWalkSpeed() + ")";
}
}
@@ -1,104 +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.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class PlayerPosition extends StoredObject {
private double posX, posY, posZ;
private float yaw, pitch;
private boolean onGround;
private boolean positionPacketReceived;
private double receivedPosY;
public PlayerPosition(UserConnection user) {
super(user);
}
public void setPos(double x, double y, double z) {
posX = x;
posY = y;
posZ = z;
}
public boolean isPositionPacketReceived() {
return positionPacketReceived;
}
public void setPositionPacketReceived(boolean positionPacketReceived) {
this.positionPacketReceived = positionPacketReceived;
}
public double getReceivedPosY() {
return receivedPosY;
}
public void setReceivedPosY(double receivedPosY) {
this.receivedPosY = receivedPosY;
}
public double getPosX() {
return posX;
}
public void setPosX(double posX) {
this.posX = posX;
}
public double getPosY() {
return posY;
}
public void setPosY(double posY) {
this.posY = posY;
}
public double getPosZ() {
return posZ;
}
public void setPosZ(double posZ) {
this.posZ = posZ;
}
public float getYaw() {
return yaw;
}
public void setYaw(float yaw) {
this.yaw = yaw;
}
public float getPitch() {
return pitch;
}
public void setPitch(float pitch) {
this.pitch = pitch;
}
public boolean isOnGround() {
return onGround;
}
public void setOnGround(boolean onGround) {
this.onGround = onGround;
}
}
@@ -0,0 +1,105 @@
/*
* 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;
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 PlayerSessionStorage extends StoredObject {
// Player info
public int gameMode;
// Player abilities
public boolean sprinting, allowFly, flying, invincible, creative;
public float flySpeed, walkSpeed;
// Player position, rotation and data
private double posX, posY, posZ;
public double receivedPosY;
public float yaw, pitch;
public boolean onGround;
// Player inventory
private final Map<UUID, Item[]> playerEquipment = new HashMap<>();
public PlayerSessionStorage(UserConnection user) {
super(user);
}
public byte combineAbilities() {
byte flags = 0;
if (invincible) flags |= 8;
if (allowFly) flags |= 4;
if (flying) flags |= 2;
if (creative) flags |= 1;
return flags;
}
public double getPosX() {
return posX;
}
public double getPosY() {
return posY;
}
public double getPosZ() {
return posZ;
}
public void setPos(double x, double y, double z) {
posX = x;
posY = y;
posZ = z;
}
public Item getPlayerEquipment(final UUID uuid, final int slot) {
final Item[] items = playerEquipment.get(uuid);
if (items == null || slot < 0 || slot >= items.length) {
return null;
}
return items[slot];
}
public void setPlayerEquipment(final UUID uuid, final Item equipment, final int slot) {
final Item[] items = playerEquipment.computeIfAbsent(uuid, it -> new Item[5]);
if (slot < 0 || slot >= items.length) {
return;
}
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
@@ -18,9 +18,9 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
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;
@@ -134,7 +134,7 @@ public class Scoreboard extends StoredObject {
scoreTeams.put(score, scoreTeam);
scoreTeamNames.add(name);
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7.TEAMS, getUser());
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.TEAMS, getUser());
teamPacket.write(Type.STRING, name);
teamPacket.write(Type.BYTE, (byte) 0);
teamPacket.write(Type.STRING, "ViaRewind");
@@ -153,7 +153,7 @@ public class Scoreboard extends StoredObject {
if (scoreTeam == null) return score;
scoreTeamNames.remove(scoreTeam.name);
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7.TEAMS, getUser());
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);
@@ -1,149 +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.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import java.util.HashMap;
public class Windows extends StoredObject {
public HashMap<Short, Short> types = new HashMap<>();
public HashMap<Short, Furnace> furnace = new HashMap<>();
public short levelCost = 0;
public short anvilId = -1;
public Windows(UserConnection user) {
super(user);
}
public short get(short windowId) {
return types.getOrDefault(windowId, (short)-1);
}
public void remove(short windowId) {
types.remove(windowId);
furnace.remove(windowId);
}
public static int getInventoryType(String name) {
switch(name) {
case "minecraft:container":
return 0;
case "minecraft:chest":
return 0;
case "minecraft:crafting_table":
return 1;
case "minecraft:furnace":
return 2;
case "minecraft:dispenser":
return 3;
case "minecraft:enchanting_table":
return 4;
case "minecraft:brewing_stand":
return 5;
case "minecraft:villager":
return 6;
case "minecraft:beacon":
return 7;
case "minecraft:anvil":
return 8;
case "minecraft:hopper":
return 9;
case "minecraft:dropper":
return 10;
case "EntityHorse":
return 11;
default:
throw new IllegalArgumentException("Unknown type " + name);
}
}
public static class Furnace {
private short fuelLeft = 0;
private short maxFuel = 0;
private short progress = 0;
private short maxProgress = 200;
public Furnace() {
}
public short getFuelLeft() {
return this.fuelLeft;
}
public short getMaxFuel() {
return this.maxFuel;
}
public short getProgress() {
return this.progress;
}
public short getMaxProgress() {
return this.maxProgress;
}
public void setFuelLeft(short fuelLeft) {
this.fuelLeft = fuelLeft;
}
public void setMaxFuel(short maxFuel) {
this.maxFuel = maxFuel;
}
public void setProgress(short progress) {
this.progress = progress;
}
public void setMaxProgress(short maxProgress) {
this.maxProgress = maxProgress;
}
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof Furnace))
return false;
final Furnace other = (Furnace) o;
if (!other.canEqual(this)) return false;
if (this.getFuelLeft() != other.getFuelLeft()) return false;
if (this.getMaxFuel() != other.getMaxFuel()) return false;
if (this.getProgress() != other.getProgress()) return false;
return this.getMaxProgress() == other.getMaxProgress();
}
protected boolean canEqual(final Object other) {
return other instanceof Furnace;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.getFuelLeft();
result = result * PRIME + this.getMaxFuel();
result = result * PRIME + this.getProgress();
result = result * PRIME + this.getMaxProgress();
return result;
}
public String toString() {
return "Windows.Furnace(fuelLeft=" + this.getFuelLeft() + ", maxFuel=" + this.getMaxFuel() + ", progress=" + this.getProgress() + ", maxProgress=" + this.getMaxProgress() + ")";
}
}
}
@@ -1,210 +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.storage;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.Tickable;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
public class WorldBorder extends StoredObject implements Tickable {
private double x, z;
private double oldDiameter, newDiameter;
private long lerpTime;
private long lerpStartTime;
private int portalTeleportBoundary;
private int warningTime, warningBlocks;
private boolean init = false;
private static final int VIEW_DISTANCE = 16;
public WorldBorder(UserConnection user) {
super(user);
}
@Override
public void tick() {
if (!isInit()) {
return;
}
sendPackets();
}
private enum Side {
NORTH(0, -1),
EAST(1, 0),
SOUTH(0, 1),
WEST(-1, 0),
;
private final int modX;
private final int modZ;
Side(int modX, int modZ) {
this.modX = modX;
this.modZ = modZ;
}
}
private void sendPackets() {
PlayerPosition position = getUser().get(PlayerPosition.class);
double radius = getSize() / 2.0;
for (Side side : Side.values()) {
double d;
double pos;
double center;
if (side.modX!=0) {
pos = position.getPosZ();
center = z;
d = Math.abs(x + radius * side.modX - position.getPosX());
} else {
center = x;
pos = position.getPosX();
d = Math.abs(z + radius * side.modZ - position.getPosZ());
}
if (d >= VIEW_DISTANCE) continue;
double r = Math.sqrt(VIEW_DISTANCE * VIEW_DISTANCE - d * d);
double minH = Math.ceil(pos - r);
double maxH = Math.floor(pos + r);
double minV = Math.ceil(position.getPosY() - r);
double maxV = Math.floor(position.getPosY() + r);
if (minH<center-radius) minH = Math.ceil(center-radius);
if (maxH>center+radius) maxH = Math.floor(center+radius);
if (minV<0.0) minV = 0.0;
double centerH = (minH+maxH) / 2.0;
double centerV = (minV+maxV) / 2.0;
int a = (int) Math.floor((maxH-minH) * (maxV-minV) * 0.5);
double b = 2.5;
PacketWrapper particles = PacketWrapper.create(0x2A, null, getUser());
particles.write(Type.STRING, "fireworksSpark");
particles.write(Type.FLOAT, (float)(side.modX!=0 ? x + (radius * side.modX) : centerH));
particles.write(Type.FLOAT, (float)centerV);
particles.write(Type.FLOAT, (float)(side.modX==0 ? z + (radius * side.modZ) : centerH));
particles.write(Type.FLOAT, (float)(side.modX!=0 ? 0f : (maxH-minH) / b));
particles.write(Type.FLOAT, (float)((maxV-minV) / b));
particles.write(Type.FLOAT, (float)(side.modX==0 ? 0f : (maxH-minH) / b));
particles.write(Type.FLOAT, 0f);
particles.write(Type.INT, a);
PacketUtil.sendPacket(particles, Protocol1_7_6_10To1_8.class, true, true);
}
}
private boolean isInit() {
return init;
}
public void init(double x, double z, double oldDiameter, double newDiameter, long lerpTime, int portalTeleportBoundary, int warningTime, int warningBlocks) {
this.x = x;
this.z = z;
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
this.portalTeleportBoundary = portalTeleportBoundary;
this.warningTime = warningTime;
this.warningBlocks = warningBlocks;
init = true;
}
public double getX() {
return x;
}
public double getZ() {
return z;
}
public void setCenter(double x, double z) {
this.x = x;
this.z = z;
}
public double getOldDiameter() {
return oldDiameter;
}
public double getNewDiameter() {
return newDiameter;
}
public long getLerpTime() {
return lerpTime;
}
public void lerpSize(double oldDiameter, double newDiameter, long lerpTime) {
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
this.lerpStartTime = System.currentTimeMillis();
}
public void setSize(double size) {
this.oldDiameter = size;
this.newDiameter = size;
this.lerpTime = 0;
}
public double getSize() {
if (lerpTime==0) return newDiameter;
long time = System.currentTimeMillis() - lerpStartTime;
double percent = ((double)(time) / (double)(lerpTime));
if (percent>1.0d) percent = 1.0d;
else if (percent<0.0d) percent = 0.0d;
return oldDiameter + (newDiameter-oldDiameter) * percent;
}
public int getPortalTeleportBoundary() {
return portalTeleportBoundary;
}
public void setPortalTeleportBoundary(int portalTeleportBoundary) {
this.portalTeleportBoundary = portalTeleportBoundary;
}
public int getWarningTime() {
return warningTime;
}
public void setWarningTime(int warningTime) {
this.warningTime = warningTime;
}
public int getWarningBlocks() {
return warningBlocks;
}
public void setWarningBlocks(int warningBlocks) {
this.warningBlocks = warningBlocks;
}
}
@@ -0,0 +1,108 @@
/*
* 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;
import com.viaversion.viaversion.api.connection.UserConnection;
public class WorldBorderEmulator extends StoredObject {
private double x, z;
private double oldDiameter, newDiameter;
private long lerpTime;
private long lerpStartTime;
private boolean init = false;
public WorldBorderEmulator(UserConnection user) {
super(user);
}
public void init(double x, double z, double oldDiameter, double newDiameter, long lerpTime) {
this.x = x;
this.z = z;
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
init = true;
}
public void setCenter(double x, double z) {
this.x = x;
this.z = z;
}
public void lerpSize(double oldDiameter, double newDiameter, long lerpTime) {
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
this.lerpStartTime = System.currentTimeMillis();
}
public void setSize(double size) {
this.oldDiameter = size;
this.newDiameter = size;
this.lerpTime = 0;
}
public double getSize() {
if (lerpTime == 0) {
return newDiameter;
}
double percent = ((double) (System.currentTimeMillis() - lerpStartTime) / (double) (lerpTime));
// Clamp value
if (percent > 1.0D) percent = 1.0d;
else if (percent < 0.0D) percent = 0.0d;
return oldDiameter + (newDiameter - oldDiameter) * percent;
}
public double getX() {
return x;
}
public double getZ() {
return z;
}
public boolean isInit() {
return init;
}
public enum Side {
NORTH(0, -1),
EAST(1, 0),
SOUTH(0, 1),
WEST(-1, 0);
public final int modX;
public final int modZ;
Side(int modX, int modZ) {
this.modX = modX;
this.modZ = modZ;
}
}
}
@@ -0,0 +1,96 @@
/*
* 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;
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.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.WorldBorderEmulator;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
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;
@Override
public void run() {
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final WorldBorderEmulator worldBorderEmulatorTracker = connection.get(WorldBorderEmulator.class);
if (!worldBorderEmulatorTracker.isInit()) continue;
final PlayerSessionStorage playerSession = connection.get(PlayerSessionStorage.class);
double radius = worldBorderEmulatorTracker.getSize() / 2.0;
for (WorldBorderEmulator.Side side : WorldBorderEmulator.Side.values()) {
double d;
double pos;
double center;
if (side.modX != 0) {
pos = playerSession.getPosZ();
center = worldBorderEmulatorTracker.getZ();
d = Math.abs(worldBorderEmulatorTracker.getX() + radius * side.modX - playerSession.getPosX());
} else {
center = worldBorderEmulatorTracker.getX();
pos = playerSession.getPosX();
d = Math.abs(worldBorderEmulatorTracker.getZ() + radius * side.modZ - playerSession.getPosZ());
}
if (d >= VIEW_DISTANCE) continue;
double r = Math.sqrt(VIEW_DISTANCE * VIEW_DISTANCE - d * d);
double minH = Math.ceil(pos - r);
double maxH = Math.floor(pos + r);
double minV = Math.ceil(playerSession.getPosY() - r);
double maxV = Math.floor(playerSession.getPosY() + r);
if (minH < center - radius) minH = Math.ceil(center - radius);
if (maxH > center + radius) maxH = Math.floor(center + radius);
if (minV < 0.0) minV = 0.0;
double centerH = (minH + maxH) / 2.0;
double centerV = (minV + maxV) / 2.0;
double particleOffset = 2.5;
final PacketWrapper spawnParticle = PacketWrapper.create(ClientboundPackets1_8.SPAWN_PARTICLE, connection);
spawnParticle.write(Type.STRING, ViaRewind.getConfig().getWorldBorderParticle()); // particle name
spawnParticle.write(Type.FLOAT, (float) (side.modX != 0 ? worldBorderEmulatorTracker.getX() + (radius * side.modX) : centerH)); // x
spawnParticle.write(Type.FLOAT, (float) centerV); // y
spawnParticle.write(Type.FLOAT, (float) (side.modX == 0 ? worldBorderEmulatorTracker.getZ() + (radius * side.modZ) : centerH)); // z
spawnParticle.write(Type.FLOAT, (float) (side.modX != 0 ? 0f : (maxH - minH) / particleOffset)); // offset x
spawnParticle.write(Type.FLOAT, (float) ((maxV - minV) / particleOffset)); // offset y
spawnParticle.write(Type.FLOAT, (float) (side.modX == 0 ? 0f : (maxH - minH) / particleOffset)); // offset z
spawnParticle.write(Type.FLOAT, 0F); // particle data
spawnParticle.write(Type.INT, (int) Math.floor((maxH - minH) * (maxV - minV) * 0.5));
try {
spawnParticle.send(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send world border particle", e);
}
}
}
}
}
@@ -1,108 +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.viaversion.api.minecraft.Environment;
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.type.PartialType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import io.netty.buffer.ByteBuf;
import java.io.ByteArrayOutputStream;
import java.util.zip.DeflaterOutputStream;
public class Chunk1_7_10Type extends PartialType<Chunk, ClientWorld> {
public Chunk1_7_10Type(ClientWorld param) {
super(param, Chunk.class);
}
@Override
public Chunk read(ByteBuf byteBuf, ClientWorld clientWorld) throws Exception {
throw new UnsupportedOperationException();
}
@Override
public void write(ByteBuf output, ClientWorld clientWorld, Chunk chunk) throws Exception {
output.writeInt(chunk.getX());
output.writeInt(chunk.getZ());
output.writeBoolean(chunk.isFullChunk());
output.writeShort(chunk.getBitmask());
output.writeShort(0);
ByteBuf dataToCompress = output.alloc().buffer();
try {
for (int i = 0; i < chunk.getSections().length; i++) {
if ((chunk.getBitmask() & 1 << i) == 0) continue;
ChunkSection section = chunk.getSections()[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < 4096; j++) {
int block = palette.idAt(j);
dataToCompress.writeByte(block >> 4);
}
}
for (int i = 0; i < chunk.getSections().length; i++) {
if ((chunk.getBitmask() & 1 << i) == 0) continue;
ChunkSection section = chunk.getSections()[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < 4096; j += 2) {
int data0 = palette.idAt(j) & 0xF;
int data1 = palette.idAt(j + 1) & 0xF;
dataToCompress.writeByte((data1 << 4) | data0);
}
}
for (int i = 0; i < chunk.getSections().length; i++) {
if ((chunk.getBitmask() & 1 << i) == 0) continue;
chunk.getSections()[i].getLight().writeBlockLight(dataToCompress);
}
boolean skyLight = clientWorld != null && clientWorld.getEnvironment() == Environment.NORMAL;
if (skyLight) {
for (int i = 0; i < chunk.getSections().length; i++) {
if ((chunk.getBitmask() & 1 << i) == 0) continue;
chunk.getSections()[i].getLight().writeSkyLight(dataToCompress);
}
}
if (chunk.isFullChunk() && chunk.isBiomeData()) {
for (int biome : chunk.getBiomeData()) {
dataToCompress.writeByte(biome);
}
}
ByteArrayOutputStream compressedStream = new ByteArrayOutputStream();
// todo config for compression level
try (DeflaterOutputStream compressorStream = new DeflaterOutputStream(compressedStream)) {
compressorStream.write(Type.REMAINING_BYTES.read(dataToCompress));
}
output.writeInt(compressedStream.size());
output.writeBytes(compressedStream.toByteArray());
} finally {
dataToCompress.release();
}
}
}
@@ -1,46 +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.viaversion.api.type.PartialType;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class CustomStringType extends PartialType<String[], Integer> {
public CustomStringType(Integer param) {
super(param, String[].class);
}
public String[] read(ByteBuf buffer, Integer size) throws Exception {
if (buffer.readableBytes() < size/4) {
throw new RuntimeException("Readable bytes does not match expected!");
} else {
String[] array = new String[size];
for (int i = 0; i<size; i++) {
array[i] = Type.STRING.read(buffer);
}
return array;
}
}
public void write(ByteBuf buffer, Integer size, String[] strings) throws Exception {
for (String s : strings) Type.STRING.write(buffer, s);
}
}
@@ -1,67 +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.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
@@ -18,6 +18,14 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.NBTType;
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.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;
@@ -26,16 +34,23 @@ import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import java.util.List;
public class Types1_7_6_10 {
public static final Type<CompoundTag> COMPRESSED_NBT = new CompressedNBTType();
public static final Type<Item[]> ITEM_ARRAY = new ItemArrayType(false);
public static final Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType(true);
public static final Type<Item> ITEM = new ItemType(false);
public static final Type<Item> COMPRESSED_NBT_ITEM = new ItemType(true);
public static final Type<List<Metadata>> METADATA_LIST = new MetadataListType();
public static final Type<Metadata> METADATA = new MetadataType();
public static final Type<CompoundTag> NBT = new NBTType();
/**
* An int array prefixed with byte representing the size
*/
public static final Type<int[]> INT_ARRAY = new IntArrayType();
// 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);
// Items
public final static Type<CompoundTag> COMPRESSED_NBT = new NBTType();
public final static Type<Item> COMPRESSED_NBT_ITEM = new ItemType();
public final static Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType();
// Metadata
public final static Type<Metadata> METADATA = new MetadataType();
public final static Type<List<Metadata>> METADATA_LIST = new MetadataListType();
}
@@ -0,0 +1,80 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Pair;
import io.netty.buffer.ByteBuf;
import java.io.ByteArrayOutputStream;
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 BulkChunkType1_7_6() {
super(Chunk[].class);
}
@Override
public Chunk[] read(ByteBuf byteBuf) throws Exception {
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/ChunkBulk1_7_6Type.java
}
@Override
public void write(ByteBuf byteBuf, Chunk[] chunks) throws Exception {
final int chunkCount = chunks.length;
final ByteArrayOutputStream output = new ByteArrayOutputStream();
final int[] chunkX = new int[chunkCount];
final int[] chunkZ = new int[chunkCount];
final short[] primaryBitMask = new short[chunkCount];
final short[] additionalBitMask = new short[chunkCount];
for (int i = 0; i < chunkCount; i++) {
final Chunk chunk = chunks[i];
final Pair<byte[], Short> chunkData = ChunkType1_7_6.serialize(chunk);
output.write(chunkData.key());
chunkX[i] = chunk.getX();
chunkZ[i] = chunk.getZ();
primaryBitMask[i] = (short) chunk.getBitmask();
additionalBitMask[i] = chunkData.value();
}
final byte[] data = output.toByteArray();
final Deflater deflater = new Deflater();
byte[] compressedData;
int compressedSize;
try {
deflater.setInput(data, 0, data.length);
deflater.finish();
compressedData = new byte[data.length];
compressedSize = deflater.deflate(compressedData);
} finally {
deflater.end();
}
byteBuf.writeShort(chunkCount);
byteBuf.writeInt(compressedSize);
boolean skyLight = false;
for (Chunk chunk : chunks) {
for (ChunkSection section : chunk.getSections()) {
if (section != null && section.getLight().hasSkyLight()) {
skyLight = true;
break;
}
}
}
byteBuf.writeBoolean(skyLight); // hasSkyLight
byteBuf.writeBytes(compressedData, 0, compressedSize);
for (int i = 0; i < chunkCount; i++) {
byteBuf.writeInt(chunkX[i]);
byteBuf.writeInt(chunkZ[i]);
byteBuf.writeShort(primaryBitMask[i]);
byteBuf.writeShort(additionalBitMask[i]);
}
}
}
@@ -0,0 +1,135 @@
/*
* 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.types.chunk;
import com.viaversion.viarewind.api.minecraft.ExtendedBlockStorage;
import com.viaversion.viaversion.api.minecraft.chunks.*;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Pair;
import io.netty.buffer.ByteBuf;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
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 ChunkType1_7_6() {
super(Chunk.class);
}
@Override
public Chunk read(ByteBuf byteBuf) throws Exception {
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/Chunk1_7_6Type.java
}
@Override
public void write(ByteBuf output, Chunk chunk) throws Exception {
final Pair<byte[], Short> chunkData = serialize(chunk);
final byte[] data = chunkData.key();
final short additionalBitMask = chunkData.value();
final Deflater deflater = new Deflater();
byte[] compressedData;
int compressedSize;
try {
deflater.setInput(data, 0, data.length);
deflater.finish();
compressedData = new byte[data.length];
compressedSize = deflater.deflate(compressedData);
} finally {
deflater.end();
}
output.writeInt(chunk.getX());
output.writeInt(chunk.getZ());
output.writeBoolean(chunk.isFullChunk());
output.writeShort(chunk.getBitmask());
output.writeShort(additionalBitMask);
output.writeInt(compressedSize);
output.writeBytes(compressedData, 0, compressedSize);
}
public static Pair<byte[], Short> serialize(final Chunk chunk) throws IOException {
final ExtendedBlockStorage[] storageArrays = new ExtendedBlockStorage[16];
for (int i = 0; i < storageArrays.length; i++) {
final ChunkSection section = chunk.getSections()[i];
if (section != null) {
final ExtendedBlockStorage storage = storageArrays[i] = new ExtendedBlockStorage(section.getLight().hasSkyLight());
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = 0; y < 16; y++) {
final int flatBlock = section.palette(PaletteType.BLOCKS).idAt(x, y, z);
storage.setBlockId(x, y, z, flatBlock >> 4);
storage.setBlockMetadata(x, y, z, flatBlock & 15);
}
}
}
storage.getBlockLightArray().setHandle(section.getLight().getBlockLight());
if (section.getLight().hasSkyLight()) {
storage.getSkyLightArray().setHandle(section.getLight().getSkyLight());
}
}
}
final ByteArrayOutputStream output = new ByteArrayOutputStream();
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0) {
output.write(storageArrays[i].getBlockLSBArray());
}
}
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0) {
output.write(storageArrays[i].getBlockMetadataArray().getHandle());
}
}
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0) {
output.write(storageArrays[i].getBlockLightArray().getHandle());
}
}
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0 && storageArrays[i].getSkyLightArray() != null) {
output.write(storageArrays[i].getSkyLightArray().getHandle());
}
}
short additionalBitMask = 0;
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0 && storageArrays[i].hasBlockMSBArray()) {
additionalBitMask |= (short) (1 << i);
output.write(storageArrays[i].getOrCreateBlockMSBArray().getHandle());
}
}
if (chunk.isFullChunk() && chunk.getBiomeData() != null) {
for (int biome : chunk.getBiomeData()) {
output.write(biome);
}
}
return new Pair<>(output.toByteArray(), additionalBitMask);
}
}
@@ -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
@@ -16,18 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
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.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
@@ -35,17 +34,17 @@ public class ItemArrayType extends Type<Item[]> {
int amount = Type.SHORT.readPrimitive(buffer);
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);
for (int i = 0; i < amount; ++i) {
items[i] = Types1_7_6_10.COMPRESSED_NBT_ITEM.read(buffer);
}
return items;
}
@Override
public void write(ByteBuf buffer, Item[] items) throws Exception {
Type.SHORT.writePrimitive(buffer, (short)items.length);
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
@@ -16,24 +16,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
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.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
public Item read(ByteBuf buffer) throws Exception {
int readerIndex = buffer.readerIndex();
short id = buffer.readShort();
if (id < 0) {
return null;
@@ -42,7 +40,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 +52,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
@@ -16,11 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
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 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 +29,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 +44,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 +58,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
@@ -16,10 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
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.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),
@@ -29,25 +31,27 @@ public enum MetaType1_7_6_10 implements MetaType {
String(4, Type.STRING),
Slot(5, Types1_7_6_10.COMPRESSED_NBT_ITEM),
Position(6, Type.VECTOR),
NonExistent(-1, Type.NOTHING);
NonExistent(-1, new VoidType());
private final int typeID;
private final Type type;
private final Type<?> type;
MetaType1_7_6_10(int typeID, Type<?> type) {
this.typeID = typeID;
this.type = type;
}
public static MetaType1_7_6_10 byId(int id) {
return values()[id];
}
MetaType1_7_6_10(int typeID, Type type) {
this.typeID = typeID;
this.type = type;
}
@Override
public int typeId() {
return this.typeID;
}
public Type type() {
@Override
public Type<?> type() {
return this.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
@@ -16,18 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
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.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.types.minecraft.MetaListTypeTemplate;
import com.viaversion.viaversion.api.type.types.metadata.MetaListTypeTemplate;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public class MetadataListType extends MetaListTypeTemplate {
private final MetadataType metadataType = new MetadataType();
@Override
public List<Metadata> read(ByteBuf buffer) throws Exception {
ArrayList<Metadata> list = new ArrayList<>();
@@ -38,7 +37,7 @@ public class MetadataListType extends MetaListTypeTemplate {
if (m != null) {
list.add(m);
}
} while(m != null);
} while (m != null);
return list;
}
@@ -49,7 +48,7 @@ public class MetadataListType extends MetaListTypeTemplate {
Types1_7_6_10.METADATA.write(buffer, meta);
}
if (metadata.isEmpty()) {
Types1_7_6_10.METADATA.write(buffer, new Metadata(0, MetaType1_7_6_10.Byte, (byte)0));
Types1_7_6_10.METADATA.write(buffer, new Metadata(0, MetaType1_7_6_10.Byte, (byte) 0));
}
buffer.writeByte(127);
}
@@ -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
@@ -16,10 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.types.minecraft.MetaTypeTemplate;
import com.viaversion.viaversion.api.type.types.metadata.MetaTypeTemplate;
import io.netty.buffer.ByteBuf;
public class MetadataType extends 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
@@ -16,14 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class IntArrayType extends Type<int[]> {
public class ByteIntArrayType extends Type<int[]> {
public IntArrayType() {
public ByteIntArrayType() {
super(int[].class);
}
@@ -0,0 +1,36 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import java.util.function.IntFunction;
public class PositionUYType<T extends Number> extends Type<Position> {
private final Type<T> yType;
private final IntFunction<T> toY;
public PositionUYType(final Type<T> yType, final IntFunction<T> toY) {
super(Position.class);
this.yType = yType;
this.toY = toY;
}
@Override
public Position read(ByteBuf buffer) throws Exception {
final int x = buffer.readInt();
final int y = yType.read(buffer).intValue();
final int z = buffer.readInt();
return new Position(x, y, z);
}
@Override
public void write(ByteBuf buffer, Position value) throws Exception {
buffer.writeInt(value.x());
yType.write(buffer, this.toY.apply(value.y()));
buffer.writeInt(value.z());
}
}
@@ -1,184 +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_7_6_10.metadata;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.Optional;
public enum MetaIndex1_8To1_7_6_10 {
ENTITY_FLAGS(Entity1_10Types.EntityType.ENTITY, 0, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_AIR(Entity1_10Types.EntityType.ENTITY, 1, MetaType1_7_6_10.Short, MetaType1_8.Short),
ENTITY_NAME_TAG(Entity1_10Types.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 2, MetaType1_8.String),
ENTITY_NAME_TAG_VISIBILITY(Entity1_10Types.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 3, MetaType1_8.Byte),
ENTITY_SILENT(Entity1_10Types.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 4, MetaType1_8.Byte),
ENTITY_LIVING_HEALTH(Entity1_10Types.EntityType.ENTITY_LIVING, 6, MetaType1_7_6_10.Float, MetaType1_8.Float),
ENTITY_LIVING_POTION_EFFECT_COLOR(Entity1_10Types.EntityType.ENTITY_LIVING, 7, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENTITY_LIVING_IS_POTION_EFFECT_AMBIENT(Entity1_10Types.EntityType.ENTITY_LIVING, 8, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_ARROWS(Entity1_10Types.EntityType.ENTITY_LIVING, 9, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_NAME_TAG(Entity1_10Types.EntityType.ENTITY_LIVING, 10, MetaType1_7_6_10.String, 2, MetaType1_8.String),
ENTITY_LIVING_NAME_TAG_VISIBILITY(Entity1_10Types.EntityType.ENTITY_LIVING, 11, MetaType1_7_6_10.Byte, 3, MetaType1_8.Byte),
ENTITY_LIVING_AI(Entity1_10Types.EntityType.ENTITY_LIVING, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Byte),
ENTITY_AGEABLE_AGE(Entity1_10Types.EntityType.ENTITY_AGEABLE, 12, MetaType1_7_6_10.Int, MetaType1_8.Byte),
ARMOR_STAND_FLAGS(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 10, MetaType1_8.Byte),
ARMOR_STAND_HEAD_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 11, MetaType1_8.Rotation),
ARMOR_STAND_BODY_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 12, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_ARM_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 13, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_ARM_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 14, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_LEG_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_LEG_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Rotation),
HUMAN_SKIN_FLAGS(Entity1_10Types.EntityType.ENTITY_HUMAN, 16, MetaType1_7_6_10.Byte, 10, MetaType1_8.Byte),
HUMAN_UNUSED(Entity1_10Types.EntityType.ENTITY_HUMAN, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Byte),
HUMAN_ABSORPTION_HEATS(Entity1_10Types.EntityType.ENTITY_HUMAN, 17, MetaType1_7_6_10.Float, MetaType1_8.Float),
HUMAN_SCORE(Entity1_10Types.EntityType.ENTITY_HUMAN, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_FLAGS(Entity1_10Types.EntityType.HORSE, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_TYPE(Entity1_10Types.EntityType.HORSE, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
HORSE_COLOR(Entity1_10Types.EntityType.HORSE, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_OWNER(Entity1_10Types.EntityType.HORSE, 21, MetaType1_7_6_10.String, MetaType1_8.String),
HORSE_ARMOR(Entity1_10Types.EntityType.HORSE, 22, MetaType1_7_6_10.Int, MetaType1_8.Int),
BAT_HANGING(Entity1_10Types.EntityType.BAT, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_FLAGS(Entity1_10Types.EntityType.ENTITY_TAMEABLE_ANIMAL, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_OWNER(Entity1_10Types.EntityType.ENTITY_TAMEABLE_ANIMAL, 17, MetaType1_7_6_10.String, MetaType1_8.String),
OCELOT_TYPE(Entity1_10Types.EntityType.OCELOT, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_FLAGS(Entity1_10Types.EntityType.WOLF, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_HEALTH(Entity1_10Types.EntityType.WOLF, 18, MetaType1_7_6_10.Float, MetaType1_8.Float),
WOLF_BEGGING(Entity1_10Types.EntityType.WOLF, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_COLLAR_COLOR(Entity1_10Types.EntityType.WOLF, 20, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
PIG_SADDLE(Entity1_10Types.EntityType.PIG, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SHEEP_COLOR_OR_SHEARED(Entity1_10Types.EntityType.SHEEP, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
VILLAGER_TYPE(Entity1_10Types.EntityType.VILLAGER, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENDERMAN_CARRIED_BLOCK(Entity1_10Types.EntityType.ENDERMAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Short),
ENDERMAN_CARRIED_BLOCK_DATA(Entity1_10Types.EntityType.ENDERMAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
ENDERMAN_IS_SCREAMING(Entity1_10Types.EntityType.ENDERMAN, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CHILD(Entity1_10Types.EntityType.ZOMBIE, 12, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_VILLAGER(Entity1_10Types.EntityType.ZOMBIE, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CONVERTING(Entity1_10Types.EntityType.ZOMBIE, 14, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
BLAZE_ON_FIRE(Entity1_10Types.EntityType.BLAZE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SPIDER_CLIMBING(Entity1_10Types.EntityType.SPIDER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_STATE(Entity1_10Types.EntityType.CREEPER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_POWERED(Entity1_10Types.EntityType.CREEPER, 17, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_STATE(Entity1_10Types.EntityType.GHAST, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_IS_POWERED(Entity1_10Types.EntityType.GHAST, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
SLIME_SIZE(Entity1_10Types.EntityType.SLIME, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SKELETON_TYPE(Entity1_10Types.EntityType.SKELETON, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITCH_AGRESSIVE(Entity1_10Types.EntityType.WITCH, 21, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
IRON_GOLEM_IS_PLAYER_CREATED(Entity1_10Types.EntityType.IRON_GOLEM, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITHER_WATCHED_TAGRET_1(Entity1_10Types.EntityType.WITHER, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TAGRET_2(Entity1_10Types.EntityType.WITHER, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TAGRET_3(Entity1_10Types.EntityType.WITHER, 19, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_INVULNERABLE_TIME(Entity1_10Types.EntityType.WITHER, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
GUARDIAN_FLAGS(Entity1_10Types.EntityType.GUARDIAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
GUARDIAN_TARGET(Entity1_10Types.EntityType.GUARDIAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Int),
BOAT_TIME_SINCE_HIT(Entity1_10Types.EntityType.BOAT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_FORWARD_DIRECTION(Entity1_10Types.EntityType.BOAT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_DAMAGE_TAKEN(Entity1_10Types.EntityType.BOAT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_SHAKING_POWER(Entity1_10Types.EntityType.MINECART_ABSTRACT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHAKING_DIRECTION(Entity1_10Types.EntityType.MINECART_ABSTRACT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_DAMAGE_TAKEN(Entity1_10Types.EntityType.MINECART_ABSTRACT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_BLOCK_INSIDE(Entity1_10Types.EntityType.MINECART_ABSTRACT, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_BLOCK_Y(Entity1_10Types.EntityType.MINECART_ABSTRACT, 21, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHOW_BLOCK(Entity1_10Types.EntityType.MINECART_ABSTRACT, 22, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FURNACE_MINECART_IS_POWERED(Entity1_10Types.EntityType.MINECART_FURNACE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ITEM_ITEM(Entity1_10Types.EntityType.DROPPED_ITEM, 10, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ARROW_IS_CRITICAL(Entity1_10Types.EntityType.ARROW, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FIREWORK_INFO(Entity1_10Types.EntityType.FIREWORK, 8, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ITEM_FRAME_ITEM(Entity1_10Types.EntityType.ITEM_FRAME, 2, MetaType1_7_6_10.Slot, 8, MetaType1_8.Slot),
ITEM_FRAME_ROTATION(Entity1_10Types.EntityType.ITEM_FRAME, 3, MetaType1_7_6_10.Byte, 9, MetaType1_8.Byte),
ENDER_CRYSTAL_HEALTH(Entity1_10Types.EntityType.ENDER_CRYSTAL, 8, MetaType1_7_6_10.Int, 9, MetaType1_8.Int),
;
private static final HashMap<Pair<Entity1_10Types.EntityType, Integer>, MetaIndex1_8To1_7_6_10> metadataRewrites = new HashMap<>();
static {
for (MetaIndex1_8To1_7_6_10 index : MetaIndex1_8To1_7_6_10.values())
metadataRewrites.put(new Pair<>(index.getClazz(), index.getIndex()), index);
}
private final Entity1_10Types.EntityType clazz;
private final int newIndex;
private final MetaType1_8 newType;
private final MetaType1_7_6_10 oldType;
private final int index;
MetaIndex1_8To1_7_6_10(Entity1_10Types.EntityType type, int index, MetaType1_7_6_10 oldType, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.newIndex = index;
this.oldType = oldType;
this.newType = newType;
}
MetaIndex1_8To1_7_6_10(Entity1_10Types.EntityType type, int index, MetaType1_7_6_10 oldType, int newIndex, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.oldType = oldType;
this.newIndex = newIndex;
this.newType = newType;
}
private static Optional<MetaIndex1_8To1_7_6_10> getIndex(Entity1_10Types.EntityType type, int index) {
Pair pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
return Optional.empty();
}
public Entity1_10Types.EntityType getClazz() {
return clazz;
}
public int getNewIndex() {
return newIndex;
}
public MetaType1_8 getNewType() {
return newType;
}
public MetaType1_7_6_10 getOldType() {
return oldType;
}
public int getIndex() {
return index;
}
public static MetaIndex1_8To1_7_6_10 searchIndex(Entity1_10Types.EntityType type, int index) {
Entity1_10Types.EntityType currentType = type;
do {
Optional<MetaIndex1_8To1_7_6_10> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
}
currentType = currentType.getParent();
} while (currentType != null);
return null;
}
}
@@ -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
@@ -18,10 +18,12 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9;
import com.viaversion.viarewind.api.rewriter.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.viarewind.protocol.protocol1_8to1_9.packets.*;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
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.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -29,25 +31,29 @@ import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import com.viaversion.viarewind.utils.Ticker;
import java.util.*;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
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 Queue<PacketWrapper> animationsToSend = new ConcurrentLinkedQueue<>();
public static final Set<String> VALID_ATTRIBUTES = new HashSet<>();
public static final ValueTransformer<Double, Integer> TO_OLD_INT = new ValueTransformer<Double, Integer>(Type.INT) {
public final static Set<String> VALID_ATTRIBUTES = new HashSet<>();
public final static ValueTransformer<Double, Integer> TO_OLD_INT = new ValueTransformer<Double, Integer>(Type.INT) {
@Override
public Integer transform(PacketWrapper wrapper, Double inputValue) {
return (int) (inputValue * 32.0D);
}
};
public static final ValueTransformer<Float, Byte> DEGREES_TO_ANGLE = new ValueTransformer<Float, Byte>(Type.BYTE) {
public final static ValueTransformer<Float, Byte> DEGREES_TO_ANGLE = new ValueTransformer<Float, Byte>(Type.BYTE) {
@Override
public Byte transform(PacketWrapper packetWrapper, Float degrees) throws Exception {
return (byte) ((degrees / 360F) * 256);
@@ -70,6 +76,8 @@ public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, Cl
@Override
protected void registerPackets() {
itemRewriter.register();
EntityPackets.register(this);
InventoryPackets.register(this);
PlayerPackets.register(this);
@@ -83,12 +91,23 @@ public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, Cl
Ticker.init();
userConnection.put(new Windows(userConnection));
userConnection.put(new EntityTracker(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));
if (!userConnection.has(ClientWorld.class)) {
userConnection.put(new ClientWorld());
}
}
@Override
public ReplacementItemRewriter<Protocol1_8To1_9> getItemRewriter() {
return itemRewriter;
}
public MetadataRewriter getMetadataRewriter() {
return metadataRewriter;
}
}
@@ -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
@@ -34,7 +34,7 @@ import com.viaversion.viarewind.utils.PacketUtil;
import java.util.*;
public class WitherBossBar implements BossBar {
private static int highestId = Integer.MAX_VALUE-10000;
private static int highestId = Integer.MAX_VALUE - 10000;
private final UUID uuid;
private String title;
@@ -72,8 +72,8 @@ public class WitherBossBar implements BossBar {
@Override
public BossBar setHealth(float health) {
this.health = health;
if (this.health<=0) this.health = 0.0001f;
this.health = health;
if (this.health <= 0) this.health = 0.0001f;
if (this.visible) updateMetadata();
return this;
}
@@ -103,22 +103,22 @@ public class WitherBossBar implements BossBar {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public BossBar addConnection(UserConnection userConnection) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public BossBar addConnection(UserConnection userConnection) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
@Override
public BossBar removePlayer(UUID uuid) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public BossBar removeConnection(UserConnection userConnection) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public BossBar removeConnection(UserConnection userConnection) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
@Override
public BossBar addFlag(BossFlag bossFlag) {
throw new UnsupportedOperationException(this.getClass().getName() + " does not support flags");
}
@@ -138,12 +138,12 @@ public class WitherBossBar implements BossBar {
return Collections.singleton(connection.getProtocolInfo().getUuid());
}
@Override
public Set<UserConnection> getConnections() {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public Set<UserConnection> getConnections() {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
@Override
public BossBar show() {
if (!this.visible) {
this.visible = true;
@@ -181,16 +181,16 @@ public class WitherBossBar implements BossBar {
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.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);
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);
List<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(0, MetaType1_8.Byte, (byte) 0x20));
@@ -209,8 +209,8 @@ public class WitherBossBar implements BossBar {
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.BYTE, (byte) 0);
packetWrapper.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
@@ -231,7 +231,7 @@ public class WitherBossBar implements BossBar {
private void despawnWither() {
PacketWrapper packetWrapper = PacketWrapper.create(0x13, null, this.connection);
packetWrapper.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[] {entityId});
packetWrapper.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
}
@@ -0,0 +1,51 @@
/*
* 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.cooldown;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
public class ActionBarVisualization implements CooldownVisualization {
private final UserConnection user;
public ActionBarVisualization(UserConnection user) {
this.user = user;
}
@Override
public void show(double progress) throws Exception {
sendActionBar(CooldownVisualization.buildProgressText("■", progress));
}
@Override
public void hide() throws Exception {
sendActionBar("§r");
}
private void sendActionBar(String bar) throws Exception {
PacketWrapper actionBarPacket = PacketWrapper.create(ClientboundPackets1_8.CHAT_MESSAGE, user);
actionBarPacket.write(Type.COMPONENT, new JsonPrimitive(bar));
actionBarPacket.write(Type.BYTE, (byte) 2); // Position - above hotbar
actionBarPacket.scheduleSend(Protocol1_8To1_9.class);
}
}
@@ -0,0 +1,68 @@
/*
* 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.cooldown;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import java.util.UUID;
public class BossBarVisualization implements CooldownVisualization {
private final UserConnection user;
private UUID bossUUID;
public BossBarVisualization(UserConnection user) {
this.user = user;
}
@Override
public void show(double progress) throws Exception {
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_9.BOSSBAR, user);
if (bossUUID == null) {
bossUUID = UUID.randomUUID();
wrapper.write(Type.UUID, bossUUID);
wrapper.write(Type.VAR_INT, 0); // Action - add
wrapper.write(Type.COMPONENT, new JsonPrimitive(" ")); // Title
wrapper.write(Type.FLOAT, (float) progress); // Health
wrapper.write(Type.VAR_INT, 0); // Color
wrapper.write(Type.VAR_INT, 0); // Division
wrapper.write(Type.UNSIGNED_BYTE, (short) 0); // Flags
} else {
wrapper.write(Type.UUID, bossUUID);
wrapper.write(Type.VAR_INT, 2); // Action - update health
wrapper.write(Type.FLOAT, (float) progress); // Health
}
wrapper.scheduleSend(Protocol1_8To1_9.class, false);
}
@Override
public void hide() throws Exception {
if (bossUUID == null) {
return;
}
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_9.BOSSBAR, null, user);
wrapper.write(Type.UUID, bossUUID);
wrapper.write(Type.VAR_INT, 1); // Action - remove
wrapper.scheduleSend(Protocol1_8To1_9.class, false);
bossUUID = null;
}
}
@@ -0,0 +1,72 @@
/*
* 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.cooldown;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.ViaRewindConfig.CooldownIndicator;
import com.viaversion.viaversion.api.connection.UserConnection;
public interface CooldownVisualization {
void show(double progress) throws Exception;
void hide() throws Exception;
int MAX_PROGRESS_TEXT_LENGTH = 10;
static String buildProgressText(String symbol, double cooldown) {
int green = (int) Math.floor(((double) MAX_PROGRESS_TEXT_LENGTH) * cooldown);
int grey = MAX_PROGRESS_TEXT_LENGTH - green;
StringBuilder builder = new StringBuilder("§8");
while (green-- > 0) builder.append(symbol);
builder.append("§7");
while (grey-- > 0) builder.append(symbol);
return builder.toString();
}
interface Factory {
CooldownVisualization create(UserConnection user);
static Factory fromConfiguration() {
try {
return fromIndicator(ViaRewind.getConfig().getCooldownIndicator());
} catch (IllegalArgumentException e) {
ViaRewind.getPlatform().getLogger().warning("Invalid cooldown-indicator setting");
return DISABLED;
}
}
static Factory fromIndicator(CooldownIndicator indicator) {
switch (indicator) {
case TITLE:
return TitleCooldownVisualization::new;
case BOSS_BAR:
return BossBarVisualization::new;
case ACTION_BAR:
return ActionBarVisualization::new;
case DISABLED:
return DISABLED;
default:
throw new IllegalArgumentException("Unexpected: " + indicator);
}
}
Factory DISABLED = user -> new DisabledCooldownVisualization();
}
}
@@ -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
@@ -16,20 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.storage;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
public class BlockState {
public class DisabledCooldownVisualization implements CooldownVisualization {
@Override
public void show(double progress) {
public static int extractId(int raw) {
return raw >> 4;
}
public static int extractData(int raw) {
return raw & 0xF;
}
@Override
public void hide() {
public static int stateToRaw(int id, int data) {
return (id << 4) | (data & 0xF);
}
}
@@ -0,0 +1,77 @@
/*
* 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.cooldown;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.function.Consumer;
public class TitleCooldownVisualization implements CooldownVisualization {
private final UserConnection user;
public TitleCooldownVisualization(UserConnection user) {
this.user = user;
}
@Override
public void show(double progress) throws Exception {
String text = CooldownVisualization.buildProgressText("˙", progress);
sendTitle("", text, 0, 2, 5);
}
@Override
public void hide() throws Exception {
sendTitlePacket(ACTION_HIDE, wrapper -> {});
}
private static final int ACTION_SET_TITLE = 0;
private static final int ACTION_SET_SUBTITLE = 1;
private static final int ACTION_SET_TIMES_AND_DISPLAY = 2;
private static final int ACTION_HIDE = 3;
private void sendTitle(String titleText, String subTitleText, int fadeIn, int stay, int fadeOut) throws Exception {
sendTitlePacket(
ACTION_SET_TITLE,
packet -> packet.write(Type.COMPONENT, new JsonPrimitive(titleText))
);
sendTitlePacket(
ACTION_SET_SUBTITLE,
packet -> packet.write(Type.COMPONENT, new JsonPrimitive(subTitleText))
);
sendTitlePacket(
ACTION_SET_TIMES_AND_DISPLAY,
packet -> {
packet.write(Type.INT, fadeIn);
packet.write(Type.INT, stay);
packet.write(Type.INT, fadeOut);
}
);
}
private void sendTitlePacket(int action, Consumer<PacketWrapper> writer) throws Exception {
PacketWrapper titlePacket = PacketWrapper.create(ClientboundPackets1_8.TITLE, user);
titlePacket.write(Type.VAR_INT, action);
writer.accept(titlePacket);
titlePacket.scheduleSend(Protocol1_8To1_9.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
@@ -19,10 +19,11 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.replacement.EntityReplacement;
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;
@@ -31,19 +32,18 @@ import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public abstract class EntityReplacement1_8to1_9 implements EntityReplacement {
protected final UserConnection user;
public abstract class EntityModel1_8To1_9 extends EntityModel<Protocol1_8To1_9> {
protected EntityReplacement1_8to1_9(UserConnection user) {
this.user = user;
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) {
sendTeleport(entityId, locX, locY, locZ, yaw, pitch);
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
sendHeadYaw(entityId, headYaw);
}
protected void sendTeleport(int entityId, double locX, double locY, double locZ, float yaw, float pitch) {
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));
@@ -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
@@ -29,20 +29,21 @@ import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
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 ShulkerBulletReplacement(int entityId, UserConnection user) {
super(user);
public ShulkerBulletModel(UserConnection user, Protocol1_8To1_9 protocol, int entityId) {
super(user, protocol);
this.entityId = entityId;
spawn();
sendSpawnPacket();
}
public void setLocation(double x, double y, double z) {
@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;
@@ -51,7 +52,8 @@ public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
}
}
public void relMove(double x, double y, double z) {
@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;
@@ -59,6 +61,7 @@ public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
updateLocation();
}
@Override
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw && this.pitch != pitch) {
this.yaw = yaw;
@@ -67,10 +70,12 @@ public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
}
}
@Override
public void setHeadYaw(float yaw) {
this.headYaw = yaw;
}
@Override
public void updateMetadata(List<Metadata> metadataList) {
}
@@ -79,18 +84,19 @@ public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
}
@Override
public void spawn() {
public void sendSpawnPacket() {
sendSpawnEntity(entityId, 66);
}
@Override
public void despawn() {
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,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
@@ -18,53 +18,58 @@
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.protocol.protocol1_8to1_9.storage.EntityTracker;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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 com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata.MetadataRewriter;
import java.util.ArrayList;
import java.util.List;
public class ShulkerReplacement extends EntityReplacement1_8to1_9 {
public class ShulkerModel extends EntityModel1_8To1_9 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
public ShulkerReplacement(int entityId, UserConnection user) {
super(user);
public ShulkerModel(UserConnection user, Protocol1_8To1_9 protocol, int entityId) {
super(user, protocol);
this.entityId = entityId;
spawn();
sendSpawnPacket();
}
public void setLocation(double x, double y, double z) {
@Override
public void updateReplacementPosition(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
public void relMove(double x, double y, double z) {
@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());
@@ -74,7 +79,7 @@ public class ShulkerReplacement extends EntityReplacement1_8to1_9 {
}
public void updateLocation() {
sendTeleport(entityId, locX, locY, locZ, 0, 0);
teleportEntity(entityId, locX, locY, locZ, 0, 0);
}
public void updateMetadata() {
@@ -88,7 +93,7 @@ public class ShulkerReplacement extends EntityReplacement1_8to1_9 {
}
metadataList.add(new Metadata(11, MetaType1_9.VarInt, 2));
MetadataRewriter.transform(Entity1_10Types.EntityType.MAGMA_CUBE, metadataList);
getProtocol().getMetadataRewriter().transform(user.get(EntityTracker.class), entityId, metadataList, EntityTypes1_10.EntityType.MAGMA_CUBE);
metadataPacket.write(Types1_8.METADATA_LIST, metadataList);
@@ -96,19 +101,20 @@ public class ShulkerReplacement extends EntityReplacement1_8to1_9 {
}
@Override
public void spawn() {
public void sendSpawnPacket() {
sendSpawn(entityId, 62);
// Old clients don't like empty metadata
}
@Override
public void despawn() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, user);
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,310 +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.items;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viarewind.utils.Enchantments;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter.potionNameFromDamage;
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "unused"})
public class ItemRewriter {
private static Map<String, Integer> ENTTIY_NAME_TO_ID;
private static Map<Integer, String> ENTTIY_ID_TO_NAME;
private static Map<String, Integer> POTION_NAME_TO_ID;
private static Map<Integer, String> POTION_ID_TO_NAME;
private static final Map<String, String> POTION_NAME_INDEX = new HashMap<>();
static {
for (Field field : ItemRewriter.class.getDeclaredFields()) {
try {
Field other = com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter.class.getDeclaredField(field.getName());
other.setAccessible(true);
field.setAccessible(true);
field.set(null, other.get(null));
} catch (Exception ignored) {}
}
POTION_NAME_TO_ID.put("luck", 8203);
POTION_NAME_INDEX.put("water", "§rWater Bottle");
POTION_NAME_INDEX.put("mundane", "§rMundane Potion");
POTION_NAME_INDEX.put("thick", "§rThick Potion");
POTION_NAME_INDEX.put("awkward", "§rAwkward Potion");
POTION_NAME_INDEX.put("water_splash", "§rSplash Water Bottle");
POTION_NAME_INDEX.put("mundane_splash", "§rMundane Splash Potion");
POTION_NAME_INDEX.put("thick_splash", "§rThick Splash Potion");
POTION_NAME_INDEX.put("awkward_splash", "§rAwkward Splash Potion");
POTION_NAME_INDEX.put("water_lingering", "§rLingering Water Bottle");
POTION_NAME_INDEX.put("mundane_lingering", "§rMundane Lingering Potion");
POTION_NAME_INDEX.put("thick_lingering", "§rThick Lingering Potion");
POTION_NAME_INDEX.put("awkward_lingering", "§rAwkward Lingering Potion");
POTION_NAME_INDEX.put("night_vision_lingering", "§rLingering Potion of Night Vision");
POTION_NAME_INDEX.put("long_night_vision_lingering", "§rLingering Potion of Night Vision");
POTION_NAME_INDEX.put("invisibility_lingering", "§rLingering Potion of Invisibility");
POTION_NAME_INDEX.put("long_invisibility_lingering", "§rLingering Potion of Invisibility");
POTION_NAME_INDEX.put("leaping_lingering", "§rLingering Potion of Leaping");
POTION_NAME_INDEX.put("long_leaping_lingering", "§rLingering Potion of Leaping");
POTION_NAME_INDEX.put("strong_leaping_lingering", "§rLingering Potion of Leaping");
POTION_NAME_INDEX.put("fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
POTION_NAME_INDEX.put("long_fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
POTION_NAME_INDEX.put("swiftness_lingering", "§rLingering Potion of Swiftness");
POTION_NAME_INDEX.put("long_swiftness_lingering", "§rLingering Potion of Swiftness");
POTION_NAME_INDEX.put("strong_swiftness_lingering", "§rLingering Potion of Swiftness");
POTION_NAME_INDEX.put("slowness_lingering", "§rLingering Potion of Slowness");
POTION_NAME_INDEX.put("long_slowness_lingering", "§rLingering Potion of Slowness");
POTION_NAME_INDEX.put("water_breathing_lingering", "§rLingering Potion of Water Breathing");
POTION_NAME_INDEX.put("long_water_breathing_lingering", "§rLingering Potion of Water Breathing");
POTION_NAME_INDEX.put("healing_lingering", "§rLingering Potion of Healing");
POTION_NAME_INDEX.put("strong_healing_lingering", "§rLingering Potion of Healing");
POTION_NAME_INDEX.put("harming_lingering", "§rLingering Potion of Harming");
POTION_NAME_INDEX.put("strong_harming_lingering", "§rLingering Potion of Harming");
POTION_NAME_INDEX.put("poison_lingering", "§rLingering Potion of Poisen");
POTION_NAME_INDEX.put("long_poison_lingering", "§rLingering Potion of Poisen");
POTION_NAME_INDEX.put("strong_poison_lingering", "§rLingering Potion of Poisen");
POTION_NAME_INDEX.put("regeneration_lingering", "§rLingering Potion of Regeneration");
POTION_NAME_INDEX.put("long_regeneration_lingering", "§rLingering Potion of Regeneration");
POTION_NAME_INDEX.put("strong_regeneration_lingering", "§rLingering Potion of Regeneration");
POTION_NAME_INDEX.put("strength_lingering", "§rLingering Potion of Strength");
POTION_NAME_INDEX.put("long_strength_lingering", "§rLingering Potion of Strength");
POTION_NAME_INDEX.put("strong_strength_lingering", "§rLingering Potion of Strength");
POTION_NAME_INDEX.put("weakness_lingering", "§rLingering Potion of Weakness");
POTION_NAME_INDEX.put("long_weakness_lingering", "§rLingering Potion of Weakness");
POTION_NAME_INDEX.put("luck_lingering", "§rLingering Potion of Luck");
POTION_NAME_INDEX.put("luck", "§rPotion of Luck");
POTION_NAME_INDEX.put("luck_splash", "§rSplash Potion of Luck");
}
public static Item toClient(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("ViaRewind1_8to1_9", 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 (ENTTIY_NAME_TO_ID.containsKey(id.getValue())) {
data = ENTTIY_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);
}
ReplacementRegistry1_8to1_9.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 (POTION_NAME_TO_ID.containsKey(potionName)) {
data = 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")) && POTION_NAME_INDEX.containsKey(potionName)) {
if (display==null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
display.put("Name", new StringTag(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("ViaRewind1_8to1_9");
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
public static Item toServer(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") && ENTTIY_ID_TO_NAME.containsKey((int) item.data())) {
CompoundTag entityTag = new CompoundTag();
entityTag.put("id", new StringTag(ENTTIY_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,105 +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.items;
import com.viaversion.viarewind.replacement.Replacement;
import com.viaversion.viarewind.replacement.ReplacementRegistry;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viarewind.storage.BlockState;
public class ReplacementRegistry1_8to1_9 {
private static final ReplacementRegistry registry = new ReplacementRegistry();
static {
registry.registerItem(198, new Replacement(50, 0, "End Rod"));
registry.registerItem(434, new Replacement(391, "Beetroot"));
registry.registerItem(435, new Replacement(361, "Beetroot Seeds"));
registry.registerItem(436, new Replacement(282, "Beetroot Soup"));
registry.registerItem(432, new Replacement(322, "Chorus Fruit"));
registry.registerItem(433, new Replacement(393, "Popped Chorus Fruit"));
registry.registerItem(437, new Replacement(373, "Dragons Breath"));
registry.registerItem(443, new Replacement(299, "Elytra"));
registry.registerItem(426, new Replacement(410, "End Crystal"));
registry.registerItem(442, new Replacement(425, "Shield"));
registry.registerItem(439, new Replacement(262, "Spectral Arrow"));
registry.registerItem(440, new Replacement(262, "Tipped Arrow"));
registry.registerItem(444, new Replacement(333, "Spruce Boat"));
registry.registerItem(445, new Replacement(333, "Birch Boat"));
registry.registerItem(446, new Replacement(333, "Jungle Boat"));
registry.registerItem(447, new Replacement(333, "Acacia Boat"));
registry.registerItem(448, new Replacement(333, "Dark Oak Boat"));
registry.registerItem(204, new Replacement(43, 7, "Purpur Double Slab"));
registry.registerItem(205, new Replacement(44, 7, "Purpur Slab"));
registry.registerBlock(209, new Replacement(119));
registry.registerBlock(198, 0, new Replacement(50, 5));
registry.registerBlock(198, 1, new Replacement(50, 5));
registry.registerBlock(198, 2, new Replacement(50, 4));
registry.registerBlock(198, 3, new Replacement(50, 3));
registry.registerBlock(198, 4, new Replacement(50, 2));
registry.registerBlock(198, 5, new Replacement(50, 1));
registry.registerBlock(204, new Replacement(43, 7));
registry.registerBlock(205, 0, new Replacement(44, 7));
registry.registerBlock(205, 8, new Replacement(44, 15));
registry.registerBlock(207, new Replacement(141));
registry.registerBlock(137, new Replacement(137, 0));
registry.registerItemBlock(199, new Replacement(35, 10, "Chorus Plant"));
registry.registerItemBlock(200, new Replacement(35, 2, "Chorus Flower"));
registry.registerItemBlock(201, new Replacement(155, 0, "Purpur Block"));
registry.registerItemBlock(202, new Replacement(155, 2, "Purpur Pillar"));
registry.registerItemBlock(203, 0, new Replacement(156, 0, "Purpur Stairs"));
registry.registerItemBlock(203, 1, new Replacement(156, 1, "Purpur Stairs"));
registry.registerItemBlock(203, 2, new Replacement(156, 2, "Purpur Stairs"));
registry.registerItemBlock(203, 3, new Replacement(156, 3, "Purpur Stairs"));
registry.registerItemBlock(203, 4, new Replacement(156, 4, "Purpur Stairs"));
registry.registerItemBlock(203, 5, new Replacement(156, 5, "Purpur Stairs"));
registry.registerItemBlock(203, 6, new Replacement(156, 6, "Purpur Stairs"));
registry.registerItemBlock(203, 7, new Replacement(156, 7, "Purpur Stairs"));
registry.registerItemBlock(203, 8, new Replacement(156, 8, "Purpur Stairs"));
registry.registerItemBlock(206, new Replacement(121, 0, "Endstone Bricks"));
registry.registerItemBlock(207, new Replacement(141, "Beetroot Block"));
registry.registerItemBlock(208, new Replacement(2, 0, "Grass Path"));
registry.registerItemBlock(209, new Replacement(90, "End Gateway"));
registry.registerItemBlock(210, new Replacement(137, 0, "Repeating Command Block"));
registry.registerItemBlock(211, new Replacement(137, 0, "Chain Command Block"));
registry.registerItemBlock(212, new Replacement(79, 0, "Frosted Ice"));
registry.registerItemBlock(214, new Replacement(87, 0, "Nether Wart Block"));
registry.registerItemBlock(215, new Replacement(112, 0, "Red Nether Brick"));
registry.registerItemBlock(217, new Replacement(166, 0, "Structure Void"));
registry.registerItemBlock(255, new Replacement(137, 0, "Structure Block"));
registry.registerItemBlock(397, 5, new Replacement(397, 0, "Dragon Head"));
}
public static Item replace(Item item) {
return registry.replace(item);
}
public static int replace(int raw) {
int data = BlockState.extractData(raw);
Replacement replace = registry.replace(BlockState.extractId(raw), data);
if (replace == null) return raw;
return BlockState.stateToRaw(replace.getId(), replace.replaceData(data));
}
public static Replacement getReplacement(int id, int data) {
return registry.replace(id, data);
}
}
@@ -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
@@ -18,7 +18,7 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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,15 +27,15 @@ import java.util.Optional;
public class MetaIndex1_8to1_9 {
private static final HashMap<Pair<Entity1_10Types.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
private final static HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
static {
for (MetaIndex index : MetaIndex.values())
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
private static Optional<MetaIndex> getIndex(Entity1_10Types.EntityType type, int index) {
Pair pair = new Pair<>(type, index);
private static Optional<MetaIndex> getIndex(EntityTypes1_10.EntityType type, int index) {
Pair<EntityTypes1_10.EntityType, Integer> pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
@@ -43,8 +43,8 @@ public class MetaIndex1_8to1_9 {
return Optional.empty();
}
public static MetaIndex searchIndex(Entity1_10Types.EntityType type, int index) {
Entity1_10Types.EntityType currentType = type;
public static MetaIndex searchIndex(EntityTypes1_10.EntityType type, int index) {
EntityTypes1_10.EntityType currentType = type;
do {
Optional<MetaIndex> optMeta = getIndex(currentType, index);
@@ -57,5 +57,4 @@ public class MetaIndex1_8to1_9 {
return null;
}
}
@@ -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
@@ -18,28 +18,56 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.items.ItemRewriter;
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.EntityTracker;
import com.viaversion.viaversion.api.minecraft.EulerAngle;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
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.protocols.protocol1_9to1_8.metadata.MetaIndex;
import com.viaversion.viarewind.ViaRewind;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MetadataRewriter {
public static void transform(Entity1_10Types.EntityType type, List<Metadata> list) {
private final Protocol1_8To1_9 protocol;
public MetadataRewriter(Protocol1_8To1_9 protocol) {
this.protocol = protocol;
}
public void transform(EntityTracker tracker, int entityId, List<Metadata> list) {
transform(tracker, entityId, list, tracker.getClientEntityTypes().get(entityId));
}
private static final byte HAND_ACTIVE_BIT = 0;
private static final byte STATUS_USE_BIT = 4;
public void transform(EntityTracker tracker, int entityId, List<Metadata> list, EntityType entityType) {
for (Metadata metadata : list) {
if (metadata.id() == MetaIndex.ENTITY_STATUS.getIndex()) {
tracker.getStatusInformation().put(entityId, (Byte) metadata.getValue());
}
}
for (Metadata entry : new ArrayList<>(list)) {
MetaIndex metaIndex = MetaIndex1_8to1_9.searchIndex(type, entry.id());
MetaIndex metaIndex = MetaIndex1_8to1_9.searchIndex(entityType, entry.id());
try {
if (metaIndex != null) {
if (metaIndex.getOldType() == MetaType1_8.NonExistent || metaIndex.getNewType()==null) {
if (metaIndex.getOldType() == MetaType1_8.NonExistent || metaIndex.getNewType() == null) {
list.remove(entry);
if (metaIndex == MetaIndex.PLAYER_HAND) {
byte status = tracker.getStatusInformation().getOrDefault(entityId, (byte) 0);
if ((((byte) entry.value()) & 1 << HAND_ACTIVE_BIT) != 0) {
status = (byte) (status | 1 << STATUS_USE_BIT);
} else {
status = (byte) (status & ~(1 << STATUS_USE_BIT));
}
list.add(new Metadata(MetaIndex.ENTITY_STATUS.getIndex(), MetaType1_8.Byte, status));
}
continue;
}
Object value = entry.getValue();
@@ -55,7 +83,7 @@ public class MetadataRewriter {
}
break;
case OptUUID:
if (metaIndex.getOldType()!=MetaType1_8.String) {
if (metaIndex.getOldType() != MetaType1_8.String) {
list.remove(entry);
break;
}
@@ -85,11 +113,11 @@ public class MetadataRewriter {
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));
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(ItemRewriter.toClient((Item) value));
entry.setValue(protocol.getItemRewriter().handleItemToClient((Item) value));
break;
case Position:
Vector vector = (Vector) value;
@@ -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
@@ -19,29 +19,25 @@
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.metadata.MetadataRewriter;
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.replacement.EntityReplacement;
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.Entity1_10Types;
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.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
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_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import com.viaversion.viaversion.util.Pair;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.items.ItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.util.RelativeMoveUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import java.util.ArrayList;
import java.util.List;
@@ -49,11 +45,7 @@ import java.util.UUID;
public class EntityPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
//Entity Status
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_STATUS, new PacketHandlers() {
@Override
public void register() {
@@ -81,10 +73,10 @@ public class EntityPackets {
int relZ = packetWrapper.read(Type.SHORT);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
replacement.relMove(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
replacement.handleOriginalMovementPacket(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
return;
}
@@ -97,7 +89,7 @@ public class EntityPackets {
boolean onGround = packetWrapper.passthrough(Type.BOOLEAN);
if (moves.length > 1) {
PacketWrapper secondPacket = PacketWrapper.create(0x15, null, packetWrapper.user());
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());
@@ -122,10 +114,10 @@ public class EntityPackets {
int relZ = packetWrapper.read(Type.SHORT);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
replacement.relMove(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
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;
}
@@ -140,14 +132,14 @@ public class EntityPackets {
byte pitch = packetWrapper.passthrough(Type.BYTE);
boolean onGround = packetWrapper.passthrough(Type.BOOLEAN);
Entity1_10Types.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.BOAT) {
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(0x17, null, packetWrapper.user());
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());
@@ -173,7 +165,7 @@ public class EntityPackets {
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
@@ -183,8 +175,8 @@ public class EntityPackets {
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
Entity1_10Types.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.BOAT) {
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);
@@ -221,8 +213,8 @@ public class EntityPackets {
create(Type.BOOLEAN, true);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
Entity1_10Types.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.BOAT) {
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);
@@ -277,7 +269,7 @@ public class EntityPackets {
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
@@ -298,7 +290,7 @@ public class EntityPackets {
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (tracker.getClientEntityTypes().containsKey(entityId)) {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityId), metadataList);
protocol.getMetadataRewriter().transform(tracker, entityId, metadataList);
if (metadataList.isEmpty()) wrapper.cancel();
} else {
tracker.addMetadataToBuffer(entityId, metadataList);
@@ -335,8 +327,8 @@ public class EntityPackets {
}
packetWrapper.write(Type.SHORT, (short) slot);
});
map(Type.ITEM);
handler(packetWrapper -> packetWrapper.set(Type.ITEM, 0, ItemRewriter.toClient(packetWrapper.get(Type.ITEM, 0))));
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToClient(packetWrapper.get(Type.ITEM1_8, 0))));
}
});
@@ -355,7 +347,7 @@ public class EntityPackets {
entityTracker.setPassengers(vehicle, passengers);
if (!oldPassengers.isEmpty()) {
for (Integer passenger : oldPassengers) {
PacketWrapper detach = PacketWrapper.create(0x1B, null, packetWrapper.user());
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);
@@ -365,7 +357,7 @@ public class EntityPackets {
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(0x1B, null, packetWrapper.user());
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);
@@ -390,8 +382,8 @@ public class EntityPackets {
map(Type.BOOLEAN);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
Entity1_10Types.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.BOAT) {
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);
@@ -407,7 +399,7 @@ public class EntityPackets {
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.INT, 0);
@@ -415,7 +407,7 @@ public class EntityPackets {
int z = packetWrapper.get(Type.INT, 2);
int yaw = packetWrapper.get(Type.BYTE, 0);
int pitch = packetWrapper.get(Type.BYTE, 1);
replacement.setLocation(x / 32.0, y / 32.0, z / 32.0);
replacement.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
@@ -436,16 +428,16 @@ public class EntityPackets {
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);
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);
packetWrapper.write(Type.VAR_INT, modifierSize);
} else {
removed++;
}
ArrayList<Pair<Byte, Double>> modifiers = new ArrayList<>();
for (int j = 0; j < modifiersize; j++) {
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);
@@ -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
@@ -18,27 +18,18 @@
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.Protocol;
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.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;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.items.ItemRewriter;
public class InventoryPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
//Confirm Transaction
//Close Window
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.CLOSE_WINDOW, new PacketHandlers() {
@Override
public void register() {
@@ -87,9 +78,9 @@ public class InventoryPackets {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
Item[] items = packetWrapper.read(Type.ITEM_ARRAY);
Item[] items = packetWrapper.read(Type.ITEM1_8_SHORT_ARRAY);
for (int i = 0; i < items.length; i++) {
items[i] = ItemRewriter.toClient(items[i]);
items[i] = protocol.getItemRewriter().handleItemToClient(items[i]);
}
if (windowId == 0 && items.length == 46) {
Item[] old = items;
@@ -106,7 +97,7 @@ public class InventoryPackets {
System.arraycopy(old, 5, items, 4, old.length - 5);
}
}
packetWrapper.write(Type.ITEM_ARRAY, items);
packetWrapper.write(Type.ITEM1_8_SHORT_ARRAY, items);
});
}
});
@@ -119,9 +110,9 @@ public class InventoryPackets {
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.SHORT);
map(Type.ITEM);
map(Type.ITEM1_8);
handler(packetWrapper -> {
packetWrapper.set(Type.ITEM, 0, ItemRewriter.toClient(packetWrapper.get(Type.ITEM, 0)));
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) {
@@ -135,16 +126,16 @@ public class InventoryPackets {
packetWrapper.set(Type.SHORT, 0, slot -= 1);
} else if (slot == 4) {
packetWrapper.cancel();
Windows.updateBrewingStand(packetWrapper.user(), packetWrapper.get(Type.ITEM, 0), windowId);
Windows.updateBrewingStand(packetWrapper.user(), packetWrapper.get(Type.ITEM1_8, 0), windowId);
} else {
packetWrapper.user().get(Windows.class).getBrewingItems(windowId)[slot] = packetWrapper.get(Type.ITEM, 0);
packetWrapper.user().get(Windows.class).getBrewingItems(windowId)[slot] = packetWrapper.get(Type.ITEM1_8, 0);
}
}
});
}
});
/* INCMOING */
/* INCOMING */
//Close Window
protocol.registerServerbound(ServerboundPackets1_8.CLOSE_WINDOW, new PacketHandlers() {
@@ -167,8 +158,8 @@ public class InventoryPackets {
map(Type.BYTE);
map(Type.SHORT);
map(Type.BYTE, Type.VAR_INT);
map(Type.ITEM);
handler(packetWrapper -> packetWrapper.set(Type.ITEM, 0, ItemRewriter.toServer(packetWrapper.get(Type.ITEM, 0))));
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);
@@ -184,16 +175,13 @@ public class InventoryPackets {
}
});
//Creative Inventory Action
protocol.registerServerbound(ServerboundPackets1_8.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT);
map(Type.ITEM);
handler(packetWrapper -> packetWrapper.set(Type.ITEM, 0, ItemRewriter.toServer(packetWrapper.get(Type.ITEM, 0))));
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToServer(packetWrapper.get(Type.ITEM1_8, 0))));
}
});
//Enchant 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
@@ -21,42 +21,32 @@ 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.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.Entity1_10Types;
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.Protocol;
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.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.items.ItemRewriter;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import java.util.ArrayList;
import java.util.UUID;
public class PlayerPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
public static void register(final Protocol1_8To1_9 protocol) {
//Animation
//Statistics
//Boss Bar
protocol.registerClientbound(ClientboundPackets1_9.BOSSBAR, null, new PacketHandlers() {
@Override
public void register() {
@@ -96,7 +86,7 @@ public class PlayerPackets {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
if (channel.equalsIgnoreCase("MC|TrList")) {
if (channel.equals("MC|TrList")) {
packetWrapper.passthrough(Type.INT); //Window Id
int size;
@@ -106,20 +96,22 @@ public class PlayerPackets {
size = packetWrapper.passthrough(Type.UNSIGNED_BYTE);
}
final ItemRewriter<?> itemRewriter = protocol.getItemRewriter();
for (int i = 0; i < size; i++) {
packetWrapper.write(Type.ITEM, ItemRewriter.toClient(packetWrapper.read(Type.ITEM))); //Buy Item 1
packetWrapper.write(Type.ITEM, ItemRewriter.toClient(packetWrapper.read(Type.ITEM))); //Buy Item 3
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.ITEM, ItemRewriter.toClient(packetWrapper.read(Type.ITEM))); //Buy Item 2
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")) {
} else if (channel.equals("MC|BOpen")) {
packetWrapper.read(Type.VAR_INT);
}
});
@@ -156,7 +148,7 @@ public class PlayerPackets {
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(), Entity1_10Types.EntityType.ENTITY_HUMAN);
tracker.getClientEntityTypes().put(tracker.getPlayerId(), EntityTypes1_10.EntityType.ENTITY_HUMAN);
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
@@ -254,7 +246,7 @@ public class PlayerPackets {
//Title
//Player List Header And Footer
/* INCMOING */
/* INCOMING */
//Chat Message
protocol.registerServerbound(ServerboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@@ -267,7 +259,7 @@ public class PlayerPackets {
packetWrapper.cancel();
PacketWrapper swapItems = PacketWrapper.create(0x13, null, packetWrapper.user());
swapItems.write(Type.VAR_INT, 6);
swapItems.write(Type.POSITION, new Position(0, 0, 0));
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);
@@ -306,7 +298,7 @@ public class PlayerPackets {
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while((animation = ((Protocol1_8To1_9)protocol).animationsToSend.poll()) != null) {
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
@@ -328,9 +320,8 @@ public class PlayerPackets {
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);
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);
@@ -353,7 +344,7 @@ public class PlayerPackets {
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while((animation = ((Protocol1_8To1_9)protocol).animationsToSend.poll()) != null) {
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
@@ -380,7 +371,7 @@ public class PlayerPackets {
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while((animation = ((Protocol1_8To1_9)protocol).animationsToSend.poll()) != null) {
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
@@ -418,7 +409,7 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.POSITION);
map(Type.POSITION1_8);
handler(packetWrapper -> {
int state = packetWrapper.get(Type.VAR_INT, 0);
if (state == 0) {
@@ -442,9 +433,9 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION);
map(Type.POSITION1_8);
map(Type.BYTE, Type.VAR_INT);
map(Type.ITEM, Type.NOTHING);
read(Type.ITEM1_8);
create(Type.VAR_INT, 0); //Main Hand
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
@@ -493,7 +484,7 @@ public class PlayerPackets {
null, packetWrapper.user());
delayedPacket.write(Type.VAR_INT, 0); //Main Hand
((Protocol1_8To1_9)protocol).animationsToSend.add(delayedPacket);
((Protocol1_8To1_9) protocol).animationsToSend.add(delayedPacket);
});
handler(packetWrapper -> {
packetWrapper.user().get(BlockPlaceDestroyTracker.class).updateMining();
@@ -538,7 +529,7 @@ public class PlayerPackets {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int playerId = tracker.getPlayerId();
int vehicle = tracker.getVehicle(playerId);
if (vehicle != -1 && tracker.getClientEntityTypes().get(vehicle) == Entity1_10Types.EntityType.BOAT) {
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);
@@ -554,7 +545,7 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION);
map(Type.POSITION1_8);
handler(packetWrapper -> {
for (int i = 0; i < 4; i++) {
packetWrapper.write(Type.STRING, ChatUtil.jsonToLegacy(packetWrapper.read(Type.COMPONENT)));
@@ -571,7 +562,7 @@ public class PlayerPackets {
public void register() {
map(Type.STRING);
handler(packetWrapper -> packetWrapper.write(Type.BOOLEAN, false));
map(Type.OPTIONAL_POSITION);
map(Type.OPTIONAL_POSITION1_8);
}
});
@@ -610,7 +601,7 @@ public class PlayerPackets {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
if (channel.equalsIgnoreCase("MC|BEdit") || channel.equalsIgnoreCase("MC|BSign")) {
if (channel.equals("MC|BEdit") || channel.equals("MC|BSign")) {
Item book = packetWrapper.passthrough(Type.ITEM);
book.setIdentifier(386);
CompoundTag tag = book.tag();
@@ -631,7 +622,7 @@ public class PlayerPackets {
page.setValue(value);
}
}
} else if (channel.equalsIgnoreCase("MC|AdvCdm")) {
} else if (channel.equals("MC|AdvCdm")) {
packetWrapper.set(Type.STRING, 0, channel = "MC|AdvCmd");
}
});
@@ -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
Loaded 100 of 138 files, more files were not shown because too many files have changed in this diff. Show more