Compare commits

..
99 Commits
Author SHA1 Message Date
FlorianMichael 901463e095 4.0.8 Release 2025-06-20 20:11:01 +02:00
FlorianMichael 227d37b2b9 Update VV api usage 2025-06-16 18:27:46 +02:00
FlorianMichael be5bb6e07c Write flags as byte in PLAYER_INPUT 1.8->1.7 2025-06-10 20:16:14 +02:00
Nassim Jahnke 064dbee920 Update profile properties type 2025-05-26 17:32:13 +02:00
FlorianMichael 783006baa5 Auto: Gradle 8.14.1 2025-05-22 17:51:04 +02:00
Adrian ba93a40d22 Change end rod block state mapping to white stained glass in 1.9->1.8 (#584) 2025-05-22 00:18:48 +02:00
dependabot[bot] 422f81dd2e Bump org.gradle.toolchains.foojay-resolver-convention (#583)
Bumps org.gradle.toolchains.foojay-resolver-convention from 0.10.0 to 1.0.0.

---
updated-dependencies:
- dependency-name: org.gradle.toolchains.foojay-resolver-convention
  dependency-version: 1.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 00:12:32 +02:00
FlorianMichael aa47e3c0a5 Update BaseProject 2025-05-19 00:12:39 +02:00
FlorianMichael 094298771e Update ClassTokenReplacer 2025-05-17 17:57:07 +02:00
FlorianMichael 66133d1ccc Update VV api usage 2025-05-17 15:37:37 +02:00
FlorianMichael 11011d59aa Rewrite build files 2025-05-15 15:28:44 +02:00
FlorianMichael 691cbf1b2a Small cleanup 2025-05-15 11:18:26 +02:00
EthanKeating 8d8675a891 Fix hologram movement by wrapping them to an interpolated entity in 1.8->1.7 (#580)
* Hologram movement fix for 1.7 clients

* fix: addressed feedback from PR review
2025-05-15 08:26:12 +02:00
Beanes 4fa2f10f3a Use correct entity id data type in 1.8->1.7 entity data sending (#579) 2025-05-08 20:24:50 +02:00
FlorianMichael c2e516dcd2 Auto: Gradle 8.14 2025-04-26 16:25:07 +02:00
BeanesandFlorianMichael 153eedd5eb Optimize memory usage for 1.7 chunk rewriting (#577)
* Optimize memory usage

* Bump version; cleanup code

---------

Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-04-22 23:52:39 +02:00
FlorianMichael 2d404608ee [ci skip] Reformat GH issue templates 2025-04-20 14:41:56 +02:00
FlorianMichael bbc1d77939 4.0.7 Release 2025-03-31 01:08:03 +02:00
dependabot[bot] fa36428391 Bump io.papermc.hangar-publish-plugin from 0.1.2 to 0.1.3 (#568)
Bumps io.papermc.hangar-publish-plugin from 0.1.2 to 0.1.3.

---
updated-dependencies:
- dependency-name: io.papermc.hangar-publish-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-29 14:47:08 +01:00
FlorianMichael b6dee43620 Update VV api usage 2025-03-29 14:46:44 +01:00
FlorianMichael 371c25f9d0 Update MCStructs to 3.0.0 2025-03-29 14:46:14 +01:00
FlorianMichael a41bbc2d67 4.0.6 Release 2025-03-28 19:07:24 +01:00
Nassim Jahnke de84a8fffc Replace deprecated class use 2025-03-26 13:47:29 +01:00
Nassim Jahnke 22ff1416c2 Fix serverbound container_close container types
Fixes #566
2025-03-13 13:58:14 +01:00
FlorianMichael 00b74ef2dd Update container id types 2025-03-12 18:31:20 +01:00
FlorianMichael 8d5b348318 Fix data field getting in ADD_ENTITY handler in 1.9->1.8 2025-03-09 01:06:11 +01:00
FlorianMichael 51f001ac3e Don't use -1 as indicator in EntityTracker1_9#getVehicle 2025-02-26 20:21:50 +01:00
FlorianMichael e27caba231 Cleanup code here and there 2025-02-25 21:40:03 +01:00
FlorianMichael 07aab015ea Auto: Gradle 8.13, .editorconfig 2025-02-25 18:44:28 +01:00
FlorianMichael 6bcf8d8895 Update ViaProxy, exclude run folder in .gitignore 2025-02-12 16:28:41 +01:00
FlorianMichael 43c42f44f6 Move handler names to the platform
As needs platform handling it should be directly exposed to the wrapper rather than being in the storage
2025-02-12 16:25:37 +01:00
FlorianMichael 295d87d49f Add functions to allow changing the handler names in TrackingCompressionHandlerProvider 2025-01-28 19:01:45 +01:00
FlorianMichael ab97e248da Auto: Gradle 8.12.1 2025-01-24 15:44:23 +01:00
FlorianMichael 276b9ba386 Update VV API usage 2025-01-10 22:44:59 +01:00
FlorianMichael 351ff79187 4.0.5 Release 2025-01-01 21:29:53 +01:00
FlorianMichael 87ed2160c9 Auto: 2025 2025-01-01 01:07:59 +01:00
FlorianMichael 668ed3c455 Auto: Gradle 8.12 2024-12-22 02:12:08 +01:00
FlorianMichael 3a0c742878 Auto: Migrate to setup-gradle action 2024-12-17 00:29:36 +01:00
FlorianMichael bc7b33f28a Handle unknown entity types correctly 2024-12-16 01:27:26 +01:00
FlorianMichael 657dcaa682 Do not persist credentials 2024-12-15 18:05:25 +01:00
FlorianMichael 3676906fbf Remove wiki.vg references 2024-12-13 22:50:24 +01:00
FlorianMichael dc9dbe9900 Bump version to 4.0.5-SNAPSHOT 2024-12-13 22:50:06 +01:00
FlorianMichael d8924485ac 4.0.4 Release 2024-12-06 16:34:00 +01:00
LeeGod b02a257383 Fix data loose in enchantment table item rewriting in 1.8->1.7 (#554) 2024-12-03 21:24:29 +01:00
FlorianMichael a4b666724f Use correct array type for reading passengers in 1.9->1.8
Closes https://github.com/ViaVersion/ViaRewind/issues/552
2024-11-27 21:51:25 +01:00
github-actions[bot]andgradle-update-robot e92b15c19f Update Gradle Wrapper from 8.11 to 8.11.1 (#551)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-11-24 02:04:41 +01:00
3fd2da9bf8 Update Gradle Wrapper from 8.10.2 to 8.11 (#549)
* Update Gradle Wrapper from 8.10.2 to 8.11

Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>

* Update Gradle API usage

---------

Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2024-11-14 23:28:48 +01:00
FlorianMichael ff4fbe2029 Bump version to 4.0.4-SNAPSHOT 2024-11-07 19:25:17 +01:00
Remigio c3d32874a7 Correct wrong name in plugin.yml (#548) 2024-11-07 19:24:04 +01:00
FlorianMichael 7b9888c758 [ci skip] Add gradle task to quickly test/debug code changes 2024-10-31 21:27:50 +01:00
FlorianMichael e0c05df633 [ci skip] Update version ranges in gradle.properties 2024-10-23 15:49:10 +02:00
FlorianMichael 3af661b256 4.0.3 Release 2024-10-14 17:26:28 +02:00
FlorianMichael 74ebb09ebc Update required ViaFabric version, don't require fabric-loader 2024-10-10 15:44:20 +02:00
FlorianMichael 36396c10b0 Define as Sponge plugin for ViaSponge 2024-10-03 18:59:02 +02:00
github-actions[bot]andgradle-update-robot bc9b84464b Update Gradle Wrapper from 8.10.1 to 8.10.2 (#544)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-09-29 04:21:22 +02:00
FlorianMichaelandBT (calcastor/mame) 0ee7c1cf16 Update correct entity data list in 1.8->1.7
Co-authored-by: "BT (calcastor/mame)" <43831917+calcastor@users.noreply.github.com>
2024-09-26 15:08:18 +02:00
dependabot[bot] 6d35536862 Bump gradle-update/update-gradle-wrapper-action from 1 to 2 (#542)
Bumps [gradle-update/update-gradle-wrapper-action](https://github.com/gradle-update/update-gradle-wrapper-action) from 1 to 2.
- [Release notes](https://github.com/gradle-update/update-gradle-wrapper-action/releases)
- [Changelog](https://github.com/gradle-update/update-gradle-wrapper-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/gradle-update/update-gradle-wrapper-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: gradle-update/update-gradle-wrapper-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-25 17:11:17 +02:00
FlorianMichael 8945193a8a Improve spectating client entity id tracking 2024-09-20 14:36:17 +02:00
FlorianMichael 546f4b14fa Add setting for player combat packet handling 2024-09-18 00:10:37 +02:00
FlorianMichael e8028cf446 Show player combat death message above hotbar in 1.9->1.8 2024-09-17 23:45:36 +02:00
FlorianMichael 6a85860132 Use RewriterBase API class for packet rewriter classes 2024-09-17 23:31:10 +02:00
FlorianMichael 4b11b8e1bb Fix client world get on level chunk packet in 1.8->1.7 2024-09-17 23:18:06 +02:00
FlorianMichael 724a6b7a4b Check if client entity id is set 2024-09-17 23:16:06 +02:00
FlorianMichael c785df5fc0 Refactor dimension switch handling 2024-09-15 22:20:36 +02:00
github-actions[bot]andgradle-update-robot de92c06dfd Update Gradle Wrapper from 8.10 to 8.10.1. (#541)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-09-15 09:55:02 +02:00
FlorianMichael 31f427a1b6 Cleanup LOGIN packet handlers 2024-08-25 21:44:17 +02:00
github-actions[bot]andgradle-update-robot fffcae9c0e Update Gradle Wrapper from 8.9 to 8.10. (#540)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2024-08-18 03:17:39 +02:00
FlorianMichael 594dbbcbe9 Only print broken components if suppression disabled 2024-08-13 04:54:38 +02:00
Clairton Santos 8c4efbbb13 Fix race condition when destroy entities on 1.7 (#539) 2024-08-11 02:46:18 +02:00
FlorianMichael 5b1dcf63d2 Add gradle wrapper update workflow 2024-08-07 00:03:39 +02:00
FlorianMichael beead5773c Update IDEA copyright configuration files 2024-08-05 19:51:47 +02:00
FlorianMichael 60a5c4ae2f Setup dependabot, cleanup build files 2024-08-05 19:48:46 +02:00
FlorianMichael d707e20b05 Bump version to 4.0.3-SNAPSHOT 2024-08-05 19:46:22 +02:00
FlorianMichael 14bad1d36f 4.0.2 Release 2024-07-28 16:36:21 +02:00
FlorianMichael 7a9bf5f465 Code cleanup 2024-07-25 18:23:45 +02:00
FlorianMichael f290af7b81 Deep copy items 2024-07-25 17:52:13 +02:00
FlorianMichael 064d0008f5 Keep entity data after respawn in 1.8->1.7 2024-07-25 17:28:04 +02:00
FlorianMichael fbe30d9da5 Cleanup build files
Delete not needed gradle.properties and moves the universal submodule to the root project
2024-07-21 19:43:38 +02:00
FlorianMichael 31490069ea Gradle 8.9 2024-07-14 20:31:37 +02:00
FlorianMichael 1b8d5eacc0 Print death message in chat 2024-07-12 01:53:45 +02:00
FlorianMichael abdb79598b Emulate PLAYER_COMBAT packet in 1.9->1.8 2024-07-12 01:27:33 +02:00
FlorianMichael 1b5b59317c Rename VREntityRewriter#removeEntities, move PLAYER_COMBAT to player packets 2024-07-12 00:59:58 +02:00
FlorianMichael 6e4ac65983 Update VB API usage 2024-07-06 21:20:23 +02:00
FlorianMichael 64cce82140 Properly skip entity data packets 2024-07-04 22:03:28 +02:00
FlorianMichael cb79316d6a Update potion mappings documentation 2024-07-04 00:03:47 +02:00
FlorianMichael 7d34c3838a Fix sign rewriting in 1.8->1.7 2024-07-04 00:03:35 +02:00
FlorianMichael c60152532d Only continue item rewriting if tag is present in 1.8->1.7 2024-06-29 22:59:22 +02:00
FlorianMichael 1894bac11b Fix nullable tag issues in 1.9->1.8 item rewriter 2024-06-29 22:57:59 +02:00
FlorianMichael a80ca442e5 Bump gradle wrapper validation to v3 2024-06-29 15:59:58 +02:00
FlorianMichael c69ce24d32 Only allow VB 5.0.0+ in fabric.mod.json 2024-06-29 15:26:54 +02:00
FlorianMichael e937a886ec Bump version to 4.0.2-SNAPSHOT 2024-06-27 18:21:39 +02:00
FlorianMichael 3e261824ef 4.0.1 Release 2024-06-27 18:13:39 +02:00
FlorianMichael 43c3bb11dc Skip metadata of entities which aren't spawned (yet) 2024-06-27 15:52:00 +02:00
FlorianMichael f57ac05bd4 Add setting for levitation emulation, cleanup code 2024-06-27 02:17:59 +02:00
FlorianMichael a3c623c202 Slightly improve wording in config.yml 2024-06-22 00:56:42 +02:00
FlorianMichael 481315f1e6 Cleanup code 2024-06-22 00:55:50 +02:00
FlorianMichael 21e50421e5 Rename Gradle convention plugin 2024-06-21 11:28:07 +02:00
FlorianMichael 233d52281b Add getter/setter for CooldownStorage#visualizationFactory
Allows servers to override the existing visualization factory with their own ones
2024-06-21 11:25:25 +02:00
FlorianMichael 6807a02de7 Bump version to 4.0.1-SNAPSHOT 2024-06-21 11:23:57 +02:00
122 changed files with 1462 additions and 1327 deletions

No files matched your search

+14 -2
View File
@@ -1,4 +1,16 @@
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = true
tab_width = 4
[*.java]
indent_style = tab
ij_java_class_count_to_use_import_on_demand = 999999
ij_java_names_count_to_use_import_on_demand = 999999
ij_java_imports_layout = *, |, $*
ij_java_generate_final_locals = true
ij_java_generate_final_parameters = true
[{*.json,*.yml}]
indent_size = 2
+1 -1
View File
@@ -1,2 +1,2 @@
github: FlorianMichael
custom: ['https://florianmichael.de/donate', 'https://viaversion.com/donate', 'https://creeper123123321.github.io/#donate']
custom: ['https://florianmichael.de/donate', 'https://creeper123123321.github.io/#donate']
+2 -2
View File
@@ -1,6 +1,6 @@
name: Bug report
description: Report a bug or console error
labels: [Unconfirmed]
labels: [ Unconfirmed ]
body:
- type: markdown
@@ -91,4 +91,4 @@ body:
- label: I have tried the latest build(s) from https://ci.viaversion.com/ and the issue still persists.
required: true
- label: I have looked at https://www.spigotmc.org/resources/viarewind-legacy-support.52924/ and it does not offer a fix for my problem
required: true
required: true
+18 -18
View File
@@ -5,34 +5,34 @@ labels: [ Feature Request ]
body:
- type: textarea
attributes:
label: Problem Description
description: |
Describe the issue you are facing or why you need the feature to be added.
placeholder: |
I am always frustrated with...
label: Problem Description
description: |
Describe the issue you are facing or why you need the feature to be added.
placeholder: |
I am always frustrated with...
validations:
required: true
required: true
- type: textarea
attributes:
label: Solution Description
description: |
Describe the solution you would like to see.
label: Solution Description
description: |
Describe the solution you would like to see.
validations:
required: true
required: true
- type: textarea
attributes:
label: Alternatives
description: |
Describe alternatives you have considered.
label: Alternatives
description: |
Describe alternatives you have considered.
validations:
required: false
required: false
- type: textarea
attributes:
label: Additional Info
description: |
Does the feature apply to any specific version or environment?
label: Additional Info
description: |
Does the feature apply to any specific version or environment?
validations:
required: false
required: false
+10
View File
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
+5 -12
View File
@@ -1,4 +1,4 @@
name: ViaRewind CI
name: Build
on: [pull_request, push, workflow_dispatch]
jobs:
@@ -7,22 +7,15 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Cache Dependencies
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build with Gradle
run: ./gradlew build
+4 -2
View File
@@ -12,8 +12,10 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
+18 -97
View File
@@ -1,113 +1,34 @@
### Java files ###
*.class
# Gradle
# Package Files
#*.jar
*.war
*.ear
.gradle/
build/
out/
classes/
.kotlin/
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Eclipse
*.launch
# Idea
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
# Ignore project files
.idea/
*.iml
# Ignore IDEA directory
.idea/*
# Include the project's dictionary
!.idea/dictionaries/
!.idea/dictionaries/*
# File-based project format:
*.ipr
*.iws
### Plugin-specific files: ###
# IntelliJ
/out/
# VSCode
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
.vscode/
bin/
.classpath
.project
# External tool builders
.externalToolBuilders/
# macOS
# Locally stored "Eclipse launch configurations"
*.launch
*.DS_Store
# CDT-specific
.cproject
# Misc
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
.nb-gradle/
### Git ###
# Don't exclude the .gitignore itself
!/.gitignore
run/
@@ -1,5 +1,5 @@
<component name="CopyrightManager">
<settings>
<settings default="viarewind-gpl">
<module2copyright>
<element module="ViaRewind" copyright="viarewind-gpl" />
</module2copyright>
+2 -2
View File
@@ -3,7 +3,7 @@
[![Build Status](https://github.com/ViaVersion/ViaRewind/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaRewind/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**ViaBackwards addon to allow 1.8.x and 1.7.x clients on newer server versions.** <br>
**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.
**You can override the included version in [ViaFabric](https://modrinth.com/mod/viafabric) or [ViaProxy](https://github.com/ViaVersion/ViaProxy):**
@@ -37,7 +37,7 @@ Other Links
Building
-
After cloning this repository, build the project with Gradle by running `./gradlew build` and take the created jar out
of the `universal/build/libs` directory.
of the `build/libs` directory.
You need JDK 17 or newer to build ViaRewind.
-7
View File
@@ -1,7 +0,0 @@
plugins {
id "groovy-gradle-plugin"
}
repositories {
gradlePluginPortal()
}
@@ -1,89 +0,0 @@
plugins {
id "java-library"
id "maven-publish"
}
repositories {
maven {
url = uri("https://repo.viaversion.com")
}
maven {
url = uri("https://repo.maven.apache.org/maven2/")
}
maven {
url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
}
maven {
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
}
maven {
url = uri("https://maven.fabricmc.net/")
}
maven {
url = uri("https://repo.spongepowered.org/repository/maven-public/")
}
maven {
url = uri("https://nexus.velocitypowered.com/repository/maven-public/")
}
}
dependencies {
compileOnly "com.viaversion:viaversion:${project.viaversion_version}"
compileOnly "com.viaversion:viabackwards:${project.viabackwards_version}"
compileOnly "io.netty:netty-all:${project.netty_version}"
compileOnly "com.google.guava:guava:${project.guava_version}"
}
base {
archivesName = project.maven_name
group = project.maven_group
version = project.maven_version
description = "ViaBackwards addon to allow 1.8.x and 1.7.x clients on newer server versions."
}
java.sourceCompatibility = JavaVersion.VERSION_17
tasks {
// Variable replacements
processResources {
for (final def file in ["plugin.yml", "fabric.mod.json"]) {
filesMatching(file) {
expand(
"version": project.version,
"description": project.description
)
}
}
}
}
publishing {
repositories {
maven {
name = "Via"
url = "https://repo.viaversion.com/"
credentials(PasswordCredentials)
authentication {
basic(BasicAuthentication)
}
}
}
publications {
main(MavenPublication) {
artifactId = project.maven_name
groupId = project.maven_group
version = project.maven_version
from(components.java)
}
}
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
tasks.withType(Javadoc) {
options.encoding = 'UTF-8'
}
+142
View File
@@ -0,0 +1,142 @@
import de.florianmichael.baseproject.*
plugins {
`java-library`
id("io.papermc.hangar-publish-plugin")
id("com.modrinth.minotaur")
id("de.florianmichael.baseproject.BaseProject")
}
allprojects {
setupProject()
setupViaPublishing()
repositories {
mavenCentral()
maven("https://repo.viaversion.com")
maven("https://repo.papermc.io/repository/maven-public")
maven("https://maven.fabricmc.net")
}
}
subprojects {
dependencies {
compileOnly("com.viaversion:viaversion:5.4.0")
compileOnly("com.viaversion:viabackwards:5.4.0")
}
tasks {
processResources {
val projectVersion = project.version
val projectDescription = project.description
filesMatching(listOf("plugin.yml", "fabric.mod.json", "META-INF/sponge_plugins.json")) {
expand("version" to projectVersion, "description" to projectDescription)
}
}
}
}
base {
archivesName.set("ViaRewind")
}
val shade = configureShadedDependencies()
dependencies {
subprojects.forEach {
shade(it)
}
}
tasks {
jar {
manifest {
attributes("paperweight-mappings-namespace" to "mojang")
}
}
}
val branch = branchName()
val baseVersion = version as String
val isRelease = !baseVersion.contains('-')
val isMainBranch = branch == "master"
if (!isRelease || isMainBranch) { // Only publish releases from the main branch
val suffixedVersion = if (isRelease) baseVersion else baseVersion + "+" + System.getenv("GITHUB_RUN_NUMBER")
val changelogContent = if (isRelease) {
"See [GitHub](https://github.com/ViaVersion/ViaRewind) for release notes."
} else {
val commitHash = latestCommitHash()
"[$commitHash](https://github.com/ViaVersion/ViaRewind/commit/$commitHash) ${latestCommitMessage()}"
}
modrinth {
val mcVersions: List<String> = (property("minecraft_versions") as String)
.split(",")
.map { it.trim() }
token.set(System.getenv("MODRINTH_TOKEN"))
projectId.set("viarewind")
versionType.set(if (isRelease) "release" else if (isMainBranch) "beta" else "alpha")
versionNumber.set(suffixedVersion)
versionName.set(suffixedVersion)
changelog.set(changelogContent)
uploadFile.set(tasks.jar.flatMap { it.archiveFile })
gameVersions.set(mcVersions)
loaders.add("fabric")
loaders.add("paper")
loaders.add("folia")
loaders.add("velocity")
autoAddDependsOn.set(false)
detectLoaders.set(false)
dependencies {
required.project("viaversion")
required.project("viabackwards")
optional.project("viafabric")
}
}
tasks.modrinth {
notCompatibleWithConfigurationCache("")
}
hangarPublish {
publications.register("plugin") {
version.set(suffixedVersion)
id.set("ViaRewind")
channel.set(if (isRelease) "Release" else if (isMainBranch) "Snapshot" else "Alpha")
changelog.set(changelogContent)
apiKey.set(System.getenv("HANGAR_TOKEN"))
platforms {
paper {
jar.set(tasks.jar.flatMap { it.archiveFile })
platformVersions.set(listOf(property("minecraft_version_range") as String))
dependencies {
hangar("ViaVersion") {
required = true
}
hangar("ViaBackwards") {
required = true
}
}
}
velocity {
jar.set(tasks.jar.flatMap { it.archiveFile })
platformVersions.set(listOf(property("velocity_version") as String))
dependencies {
hangar("ViaVersion") {
required = true
}
hangar("ViaBackwards") {
required = true
}
}
}
}
}
}
tasks.named("publishPluginPublicationToHangar") {
notCompatibleWithConfigurationCache("")
}
}
-9
View File
@@ -1,9 +0,0 @@
plugins {
id "com.viaversion.java-conventions"
}
dependencies {
api project(":viarewind-common")
compileOnly(annotationProcessor("org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT"))
}
+4
View File
@@ -0,0 +1,4 @@
dependencies {
compileOnly(project(":viarewind-common"))
compileOnly("org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT")
}
-1
View File
@@ -1 +0,0 @@
maven_name=viarewind-bukkit
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
+1 -1
View File
@@ -1,6 +1,6 @@
name: ViaRewind
main: com.viaversion.viarewind.BukkitPlugin
authors: [FlorianMichael/EnZaXD, Gerrygames, creeper123321123]
authors: [FlorianMichael/EnZaXD, Gerrygames, creeper123123321]
version: ${version}
description: ${description}
website: https://viaversion.com/rewind
-28
View File
@@ -1,28 +0,0 @@
plugins {
id "com.viaversion.java-conventions"
}
plugins {
id "net.raphimc.class-token-replacer" version "1.0.0"
}
dependencies {
}
sourceSets {
main {
classTokenReplacer {
property("\${version}", rootProject.maven_version)
property("\${impl_version}", "git-ViaRewind-${rootProject.maven_version}:${project.latestCommitHash()}")
}
}
}
String latestCommitHash() {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = stdout
}
return stdout.toString().trim()
}
+58
View File
@@ -0,0 +1,58 @@
import de.florianmichael.baseproject.*
plugins {
id("net.raphimc.class-token-replacer")
}
val viaProxy: Configuration by configurations.creating
dependencies {
compileOnly("io.netty:netty-all:4.0.20.Final")
compileOnly("com.google.guava:guava:17.0")
viaProxy("net.raphimc:ViaProxy:3.4.2-SNAPSHOT") {
isTransitive = false
}
}
sourceSets.configureEach {
classTokenReplacer {
replaceInPlace.set(true)
property("\${version}", project.version)
property("\${impl_version}", "git-ViaRewind-${project.version}:${latestCommitHash()}")
}
}
// Task to quickly test/debug code changes using https://github.com/ViaVersion/ViaProxy
// For further instructions see the ViaProxy repository README
val prepareViaProxyFiles by tasks.registering(Copy::class) {
dependsOn(project.tasks.jar)
from(project.tasks.jar.get().archiveFile.get().asFile)
into(layout.projectDirectory.dir("run/jars"))
val projectName = project.name
rename { "${projectName}.jar" }
}
val cleanupViaProxyFiles by tasks.registering(Delete::class) {
delete(
layout.projectDirectory.file("run/jars/${project.name}.jar"),
layout.projectDirectory.dir("run/logs")
)
}
tasks.register<JavaExec>("runViaProxy") {
dependsOn(prepareViaProxyFiles)
finalizedBy(cleanupViaProxyFiles)
mainClass.set("net.raphimc.viaproxy.ViaProxy")
classpath = viaProxy
workingDir = layout.projectDirectory.dir("run").asFile
jvmArgs = listOf("-DskipUpdateCheck")
if (System.getProperty("viaproxy.gui.autoStart") != null) {
jvmArgs("-Dviaproxy.gui.autoStart")
}
}
-1
View File
@@ -1 +0,0 @@
maven_name=viarewind-common
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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,6 +39,8 @@ public class ViaRewindConfig extends Config implements com.viaversion.viarewind.
private String worldBorderParticle;
private boolean enableOffhand;
private String offhandCommand;
private boolean emulateLevitationEffect;
private boolean handlePlayerCombatPacket;
public ViaRewindConfig(File configFile, Logger logger) {
super(configFile, logger);
@@ -61,6 +63,8 @@ public class ViaRewindConfig extends Config implements com.viaversion.viarewind.
worldBorderParticle = getString("world-border-particle", "fireworksSpark");
enableOffhand = getBoolean("enable-offhand", true);
offhandCommand = getString("offhand-command", "/offhand");
emulateLevitationEffect = getBoolean("emulate-levitation-effect", true);
handlePlayerCombatPacket = getBoolean("handle-player-combat-packet", true);
}
@Override
@@ -113,6 +117,16 @@ public class ViaRewindConfig extends Config implements com.viaversion.viarewind.
return offhandCommand;
}
@Override
public boolean emulateLevitationEffect() {
return emulateLevitationEffect;
}
@Override
public boolean handlePlayerCombatPacket() {
return handlePlayerCombatPacket;
}
@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) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -86,7 +86,7 @@ public interface ViaRewindConfig extends Config {
/**
* 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>)
* @return the particle name
*/
String getWorldBorderParticle();
@@ -103,4 +103,18 @@ public interface ViaRewindConfig extends Config {
* @return the offhand command
*/
String getOffhandCommand();
/**
* If enabled, 1.8 players on 1.9+ servers will also experience the levitation effect by sending velocity packets.
*
* @return true if enabled
*/
boolean emulateLevitationEffect();
/**
* If enabled, 1.8 players will handle the player combat packet added in 1.9 by showing the custom death message above the hotbar.
*
* @return true if enabled
*/
boolean handlePlayerCombatPacket();
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -70,4 +70,23 @@ public interface ViaRewindPlatform {
* @return data folder
*/
File getDataFolder();
/**
* Returns the platform's compression handler name. Only used in the 1.8 -> 1.7 protocol.
*
* @return the compression handler name
*/
default String compressHandlerName() {
return "compress";
}
/**
* Returns the platform's decompression handler name. Only used in the 1.8 -> 1.7 protocol.
*
* @return the decompression handler name
*/
default String decompressHandlerName() {
return "decompress";
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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,7 +21,7 @@ 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 byte[] blockLSBArray = new byte[ChunkSection.SIZE];
private final NibbleArray blockMetadataArray = new NibbleArray(this.blockLSBArray.length);
private final NibbleArray blockLightArray = new NibbleArray(this.blockLSBArray.length);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -25,7 +25,7 @@ import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_8;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
@@ -39,28 +39,23 @@ public abstract class VREntityRewriter<C extends ClientboundPacketType, T extend
super(protocol, displayType, displayVisibilityType);
}
protected void registerJoinGame1_8(final C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
protected void register() {
map(Types.INT); // Entity id
map(Types.UNSIGNED_BYTE); // Game mode
map(Types.BYTE); // Dimension
handler(playerTrackerHandler());
handler(wrapper -> wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Types.BYTE, 0)));
}
});
}
protected void untrackEntities(final UserConnection connection, final int[] entities) {
protected void removeEntities(final UserConnection connection, final int[] entities) {
final EntityTrackerBase tracker = tracker(connection);
for (int entityId : entities) {
tracker.removeEntity(entityId);
}
}
protected PacketHandler getDimensionHandler() {
return wrapper -> {
final int dimension = wrapper.get(Types.BYTE, 0);
final ClientWorld clientWorld = wrapper.user().getClientWorld(protocol.getClass());
clientWorld.setEnvironment(dimension);
};
}
@Override
protected Object getDisplayVisibilityMetaValue() {
protected Object getDisplayVisibilityDataValue() {
return (byte) 1;
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -47,4 +47,7 @@ public class RewindTypes {
public static final Type<Item> COMPRESSED_NBT_ITEM = new ItemType();
public static final Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType();
public static final Type<EntityData> ENTITY_DATA1_7 = new EntityDataType();
public static final Type<List<EntityData>> ENTITY_DATA_LIST1_7 = new EntityDataListType(ENTITY_DATA1_7);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -23,7 +23,6 @@ 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[]> {
@@ -42,18 +41,22 @@ public class BulkChunkType1_7_6 extends Type<Chunk[]> {
@Override
public void write(ByteBuf byteBuf, Chunk[] chunks) {
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];
final byte[][] dataArrays = new byte[chunkCount][];
int dataSize = 0;
for (int i = 0; i < chunkCount; i++) {
final Chunk chunk = chunks[i];
Pair<byte[], Short> chunkData;
try {
chunkData = ChunkType1_7_6.serialize(chunk);
output.write(chunkData.key());
final byte[] data = chunkData.key();
dataArrays[i] = data;
dataSize += data.length;
} catch (Exception e) {
throw new RuntimeException("Unable to serialize chunk", e);
}
@@ -62,7 +65,13 @@ public class BulkChunkType1_7_6 extends Type<Chunk[]> {
primaryBitMask[i] = (short) chunk.getBitmask();
additionalBitMask[i] = chunkData.value();
}
final byte[] data = output.toByteArray();
final byte[] data = new byte[dataSize];
int destPos = 0;
for (final byte[] array : dataArrays) {
System.arraycopy(array, 0, data, destPos, array.length);
destPos += array.length;
}
final Deflater deflater = new Deflater();
byte[] compressedData;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -23,10 +23,12 @@ 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;
import static com.viaversion.viaversion.api.minecraft.chunks.ChunkSection.SIZE;
import static com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionLight.LIGHT_LENGTH;
public class ChunkType1_7_6 extends Type<Chunk> {
public static final ChunkType1_7_6 TYPE = new ChunkType1_7_6();
@@ -94,29 +96,41 @@ public class ChunkType1_7_6 extends Type<Chunk> {
}
}
final ByteArrayOutputStream output = new ByteArrayOutputStream();
final boolean biomes = chunk.isFullChunk() && chunk.getBiomeData() != null;
final int totalSize = calculateSize(storageArrays, chunk.getBitmask(), biomes);
final byte[] output = new byte[totalSize];
int index = 0;
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0) {
output.write(storageArrays[i].getBlockLSBArray());
final byte[] blockLSBArray = storageArrays[i].getBlockLSBArray();
System.arraycopy(blockLSBArray, 0, output, index, blockLSBArray.length);
index += blockLSBArray.length;
}
}
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0) {
output.write(storageArrays[i].getBlockMetadataArray().getHandle());
final byte[] blockMetadataArray = storageArrays[i].getBlockMetadataArray().getHandle();
System.arraycopy(blockMetadataArray, 0, output, index, blockMetadataArray.length);
index += blockMetadataArray.length;
}
}
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0) {
output.write(storageArrays[i].getBlockLightArray().getHandle());
final byte[] blockLightArray = storageArrays[i].getBlockLightArray().getHandle();
System.arraycopy(blockLightArray, 0, output, index, blockLightArray.length);
index += blockLightArray.length;
}
}
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0 && storageArrays[i].getSkyLightArray() != null) {
output.write(storageArrays[i].getSkyLightArray().getHandle());
final byte[] skyLightArray = storageArrays[i].getSkyLightArray().getHandle();
System.arraycopy(skyLightArray, 0, output, index, skyLightArray.length);
index += skyLightArray.length;
}
}
@@ -124,16 +138,42 @@ public class ChunkType1_7_6 extends Type<Chunk> {
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());
final byte[] blockMSBArray = storageArrays[i].getOrCreateBlockMSBArray().getHandle();
System.arraycopy(blockMSBArray, 0, output, index, blockMSBArray.length);
index += blockMSBArray.length;
}
}
if (chunk.isFullChunk() && chunk.getBiomeData() != null) {
if (biomes) {
for (int biome : chunk.getBiomeData()) {
output.write(biome);
output[index++] = (byte) biome;
}
}
return new Pair<>(output.toByteArray(), additionalBitMask);
return new Pair<>(output, additionalBitMask);
}
private static int calculateSize(final ExtendedBlockStorage[] storageArrays, final int bitmask, final boolean biomes) {
int totalSize = 0;
for (int i = 0; i < storageArrays.length; i++) {
if ((bitmask & 1 << i) != 0) {
totalSize += SIZE; // Block lsb array
totalSize += SIZE / 2; // Block metadata array
totalSize += LIGHT_LENGTH; // Block light array
if (storageArrays[i].getSkyLightArray() != null) {
totalSize += LIGHT_LENGTH;
}
if (storageArrays[i].hasBlockMSBArray()) {
totalSize += SIZE / 2; // Block msb array
}
}
}
if (biomes) {
totalSize += 256;
}
return totalSize;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,15 +0,0 @@
package com.viaversion.viarewind.api.type.version;
import com.viaversion.viarewind.api.type.entitydata.EntityDataListType;
import com.viaversion.viarewind.api.type.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.type.Type;
import java.util.List;
public class Types1_7_6_10 {
public static final Type<EntityData> ENTITY_DATA = new EntityDataType();
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -17,7 +17,7 @@
*/
package com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5;
import com.viaversion.viarewind.api.type.version.Types1_7_6_10;
import com.viaversion.viarewind.api.type.RewindTypes;
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ServerboundPackets1_7_2_5;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
@@ -47,7 +47,7 @@ public class Protocol1_7_6_10To1_7_2_5 extends AbstractProtocol<ClientboundPacke
@Override
protected void registerPackets() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), new PacketHandlers() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_FINISHED, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING, REMOVE_DASHES); // Uuid
@@ -75,7 +75,7 @@ public class Protocol1_7_6_10To1_7_2_5 extends AbstractProtocol<ClientboundPacke
map(Types.BYTE); // Yaw
map(Types.BYTE); // Pitch
map(Types.SHORT); // Item in hand
map(Types1_7_6_10.ENTITY_DATA_LIST); // Entity data
map(RewindTypes.ENTITY_DATA_LIST1_7); // Entity data
}
});
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -61,11 +61,11 @@ public class Protocol1_8To1_7_6_10 extends BackwardsProtocol<ClientboundPackets1
itemRewriter.register();
entityRewriter.register();
PlayerPacketRewriter1_8.register(this);
ScoreboardPacketRewriter1_8.register(this);
WorldPacketRewriter1_8.register(this);
new PlayerPacketRewriter1_8(this).register();
new ScoreboardPacketRewriter1_8(this).register();
new WorldPacketRewriter1_8(this).register();
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketHandlers() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // server hash
@@ -73,7 +73,7 @@ public class Protocol1_8To1_7_6_10 extends BackwardsProtocol<ClientboundPackets1
map(Types.BYTE_ARRAY_PRIMITIVE, Types.SHORT_BYTE_ARRAY); // verification token
}
});
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_COMPRESSION.getId(), ClientboundLoginPackets.LOGIN_COMPRESSION.getId(), new PacketHandlers() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_COMPRESSION, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
@@ -92,7 +92,7 @@ public class Protocol1_8To1_7_6_10 extends BackwardsProtocol<ClientboundPackets1
}
});
this.registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketHandlers() {
this.registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY, new PacketHandlers() {
@Override
public void register() {
map(Types.SHORT_BYTE_ARRAY, Types.BYTE_ARRAY_PRIMITIVE); // shared secret
@@ -118,6 +118,7 @@ public class Protocol1_8To1_7_6_10 extends BackwardsProtocol<ClientboundPackets1
@Override
public void init(UserConnection connection) {
connection.addEntityTracker(this.getClass(), new EntityTracker1_8(connection));
connection.addClientWorld(this.getClass(), new ClientWorld());
connection.put(new InventoryTracker(connection));
connection.put(new PlayerSessionStorage(connection));
@@ -125,10 +126,6 @@ public class Protocol1_8To1_7_6_10 extends BackwardsProtocol<ClientboundPackets1
connection.put(new ScoreboardTracker(connection));
connection.put(new CompressionStatusTracker(connection));
connection.put(new WorldBorderEmulator(connection));
if (!connection.has(ClientWorld.class)) {
connection.put(new ClientWorld());
}
}
@Override
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -174,12 +174,8 @@ public enum EntityDataIndex1_7_6_10 {
}
private static Optional<EntityDataIndex1_7_6_10> getIndex(EntityType type, int index) {
Pair<EntityType, Integer> pair = new Pair<>(type, index);
if (ENTITY_DATA_REWRITES.containsKey(pair)) {
return Optional.of(ENTITY_DATA_REWRITES.get(pair));
}
return Optional.empty();
final Pair<EntityType, Integer> pair = new Pair<>(type, index);
return Optional.ofNullable(ENTITY_DATA_REWRITES.get(pair));
}
public EntityTypes1_8.EntityType getClazz() {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -17,13 +17,13 @@
*/
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.data;
import com.viaversion.viarewind.api.type.version.Types1_7_6_10;
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.Protocol1_8To1_7_6_10;
import com.viaversion.viarewind.api.minecraft.entitydata.EntityDataTypes1_7_6_10;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter.EntityPacketRewriter1_8;
import com.viaversion.viarewind.api.minecraft.math.AABB;
import com.viaversion.viarewind.api.minecraft.math.Vector3d;
import com.viaversion.viarewind.api.type.RewindTypes;
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.Protocol1_8To1_7_6_10;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter.EntityPacketRewriter1_8;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
@@ -33,293 +33,294 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.TrackedEntityImpl;
import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandlerEvent;
import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandlerEventImpl;
import java.util.ArrayList;
import java.util.List;
public class VirtualHologramEntity {
private final List<EntityData> entityDataTracker = new ArrayList<>();
private double locX, locY, locZ;
private final List<EntityData> entityDataTracker = new ArrayList<>();
private final UserConnection user;
private final int entityId;
private double locX, locY, locZ;
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;
private final UserConnection user;
private final int entityId;
public VirtualHologramEntity(final UserConnection user, final int entityId) {
this.user = user;
this.entityId = 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 void setPosition(final double x, final double y, final double z) {
if (x == this.locX && y == this.locY && z == this.locZ) return;
this.locX = x;
this.locY = y;
this.locZ = z;
public VirtualHologramEntity(final UserConnection user, final int entityId) {
this.user = user;
this.entityId = entityId;
}
updateLocation(false);
}
public void setPosition(final double x, final double y, final double z) {
if (x == this.locX && y == this.locY && z == this.locZ) return;
this.locX = x;
this.locY = y;
this.locZ = z;
public void setRelativePosition(final double x, final double y, final double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) return;
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation(false);
}
updateLocation(false);
}
public void setRelativePosition(final double x, final double y, final double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) return;
this.locX += x;
this.locY += y;
this.locZ += z;
public void setRotation(final float yaw, final float pitch) {
if (this.yaw == yaw || this.headYaw == yaw || this.pitch == pitch) return;
this.yaw = yaw;
this.headYaw = yaw;
this.pitch = pitch;
updateLocation(false);
}
updateLocation(false);
}
public void setRotation(final float yaw, final float pitch) {
if (this.yaw == yaw || this.headYaw == yaw || this.pitch == pitch) return;
this.yaw = yaw;
this.headYaw = yaw;
this.pitch = pitch;
public void setHeadYaw(float yaw) {
if (this.headYaw == yaw) return;
this.headYaw = yaw;
updateLocation(false);
}
updateLocation(false);
}
public void setHeadYaw(float yaw) {
if (this.headYaw == yaw) return;
this.headYaw = yaw;
public void syncState(final EntityPacketRewriter1_8 entityRewriter, final List<EntityData> entityDataList) {
// Merge entity data updates into current tracker
for (EntityData entityData : entityDataList) {
entityDataTracker.removeIf(m -> m.id() == entityData.id());
entityDataTracker.add(entityData);
}
updateLocation(false);
}
// Filter armor stand data to calculate emulation
byte flags = 0;
byte armorStandFlags = 0;
for (EntityData entityData : entityDataTracker) {
if (entityData.id() == 0 && entityData.dataType() == EntityDataTypes1_8.BYTE) {
flags = ((Number) entityData.getValue()).byteValue();
} else if (entityData.id() == 2 && entityData.dataType() == EntityDataTypes1_8.STRING) {
name = entityData.getValue().toString();
if (name != null && name.isEmpty()) name = null;
} else if (entityData.id() == 10 && entityData.dataType() == EntityDataTypes1_8.BYTE) {
armorStandFlags = ((Number) entityData.getValue()).byteValue();
}
}
final boolean invisible = (flags & 0x20) != 0;
small = (armorStandFlags & 0x01) != 0;
marker = (armorStandFlags & 0x10) != 0;
public void syncState(final EntityPacketRewriter1_8 entityRewriter, final List<EntityData> entityDataList) {
// Merge entity data updates into current tracker
for (EntityData entityData : entityDataList) {
entityDataTracker.removeIf(m -> m.id() == entityData.id());
entityDataTracker.add(entityData);
}
State prevState = currentState;
if (invisible && name != null) {
currentState = State.HOLOGRAM;
} else {
currentState = State.ZOMBIE;
}
// Filter armor stand data to calculate emulation
byte flags = 0;
byte armorStandFlags = 0;
for (EntityData entityData : entityDataTracker) {
if (entityData.id() == 0 && entityData.dataType() == EntityDataTypes1_8.BYTE) {
flags = ((Number) entityData.getValue()).byteValue();
} else if (entityData.id() == 2 && entityData.dataType() == EntityDataTypes1_8.STRING) {
name = entityData.getValue().toString();
if (name != null && name.isEmpty()) name = null;
} else if (entityData.id() == 10 && entityData.dataType() == EntityDataTypes1_8.BYTE) {
armorStandFlags = ((Number) entityData.getValue()).byteValue();
}
}
final boolean invisible = (flags & 0x20) != 0;
small = (armorStandFlags & 0x01) != 0;
marker = (armorStandFlags & 0x10) != 0;
if (currentState != prevState) {
deleteEntity();
sendSpawnPacket(entityRewriter);
} else {
sendEntityDataUpdate(entityRewriter);
updateLocation(false);
}
}
State prevState = currentState;
if (invisible && name != null) {
currentState = State.HOLOGRAM;
} else {
currentState = State.ZOMBIE;
}
private void updateLocation(final boolean remount) {
if (entityIds == null) {
return;
}
if (currentState == State.ZOMBIE) {
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
if (currentState != prevState) {
deleteEntity();
sendSpawnPacket(entityRewriter);
} else {
sendEntityDataUpdate(entityRewriter);
updateLocation(false);
}
}
final PacketWrapper entityHeadLook = PacketWrapper.create(ClientboundPackets1_7_2_5.ROTATE_HEAD, user);
private void updateLocation(final boolean remount) {
if (entityIds == null) {
return;
}
if (currentState == State.ZOMBIE) {
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
entityHeadLook.write(Types.INT, entityId);
entityHeadLook.write(Types.BYTE, (byte) ((headYaw / 360f) * 256));
final PacketWrapper entityHeadLook = PacketWrapper.create(ClientboundPackets1_7_2_5.ROTATE_HEAD, user);
entityHeadLook.send(Protocol1_8To1_7_6_10.class);
} else if (currentState == State.HOLOGRAM) {
if (remount) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_LINK, user);
detach.write(Types.INT, entityIds[1]);
detach.write(Types.INT, -1);
detach.write(Types.BOOLEAN, false);
detach.send(Protocol1_8To1_7_6_10.class);
}
entityHeadLook.write(Types.INT, entityId);
entityHeadLook.write(Types.BYTE, (byte) ((headYaw / 360f) * 256));
// Don't ask me where this offset is coming from
teleportEntity(entityIds[0], locX, (locY + (marker ? 54.3625 : small ? 56 : 57) - 0.16), locZ, 0, 0); // Skull
entityHeadLook.send(Protocol1_8To1_7_6_10.class);
} else if (currentState == State.HOLOGRAM) {
if (remount) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_LINK, user);
detach.write(Types.INT, entityIds[1]);
detach.write(Types.INT, -1);
detach.write(Types.BOOLEAN, false);
detach.send(Protocol1_8To1_7_6_10.class);
}
if (remount) {
teleportEntity(entityIds[1], locX, locY + 56.75, locZ, 0, 0); // Horse
// 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
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_LINK, null, user);
attach.write(Types.INT, entityIds[1]);
attach.write(Types.INT, entityIds[0]);
attach.write(Types.BOOLEAN, false);
attach.send(Protocol1_8To1_7_6_10.class);
}
}
}
if (remount) {
teleportEntity(entityIds[1], locX, locY + 56.75, locZ, 0, 0); // Horse
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.TELEPORT_ENTITY, user);
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_LINK, null, user);
attach.write(Types.INT, entityIds[1]);
attach.write(Types.INT, entityIds[0]);
attach.write(Types.BOOLEAN, false);
attach.send(Protocol1_8To1_7_6_10.class);
}
}
}
entityTeleport.write(Types.INT, entityId); // entity id
entityTeleport.write(Types.INT, (int) (x * 32.0)); // x
entityTeleport.write(Types.INT, (int) (y * 32.0)); // y
entityTeleport.write(Types.INT, (int) (z * 32.0)); // z
entityTeleport.write(Types.BYTE, (byte) ((yaw / 360f) * 256)); // yaw
entityTeleport.write(Types.BYTE, (byte) ((pitch / 360f) * 256)); // pitch
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.TELEPORT_ENTITY, user);
entityTeleport.send(Protocol1_8To1_7_6_10.class);
}
entityTeleport.write(Types.INT, entityId); // entity id
entityTeleport.write(Types.INT, (int) (x * 32.0)); // x
entityTeleport.write(Types.INT, (int) (y * 32.0)); // y
entityTeleport.write(Types.INT, (int) (z * 32.0)); // z
entityTeleport.write(Types.BYTE, (byte) ((yaw / 360f) * 256)); // yaw
entityTeleport.write(Types.BYTE, (byte) ((pitch / 360f) * 256)); // pitch
protected void spawnEntity(final int entityId, final int type, final double locX, final double locY, final double locZ, final List<EntityData> entityData) {
final PacketWrapper addMob = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_MOB, user);
entityTeleport.send(Protocol1_8To1_7_6_10.class);
}
addMob.write(Types.VAR_INT, entityId); // Entity id
addMob.write(Types.UNSIGNED_BYTE, (short) type); // Entity type
addMob.write(Types.INT, (int) (locX * 32.0)); // X
addMob.write(Types.INT, (int) (locY * 32.0)); // Y
addMob.write(Types.INT, (int) (locZ * 32.0)); // Z
addMob.write(Types.BYTE, (byte) 0); // Yaw
addMob.write(Types.BYTE, (byte) 0); // Pitch
addMob.write(Types.BYTE, (byte) 0); // Head pitch
addMob.write(Types.SHORT, (short) 0); // Velocity x
addMob.write(Types.SHORT, (short) 0); // Velocity y
addMob.write(Types.SHORT, (short) 0); // Velocity z
addMob.write(RewindTypes.ENTITY_DATA_LIST1_7, entityData); // Entity data
protected void spawnEntity(final int entityId, final int type, final double locX, final double locY, final double locZ) {
final PacketWrapper addMob = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_MOB, user);
addMob.send(Protocol1_8To1_7_6_10.class);
}
addMob.write(Types.VAR_INT, entityId); // Entity id
addMob.write(Types.UNSIGNED_BYTE, (short) type); // Entity type
addMob.write(Types.INT, (int) (locX * 32.0)); // X
addMob.write(Types.INT, (int) (locY * 32.0)); // Y
addMob.write(Types.INT, (int) (locZ * 32.0)); // Z
addMob.write(Types.BYTE, (byte) 0); // Yaw
addMob.write(Types.BYTE, (byte) 0); // Pitch
addMob.write(Types.BYTE, (byte) 0); // Head pitch
addMob.write(Types.SHORT, (short) 0); // Velocity x
addMob.write(Types.SHORT, (short) 0); // Velocity y
addMob.write(Types.SHORT, (short) 0); // Velocity z
addMob.write(Types1_7_6_10.ENTITY_DATA_LIST, new ArrayList<>()); // Entity data
public void sendEntityDataUpdate(final EntityPacketRewriter1_8 entityRewriter) {
if (entityIds == null) {
return;
}
final PacketWrapper setEntityData = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_DATA, user);
addMob.send(Protocol1_8To1_7_6_10.class);
}
if (currentState == State.ZOMBIE) {
writeZombieMeta(entityRewriter, setEntityData);
} else if (currentState == State.HOLOGRAM) {
writeHologramMeta(setEntityData);
} else {
return;
}
setEntityData.send(Protocol1_8To1_7_6_10.class);
}
public void sendEntityDataUpdate(final EntityPacketRewriter1_8 entityRewriter) {
if (entityIds == null) {
return;
}
final PacketWrapper setEntityData = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_DATA, user);
private void writeZombieMeta(final EntityPacketRewriter1_8 entityRewriter, final PacketWrapper wrapper) {
wrapper.write(Types.INT, entityIds[0]);
if (currentState == State.ZOMBIE) {
writeZombieMeta(entityRewriter, setEntityData);
} else if (currentState == State.HOLOGRAM) {
writeHologramMeta(setEntityData);
} else {
return;
}
setEntityData.send(Protocol1_8To1_7_6_10.class);
}
// Filter entity data sent by the server and convert them together with our custom entity data
final List<EntityData> entityDataList = new ArrayList<>();
for (EntityData entityData : entityDataTracker) {
// Remove non existent entityData
if (entityData.id() < 0 || entityData.id() > 9) {
continue;
}
entityDataList.add(new EntityData(entityData.id(), entityData.dataType(), entityData.getValue()));
}
if (small) {
entityDataList.add(new EntityData(12, EntityDataTypes1_8.BYTE, (byte) 1));
}
private void writeZombieMeta(final EntityPacketRewriter1_8 entityRewriter, PacketWrapper wrapper) {
wrapper.write(Types.INT, entityIds[0]);
// Push entity data from the server through entity data conversion 1.7->1.8
for (EntityData entityData : entityDataList.toArray(new EntityData[0])) {
final EntityDataHandlerEvent event = new EntityDataHandlerEventImpl(wrapper.user(), new TrackedEntityImpl(EntityTypes1_8.EntityType.ZOMBIE), -1, entityData, entityDataList);
try {
entityRewriter.handleEntityData(event, entityData);
} catch (Exception e) {
entityDataList.remove(entityData);
break;
}
if (event.cancelled()) {
entityDataList.remove(entityData);
break;
}
}
wrapper.write(RewindTypes.ENTITY_DATA_LIST1_7, entityDataList);
}
// Filter entity data sent by the server and convert them together with our custom entity data
final List<EntityData> entityDataList = new ArrayList<>();
for (EntityData entityData : entityDataTracker) {
// Remove non existent entityData
if (entityData.id() < 0 || entityData.id() > 9) {
continue;
}
entityDataList.add(new EntityData(entityData.id(), entityData.dataType(), entityData.getValue()));
}
if (small) {
entityDataList.add(new EntityData(12, EntityDataTypes1_8.BYTE, (byte) 1));
}
private void writeHologramMeta(PacketWrapper wrapper) {
wrapper.write(Types.INT, entityIds[1]);
// Push entity data from the server through entity data conversion 1.7->1.8
for (EntityData entityData : entityDataList.toArray(new EntityData[0])) {
final EntityDataHandlerEvent event = new EntityDataHandlerEventImpl(wrapper.user(), new TrackedEntityImpl(EntityTypes1_8.EntityType.ZOMBIE), -1, entityData, entityDataList);
try {
entityRewriter.handleEntityData(event, entityData);
} catch (Exception e) {
entityDataList.remove(entityData);
break;
}
if (event.cancelled()) {
entityDataList.remove(entityData);
break;
}
}
wrapper.write(Types1_7_6_10.ENTITY_DATA_LIST, entityDataList);
}
// Directly write 1.7 entity data here since we are making them up
final List<EntityData> entityDataList = new ArrayList<>();
entityDataList.add(new EntityData(EntityDataIndex1_7_6_10.ABSTRACT_AGEABLE_AGE.getIndex(), EntityDataTypes1_7_6_10.INT, -1700000));
entityDataList.add(new EntityData(EntityDataIndex1_7_6_10.LIVING_ENTITY_BASE_NAME_TAG.getIndex(), EntityDataTypes1_7_6_10.STRING, name));
entityDataList.add(new EntityData(EntityDataIndex1_7_6_10.LIVING_ENTITY_BASE_NAME_TAG_VISIBILITY.getIndex(), EntityDataTypes1_7_6_10.BYTE, (byte) 1));
private void writeHologramMeta(PacketWrapper wrapper) {
wrapper.write(Types.INT, entityIds[1]);
wrapper.write(RewindTypes.ENTITY_DATA_LIST1_7, entityDataList);
}
// Directly write 1.7 entity data here since we are making them up
final List<EntityData> entityDataList = new ArrayList<>();
entityDataList.add(new EntityData(EntityDataIndex1_7_6_10.ABSTRACT_AGEABLE_AGE.getIndex(), EntityDataTypes1_7_6_10.INT, -1700000));
entityDataList.add(new EntityData(EntityDataIndex1_7_6_10.LIVING_ENTITY_BASE_NAME_TAG.getIndex(), EntityDataTypes1_7_6_10.STRING, name));
entityDataList.add(new EntityData(EntityDataIndex1_7_6_10.LIVING_ENTITY_BASE_NAME_TAG_VISIBILITY.getIndex(), EntityDataTypes1_7_6_10.BYTE, (byte) 1));
public void sendSpawnPacket(final EntityPacketRewriter1_8 entityRewriter) {
if (entityIds != null) {
deleteEntity();
}
if (currentState == State.ZOMBIE) {
spawnEntity(entityId, EntityTypes1_8.EntityType.ZOMBIE.getId(), locX, locY, locZ, new ArrayList<>());
wrapper.write(Types1_7_6_10.ENTITY_DATA_LIST, entityDataList);
}
entityIds = new int[]{entityId};
} else if (currentState == State.HOLOGRAM) {
final int[] entityIds = {entityId, additionalEntityId()};
public void sendSpawnPacket(final EntityPacketRewriter1_8 entityRewriter) {
if (entityIds != null) {
deleteEntity();
}
if (currentState == State.ZOMBIE) {
spawnEntity(entityId, EntityTypes1_8.EntityType.ZOMBIE.getId(), locX, locY, locZ);
final PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_ENTITY, user);
spawnSkull.write(Types.VAR_INT, entityIds[0]);
spawnSkull.write(Types.BYTE, (byte) 66);
spawnSkull.write(Types.INT, (int) (locX * 32.0));
spawnSkull.write(Types.INT, (int) (locY * 32.0));
spawnSkull.write(Types.INT, (int) (locZ * 32.0));
spawnSkull.write(Types.BYTE, (byte) 0);
spawnSkull.write(Types.BYTE, (byte) 0);
spawnSkull.write(Types.INT, 0);
spawnSkull.send(Protocol1_8To1_7_6_10.class);
entityIds = new int[]{entityId};
} else if (currentState == State.HOLOGRAM) {
final int[] entityIds = { entityId, additionalEntityId() };
final List<EntityData> squidEntityData = new ArrayList<>();
squidEntityData.add(new EntityData(0, EntityDataTypes1_8.BYTE, (byte) 32));
final PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_ENTITY, user);
spawnSkull.write(Types.VAR_INT, entityIds[0]);
spawnSkull.write(Types.BYTE, (byte) 66);
spawnSkull.write(Types.INT, (int) (locX * 32.0));
spawnSkull.write(Types.INT, (int) (locY * 32.0));
spawnSkull.write(Types.INT, (int) (locZ * 32.0));
spawnSkull.write(Types.BYTE, (byte) 0);
spawnSkull.write(Types.BYTE, (byte) 0);
spawnSkull.write(Types.INT, 0);
spawnSkull.send(Protocol1_8To1_7_6_10.class);
spawnEntity(entityIds[0], EntityTypes1_8.EntityType.SQUID.getId(), locX, locY, locZ, squidEntityData);
spawnEntity(entityIds[1], EntityTypes1_8.EntityType.HORSE.getId(), locX, locY, locZ, new ArrayList<>());
spawnEntity(entityIds[1], EntityTypes1_8.EntityType.HORSE.getId(), locX, locY, locZ); // Horse
this.entityIds = entityIds;
}
this.entityIds = entityIds;
}
sendEntityDataUpdate(entityRewriter);
updateLocation(true);
}
sendEntityDataUpdate(entityRewriter);
updateLocation(true);
}
public AABB getBoundingBox() {
final double width = this.small ? 0.25 : 0.5;
final double height = this.small ? 0.9875 : 1.975;
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);
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);
}
return new AABB(min, max);
}
private int additionalEntityId() {
return Integer.MAX_VALUE - 16000 - entityId;
}
private int additionalEntityId() {
return Integer.MAX_VALUE - 16000 - entityId;
}
public void deleteEntity() {
if (entityIds == null) {
return;
}
final PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.REMOVE_ENTITIES, user);
despawn.write(Types.BYTE, (byte) entityIds.length);
for (int id : entityIds) {
despawn.write(Types.INT, id);
}
entityIds = null;
despawn.send(Protocol1_8To1_7_6_10.class);
}
public void deleteEntity() {
if (entityIds == null) {
return;
}
final PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.REMOVE_ENTITIES, user);
despawn.write(Types.BYTE, (byte) entityIds.length);
for (int id : entityIds) {
despawn.write(Types.INT, id);
}
entityIds = null;
despawn.send(Protocol1_8To1_7_6_10.class);
}
private enum State {
HOLOGRAM, ZOMBIE
}
private enum State {
HOLOGRAM, ZOMBIE
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -17,6 +17,7 @@
*/
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.minecraft.netty.EmptyChannelHandler;
import com.viaversion.viarewind.api.minecraft.netty.ForwardMessageToByteEncoder;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.CompressionHandlerProvider;
@@ -26,15 +27,13 @@ import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
public class TrackingCompressionHandlerProvider extends CompressionHandlerProvider {
public static final String COMPRESS_HANDLER_NAME = "compress";
public static final 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));
pipeline.addBefore(Via.getManager().getInjector().getEncoderName(), ViaRewind.getPlatform().compressHandlerName(), getEncoder(threshold));
pipeline.addBefore(Via.getManager().getInjector().getDecoderName(), ViaRewind.getPlatform().decompressHandlerName(), getDecoder(threshold));
} else {
setCompressionEnabled(user, true); // We need to remove compression for 1.7 clients
}
@@ -47,12 +46,9 @@ public class TrackingCompressionHandlerProvider extends CompressionHandlerProvid
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 (pipeline.get(ViaRewind.getPlatform().compressHandlerName()) != null) {
compressor = ViaRewind.getPlatform().compressHandlerName();
decompressor = ViaRewind.getPlatform().decompressHandlerName();
}
if (compressor != null) { // We can neutralize the effect of compressor to the client
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -57,7 +57,7 @@ public class BlockItemPacketRewriter1_8 extends VRBlockItemRewriter<ClientboundP
wrapper.write(Types.UNSIGNED_BYTE, windowTypeId); // Window type id
final JsonElement titleComponent = wrapper.read(Types.COMPONENT); // Title
String title = ChatUtil.jsonToLegacy(wrapper.user(), titleComponent);
String title = ChatUtil.jsonToLegacy(titleComponent);
title = ChatUtil.removeUnusedColor(title, '8');
if (title.length() > 32) {
title = title.substring(0, 32);
@@ -81,11 +81,11 @@ public class BlockItemPacketRewriter1_8 extends VRBlockItemRewriter<ClientboundP
protocol.registerClientbound(ClientboundPackets1_8.CONTAINER_SET_SLOT, new PacketHandlers() {
@Override
public void register() {
map(Types.UNSIGNED_BYTE); // Window id
map(Types.BYTE); // Window id
map(Types.SHORT); // Slot
handler(wrapper -> {
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Types.UNSIGNED_BYTE, 0));
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Types.BYTE, 0));
final short slot = wrapper.get(Types.SHORT, 0);
if (windowType == 4) { // Enchantment Table
if (slot == 1) {
@@ -100,7 +100,7 @@ public class BlockItemPacketRewriter1_8 extends VRBlockItemRewriter<ClientboundP
handler(wrapper -> handleItemToClient(wrapper.user(), wrapper.get(RewindTypes.COMPRESSED_NBT_ITEM, 0)));
handler(wrapper -> {
final short windowId = wrapper.get(Types.UNSIGNED_BYTE, 0);
final byte windowId = wrapper.get(Types.BYTE, 0);
if (windowId != 0) {
return;
}
@@ -134,7 +134,7 @@ public class BlockItemPacketRewriter1_8 extends VRBlockItemRewriter<ClientboundP
Item[] old = items;
items = new Item[old.length - 1];
items[0] = old[0];
System.arraycopy(old, 2, items, 1, old.length - 3);
System.arraycopy(old, 2, items, 1, old.length - 2);
}
for (int i = 0; i < items.length; i++) {
items[i] = handleItemToClient(wrapper.user(), items[i]);
@@ -224,7 +224,7 @@ public class BlockItemPacketRewriter1_8 extends VRBlockItemRewriter<ClientboundP
});
protocol.registerServerbound(ServerboundPackets1_7_2_5.CONTAINER_CLOSE, wrapper -> {
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
final byte windowId = wrapper.passthrough(Types.BYTE);
wrapper.user().get(InventoryTracker.class).remove(windowId);
});
@@ -232,10 +232,10 @@ public class BlockItemPacketRewriter1_8 extends VRBlockItemRewriter<ClientboundP
protocol.registerServerbound(ServerboundPackets1_7_2_5.CONTAINER_CLICK, new PacketHandlers() {
@Override
public void register() {
map(Types.BYTE, Types.UNSIGNED_BYTE); // Window id
map(Types.BYTE); // Window id
map(Types.SHORT); // Slot
handler(wrapper -> {
final short windowId = wrapper.get(Types.UNSIGNED_BYTE, 0); // Window id
final byte windowId = wrapper.get(Types.BYTE, 0); // Window id
final short slot = wrapper.get(Types.SHORT, 0);
final short windowType = wrapper.user().get(InventoryTracker.class).get(windowId);
@@ -277,9 +277,8 @@ public class BlockItemPacketRewriter1_8 extends VRBlockItemRewriter<ClientboundP
super.handleItemToClient(connection, item);
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
if (tag == null) return item;
enchantmentRewriter.handleToClient(item);
if (item.identifier() == 387) {
@@ -292,7 +291,7 @@ public class BlockItemPacketRewriter1_8 extends VRBlockItemRewriter<ClientboundP
for (StringTag page : pages) {
final String value = page.getValue();
oldPages.add(new StringTag(value));
page.setValue(ChatUtil.jsonToLegacy(connection, value));
page.setValue(ChatUtil.jsonToLegacy(value));
}
}
return item;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -23,7 +23,6 @@ import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.VREntityRewriter;
import com.viaversion.viarewind.api.type.RewindTypes;
import com.viaversion.viarewind.api.minecraft.entitydata.EntityDataTypes1_7_6_10;
import com.viaversion.viarewind.api.type.version.Types1_7_6_10;
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.Protocol1_8To1_7_6_10;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.data.EntityDataIndex1_7_6_10;
@@ -33,7 +32,6 @@ import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.GameProfileStora
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.ScoreboardTracker;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
@@ -42,7 +40,6 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandlerEvent;
import com.viaversion.viaversion.util.IdAndData;
@@ -70,6 +67,7 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
read(Types.BOOLEAN); // Reduced debug info
handler(playerTrackerHandler());
handler(getDimensionHandler());
handler(wrapper -> {
final int entityId = wrapper.get(Types.INT, 0);
@@ -81,9 +79,8 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_7_6_10.class);
tracker.addPlayer(entityId, wrapper.user().getProtocolInfo().getUuid());
tracker.setClientEntityGameMode(wrapper.get(Types.UNSIGNED_BYTE, 0));
wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Types.BYTE, 0));
tracker.setClientEntityGameMode(wrapper.get(Types.UNSIGNED_BYTE, 0));
// Reset on Velocity server change
wrapper.user().put(new ScoreboardTracker(wrapper.user()));
@@ -92,7 +89,7 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
});
protocol.registerClientbound(ClientboundPackets1_8.REMOVE_ENTITIES, wrapper -> {
final int[] entities = wrapper.read(Types.VAR_INT_ARRAY_PRIMITIVE);
untrackEntities(wrapper.user(), entities);
removeEntities(wrapper.user(), entities);
wrapper.cancel();
@@ -102,23 +99,28 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
for (List<Integer> part : parts) {
final PacketWrapper destroy = PacketWrapper.create(ClientboundPackets1_7_2_5.REMOVE_ENTITIES, wrapper.user());
destroy.write(RewindTypes.INT_ARRAY, part.stream().mapToInt(Integer::intValue).toArray());
destroy.scheduleSend(Protocol1_8To1_7_6_10.class);
destroy.send(Protocol1_8To1_7_6_10.class);
}
});
protocol.registerClientbound(ClientboundPackets1_8.SET_ENTITY_DATA, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT, Types.INT); // Entity id
map(Types1_8.ENTITY_DATA_LIST, Types1_7_6_10.ENTITY_DATA_LIST); // Entity data
map(Types.ENTITY_DATA_LIST1_8, RewindTypes.ENTITY_DATA_LIST1_7); // Entity data
handler(wrapper -> {
final EntityTracker1_8 tracker = tracker(wrapper.user());
final int entityId = wrapper.get(Types.INT, 0);
final List<EntityData> entityData = wrapper.get(Types1_7_6_10.ENTITY_DATA_LIST, 0);
final List<EntityData> entityData = wrapper.get(RewindTypes.ENTITY_DATA_LIST1_7, 0);
if (tracker.getHolograms().containsKey(entityId)) {
wrapper.cancel();
tracker.getHolograms().get(entityId).syncState(EntityPacketRewriter1_8.this, entityData);
} else {
} else if (tracker.hasEntity(entityId)) {
handleEntityData(entityId, entityData, wrapper.user());
} else {
wrapper.cancel();
}
if (tracker.clientEntityId() == entityId) {
tracker.updateEntityData(entityData);
}
});
}
@@ -141,7 +143,11 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
handler(wrapper -> {
final int entityId = wrapper.get(Types.VAR_INT, 0);
final EntityTypes1_8.EntityType type = EntityTypes1_8.getTypeFromId(wrapper.get(Types.BYTE, 0), true);
int data = wrapper.get(Types.INT, 3);
final EntityTypes1_8.EntityType type = EntityTypes1_8.ObjectType.getEntityType(wrapper.get(Types.BYTE, 0), data);
if (type == null) {
return;
}
int x = wrapper.get(Types.INT, 0);
int y = wrapper.get(Types.INT, 1);
@@ -150,8 +156,6 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
byte pitch = wrapper.get(Types.BYTE, 1);
byte yaw = wrapper.get(Types.BYTE, 2);
int data = wrapper.get(Types.INT, 3);
if (type == EntityTypes1_8.ObjectType.ITEM_FRAME.getType()) {
yaw = switch (yaw) {
case -128 -> {
@@ -180,7 +184,7 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
hologram.setPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(yaw * 360f / 256);
} else if (type != null && type.isOrHasParent(EntityTypes1_8.EntityType.FALLING_BLOCK)) {
} else if (type.isOrHasParent(EntityTypes1_8.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
final IdAndData replace = protocol.getItemRewriter().handleBlock(blockId, blockData);
@@ -252,7 +256,7 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
map(Types.SHORT); // Velocity x
map(Types.SHORT); // Velocity y
map(Types.SHORT); // Velocity z
map(Types1_8.ENTITY_DATA_LIST, Types1_7_6_10.ENTITY_DATA_LIST); // Entity data
map(Types.ENTITY_DATA_LIST1_8, RewindTypes.ENTITY_DATA_LIST1_7); // Entity data
handler(getTrackerHandler(Types.UNSIGNED_BYTE, 0));
@@ -260,7 +264,7 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
handler(wrapper -> {
final short typeId = wrapper.get(Types.UNSIGNED_BYTE, 0);
final EntityTypes1_8.EntityType type = EntityTypes1_8.getTypeFromId(typeId, false);
final EntityTypes1_8.EntityType type = EntityTypes1_8.EntityType.findById(typeId);
if (type == EntityTypes1_8.EntityType.ARMOR_STAND) {
wrapper.cancel();
final int entityId = wrapper.get(Types.VAR_INT, 0);
@@ -278,10 +282,10 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
hologram.setPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(headYaw * 360f / 256);
hologram.syncState(protocol().getEntityRewriter(), wrapper.get(Types1_7_6_10.ENTITY_DATA_LIST, 0));
hologram.syncState(protocol().getEntityRewriter(), wrapper.get(RewindTypes.ENTITY_DATA_LIST1_7, 0));
}
});
handler(getMobSpawnRewriter(Types1_7_6_10.ENTITY_DATA_LIST));
handler(getMobSpawnRewriter(RewindTypes.ENTITY_DATA_LIST1_7));
}
});
protocol.registerClientbound(ClientboundPackets1_8.ADD_PLAYER, new PacketHandlers() {
@@ -331,9 +335,9 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
map(Types.BYTE); // Yaw
map(Types.BYTE); // Pitch
map(Types.SHORT); // Current item
map(Types1_8.ENTITY_DATA_LIST, Types1_7_6_10.ENTITY_DATA_LIST); // Entity data
map(Types.ENTITY_DATA_LIST1_8, RewindTypes.ENTITY_DATA_LIST1_7); // Entity data
handler(getTrackerAndMetaHandler(Types1_7_6_10.ENTITY_DATA_LIST, EntityTypes1_8.EntityType.PLAYER));
handler(getTrackerAndDataHandler(RewindTypes.ENTITY_DATA_LIST1_7, EntityTypes1_8.EntityType.PLAYER));
}
});
protocol.registerClientbound(ClientboundPackets1_8.SET_EQUIPPED_ITEM, new PacketHandlers() {
@@ -691,11 +695,11 @@ public class EntityPacketRewriter1_8 extends VREntityRewriter<ClientboundPackets
@Override
public EntityTypes1_8.EntityType typeFromId(int type) {
return EntityTypes1_8.getTypeFromId(type, false);
return EntityTypes1_8.EntityType.findById(type);
}
@Override
public EntityTypes1_8.EntityType objectTypeFromId(int type) {
return EntityTypes1_8.getTypeFromId(type, true);
public EntityTypes1_8.EntityType objectTypeFromId(int type, int data) {
return EntityTypes1_8.ObjectType.getEntityType(type, data);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -30,12 +30,11 @@ import com.viaversion.viarewind.api.minecraft.math.Ray3d;
import com.viaversion.viarewind.api.minecraft.math.RayTracing;
import com.viaversion.viarewind.api.minecraft.math.Vector3d;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8;
import com.viaversion.viaversion.api.minecraft.GameProfile;
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.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.nbt.tag.CompoundTag;
@@ -51,11 +50,17 @@ import io.netty.buffer.Unpooled;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class PlayerPacketRewriter1_8 {
public class PlayerPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10> {
public static void register(Protocol1_8To1_7_6_10 protocol) {
public PlayerPacketRewriter1_8(Protocol1_8To1_7_6_10 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_8.CHAT, new PacketHandlers() {
@Override
public void register() {
@@ -101,15 +106,26 @@ public class PlayerPacketRewriter1_8 {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_7_6_10.class);
tracker.setClientEntityGameMode(wrapper.get(Types.UNSIGNED_BYTE, 1));
final Environment dimension = Environment.getEnvironmentById(wrapper.get(Types.INT, 0));
final int dimension = wrapper.get(Types.INT, 0);
// Clear entities on dimension change and re-track player
final ClientWorld world = wrapper.user().get(ClientWorld.class);
if (world.getEnvironment() != dimension) {
world.setEnvironment(dimension.id());
final ClientWorld world = wrapper.user().getClientWorld(Protocol1_8To1_7_6_10.class);
if (world.setEnvironment(dimension)) {
tracker.clearEntities();
tracker.addEntity(tracker.clientEntityId(), EntityTypes1_8.EntityType.PLAYER);
tracker.addPlayer(tracker.clientEntityId(), wrapper.user().getProtocolInfo().getUuid());
}
wrapper.send(Protocol1_8To1_7_6_10.class);
wrapper.cancel();
if (tracker.getEntityData().isEmpty()) {
return;
}
// 1.8 clients do keep entity data after respawn, 1.7 clients don't
final PacketWrapper setEntityData = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_DATA, wrapper.user());
setEntityData.write(Types.INT, tracker.clientEntityId());
setEntityData.write(RewindTypes.ENTITY_DATA_LIST1_7, tracker.getEntityData());
setEntityData.send(Protocol1_8To1_7_6_10.class);
});
}
});
@@ -149,7 +165,7 @@ public class PlayerPacketRewriter1_8 {
wrapper.write(Types.BOOLEAN, playerSession.onGround);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_7_6_10.class);
if (tracker.spectatingClientEntityId != tracker.clientEntityId()) {
if (!Objects.equals(tracker.spectatingClientEntityId, tracker.clientEntityIdOrNull())) {
wrapper.cancel();
}
});
@@ -225,13 +241,10 @@ public class PlayerPacketRewriter1_8 {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) gameProfile = gameProfileStorage.put(uuid, name);
int propertyCount = wrapper.read(Types.VAR_INT);
while (propertyCount-- > 0) {
String propertyName = wrapper.read(Types.STRING);
String propertyValue = wrapper.read(Types.STRING);
String propertySignature = wrapper.read(Types.OPTIONAL_STRING);
gameProfile.properties.add(new GameProfileStorage.Property(propertyName, propertyValue, propertySignature));
}
GameProfile.Property[] properties = wrapper.read(Types.PROFILE_PROPERTY_ARRAY);
for (GameProfile.Property property : properties) {
gameProfile.properties.add(new GameProfileStorage.Property(property.name(), property.value(), property.signature()));
}
int gamemode = wrapper.read(Types.VAR_INT);
int ping = wrapper.read(Types.VAR_INT);
@@ -239,7 +252,7 @@ public class PlayerPacketRewriter1_8 {
gameProfile.gamemode = gamemode;
JsonElement displayName = wrapper.read(Types.OPTIONAL_COMPONENT);
if (displayName != null) {
gameProfile.setDisplayName(ChatUtil.jsonToLegacy(wrapper.user(), displayName));
gameProfile.setDisplayName(ChatUtil.jsonToLegacy(displayName));
}
final PacketWrapper playerInfo = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, wrapper.user());
@@ -302,7 +315,7 @@ public class PlayerPacketRewriter1_8 {
packet.scheduleSend(Protocol1_8To1_7_6_10.class);
} else if (action == 3) {
JsonElement displayNameComponent = wrapper.read(Types.OPTIONAL_COMPONENT);
String displayName = displayNameComponent != null ? ChatUtil.jsonToLegacy(wrapper.user(), displayNameComponent) : null;
String displayName = displayNameComponent != null ? ChatUtil.jsonToLegacy(displayNameComponent) : null;
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null || gameProfile.displayName == null && displayName == null) continue;
@@ -445,6 +458,7 @@ public class PlayerPacketRewriter1_8 {
});
protocol.cancelClientbound(ClientboundPackets1_8.TAB_LIST);
protocol.cancelClientbound(ClientboundPackets1_8.PLAYER_COMBAT);
protocol.registerClientbound(ClientboundPackets1_8.RESOURCE_PACK, ClientboundPackets1_7_2_5.CUSTOM_PAYLOAD, new PacketHandlers() {
@Override
@@ -640,10 +654,10 @@ public class PlayerPacketRewriter1_8 {
handler(wrapper -> {
final boolean jump = wrapper.read(Types.BOOLEAN);
final boolean unmount = wrapper.read(Types.BOOLEAN);
short flags = 0;
byte flags = 0;
if (jump) flags += 0x01;
if (unmount) flags += 0x02;
wrapper.write(Types.UNSIGNED_BYTE, flags);
wrapper.write(Types.BYTE, flags);
if (!unmount) {
return;
@@ -664,7 +678,7 @@ public class PlayerPacketRewriter1_8 {
protocol.registerServerbound(ServerboundPackets1_7_2_5.SIGN_UPDATE, new PacketHandlers() {
@Override
public void register() {
map(Types.BLOCK_POSITION1_8, RewindTypes.SHORT_POSITION); // Position
map(RewindTypes.SHORT_POSITION, Types.BLOCK_POSITION1_8); // Position
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
final String line = wrapper.read(Types.STRING);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -22,6 +22,7 @@ import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.Protocol1_8To1_7_6_10;
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.ScoreboardTracker;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
import com.viaversion.viaversion.util.ChatColorUtil;
@@ -30,9 +31,14 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class ScoreboardPacketRewriter1_8 {
public class ScoreboardPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10> {
public static void register(Protocol1_8To1_7_6_10 protocol) {
public ScoreboardPacketRewriter1_8(Protocol1_8To1_7_6_10 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_8.SET_OBJECTIVE, wrapper -> {
String name = wrapper.passthrough(Types.STRING);
if (name.length() > 16) {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -28,6 +28,7 @@ import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.FixedByteArrayType;
import com.viaversion.viaversion.api.type.types.chunk.BulkChunkType1_8;
@@ -37,11 +38,16 @@ import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_
import com.viaversion.viaversion.util.ChatColorUtil;
import com.viaversion.viaversion.util.IdAndData;
public class WorldPacketRewriter1_8 {
public class WorldPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10> {
public static void register(Protocol1_8To1_7_6_10 protocol) {
public WorldPacketRewriter1_8(Protocol1_8To1_7_6_10 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_8.LEVEL_CHUNK, wrapper -> {
final ClientWorld world = wrapper.user().get(ClientWorld.class);
final ClientWorld world = wrapper.user().getClientWorld(Protocol1_8To1_7_6_10.class);
final Chunk chunk = wrapper.read(ChunkType1_8.forEnvironment(world.getEnvironment()));
protocol.getItemRewriter().handleChunk(chunk);
@@ -173,7 +179,7 @@ public class WorldPacketRewriter1_8 {
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
String line = wrapper.read(Types.STRING);
line = ChatUtil.jsonToLegacy(wrapper.user(), line);
line = ChatUtil.jsonToLegacy(line);
line = ChatUtil.removeUnusedColor(line, '0');
if (line.length() > 15) {
@@ -263,7 +269,6 @@ public class WorldPacketRewriter1_8 {
});
protocol.cancelClientbound(ClientboundPackets1_8.CHANGE_DIFFICULTY);
protocol.cancelClientbound(ClientboundPackets1_8.PLAYER_COMBAT);
protocol.registerClientbound(ClientboundPackets1_8.SET_BORDER, null, wrapper -> {
final WorldBorderEmulator emulator = wrapper.user().get(WorldBorderEmulator.class);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -24,6 +24,8 @@ import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.data.VirtualHologramEnti
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
@@ -35,149 +37,177 @@ import com.viaversion.viaversion.libs.fastutil.objects.Object2IntMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntOpenHashMap;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.logging.Level;
public class EntityTracker1_8 extends EntityTrackerBase {
private final Int2ObjectMap<VirtualHologramEntity> holograms = new Int2ObjectArrayMap<>();
private final Int2IntMap vehicles = new Int2IntArrayMap();
private final Int2ObjectMap<UUID> entityIdToUUID = new Int2ObjectArrayMap<>();
private final Object2IntMap<UUID> entityUUIDToId = new Object2IntOpenHashMap<>();
private final Int2ObjectMap<VirtualHologramEntity> holograms = new Int2ObjectArrayMap<>();
private final Int2IntMap vehicles = new Int2IntArrayMap();
private final Int2ObjectMap<UUID> entityIdToUUID = new Int2ObjectArrayMap<>();
private final Object2IntMap<UUID> entityUUIDToId = new Object2IntOpenHashMap<>();
public int spectatingClientEntityId = -1;
private int clientEntityGameMode;
private final List<EntityData> entityData = new ArrayList<>();
public EntityTracker1_8(UserConnection connection) {
super(connection, EntityTypes1_8.EntityType.PLAYER);
}
public Integer spectatingClientEntityId;
private int clientEntityGameMode;
@Override
public void addEntity(int id, EntityType type) {
super.addEntity(id, type);
if (type == EntityTypes1_8.EntityType.ARMOR_STAND) {
holograms.put(id, new VirtualHologramEntity(user(), id));
}
}
public EntityTracker1_8(UserConnection connection) {
super(connection, EntityTypes1_8.EntityType.PLAYER);
}
@Override
public void removeEntity(int entityId) {
super.removeEntity(entityId);
@Override
public void addEntity(int id, EntityType type) {
super.addEntity(id, type);
if (type == EntityTypes1_8.EntityType.ARMOR_STAND) {
holograms.put(id, new VirtualHologramEntity(user(), id));
}
}
if (entityIdToUUID.containsKey(entityId)) {
final UUID playerId = entityIdToUUID.remove(entityId);
@Override
public void removeEntity(int entityId) {
super.removeEntity(entityId);
entityUUIDToId.removeInt(playerId);
user().get(PlayerSessionStorage.class).getPlayerEquipment().remove(playerId);
}
}
final VirtualHologramEntity hologram = holograms.get(entityId);
if (hologram != null) {
hologram.deleteEntity();
holograms.remove(entityId);
}
@Override
public void clearEntities() {
super.clearEntities();
vehicles.clear();
}
if (entityIdToUUID.containsKey(entityId)) {
final UUID playerId = entityIdToUUID.remove(entityId);
@Override
public void setClientEntityId(int entityId) {
if (this.spectatingClientEntityId == this.clientEntityId()) {
this.spectatingClientEntityId = entityId;
}
super.setClientEntityId(entityId);
}
entityUUIDToId.removeInt(playerId);
user().get(PlayerSessionStorage.class).getPlayerEquipment().remove(playerId);
}
}
public void addPlayer(final int entityId, final UUID uuid) {
entityUUIDToId.put(uuid, entityId);
entityIdToUUID.put(entityId, uuid);
}
@Override
public void clearEntities() {
super.clearEntities();
vehicles.clear();
}
public UUID getPlayerUUID(final int entityId) {
return entityIdToUUID.get(entityId);
}
@Override
public void setClientEntityId(int entityId) {
if (Objects.equals(this.spectatingClientEntityId, clientEntityIdOrNull())) {
this.spectatingClientEntityId = entityId;
}
super.setClientEntityId(entityId);
}
public int getPlayerEntityId(final UUID uuid) {
return entityUUIDToId.getOrDefault(uuid, -1);
}
public Integer clientEntityIdOrNull() {
return this.hasClientEntityId() ? this.clientEntityId() : null;
}
public int getVehicle(final int passengerId) {
for (Map.Entry<Integer, Integer> vehicle : vehicles.entrySet()) {
if (vehicle.getValue() == passengerId) {
return vehicle.getValue();
}
}
return -1;
}
public void addPlayer(final int entityId, final UUID uuid) {
entityUUIDToId.put(uuid, entityId);
entityIdToUUID.put(entityId, uuid);
}
public int getPassenger(int vehicleId) {
return vehicles.getOrDefault(vehicleId, -1);
}
public UUID getPlayerUUID(final int entityId) {
return entityIdToUUID.get(entityId);
}
protected void startSneaking() {
try {
final PacketWrapper entityAction = PacketWrapper.create(ServerboundPackets1_7_2_5.PLAYER_COMMAND, user());
entityAction.write(Types.VAR_INT, this.clientEntityId()); // Entity id
entityAction.write(Types.VAR_INT, 0); // Action id
entityAction.write(Types.VAR_INT, 0); // Jump boost
public int getPlayerEntityId(final UUID uuid) {
return entityUUIDToId.getOrDefault(uuid, -1);
}
entityAction.sendToServer(Protocol1_8To1_7_6_10.class);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send sneak packet", e);
}
}
public int getVehicle(final int passengerId) {
for (Map.Entry<Integer, Integer> vehicle : vehicles.int2IntEntrySet()) {
if (vehicle.getValue() == passengerId) {
return vehicle.getValue();
}
}
return -1;
}
public void setPassenger(final int vehicleId, final int passengerId) {
if (vehicleId == this.spectatingClientEntityId && this.spectatingClientEntityId != this.clientEntityId()) {
startSneaking();
setSpectating(this.clientEntityId());
}
public int getPassenger(int vehicleId) {
return vehicles.getOrDefault(vehicleId, -1);
}
if (vehicleId == -1) {
vehicles.remove(getVehicle(passengerId));
} else if (passengerId == -1) {
vehicles.remove(vehicleId);
} else {
vehicles.put(vehicleId, passengerId);
}
}
protected void startSneaking() {
try {
final PacketWrapper entityAction = PacketWrapper.create(ServerboundPackets1_7_2_5.PLAYER_COMMAND, user());
entityAction.write(Types.VAR_INT, this.clientEntityId()); // Entity id
entityAction.write(Types.VAR_INT, 0); // Action id
entityAction.write(Types.VAR_INT, 0); // Jump boost
protected void attachEntity(final int target) {
try {
final PacketWrapper attachEntity = PacketWrapper.create(ClientboundPackets1_8.SET_ENTITY_LINK, user());
attachEntity.write(Types.INT, this.clientEntityId()); // vehicle id
attachEntity.write(Types.INT, target); // passenger id
attachEntity.write(Types.BOOLEAN, false); // leash
entityAction.sendToServer(Protocol1_8To1_7_6_10.class);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send sneak packet", e);
}
}
attachEntity.scheduleSend(Protocol1_8To1_7_6_10.class);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send attach packet", e);
}
}
public void setPassenger(final int vehicleId, final int passengerId) {
if (vehicleId == this.spectatingClientEntityId && this.spectatingClientEntityId != this.clientEntityId()) {
startSneaking();
setSpectating(this.clientEntityId());
}
public void setSpectating(int spectating) {
if (spectating != this.clientEntityId() && getPassenger(spectating) != -1) {
startSneaking();
setSpectating(this.clientEntityId());
return;
}
if (this.spectatingClientEntityId != spectating && this.spectatingClientEntityId != this.clientEntityId()) {
attachEntity(-1);
}
this.spectatingClientEntityId = spectating;
if (spectating != this.clientEntityId()) {
attachEntity(this.spectatingClientEntityId);
}
}
if (vehicleId == -1) {
vehicles.remove(getVehicle(passengerId));
} else if (passengerId == -1) {
vehicles.remove(vehicleId);
} else {
vehicles.put(vehicleId, passengerId);
}
}
public Int2ObjectMap<VirtualHologramEntity> getHolograms() {
return holograms;
}
protected void attachEntity(final int target) {
try {
final PacketWrapper attachEntity = PacketWrapper.create(ClientboundPackets1_8.SET_ENTITY_LINK, user());
attachEntity.write(Types.INT, this.clientEntityId()); // vehicle id
attachEntity.write(Types.INT, target); // passenger id
attachEntity.write(Types.BOOLEAN, false); // leash
public boolean isSpectator() {
return clientEntityGameMode == 3;
}
attachEntity.scheduleSend(Protocol1_8To1_7_6_10.class);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send attach packet", e);
}
}
public void setSpectating(int spectating) {
if (spectating != this.clientEntityId() && getPassenger(spectating) != -1) {
startSneaking();
setSpectating(this.clientEntityId());
return;
}
if (this.spectatingClientEntityId != spectating && this.spectatingClientEntityId != this.clientEntityId()) {
attachEntity(-1);
}
this.spectatingClientEntityId = spectating;
if (spectating != this.clientEntityId()) {
attachEntity(this.spectatingClientEntityId);
}
}
public Int2ObjectMap<VirtualHologramEntity> getHolograms() {
return holograms;
}
public boolean isSpectator() {
return clientEntityGameMode == 3;
}
public void setClientEntityGameMode(int clientEntityGameMode) {
this.clientEntityGameMode = clientEntityGameMode;
}
public void updateEntityData(List<EntityData> entityData) {
this.entityData.removeIf(first -> entityData.stream().anyMatch(second -> first.id() == second.id()));
for (final EntityData data : entityData) {
final Object value = data.value();
if (value instanceof Item item) {
this.entityData.add(new EntityData(data.id(), data.dataType(), item.copy()));
} else {
this.entityData.add(new EntityData(data.id(), data.dataType(), value));
}
}
}
public List<EntityData> getEntityData() {
return entityData;
}
public void setClientEntityGameMode(int clientEntityGameMode) {
this.clientEntityGameMode = clientEntityGameMode;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -40,13 +40,13 @@ import java.util.concurrent.TimeUnit;
public class Protocol1_9To1_8 extends BackwardsProtocol<ClientboundPackets1_9, ClientboundPackets1_8, ServerboundPackets1_9, ServerboundPackets1_8> {
public static final ValueTransformer<Double, Integer> DOUBLE_TO_INT_TIMES_32 = new ValueTransformer<Double, Integer>(Types.INT) {
public static final ValueTransformer<Double, Integer> DOUBLE_TO_INT_TIMES_32 = new ValueTransformer<>(Types.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>(Types.BYTE) {
public static final ValueTransformer<Float, Byte> DEGREES_TO_ANGLE = new ValueTransformer<>(Types.BYTE) {
@Override
public Byte transform(PacketWrapper packetWrapper, Float degrees) {
return (byte) ((degrees / 360F) * 256);
@@ -66,14 +66,14 @@ public class Protocol1_9To1_8 extends BackwardsProtocol<ClientboundPackets1_9, C
protected void registerPackets() {
entityRewriter.register();
itemRewriter.register();
PlayerPacketRewriter1_9.register(this);
WorldPacketRewriter1_9.register(this);
new PlayerPacketRewriter1_9(this).register();
new WorldPacketRewriter1_9(this).register();
}
@Override
public void init(UserConnection connection) {
connection.addEntityTracker(this.getClass(), new EntityTracker1_9(connection));
connection.addClientWorld(this.getClass(), new ClientWorld());
connection.put(new WindowTracker(connection));
connection.put(new LevitationStorage());
@@ -81,10 +81,6 @@ public class Protocol1_9To1_8 extends BackwardsProtocol<ClientboundPackets1_9, C
connection.put(new CooldownStorage());
connection.put(new BlockPlaceDestroyTracker());
connection.put(new BossBarStorage(connection));
if (!connection.has(ClientWorld.class)) {
connection.put(new ClientWorld());
}
}
@Override
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -57,7 +57,6 @@ public interface CooldownVisualization {
case BOSS_BAR -> BossBarVisualization::new;
case ACTION_BAR -> ActionBarVisualization::new;
case DISABLED -> DISABLED;
default -> throw new IllegalArgumentException("Unexpected: " + indicator);
};
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -37,11 +37,7 @@ public class EntityDataIndex1_8 {
private static Optional<EntityDataIndex1_9> getIndex(final EntityType type, final int index) {
final Pair<EntityType, Integer> pair = new Pair<>(type, index);
if (ENTITY_DATA_REWRITES.containsKey(pair)) {
return Optional.of(ENTITY_DATA_REWRITES.get(pair));
} else {
return Optional.empty();
}
return Optional.ofNullable(ENTITY_DATA_REWRITES.get(pair));
}
public static EntityDataIndex1_9 searchIndex(final EntityType type, final int index) {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -22,14 +22,13 @@ import com.viaversion.viaversion.protocols.v1_8to1_9.data.PotionIdMappings1_9;
import java.util.HashMap;
import java.util.Map;
// TODO | Check if this is correct???
public class PotionIdMappings1_8 {
public static final Map<String, String> POTION_NAME_INDEX = new HashMap<>();
public static final Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
static {
POTION_NAME_TO_ID.putAll(PotionIdMappings1_9.POTION_NAME_TO_ID);
POTION_NAME_TO_ID.put("luck", 8203);
POTION_NAME_TO_ID.put("luck", 8203); // Map new potion to similar one (luck->leaping)
POTION_NAME_INDEX.put("water", "§rWater Bottle");
POTION_NAME_INDEX.put("mundane", "§rMundane Potion");
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -28,7 +28,6 @@ import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import java.util.*;
@@ -204,7 +203,7 @@ public class WitherBossBar implements BossBar {
entityData.add(new EntityData(3, EntityDataTypes1_8.BYTE, (byte) 1));
entityData.add(new EntityData(6, EntityDataTypes1_8.FLOAT, health * 300f));
addMob.write(Types1_8.ENTITY_DATA_LIST, entityData);
addMob.write(Types.ENTITY_DATA_LIST1_8, entityData);
addMob.scheduleSend(Protocol1_9To1_8.class);
}
@@ -228,7 +227,7 @@ public class WitherBossBar implements BossBar {
entityData.add(new EntityData(2, EntityDataTypes1_8.STRING, title));
entityData.add(new EntityData(6, EntityDataTypes1_8.FLOAT, health * 300f));
setEntityData.write(Types1_8.ENTITY_DATA_LIST, entityData);
setEntityData.write(Types.ENTITY_DATA_LIST1_8, entityData);
setEntityData.scheduleSend(Protocol1_9To1_8.class);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -107,7 +107,7 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
});
protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_SET_SLOT, wrapper -> {
final byte windowId = wrapper.passthrough(Types.UNSIGNED_BYTE).byteValue();
final byte windowId = wrapper.passthrough(Types.BYTE);
final short slot = wrapper.passthrough(Types.SHORT);
final Item item = wrapper.passthrough(Types.ITEM1_8);
@@ -131,14 +131,14 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
});
protocol.registerServerbound(ServerboundPackets1_8.CONTAINER_CLOSE, wrapper -> {
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
final byte windowId = wrapper.passthrough(Types.BYTE);
wrapper.user().get(WindowTracker.class).remove(windowId);
});
protocol.registerServerbound(ServerboundPackets1_8.CONTAINER_CLICK, new PacketHandlers() {
@Override
public void register() {
map(Types.UNSIGNED_BYTE); // Window id
map(Types.BYTE); // Window id
map(Types.SHORT); // Slot
map(Types.BYTE); // Button
map(Types.SHORT); // Action number
@@ -146,7 +146,7 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
map(Types.ITEM1_8); // Clicked item
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Types.ITEM1_8, 0)));
handler(wrapper -> {
final short windowId = wrapper.get(Types.UNSIGNED_BYTE, 0);
final byte windowId = wrapper.get(Types.BYTE, 0);
final String windowType = wrapper.user().get(WindowTracker.class).get(windowId);
if (windowType != null && windowType.equalsIgnoreCase("minecraft:brewing_stand")) {
@@ -194,15 +194,11 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
super.handleItemToClient(connection, item);
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
enchantmentRewriter.handleToClient(item);
CompoundTag displayTag = tag.getCompoundTag("display");
if (item.data() != 0 && tag.contains("Unbreakable")) {
final ByteTag unbreakableTag = tag.getByteTag("Unbreakable");
CompoundTag displayTag = tag == null ? null : tag.getCompoundTag("display");
if (item.data() != 0) {
final ByteTag unbreakableTag = tag == null ? null : tag.getByteTag("Unbreakable");
if (unbreakableTag != null && unbreakableTag.asByte() != 0) {
tag.put(nbtTagName() + "|Unbreakable", new ByteTag(unbreakableTag.asByte()));
tag.remove("Unbreakable");
@@ -222,7 +218,7 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
if (item.identifier() == 383 && item.data() == 0) { // Spawn eggs
int data = 0;
final CompoundTag entityTag = tag.getCompoundTag("EntityTag");
final CompoundTag entityTag = tag == null ? null : tag.getCompoundTag("EntityTag");
if (entityTag != null) {
final StringTag idTag = entityTag.getStringTag("id");
if (idTag != null) {
@@ -246,7 +242,7 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
if (potion || splashPotion || lingeringPotion) {
int data = 0;
final StringTag potionTag = tag.getStringTag("Potion");
final StringTag potionTag = tag == null ? null : tag.getStringTag("Potion");
if (potionTag != null) {
String potionName = Key.stripMinecraftNamespace(potionTag.getValue());
if (PotionIdMappings1_8.POTION_NAME_TO_ID.containsKey(potionName)) {
@@ -272,7 +268,7 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
item.setData((short) data);
}
final ListTag<CompoundTag> attributeModifiers = tag.getListTag("AttributeModifiers", CompoundTag.class);
final ListTag<CompoundTag> attributeModifiers = tag == null ? null : tag.getListTag("AttributeModifiers", CompoundTag.class);
if (attributeModifiers != null) {
tag.put(nbtTagName() + "|AttributeModifiers", attributeModifiers.copy());
attributeModifiers.getValue().removeIf(entries -> {
@@ -290,14 +286,14 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
super.handleItemToServer(connection, item);
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
enchantmentRewriter.handleToServer(item);
if (item.identifier() == 383 && item.data() != 0) { // Spawn eggs
if (!tag.contains("EntityTag") && EntityIds1_8.ENTITY_ID_TO_NAME.containsKey((int) item.data())) {
if ((tag == null || !tag.contains("EntityTag")) && EntityIds1_8.ENTITY_ID_TO_NAME.containsKey((int) item.data())) {
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
final CompoundTag entityTag = new CompoundTag();
entityTag.put("id", new StringTag(EntityIds1_8.ENTITY_ID_TO_NAME.get((int) item.data())));
tag.put("EntityTag", entityTag);
@@ -305,20 +301,30 @@ public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundP
item.setData((short) 0);
}
if (item.identifier() == 373 && !tag.contains("Potion")) { // Potions
if (item.identifier() == 373 && (tag == null || !tag.contains("Potion"))) { // Potions
if (item.data() >= 16384) {
item.setIdentifier(438);
item.setData((short) (item.data() - 8192));
}
final String name = item.data() == 8192 ? "water" : PotionIdMappings1_9.potionNameFromDamage(item.data());
tag.put("Potion", new StringTag("minecraft:" + name));
if (tag == null) {
item.setTag(tag = new CompoundTag());
final String name = item.data() == 8192 ? "water" : PotionIdMappings1_9.potionNameFromDamage(item.data());
tag.put("Potion", new StringTag("minecraft:" + name));
}
item.setData((short) 0);
}
if (tag == null) {
return item;
}
final Tag noDisplayTag = tag.remove(nbtTagName() + "|noDisplay");
if (noDisplayTag != null) {
tag.remove("display");
if (tag.isEmpty()) {
item.setTag(null);
}
}
final Tag unbreakableTag = tag.remove(nbtTagName() + "|Unbreakable");
if (unbreakableTag != null) {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -17,7 +17,6 @@
*/
package com.viaversion.viarewind.protocol.v1_9to1_8.rewriter;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.minecraft.math.RelativeMoveUtil;
import com.viaversion.viarewind.api.rewriter.VREntityRewriter;
import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
@@ -26,8 +25,8 @@ import com.viaversion.viarewind.protocol.v1_9to1_8.storage.CooldownStorage;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.EntityTracker1_9;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.LevitationStorage;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.PlayerPositionTracker;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.EulerAngle;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
@@ -38,8 +37,6 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.libs.fastutil.ints.IntArrayList;
import com.viaversion.viaversion.libs.fastutil.ints.IntList;
import com.viaversion.viaversion.protocols.v1_8to1_9.data.EntityDataIndex1_9;
@@ -52,7 +49,6 @@ import com.viaversion.viaversion.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets1_9, Protocol1_9To1_8> {
@@ -65,9 +61,28 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
@Override
protected void registerPackets() {
registerJoinGame1_8(ClientboundPackets1_9.LOGIN);
registerRemoveEntities(ClientboundPackets1_9.REMOVE_ENTITIES);
registerSetEntityData(ClientboundPackets1_9.SET_ENTITY_DATA, Types1_9.ENTITY_DATA_LIST, Types1_8.ENTITY_DATA_LIST);
protocol.registerClientbound(ClientboundPackets1_9.LOGIN, wrapper -> {
final int entityId = wrapper.passthrough(Types.INT);
wrapper.passthrough(Types.UNSIGNED_BYTE); // Game mode
final int dimension = wrapper.passthrough(Types.BYTE);
trackPlayer(wrapper.user(), entityId);
final ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_9To1_8.class);
clientWorld.setEnvironment(dimension);
});
protocol.registerClientbound(ClientboundPackets1_9.SET_ENTITY_DATA, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
if (!tracker(wrapper.user()).hasEntity(entityId)) {
wrapper.cancel();
return;
}
final List<EntityData> entityData = wrapper.read(Types.ENTITY_DATA_LIST1_9);
handleEntityData(entityId, entityData, wrapper.user());
wrapper.write(Types.ENTITY_DATA_LIST1_8, entityData);
});
protocol.registerClientbound(ClientboundPackets1_9.ADD_ENTITY, new PacketHandlers() {
@Override
@@ -89,10 +104,11 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
handler(wrapper -> {
final int entityId = wrapper.get(Types.VAR_INT, 0);
final int entityType = wrapper.get(Types.BYTE, 0);
final EntityTypes1_9.EntityType type = EntityTypes1_9.getTypeFromId(entityType, true);
int data = wrapper.get(Types.INT, 3);
final EntityTypes1_9.EntityType type = EntityTypes1_9.ObjectType.getEntityType(entityType, data);
// Cancel new entities which can't be handled properly
if (type == EntityTypes1_9.EntityType.AREA_EFFECT_CLOUD || type == EntityTypes1_9.EntityType.SPECTRAL_ARROW || type == EntityTypes1_9.EntityType.DRAGON_FIREBALL) {
if (type == null || type == EntityTypes1_9.EntityType.AREA_EFFECT_CLOUD || type == EntityTypes1_9.EntityType.SPECTRAL_ARROW || type == EntityTypes1_9.EntityType.DRAGON_FIREBALL) {
wrapper.cancel();
return;
}
@@ -107,8 +123,6 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
wrapper.set(Types.INT, 1, y);
}
int data = wrapper.get(Types.INT, 3);
if (type.isOrHasParent(EntityTypes1_9.EntityType.ARROW) && data != 0) {
wrapper.set(Types.INT, 3, --data);
}
@@ -186,10 +200,10 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
map(Types.SHORT); // Velocity x
map(Types.SHORT); // Velocity y
map(Types.SHORT); // Velocity z
map(Types1_9.ENTITY_DATA_LIST, Types1_8.ENTITY_DATA_LIST); // Entity data
map(Types.ENTITY_DATA_LIST1_9, Types.ENTITY_DATA_LIST1_8); // Entity data
handler(getTrackerHandler(Types.UNSIGNED_BYTE, 0));
handler(getMobSpawnRewriter(Types1_8.ENTITY_DATA_LIST));
handler(getMobSpawnRewriter(Types.ENTITY_DATA_LIST1_8));
}
});
@@ -219,9 +233,9 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
map(Types.BYTE); // Yaw
map(Types.BYTE); // Pitch
create(Types.SHORT, (short) 0); // Current item
map(Types1_9.ENTITY_DATA_LIST, Types1_8.ENTITY_DATA_LIST); // Entity data
map(Types.ENTITY_DATA_LIST1_9, Types.ENTITY_DATA_LIST1_8); // Entity data
handler(getTrackerAndMetaHandler(Types1_8.ENTITY_DATA_LIST, EntityTypes1_9.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types.ENTITY_DATA_LIST1_8, EntityTypes1_9.EntityType.PLAYER));
}
});
@@ -317,11 +331,12 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
public void register() {
handler(wrapper -> {
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class);
final int vehicle = tracker.getVehicle(tracker.clientEntityId());
if (vehicle == -1) {
final Integer vehicle = tracker.getVehicle(tracker.clientEntityId());
if (vehicle == null) {
wrapper.cancel();
}
wrapper.write(Types.VAR_INT, vehicle);
} else {
wrapper.write(Types.VAR_INT, vehicle);
}
});
map(Types.DOUBLE, Protocol1_9To1_8.DOUBLE_TO_INT_TIMES_32); // X
map(Types.DOUBLE, Protocol1_9To1_8.DOUBLE_TO_INT_TIMES_32); // Y
@@ -332,6 +347,7 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
if (wrapper.isCancelled()) {
return;
}
final PlayerPositionTracker storage = wrapper.user().get(PlayerPositionTracker.class);
double x = wrapper.get(Types.INT, 0) / 32d;
double y = wrapper.get(Types.INT, 1) / 32d;
@@ -340,6 +356,10 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
});
create(Types.BOOLEAN, true);
handler(wrapper -> {
if (wrapper.isCancelled()) {
return;
}
final int entityId = wrapper.get(Types.VAR_INT, 0);
final EntityType type = wrapper.user().getEntityTracker(Protocol1_9To1_8.class).entityType(entityId);
if (type == EntityTypes1_9.EntityType.BOAT) {
@@ -401,11 +421,7 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
final int vehicle = wrapper.read(Types.VAR_INT);
final IntList oldPassengers = tracker.getPassengers(vehicle);
final int count = wrapper.read(Types.VAR_INT);
final IntList passengers = new IntArrayList();
for (int i = 0; i < count; i++) {
passengers.add(wrapper.read(Types.VAR_INT));
}
final IntList passengers = new IntArrayList(wrapper.read(Types.VAR_INT_ARRAY_PRIMITIVE));
tracker.setPassengers(vehicle, passengers);
if (!oldPassengers.isEmpty()) {
@@ -417,7 +433,7 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
detach.scheduleSend(Protocol1_9To1_8.class);
}
}
for (int i = 0; i < count; i++) {
for (int i = 0; i < passengers.size(); i++) {
final int attachedEntityId = passengers.getInt(i);
final int holdingEntityId = i == 0 ? vehicle : passengers.getInt(i - 1);
@@ -619,11 +635,11 @@ public class EntityPacketRewriter1_9 extends VREntityRewriter<ClientboundPackets
@Override
public EntityTypes1_9.EntityType typeFromId(int type) {
return EntityTypes1_9.getTypeFromId(type, false);
return EntityTypes1_9.EntityType.findById(type);
}
@Override
public EntityTypes1_9.EntityType objectTypeFromId(int type) {
return EntityTypes1_9.getTypeFromId(type, true);
public EntityTypes1_9.EntityType objectTypeFromId(int type, int data) {
return EntityTypes1_9.ObjectType.getEntityType(type, data);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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,6 +21,7 @@ import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.*;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_9;
import com.viaversion.viaversion.api.minecraft.item.Item;
@@ -28,9 +29,8 @@ import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
@@ -45,9 +45,14 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class PlayerPacketRewriter1_9 {
public class PlayerPacketRewriter1_9 extends RewriterBase<Protocol1_9To1_8> {
public static void register(final Protocol1_9To1_8 protocol) {
public PlayerPacketRewriter1_9(Protocol1_9To1_8 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_9.BOSS_EVENT, null, wrapper -> {
wrapper.cancel();
final BossBarStorage bossbar = wrapper.user().get(BossBarStorage.class);
@@ -61,7 +66,7 @@ public class PlayerPacketRewriter1_9 {
wrapper.read(Types.VAR_INT); // Division
wrapper.read(Types.UNSIGNED_BYTE); // Flags
bossbar.add(uuid, ChatUtil.jsonToLegacy(wrapper.user(), title), health);
bossbar.add(uuid, ChatUtil.jsonToLegacy(title), health);
} else if (action == 1 /* remove */) {
bossbar.remove(uuid);
} else if (action == 2 /* update health */) {
@@ -69,7 +74,7 @@ public class PlayerPacketRewriter1_9 {
bossbar.updateHealth(uuid, health);
} else if (action == 3 /* update title */) {
final JsonElement title = wrapper.read(Types.COMPONENT);
bossbar.updateTitle(uuid, ChatUtil.jsonToLegacy(wrapper.user(), title));
bossbar.updateTitle(uuid, ChatUtil.jsonToLegacy(title));
}
});
@@ -166,14 +171,52 @@ public class PlayerPacketRewriter1_9 {
@Override
public void register() {
map(Types.INT); // Dimension
handler(wrapper -> wrapper.user().get(BossBarStorage.class).reset());
handler(wrapper -> {
final ClientWorld world = wrapper.user().get(ClientWorld.class);
world.setEnvironment(wrapper.get(Types.INT, 0));
final ClientWorld world = wrapper.user().getClientWorld(Protocol1_9To1_8.class);
final int dimension = wrapper.get(Types.INT, 0);
if (world.setEnvironment(dimension)) {
final EntityTracker tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class);
tracker.clearEntities();
wrapper.user().get(BossBarStorage.class).reset();
}
});
}
});
// Packet implementation doesn't do anything until 1.9
protocol.registerClientbound(ClientboundPackets1_9.PLAYER_COMBAT, wrapper -> {
if (!ViaRewind.getConfig().handlePlayerCombatPacket()) {
return;
}
final int action = wrapper.passthrough(Types.VAR_INT);
if (action != 2) {
return;
}
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class);
final int entityId = wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.INT); // Killer id
if (entityId != tracker.clientEntityId()) {
return;
}
final JsonElement message = wrapper.passthrough(Types.COMPONENT);
final PacketWrapper killPlayer = wrapper.create(ClientboundPackets1_8.SET_HEALTH);
killPlayer.write(Types.FLOAT, 0F); // Health
killPlayer.write(Types.VAR_INT, 0); // Food
killPlayer.write(Types.FLOAT, 0F); // Food Saturation
killPlayer.scheduleSend(Protocol1_9To1_8.class);
final PacketWrapper chatMessage = wrapper.create(ClientboundPackets1_8.CHAT);
chatMessage.write(Types.COMPONENT, message);
chatMessage.write(Types.BYTE, (byte) 2); // Position - above hotbar
chatMessage.scheduleSend(Protocol1_9To1_8.class);
});
protocol.registerServerbound(ServerboundPackets1_8.CHAT, new PacketHandlers() {
@Override
public void register() {
@@ -238,14 +281,14 @@ public class PlayerPacketRewriter1_9 {
map(Types.DOUBLE); // Z
map(Types.BOOLEAN); // On ground
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
final PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (pos.getConfirmId() != -1) {
final PlayerPositionTracker storage = wrapper.user().get(PlayerPositionTracker.class);
storage.sendAnimations();
if (storage.getConfirmId() != -1) {
return;
}
pos.setPos(wrapper.get(Types.DOUBLE, 0), wrapper.get(Types.DOUBLE, 1), wrapper.get(Types.DOUBLE, 2));
pos.setOnGround(wrapper.get(Types.BOOLEAN, 0));
storage.setPos(wrapper.get(Types.DOUBLE, 0), wrapper.get(Types.DOUBLE, 1), wrapper.get(Types.DOUBLE, 2));
storage.setOnGround(wrapper.get(Types.BOOLEAN, 0));
});
handler(wrapper -> wrapper.user().get(BossBarStorage.class).updateLocation());
}
@@ -258,13 +301,15 @@ public class PlayerPacketRewriter1_9 {
map(Types.FLOAT); // Pitch
map(Types.BOOLEAN); // On ground
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
final PlayerPositionTracker storage = wrapper.user().get(PlayerPositionTracker.class);
storage.sendAnimations();
if (storage.getConfirmId() != -1) {
return;
}
PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (pos.getConfirmId() != -1) return;
pos.setYaw(wrapper.get(Types.FLOAT, 0));
pos.setPitch(wrapper.get(Types.FLOAT, 1));
pos.setOnGround(wrapper.get(Types.BOOLEAN, 0));
storage.setYaw(wrapper.get(Types.FLOAT, 0));
storage.setPitch(wrapper.get(Types.FLOAT, 1));
storage.setOnGround(wrapper.get(Types.BOOLEAN, 0));
});
handler(wrapper -> wrapper.user().get(BossBarStorage.class).updateLocation());
}
@@ -278,7 +323,7 @@ public class PlayerPacketRewriter1_9 {
final float pitch = wrapper.passthrough(Types.FLOAT);
final boolean onGround = wrapper.passthrough(Types.BOOLEAN);
PlayerPositionTracker storage = wrapper.user().get(PlayerPositionTracker.class);
final PlayerPositionTracker storage = wrapper.user().get(PlayerPositionTracker.class);
storage.sendAnimations();
if (storage.getConfirmId() != -1) {
if (storage.getPosX() == x && storage.getPosY() == y && storage.getPosZ() == z && storage.getYaw() == yaw && storage.getPitch() == pitch) {
@@ -377,9 +422,9 @@ public class PlayerPacketRewriter1_9 {
final float forward = wrapper.passthrough(Types.FLOAT);
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class);
final int vehicle = tracker.getVehicle(tracker.clientEntityId());
final Integer vehicle = tracker.getVehicle(tracker.clientEntityId());
if (vehicle != -1 && tracker.entityType(vehicle) == EntityTypes1_9.EntityType.BOAT) {
if (vehicle != null && tracker.entityType(vehicle) == EntityTypes1_9.EntityType.BOAT) {
final PacketWrapper paddleBoat = PacketWrapper.create(ServerboundPackets1_9.PADDLE_BOAT, wrapper.user());
paddleBoat.write(Types.BOOLEAN, forward != 0.0f || sideways < 0.0f);
paddleBoat.write(Types.BOOLEAN, forward != 0.0f || sideways > 0.0f);
@@ -393,7 +438,7 @@ public class PlayerPacketRewriter1_9 {
map(Types.BLOCK_POSITION1_8); // Position
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
wrapper.write(Types.STRING, ChatUtil.jsonToLegacy(wrapper.user(), wrapper.read(Types.COMPONENT)));
wrapper.write(Types.STRING, ChatUtil.jsonToLegacy(wrapper.read(Types.COMPONENT)));
}
});
}
@@ -426,7 +471,7 @@ public class PlayerPacketRewriter1_9 {
final List<EntityData> entityData = new ArrayList<>();
entityData.add(new EntityData(10, EntityDataTypes1_8.BYTE, (byte) flags));
updateSkin.write(Types1_8.ENTITY_DATA_LIST, entityData);
updateSkin.write(Types.ENTITY_DATA_LIST1_8, entityData);
updateSkin.scheduleSend(Protocol1_9To1_8.class);
});
}
@@ -439,25 +484,30 @@ public class PlayerPacketRewriter1_9 {
handlerSoftFail(wrapper -> {
final String channel = wrapper.get(Types.STRING, 0);
if (channel.equals("MC|BEdit") || channel.equals("MC|BSign")) {
Item book = wrapper.passthrough(Types.ITEM1_8);
final Item book = wrapper.passthrough(Types.ITEM1_8);
book.setIdentifier(386);
CompoundTag tag = book.tag();
if (tag.contains("pages")) {
ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
if (pages.size() > ViaRewind.getConfig().getMaxBookPages()) {
wrapper.user().disconnect("Too many book pages");
final CompoundTag tag = book.tag();
if (tag == null) {
return;
}
final ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
if (pages == null) {
return;
}
if (pages.size() > ViaRewind.getConfig().getMaxBookPages()) {
wrapper.user().disconnect("Too many book pages");
return;
}
for (int i = 0; i < pages.size(); i++) {
final StringTag pageTag = pages.get(i);
final String value = pageTag.getValue();
if (value.length() > ViaRewind.getConfig().getMaxBookPageSize()) {
wrapper.user().disconnect("Book page too large");
return;
}
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
if (value.length() > ViaRewind.getConfig().getMaxBookPageSize()) {
wrapper.user().disconnect("Book page too large");
return;
}
value = ChatUtil.jsonToLegacy(wrapper.user(), value);
page.setValue(value);
}
pageTag.setValue(ChatUtil.jsonToLegacy(value));
}
} else if (channel.equals("MC|AdvCdm")) {
wrapper.set(Types.STRING, 0, "MC|AdvCmd");
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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,7 +21,6 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
import com.viaversion.viarewind.protocol.v1_9to1_8.data.EffectIdMappings1_8;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.chunks.BaseChunk;
@@ -32,6 +31,7 @@ import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_8;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_9_1;
@@ -39,13 +39,17 @@ import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import java.util.ArrayList;
public class WorldPacketRewriter1_9 {
public class WorldPacketRewriter1_9 extends RewriterBase<Protocol1_9To1_8> {
public static void register(Protocol1_9To1_8 protocol) {
public WorldPacketRewriter1_9(Protocol1_9To1_8 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_ENTITY_DATA, new PacketHandlers() {
@Override
public void register() {
@@ -107,7 +111,7 @@ public class WorldPacketRewriter1_9 {
@Override
public void register() {
handler(wrapper -> {
final Environment environment = wrapper.user().get(ClientWorld.class).getEnvironment();
final Environment environment = wrapper.user().getClientWorld(Protocol1_9To1_8.class).getEnvironment();
final int chunkX = wrapper.read(Types.INT);
final int chunkZ = wrapper.read(Types.INT);
@@ -121,7 +125,7 @@ public class WorldPacketRewriter1_9 {
@Override
public void register() {
handler(wrapper -> {
final Environment environment = wrapper.user().get(ClientWorld.class).getEnvironment();
final Environment environment = wrapper.user().getClientWorld(Protocol1_9To1_8.class).getEnvironment();
Chunk chunk = wrapper.read(ChunkType1_9_1.forEnvironment(environment));
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -28,11 +28,12 @@ import java.util.logging.Level;
public class CooldownStorage implements StorableObject {
private double attackSpeed = 4.0;
private long lastHit = 0;
private CooldownVisualization.Factory visualizationFactory = CooldownVisualization.Factory.fromConfiguration();
private CooldownVisualization current;
private double attackSpeed = 4.0;
private long lastHit = 0;
public void tick(final UserConnection connection) {
if (!hasCooldown()) {
endCurrentVisualization();
@@ -110,4 +111,12 @@ public class CooldownStorage implements StorableObject {
public void setLastHit(long lastHit) {
this.lastHit = lastHit;
}
public CooldownVisualization.Factory getVisualizationFactory() {
return visualizationFactory;
}
public void setVisualizationFactory(CooldownVisualization.Factory visualizationFactory) {
this.visualizationFactory = visualizationFactory;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -74,11 +74,11 @@ public class EntityTracker1_9 extends EntityTrackerBase {
return false;
}
public int getVehicle(final int passenger) {
public Integer getVehicle(final int passenger) {
for (Map.Entry<Integer, IntList> vehicle : vehicles.int2ObjectEntrySet()) {
if (vehicle.getValue().contains(passenger)) return vehicle.getKey();
}
return -1;
return null;
}
public Int2IntMap getStatus() {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -24,8 +24,8 @@ import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.libs.mcstructs.core.TextFormatting;
import com.viaversion.viaversion.libs.mcstructs.text.ATextComponent;
import com.viaversion.viaversion.libs.mcstructs.text.TextComponent;
import com.viaversion.viaversion.libs.mcstructs.text.TextFormatting;
import com.viaversion.viaversion.libs.mcstructs.text.components.StringComponent;
import com.viaversion.viaversion.libs.mcstructs.text.components.TranslationComponent;
import com.viaversion.viaversion.libs.mcstructs.text.serializer.TextComponentSerializer;
@@ -90,7 +90,7 @@ public class WindowTracker extends StoredObject {
openWindow.write(Types.UNSIGNED_BYTE, windowId);
openWindow.write(Types.STRING, "minecraft:brewing_stand");
ATextComponent title = new StringComponent().
TextComponent title = new StringComponent().
append(new TranslationComponent("container.brewing")).
append(new StringComponent(": " + TextFormatting.DARK_GRAY)).
append(new StringComponent(amount + " " + TextFormatting.DARK_RED)).
@@ -103,7 +103,7 @@ public class WindowTracker extends StoredObject {
Item[] items = user.get(WindowTracker.class).getBrewingItems(windowId);
for (int i = 0; i < items.length; i++) {
PacketWrapper setSlot = PacketWrapper.create(ClientboundPackets1_8.CONTAINER_SET_SLOT, user);
setSlot.write(Types.UNSIGNED_BYTE, windowId);
setSlot.write(Types.BYTE, (byte) windowId);
setSlot.write(Types.SHORT, (short) i);
setSlot.write(Types.ITEM1_8, items[i]);
setSlot.scheduleSend(Protocol1_9To1_8.class);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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
@@ -32,6 +32,9 @@ public class LevitationUpdateTask implements Runnable {
@Override
public void run() {
if (!ViaRewind.getConfig().emulateLevitationEffect()) {
return;
}
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final LevitationStorage levitation = connection.get(LevitationStorage.class);
if (!levitation.isActive()) {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
* Copyright (C) 2018-2025 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,13 +18,13 @@
package com.viaversion.viarewind.utils;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
import com.viaversion.viaversion.util.ComponentUtil;
import java.util.logging.Level;
@@ -33,7 +33,7 @@ import java.util.regex.Pattern;
@Deprecated
public class ChatUtil {
private static final Pattern UNUSED_COLOR_PATTERN = Pattern.compile("(?>(?>§[0-fk-or])*(§r|\\Z))|(?>(?>§[0-f])*(§[0-f]))");
private static final ComponentRewriter<ClientboundPacketType> LEGACY_REWRITER = new ComponentRewriter<ClientboundPacketType>(null, ComponentRewriter.ReadType.JSON) {
private static final JsonNBTComponentRewriter<ClientboundPacketType> LEGACY_REWRITER = new JsonNBTComponentRewriter<>(null, JsonNBTComponentRewriter.ReadType.JSON) {
@Override
protected void handleTranslate(JsonObject object, String translate) {
String text = Protocol1_12_2To1_13.MAPPINGS.getMojangTranslation().get(translate);
@@ -43,29 +43,35 @@ public class ChatUtil {
}
};
public static String jsonToLegacy(UserConnection connection, String json) {
if (json == null || json.equals("null") || json.isEmpty()) return "";
public static String jsonToLegacy(String json) {
if (json == null || json.equals("null") || json.isEmpty()) {
return "";
}
try {
return jsonToLegacy(connection, JsonParser.parseString(json));
return jsonToLegacy(JsonParser.parseString(json));
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Could not convert component to legacy text: " + json, e);
if (!Via.getConfig().isSuppressConversionWarnings()) {
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Could not convert component to legacy text: " + json, e);
}
}
return "";
}
public static String jsonToLegacy(UserConnection connection, JsonElement component) {
public static String jsonToLegacy(JsonElement component) {
if (component.isJsonNull() || component.isJsonArray() && component.getAsJsonArray().isEmpty() || component.isJsonObject() && component.getAsJsonObject().isEmpty()) {
return "";
} else if (component.isJsonPrimitive()) {
return component.getAsString();
} else {
try {
LEGACY_REWRITER.processText(connection, component);
LEGACY_REWRITER.processText(null, component);
String legacy = ComponentUtil.jsonToLegacy(component);
while (legacy.startsWith("§f")) legacy = legacy.substring(2);
return legacy;
} catch (Exception ex) {
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Could not convert component to legacy text: " + component, ex);
if (!Via.getConfig().isSuppressConversionWarnings()) {
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Could not convert component to legacy text: " + component, ex);
}
}
return "";
}
@@ -3,7 +3,8 @@
# Specifies how 1.8.x clients should see the cooldown indicator
# You can choose between TITLE, ACTION_BAR, BOSS_BAR and DISABLED
# ONLY DISABLE IF YOU HAVE 1.9 COOLDOWN DISABLED ON YOUR SERVER
# 1.8 PLAYERS MAY ASK WHY PVP IS NOT WORKING OTHERWISE
# 1.8 PLAYERS MAY ASK WHY PVP IS NOT WORKING OTHERWISE.
# REQUIRES A SERVER RESTART TO TAKE EFFECT
cooldown-indicator: 'TITLE'
#
# Replaces Adventure mode with Survival mode for 1.7.x clients
@@ -11,14 +12,14 @@ cooldown-indicator: 'TITLE'
# or 'CanPlaceOn' flags on items
replace-adventure: false
#
# Whether 1.9 particles should be replaced by similar ones in
# Whether similar ones should replace 1.9 particles in
# 1.8 and lower
replace-particles: false
#
# Max amount of pages for written books before a client gets kicked
# Max number of pages for written books before a client gets kicked
max-book-pages: 100
#
# Max amount of characters in the json (!) string of a book page before a client gets kicked
# Max number of characters in the json (!) string of a book page before a client gets kicked
max-book-page-length: 5000
#
# Whether to emulate the 1.8+ world border for 1.7.x clients
@@ -28,11 +29,16 @@ emulate-world-border: true
always-show-original-mob-name: true
#
# The particle to show the world border for the 1.8+ world border for 1.7.x clients
# see https://wiki.vg/index.php?title=Protocol&oldid=7368#Particle_2
world-border-particle: 'fireworksSpark'
#
# If enabled, 1.8 players on 1.9+ servers can use /offhand to switch items between their main hand and offhand.
enable-offhand: true
#
# Allows to define the offhand command
offhand-command: '/offhand'
# Allows defining the offhand command
offhand-command: '/offhand'
#
# If enabled, 1.8 players on 1.9+ servers will also experience the levitation effect by sending velocity packets.
emulate-levitation-effect: true
#
# If enabled, 1.8 players will handle the player combat packet added in 1.9 by showing the custom death message above the hotbar.
handle-player-combat-packet: true
Loaded 100 of 122 files, more files were not shown because too many files have changed in this diff. Show more