mirror of
https://github.com/ViaVersion/ViaRewind.git
synced 2026-11-04 17:00:20 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8e4746053 | ||
|
|
82a3ee84e0 | ||
|
|
9df4d11f8c | ||
|
|
c92916a265 | ||
|
|
dc04defeb6 | ||
|
|
c7edeba340 | ||
|
|
d232bd020f | ||
|
|
2525d42666 | ||
|
|
4d51a62410 | ||
|
|
b177e048dd | ||
|
|
7577279fcb | ||
|
|
e3211f99ef | ||
|
|
d562f9745a | ||
|
|
7339df9fdb | ||
|
|
d98d5bed9b | ||
|
|
786529efbe | ||
|
|
71546a7699 | ||
|
|
9e7c853a5d | ||
|
|
315a1a0fab | ||
|
|
7a2898e44a | ||
|
|
5783fa98e9 | ||
|
|
77d9d9143e | ||
|
|
ede1920686 | ||
|
|
189249478f | ||
|
|
6c19760af6 | ||
|
|
69f8213445 | ||
|
|
f95871bdc5 | ||
|
|
7d6c75ad31 | ||
|
|
0bb7be88ff | ||
|
|
4b7264c944 | ||
|
|
db6afa5b1b | ||
|
|
02f55edb0c | ||
|
|
5ef900a61e | ||
|
|
4fe7e35f6b | ||
|
|
1af08ced41 | ||
|
|
fd1d3ed221 | ||
|
|
1d6ef8833f | ||
|
|
f2e2f18511 | ||
|
|
2adf7757f0 | ||
|
|
4dd3de2ce9 | ||
|
|
ddbdbdb1cc | ||
|
|
28b4998912 | ||
|
|
f9b0fd5c5a | ||
|
|
a676368588 | ||
|
|
966231ad1c | ||
|
|
d73c2198ea | ||
|
|
6f319932be | ||
|
|
f172de2742 | ||
|
|
ca25da9445 | ||
|
|
ea548dfd91 | ||
|
|
d0561f2e19 | ||
|
|
2c8189a447 | ||
|
|
48c9e45bcf | ||
|
|
ecb4f4bf00 | ||
|
|
6ea9377622 | ||
|
|
b789fdebb7 | ||
|
|
e7b0606e18 | ||
|
|
bf490c3805 | ||
|
|
7ca7078141 | ||
|
|
170af55f91 | ||
|
|
00d82f9f2f | ||
|
|
79ef613c15 | ||
|
|
e2fcbafc70 | ||
|
|
9ae46145e5 | ||
|
|
76f90b68b8 | ||
|
|
32a2ee6bfa | ||
|
|
04878b7e34 | ||
|
|
adccdc4b41 | ||
|
|
0accea66f2 | ||
|
|
65257be3ee | ||
|
|
880e879dce | ||
|
|
0ccc6a0923 | ||
|
|
7bff361e14 | ||
|
|
c2c28473cc | ||
|
|
048d502998 | ||
|
|
e0c1f53115 | ||
|
|
e5313a466b | ||
|
|
e30633e367 | ||
|
|
a443dd5d11 | ||
|
|
3820426bce | ||
|
|
031ae32f27 | ||
|
|
e83616139e | ||
|
|
7325b733d6 | ||
|
|
e64501eae8 | ||
|
|
2d99607c35 | ||
|
|
4d159189c0 | ||
|
|
2076294856 | ||
|
|
49f7bd22be | ||
|
|
298605874d | ||
|
|
35b94f1878 | ||
|
|
37955059c4 | ||
|
|
af4306bc81 | ||
|
|
98ca00f625 | ||
|
|
598804432b | ||
|
|
92bae0a5c4 | ||
|
|
d50b6a2f89 | ||
|
|
54cc085717 | ||
|
|
bd0d4c31b2 | ||
|
|
705c88f4b3 | ||
|
|
7306a795b9 | ||
|
|
dfdfad4bfc | ||
|
|
c87654848d | ||
|
|
08a7077d10 | ||
|
|
73afaaf493 | ||
|
|
f0f8038b18 | ||
|
|
540c0d0d47 | ||
|
|
d00b0c8afe | ||
|
|
b34385c09e | ||
|
|
ff47845df1 | ||
|
|
fc37b9c0ba | ||
|
|
e3baafa2a2 | ||
|
|
11914da37e | ||
|
|
30fa58af81 | ||
|
|
52b6aed005 | ||
|
|
9d74706e84 | ||
|
|
7d5ad45ffc | ||
|
|
bd3593e15a | ||
|
|
835fb5de08 | ||
|
|
8b2769f19b | ||
|
|
4da08b5a35 | ||
|
|
7da8e62a39 | ||
|
|
31c62f96b9 | ||
|
|
0f866d8b50 | ||
|
|
32d265116a | ||
|
|
b7d1197be3 | ||
|
|
d4363b67b6 | ||
|
|
dcdce8ad52 | ||
|
|
af44f88d6e | ||
|
|
1d1d77abfd | ||
|
|
ae800f16be | ||
|
|
f31d731f34 | ||
|
|
2ddd0d8b66 | ||
|
|
f97884158b | ||
|
|
1e2fcb9c58 | ||
|
|
5110326a90 | ||
|
|
6887556b2c | ||
|
|
66cf650d36 | ||
|
|
1426631c97 | ||
|
|
b6a32823cc | ||
|
|
aff88a6ca3 | ||
|
|
0edfd844b9 | ||
|
|
57a64740aa | ||
|
|
f7903050bf | ||
|
|
3a7ac0765b | ||
|
|
48f500a470 | ||
|
|
c3e19b769b | ||
|
|
561829d952 | ||
|
|
6767379526 | ||
|
|
a10ce1f35f | ||
|
|
49f0c673e6 | ||
|
|
fd2c81a6fd |
No files matched your search
+2
-2
@@ -1,2 +1,2 @@
|
||||
github: FlorianMichael
|
||||
custom: ['https://florianmichael.de/donate', 'https://creeper123123321.github.io/#donate']
|
||||
github: florianreuth
|
||||
custom: [ 'https://florianreuth.de/donate', 'https://creeper123123321.github.io/#donate' ]
|
||||
+14
-2
@@ -1,10 +1,22 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gradle"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
groups:
|
||||
all-dependencies:
|
||||
patterns:
|
||||
- "*"
|
||||
- package-ecosystem: "github-actions"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
interval: "monthly"
|
||||
groups:
|
||||
all-dependencies:
|
||||
patterns:
|
||||
- "*"
|
||||
@@ -1,21 +1,32 @@
|
||||
name: Build
|
||||
on: [pull_request, push, workflow_dispatch]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-26.04
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0
|
||||
with:
|
||||
cache-disabled: true
|
||||
cache-provider: basic
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6.0.0
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
java-version: 25
|
||||
check-latest: true
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
run: ./gradlew build --stacktrace
|
||||
- name: Upload Artifacts to GitHub
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: Artifacts
|
||||
path: build/libs/
|
||||
if-no-files-found: error
|
||||
@@ -4,26 +4,41 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
if: github.repository_owner == 'ViaVersion'
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-26.04
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0
|
||||
with:
|
||||
cache-disabled: true
|
||||
cache-provider: basic
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6.0.0
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
java-version: 25
|
||||
check-latest: true
|
||||
- name: Publish
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build --stacktrace
|
||||
- name: Publish to Hangar
|
||||
env:
|
||||
HANGAR_TOKEN: ${{ secrets.HANGAR_TOKEN }}
|
||||
run: ./gradlew publishAllPublicationsToHangar --stacktrace
|
||||
continue-on-error: true
|
||||
- name: Publish to Modrinth
|
||||
env:
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
run: ./gradlew build modrinth publishAllPublicationsToHangar
|
||||
run: ./gradlew modrinth --stacktrace
|
||||
continue-on-error: true
|
||||
+4
-2
@@ -13,6 +13,8 @@ classes/
|
||||
# Idea
|
||||
|
||||
.idea/
|
||||
!.idea/copyright/*
|
||||
!.idea/scopes/*
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
@@ -27,8 +29,8 @@ bin/
|
||||
|
||||
# macOS
|
||||
|
||||
*.DS_Store
|
||||
DS_Store
|
||||
|
||||
# Misc
|
||||
|
||||
run/
|
||||
run/
|
||||
@@ -1,4 +1,5 @@
|
||||
# ViaRewind
|
||||
|
||||
[](https://github.com/ViaVersion/ViaRewind/releases)
|
||||
[](https://github.com/ViaVersion/ViaRewind/actions)
|
||||
[](https://viaversion.com/discord)
|
||||
@@ -6,13 +7,17 @@
|
||||
**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):**
|
||||
**You can override the included version in [ViaFabric](https://modrinth.com/mod/viafabric)
|
||||
or [ViaProxy](https://github.com/ViaVersion/ViaProxy):**
|
||||
|
||||
- in **ViaFabric**, put ViaRewind into the `mods` folder
|
||||
- in **ViaProxy**, put ViaRewind into the `jars` folder
|
||||
|
||||
Note: when using ViaFabric <= 1.16.5 or J8 ViaProxy builds, you need [J8 ViaRewind](https://ci.viaversion.com/view/ViaRewind/job/ViaRewind-Java8/) builds.
|
||||
Note: when using ViaFabric <= 1.16.5 or J8 ViaProxy builds, you
|
||||
need [J8 ViaRewind](https://ci.viaversion.com/view/ViaRewind/job/ViaRewind-Java8/) builds.
|
||||
|
||||
**Requires [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) and [ViaBackwards](https://hangar.papermc.io/ViaVersion/ViaBackwards) to be installed..**
|
||||
**Requires [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion)
|
||||
and [ViaBackwards](https://hangar.papermc.io/ViaVersion/ViaBackwards) to be installed..**
|
||||
|
||||
Releases/Dev Builds
|
||||
-
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you discover a **security vulnerability**, please **do not** open a public issue. Instead, use one of the following
|
||||
**confidential contact methods**:
|
||||
|
||||
* **Email:** [security@viaversion.com](mailto:security@viaversion.com)
|
||||
* **Discord:** Join our [Discord server](https://discord.gg/viaversion) and visit
|
||||
the [#exploit-report](https://discord.com/channels/316206679014244363/1388847764137316485) channel for further
|
||||
instructions.
|
||||
|
||||
If your issue is **not security-related** (e.g., bug reports, feature requests, or usage questions), please use
|
||||
the [GitHub Issues page](https://github.com/ViaVersion/ViaRewind/issues) or contact us via
|
||||
the [Discord server](https://discord.gg/viaversion).
|
||||
+24
-11
@@ -1,10 +1,17 @@
|
||||
import de.florianmichael.baseproject.*
|
||||
import de.florianreuth.baseproject.core.configureEmbeddedDependencies
|
||||
import de.florianreuth.baseproject.integration.branchName
|
||||
import de.florianreuth.baseproject.integration.latestCommitHash
|
||||
import de.florianreuth.baseproject.integration.latestCommitMessage
|
||||
import de.florianreuth.baseproject.setupProject
|
||||
import de.florianreuth.baseproject.setupViaPublishing
|
||||
import net.raphimc.classtokenreplacer.extension.ClassTokenReplacerExtension
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
id("io.papermc.hangar-publish-plugin")
|
||||
id("com.modrinth.minotaur")
|
||||
id("de.florianmichael.baseproject.BaseProject")
|
||||
id("de.florianreuth.baseproject")
|
||||
id("net.raphimc.class-token-replacer") apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -13,7 +20,6 @@ allprojects {
|
||||
setupViaPublishing()
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.viaversion.com")
|
||||
maven("https://repo.papermc.io/repository/maven-public")
|
||||
maven("https://maven.fabricmc.net")
|
||||
@@ -21,11 +27,22 @@ allprojects {
|
||||
|
||||
}
|
||||
|
||||
val commitHash = latestCommitHash()
|
||||
|
||||
subprojects {
|
||||
|
||||
apply(plugin = "net.raphimc.class-token-replacer")
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.viaversion:viaversion:5.4.0")
|
||||
compileOnly("com.viaversion:viabackwards:5.4.0")
|
||||
compileOnly("com.viaversion:viaversion:5.12.0")
|
||||
compileOnly("com.viaversion:viabackwards:5.12.0")
|
||||
}
|
||||
|
||||
extensions.getByType<SourceSetContainer>().configureEach {
|
||||
extensions.getByType(ClassTokenReplacerExtension::class.java).apply {
|
||||
property("\${version}", project.version)
|
||||
property("\${impl_version}", "git-ViaRewind-${project.version}:${commitHash}")
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -33,18 +50,14 @@ subprojects {
|
||||
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)
|
||||
expand(mapOf("version" to projectVersion, "description" to projectDescription))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
base {
|
||||
archivesName.set("ViaRewind")
|
||||
}
|
||||
|
||||
val shade = configureShadedDependencies()
|
||||
val shade = configureEmbeddedDependencies()
|
||||
|
||||
dependencies {
|
||||
subprojects.forEach {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,14 +18,22 @@
|
||||
package com.viaversion.viarewind;
|
||||
|
||||
import com.viaversion.viarewind.api.ViaRewindPlatform;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.provider.InventoryProvider;
|
||||
import com.viaversion.viarewind.provider.BukkitInventoryProvider;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class BukkitPlugin extends JavaPlugin implements ViaRewindPlatform {
|
||||
|
||||
public BukkitPlugin() {
|
||||
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
|
||||
}
|
||||
public BukkitPlugin() {
|
||||
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
final ViaProviders providers = Via.getManager().getProviders();
|
||||
providers.use(InventoryProvider.class, new BukkitInventoryProvider());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.provider;
|
||||
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.provider.InventoryProvider;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public final class BukkitInventoryProvider extends InventoryProvider {
|
||||
|
||||
@Override
|
||||
public boolean hasElytra(final UserConnection connection) {
|
||||
final Player player = Bukkit.getPlayer(connection.getProtocolInfo().getUuid());
|
||||
final ItemStack chestplate = player.getInventory().getChestplate();
|
||||
return chestplate != null && chestplate.getType() == Material.ELYTRA;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
name: ViaRewind
|
||||
main: com.viaversion.viarewind.BukkitPlugin
|
||||
authors: [FlorianMichael/EnZaXD, Gerrygames, creeper123123321]
|
||||
authors: [ EnZaXD, Gerrygames, creeper123123321 ]
|
||||
version: ${version}
|
||||
description: ${description}
|
||||
website: https://viaversion.com/rewind
|
||||
api-version: 1.13
|
||||
folia-supported: true
|
||||
load: STARTUP
|
||||
depend: [ViaVersion, ViaBackwards]
|
||||
depend: [ ViaVersion, ViaBackwards ]
|
||||
+2
-16
@@ -1,29 +1,15 @@
|
||||
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")
|
||||
compileOnly("com.velocitypowered:velocity-native:3.4.0-SNAPSHOT")
|
||||
|
||||
viaProxy("net.raphimc:ViaProxy:3.4.2-SNAPSHOT") {
|
||||
viaProxy("net.raphimc:ViaProxy:[3.0.0,4.0.0)") {
|
||||
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) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,21 +23,21 @@ import com.viaversion.viarewind.api.ViaRewindPlatform;
|
||||
|
||||
public class ViaRewind {
|
||||
|
||||
private static ViaRewindPlatform platform;
|
||||
private static ViaRewindConfig config;
|
||||
private static ViaRewindPlatform platform;
|
||||
private static ViaRewindConfig config;
|
||||
|
||||
public static void init(ViaRewindPlatform platform, ViaRewindConfig config) {
|
||||
Preconditions.checkArgument(ViaRewind.platform == null, "ViaRewind is already initialized");
|
||||
public static void init(ViaRewindPlatform platform, ViaRewindConfig config) {
|
||||
Preconditions.checkArgument(ViaRewind.platform == null, "ViaRewind is already initialized");
|
||||
|
||||
ViaRewind.platform = platform;
|
||||
ViaRewind.config = config;
|
||||
}
|
||||
ViaRewind.platform = platform;
|
||||
ViaRewind.config = config;
|
||||
}
|
||||
|
||||
public static ViaRewindPlatform getPlatform() {
|
||||
return ViaRewind.platform;
|
||||
}
|
||||
public static ViaRewindPlatform getPlatform() {
|
||||
return ViaRewind.platform;
|
||||
}
|
||||
|
||||
public static ViaRewindConfig getConfig() {
|
||||
return ViaRewind.config;
|
||||
}
|
||||
public static ViaRewindConfig getConfig() {
|
||||
return ViaRewind.config;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,7 +18,6 @@
|
||||
package com.viaversion.viarewind;
|
||||
|
||||
import com.viaversion.viaversion.util.Config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
@@ -29,105 +28,105 @@ import java.util.logging.Logger;
|
||||
|
||||
public class ViaRewindConfig extends Config implements com.viaversion.viarewind.api.ViaRewindConfig {
|
||||
|
||||
private CooldownIndicator cooldownIndicator;
|
||||
private boolean replaceAdventureMode;
|
||||
private boolean replaceParticles;
|
||||
private int maxBookPages;
|
||||
private int maxBookPageSize;
|
||||
private boolean emulateWorldBorder;
|
||||
private boolean alwaysShowOriginalMobName;
|
||||
private String worldBorderParticle;
|
||||
private boolean enableOffhand;
|
||||
private String offhandCommand;
|
||||
private boolean emulateLevitationEffect;
|
||||
private boolean handlePlayerCombatPacket;
|
||||
private CooldownIndicator cooldownIndicator;
|
||||
private boolean replaceAdventureMode;
|
||||
private boolean replaceParticles;
|
||||
private int maxBookPages;
|
||||
private int maxBookPageSize;
|
||||
private boolean emulateWorldBorder;
|
||||
private boolean alwaysShowOriginalMobName;
|
||||
private String worldBorderParticle;
|
||||
private boolean enableOffhand;
|
||||
private String offhandCommand;
|
||||
private boolean emulateLevitationEffect;
|
||||
private boolean handlePlayerCombatPacket;
|
||||
|
||||
public ViaRewindConfig(File configFile, Logger logger) {
|
||||
super(configFile, logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
loadFields();
|
||||
}
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
loadFields();
|
||||
}
|
||||
|
||||
private void loadFields() {
|
||||
cooldownIndicator = CooldownIndicator.valueOf(getString("cooldown-indicator", "TITLE").toUpperCase());
|
||||
replaceAdventureMode = getBoolean("replace-adventure", false);
|
||||
replaceParticles = getBoolean("replace-particles", false);
|
||||
maxBookPages = getInt("max-book-pages", 100);
|
||||
maxBookPageSize = getInt("max-book-page-length", 5000);
|
||||
emulateWorldBorder = getBoolean("emulate-world-border", true);
|
||||
alwaysShowOriginalMobName = getBoolean("always-show-original-mob-name", true);
|
||||
worldBorderParticle = getString("world-border-particle", "fireworksSpark");
|
||||
enableOffhand = getBoolean("enable-offhand", true);
|
||||
offhandCommand = getString("offhand-command", "/offhand");
|
||||
emulateLevitationEffect = getBoolean("emulate-levitation-effect", true);
|
||||
handlePlayerCombatPacket = getBoolean("handle-player-combat-packet", true);
|
||||
}
|
||||
private void loadFields() {
|
||||
cooldownIndicator = CooldownIndicator.valueOf(getString("cooldown-indicator", "TITLE").toUpperCase());
|
||||
replaceAdventureMode = getBoolean("replace-adventure", false);
|
||||
replaceParticles = getBoolean("replace-particles", false);
|
||||
maxBookPages = getInt("max-book-pages", 100);
|
||||
maxBookPageSize = getInt("max-book-page-length", 5000);
|
||||
emulateWorldBorder = getBoolean("emulate-world-border", true);
|
||||
alwaysShowOriginalMobName = getBoolean("always-show-original-mob-name", true);
|
||||
worldBorderParticle = getString("world-border-particle", "fireworksSpark");
|
||||
enableOffhand = getBoolean("enable-offhand", true);
|
||||
offhandCommand = getString("offhand-command", "/offhand");
|
||||
emulateLevitationEffect = getBoolean("emulate-levitation-effect", true);
|
||||
handlePlayerCombatPacket = getBoolean("handle-player-combat-packet", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public CooldownIndicator getCooldownIndicator() {
|
||||
return cooldownIndicator;
|
||||
return cooldownIndicator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReplaceAdventureMode() {
|
||||
return replaceAdventureMode;
|
||||
return replaceAdventureMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReplaceParticles() {
|
||||
return replaceParticles;
|
||||
return replaceParticles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxBookPages() {
|
||||
return maxBookPages;
|
||||
return maxBookPages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxBookPageSize() {
|
||||
return maxBookPageSize;
|
||||
return maxBookPageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmulateWorldBorder() {
|
||||
return emulateWorldBorder;
|
||||
}
|
||||
@Override
|
||||
public boolean isEmulateWorldBorder() {
|
||||
return emulateWorldBorder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean alwaysShowOriginalMobName() {
|
||||
return alwaysShowOriginalMobName;
|
||||
}
|
||||
@Override
|
||||
public boolean alwaysShowOriginalMobName() {
|
||||
return alwaysShowOriginalMobName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldBorderParticle() {
|
||||
return worldBorderParticle;
|
||||
}
|
||||
@Override
|
||||
public String getWorldBorderParticle() {
|
||||
return worldBorderParticle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnableOffhand() {
|
||||
return enableOffhand;
|
||||
}
|
||||
@Override
|
||||
public boolean isEnableOffhand() {
|
||||
return enableOffhand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOffhandCommand() {
|
||||
return offhandCommand;
|
||||
}
|
||||
@Override
|
||||
public String getOffhandCommand() {
|
||||
return offhandCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean emulateLevitationEffect() {
|
||||
return emulateLevitationEffect;
|
||||
}
|
||||
@Override
|
||||
public boolean emulateLevitationEffect() {
|
||||
return emulateLevitationEffect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePlayerCombatPacket() {
|
||||
return handlePlayerCombatPacket;
|
||||
}
|
||||
@Override
|
||||
public boolean handlePlayerCombatPacket() {
|
||||
return handlePlayerCombatPacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public URL getDefaultConfigURL() {
|
||||
return getClass().getClassLoader().getResource("assets/viarewind/config.yml");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind;
|
||||
|
||||
import com.viaversion.viarewind.api.ViaRewindPlatform;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import java.io.File;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ViaRewindPlatformImpl implements ViaRewindPlatform {
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
public ViaRewindPlatformImpl() {
|
||||
logger = Via.getPlatform().createLogger("ViaRewind");
|
||||
init(new File(getDataFolder(), "viarewind.yml"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataFolder() {
|
||||
return Via.getPlatform().getDataFolder();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,97 +24,97 @@ import com.viaversion.viaversion.api.configuration.Config;
|
||||
*/
|
||||
public interface ViaRewindConfig extends Config {
|
||||
|
||||
enum CooldownIndicator {
|
||||
TITLE, ACTION_BAR, BOSS_BAR, DISABLED
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @return the cooldown indicator
|
||||
*/
|
||||
CooldownIndicator getCooldownIndicator();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @return the cooldown indicator
|
||||
*/
|
||||
CooldownIndicator getCooldownIndicator();
|
||||
/**
|
||||
* Replaces Adventure mode with Survival mode for 1.7.x clients
|
||||
* Enable this option if your server is using the 'CanDestroy'
|
||||
* or 'CanPlaceOn' flags on items
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean isReplaceAdventureMode();
|
||||
|
||||
/**
|
||||
* Replaces Adventure mode with Survival mode for 1.7.x clients
|
||||
* Enable this option if your server is using the 'CanDestroy'
|
||||
* or 'CanPlaceOn' flags on items
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean isReplaceAdventureMode();
|
||||
/**
|
||||
* Whether 1.9 particles should be replaced by similar ones in
|
||||
* 1.8 and lower
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean isReplaceParticles();
|
||||
|
||||
/**
|
||||
* Whether 1.9 particles should be replaced by similar ones in
|
||||
* 1.8 and lower
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean isReplaceParticles();
|
||||
/**
|
||||
* Max amount of pages for written books before a client gets kicked
|
||||
*
|
||||
* @return the max amount of pages
|
||||
*/
|
||||
int getMaxBookPages();
|
||||
|
||||
/**
|
||||
* Max amount of pages for written books before a client gets kicked
|
||||
*
|
||||
* @return the max amount of pages
|
||||
*/
|
||||
int getMaxBookPages();
|
||||
/**
|
||||
* Max amount of characters in the json (!) string of a book page before a client gets kicked
|
||||
*
|
||||
* @return the max amount of characters
|
||||
*/
|
||||
int getMaxBookPageSize();
|
||||
|
||||
/**
|
||||
* Max amount of characters in the json (!) string of a book page before a client gets kicked
|
||||
*
|
||||
* @return the max amount of characters
|
||||
*/
|
||||
int getMaxBookPageSize();
|
||||
/**
|
||||
* Whether to emulate the 1.8+ world border for 1.7.x clients
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean isEmulateWorldBorder();
|
||||
|
||||
/**
|
||||
* Whether to emulate the 1.8+ world border for 1.7.x clients
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean isEmulateWorldBorder();
|
||||
/**
|
||||
* Always shows the original mob's name instead of only when hovering over them with the cursor.
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean alwaysShowOriginalMobName();
|
||||
|
||||
/**
|
||||
* Always shows the original mob's name instead of only when hovering over them with the cursor.
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean alwaysShowOriginalMobName();
|
||||
/**
|
||||
* The particle to show the world border for the 1.8+ world border for 1.7.x clients
|
||||
*
|
||||
* @return the particle name
|
||||
*/
|
||||
String getWorldBorderParticle();
|
||||
|
||||
/**
|
||||
* The particle to show the world border for the 1.8+ world border for 1.7.x clients
|
||||
*
|
||||
* @return the particle name
|
||||
*/
|
||||
String getWorldBorderParticle();
|
||||
/**
|
||||
* If enabled, 1.8 players on 1.9+ servers can use /offhand to switch items between their main hand and offhand.
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean isEnableOffhand();
|
||||
|
||||
/**
|
||||
* If enabled, 1.8 players on 1.9+ servers can use /offhand to switch items between their main hand and offhand.
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean isEnableOffhand();
|
||||
/**
|
||||
* Allows to define the offhand command
|
||||
*
|
||||
* @return the offhand command
|
||||
*/
|
||||
String getOffhandCommand();
|
||||
|
||||
/**
|
||||
* Allows to define the offhand command
|
||||
*
|
||||
* @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 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();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
enum CooldownIndicator {
|
||||
TITLE, ACTION_BAR, BOSS_BAR, DISABLED
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,6 @@ import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolManager;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -34,59 +33,62 @@ import java.util.logging.Logger;
|
||||
*/
|
||||
public interface ViaRewindPlatform {
|
||||
|
||||
String VERSION = "${version}";
|
||||
String IMPL_VERSION = "${impl_version}";
|
||||
String VERSION = "${version}";
|
||||
String IMPL_VERSION = "${impl_version}";
|
||||
|
||||
/**
|
||||
* Initialize ViaRewind
|
||||
*/
|
||||
default void init(final File configFile) {
|
||||
ViaRewindConfig config = new ViaRewindConfig(configFile, getLogger());
|
||||
config.reload();
|
||||
Via.getManager().getConfigurationProvider().register(config);
|
||||
default void init(final File configFile) {
|
||||
init(new ViaRewindConfig(configFile, getLogger()));
|
||||
}
|
||||
|
||||
ViaRewind.init(this, config);
|
||||
/**
|
||||
* Initialize ViaRewind
|
||||
*/
|
||||
default void init(final com.viaversion.viarewind.api.ViaRewindConfig config) {
|
||||
config.reload();
|
||||
Via.getManager().getConfigurationProvider().register(config);
|
||||
|
||||
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
|
||||
ViaRewind.init(this, config);
|
||||
|
||||
getLogger().info("Registering protocols...");
|
||||
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
|
||||
protocolManager.registerProtocol(new Protocol1_7_6_10To1_7_2_5(), ProtocolVersion.v1_7_2, ProtocolVersion.v1_7_6);
|
||||
protocolManager.registerProtocol(new Protocol1_8To1_7_6_10(), ProtocolVersion.v1_7_6, ProtocolVersion.v1_8);
|
||||
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
|
||||
|
||||
protocolManager.registerProtocol(new Protocol1_9To1_8(), ProtocolVersion.v1_8, ProtocolVersion.v1_9);
|
||||
}
|
||||
getLogger().info("Registering protocols...");
|
||||
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
|
||||
protocolManager.registerProtocol(new Protocol1_7_6_10To1_7_2_5(), ProtocolVersion.v1_7_2, ProtocolVersion.v1_7_6);
|
||||
protocolManager.registerProtocol(new Protocol1_8To1_7_6_10(), ProtocolVersion.v1_7_6, ProtocolVersion.v1_8);
|
||||
|
||||
/**
|
||||
* Get the platform logger
|
||||
*
|
||||
* @return the logger
|
||||
*/
|
||||
Logger getLogger();
|
||||
protocolManager.registerProtocol(new Protocol1_9To1_8(), ProtocolVersion.v1_8, ProtocolVersion.v1_9);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ViaRewind's data folder.
|
||||
*
|
||||
* @return data folder
|
||||
*/
|
||||
File getDataFolder();
|
||||
/**
|
||||
* Get the platform logger
|
||||
*
|
||||
* @return the logger
|
||||
*/
|
||||
Logger getLogger();
|
||||
|
||||
/**
|
||||
* 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 ViaRewind's data folder.
|
||||
*
|
||||
* @return data folder
|
||||
*/
|
||||
File getDataFolder();
|
||||
|
||||
/**
|
||||
* 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";
|
||||
}
|
||||
/**
|
||||
* 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";
|
||||
}
|
||||
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.api.compression;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
/**
|
||||
* A ThreadLocal-based compression provider that either uses Velocity's native compression
|
||||
* or falls back to Java's built-in compression (Deflater/Inflater).
|
||||
*/
|
||||
public final class ThreadLocalCompressionProvider {
|
||||
|
||||
private static final boolean VELOCITY_NATIVES_AVAILABLE;
|
||||
|
||||
static {
|
||||
boolean velocityAvailable = false;
|
||||
try {
|
||||
Class.forName("com.velocitypowered.natives.compression.VelocityCompressor");
|
||||
velocityAvailable = true;
|
||||
} catch (final ClassNotFoundException ignored) {
|
||||
}
|
||||
VELOCITY_NATIVES_AVAILABLE = velocityAvailable;
|
||||
}
|
||||
|
||||
// ThreadLocal for Java's Deflater (used when Velocity natives are not available)
|
||||
private static final ThreadLocal<Deflater> JAVA_DEFLATER = ThreadLocal.withInitial(Deflater::new);
|
||||
|
||||
// ThreadLocal for Java's Inflater (used when Velocity natives are not available)
|
||||
private static final ThreadLocal<Inflater> JAVA_INFLATER = ThreadLocal.withInitial(Inflater::new);
|
||||
|
||||
private ThreadLocalCompressionProvider() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses data from the source buffer into the destination buffer.
|
||||
*
|
||||
* @param source the source buffer containing uncompressed data
|
||||
* @param destination the destination buffer to write compressed data to
|
||||
* @throws DataFormatException if compression fails
|
||||
*/
|
||||
public static void deflate(final ByteBuf source, final ByteBuf destination) throws DataFormatException {
|
||||
if (VELOCITY_NATIVES_AVAILABLE) {
|
||||
deflateVelocity(source, destination);
|
||||
} else {
|
||||
deflateJava(source, destination);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decompresses data from the source buffer into the destination buffer.
|
||||
*
|
||||
* @param source the source buffer containing compressed data
|
||||
* @param destination the destination buffer to write decompressed data to
|
||||
* @param expectedSize the expected size of the decompressed data
|
||||
* @throws DataFormatException if decompression fails
|
||||
*/
|
||||
public static void inflate(final ByteBuf source, final ByteBuf destination, final int expectedSize) throws DataFormatException {
|
||||
if (VELOCITY_NATIVES_AVAILABLE) {
|
||||
inflateVelocity(source, destination, expectedSize);
|
||||
} else {
|
||||
inflateJava(source, destination, expectedSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Java native implementation
|
||||
|
||||
private static void deflateJava(final ByteBuf source, final ByteBuf destination) throws DataFormatException {
|
||||
ByteBuf temp = source;
|
||||
if (!source.hasArray()) {
|
||||
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(source);
|
||||
} else {
|
||||
source.retain();
|
||||
}
|
||||
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer();
|
||||
try {
|
||||
final Deflater deflater = JAVA_DEFLATER.get();
|
||||
deflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
|
||||
deflater.finish();
|
||||
|
||||
while (!deflater.finished()) {
|
||||
output.ensureWritable(4096);
|
||||
output.writerIndex(output.writerIndex() + deflater.deflate(output.array(), output.arrayOffset() + output.writerIndex(), output.writableBytes()));
|
||||
}
|
||||
destination.writeBytes(output);
|
||||
} finally {
|
||||
output.release();
|
||||
temp.release();
|
||||
JAVA_DEFLATER.get().reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void inflateJava(final ByteBuf source, final ByteBuf destination, final int expectedSize) throws DataFormatException {
|
||||
ByteBuf temp = source;
|
||||
if (!source.hasArray()) {
|
||||
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(source);
|
||||
} else {
|
||||
source.retain();
|
||||
}
|
||||
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer(expectedSize, expectedSize);
|
||||
try {
|
||||
final Inflater inflater = JAVA_INFLATER.get();
|
||||
inflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
|
||||
output.writerIndex(output.writerIndex() + inflater.inflate(output.array(), output.arrayOffset(), expectedSize));
|
||||
destination.writeBytes(output);
|
||||
} finally {
|
||||
output.release();
|
||||
temp.release();
|
||||
JAVA_INFLATER.get().reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Velocity native implementation
|
||||
private static void deflateVelocity(final ByteBuf source, final ByteBuf destination) throws DataFormatException {
|
||||
VelocityHolder.deflate(source, destination);
|
||||
}
|
||||
|
||||
private static void inflateVelocity(final ByteBuf source, final ByteBuf destination, final int expectedSize) throws DataFormatException {
|
||||
VelocityHolder.inflate(source, destination, expectedSize);
|
||||
}
|
||||
|
||||
private static final class VelocityHolder {
|
||||
|
||||
private static final ThreadLocal<com.velocitypowered.natives.compression.VelocityCompressor> COMPRESSOR =
|
||||
ThreadLocal.withInitial(() -> com.velocitypowered.natives.util.Natives.compress.get().create(-1));
|
||||
|
||||
static void deflate(final ByteBuf source, final ByteBuf destination) throws DataFormatException {
|
||||
COMPRESSOR.get().deflate(source, destination);
|
||||
}
|
||||
|
||||
static void inflate(final ByteBuf source, final ByteBuf destination, final int expectedSize) throws DataFormatException {
|
||||
COMPRESSOR.get().inflate(source, destination, expectedSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,25 +17,33 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.api.data;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
|
||||
import com.viaversion.viarewind.ViaRewind;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
|
||||
import com.viaversion.viaversion.api.data.FullMappings;
|
||||
import com.viaversion.viaversion.api.data.LegacyFullStringMappingsBase;
|
||||
import com.viaversion.viaversion.api.data.MappingDataLoader;
|
||||
import com.viaversion.viaversion.api.data.Mappings;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class RewindMappingData extends BackwardsMappingData {
|
||||
|
||||
public RewindMappingData(String unmappedVersion, String mappedVersion) {
|
||||
super(unmappedVersion, mappedVersion);
|
||||
}
|
||||
public RewindMappingData(String unmappedVersion, String mappedVersion) {
|
||||
super(unmappedVersion, mappedVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Logger getLogger() {
|
||||
return ViaRewind.getPlatform().getLogger();
|
||||
}
|
||||
@Override
|
||||
protected Logger getLogger() {
|
||||
return ViaRewind.getPlatform().getLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompoundTag readMappingsFile(String name) {
|
||||
return RewindMappingDataLoader.INSTANCE.loadNBTFromDir(name);
|
||||
}
|
||||
@Override
|
||||
protected CompoundTag readMappingsFile(String name) {
|
||||
return RewindMappingDataLoader.INSTANCE.loadNBTFromDir(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FullMappings createFullMappings(MappingDataLoader.IdentifiersPair identifiersPair, Mappings mappings) {
|
||||
return new LegacyFullStringMappingsBase(identifiersPair, mappings);
|
||||
}
|
||||
}
|
||||
+13
-14
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,26 +19,25 @@ package com.viaversion.viarewind.api.data;
|
||||
|
||||
import com.viaversion.viabackwards.api.data.BackwardsMappingDataLoader;
|
||||
import com.viaversion.viarewind.ViaRewind;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class RewindMappingDataLoader extends BackwardsMappingDataLoader {
|
||||
|
||||
public static final RewindMappingDataLoader INSTANCE = new RewindMappingDataLoader();
|
||||
public static final RewindMappingDataLoader INSTANCE = new RewindMappingDataLoader();
|
||||
|
||||
public RewindMappingDataLoader() {
|
||||
super(RewindMappingDataLoader.class, "assets/viarewind/data/");
|
||||
}
|
||||
public RewindMappingDataLoader() {
|
||||
super(RewindMappingDataLoader.class, "assets/viarewind/data/");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return ViaRewind.getPlatform().getLogger();
|
||||
}
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return ViaRewind.getPlatform().getLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataFolder() {
|
||||
return ViaRewind.getPlatform().getDataFolder();
|
||||
}
|
||||
@Override
|
||||
public File getDataFolder() {
|
||||
return ViaRewind.getPlatform().getDataFolder();
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.api.minecraft;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.NibbleArray;
|
||||
|
||||
public class ExtendedBlockStorage {
|
||||
private final byte[] blockLSBArray = new byte[ChunkSection.SIZE];
|
||||
|
||||
private final NibbleArray blockMetadataArray = new NibbleArray(this.blockLSBArray.length);
|
||||
private final NibbleArray blockLightArray = new NibbleArray(this.blockLSBArray.length);
|
||||
|
||||
private NibbleArray blockMSBArray;
|
||||
private NibbleArray skyLightArray;
|
||||
|
||||
public ExtendedBlockStorage(final boolean skylight) {
|
||||
if (skylight) {
|
||||
this.skyLightArray = new NibbleArray(this.blockLSBArray.length);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBlockId(final int x, final int y, final int z, final int value) {
|
||||
this.blockLSBArray[ChunkSection.index(x, y, z)] = (byte) (value & 255);
|
||||
if (value > 255) {
|
||||
this.getOrCreateBlockMSBArray().set(x, y, z, (value & 0xF00) >> 8);
|
||||
} else if (this.blockMSBArray != null) {
|
||||
this.blockMSBArray.set(x, y, z, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBlockMetadata(final int x, final int y, final int z, final int value) {
|
||||
this.blockMetadataArray.set(x, y, z, value);
|
||||
}
|
||||
|
||||
public boolean hasBlockMSBArray() {
|
||||
return this.blockMSBArray != null;
|
||||
}
|
||||
|
||||
public byte[] getBlockLSBArray() {
|
||||
return this.blockLSBArray;
|
||||
}
|
||||
|
||||
public NibbleArray getOrCreateBlockMSBArray() {
|
||||
if (this.blockMSBArray == null) {
|
||||
return this.blockMSBArray = new NibbleArray(this.blockLSBArray.length);
|
||||
}
|
||||
return this.blockMSBArray;
|
||||
}
|
||||
|
||||
public NibbleArray getBlockMetadataArray() {
|
||||
return this.blockMetadataArray;
|
||||
}
|
||||
|
||||
public NibbleArray getBlockLightArray() {
|
||||
return this.blockLightArray;
|
||||
}
|
||||
|
||||
public NibbleArray getSkyLightArray() {
|
||||
return this.skyLightArray;
|
||||
}
|
||||
}
|
||||
+25
-25
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,33 +23,33 @@ import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
|
||||
public enum EntityDataTypes1_7_6_10 implements EntityDataType {
|
||||
BYTE(0, Types.BYTE),
|
||||
SHORT(1, Types.SHORT),
|
||||
INT(2, Types.INT),
|
||||
FLOAT(3, Types.FLOAT),
|
||||
STRING(4, Types.STRING),
|
||||
ITEM(5, RewindTypes.COMPRESSED_NBT_ITEM),
|
||||
POSITION(6, Types.VECTOR);
|
||||
BYTE(0, Types.BYTE),
|
||||
SHORT(1, Types.SHORT),
|
||||
INT(2, Types.INT),
|
||||
FLOAT(3, Types.FLOAT),
|
||||
STRING(4, Types.STRING),
|
||||
ITEM(5, RewindTypes.COMPRESSED_NBT_ITEM),
|
||||
POSITION(6, Types.VECTOR);
|
||||
|
||||
private final int typeID;
|
||||
private final Type<?> type;
|
||||
private final int typeID;
|
||||
private final Type<?> type;
|
||||
|
||||
EntityDataTypes1_7_6_10(int typeID, Type<?> type) {
|
||||
this.typeID = typeID;
|
||||
this.type = type;
|
||||
}
|
||||
EntityDataTypes1_7_6_10(int typeID, Type<?> type) {
|
||||
this.typeID = typeID;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static EntityDataTypes1_7_6_10 byId(int id) {
|
||||
return values()[id];
|
||||
}
|
||||
public static EntityDataTypes1_7_6_10 byId(int id) {
|
||||
return values()[id];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int typeId() {
|
||||
return this.typeID;
|
||||
}
|
||||
@Override
|
||||
public int typeId() {
|
||||
return this.typeID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<?> type() {
|
||||
return this.type;
|
||||
}
|
||||
@Override
|
||||
public Type<?> type() {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,19 +18,19 @@
|
||||
package com.viaversion.viarewind.api.minecraft.math;
|
||||
|
||||
public class AABB {
|
||||
Vector3d min;
|
||||
Vector3d max;
|
||||
Vector3d min;
|
||||
Vector3d max;
|
||||
|
||||
public AABB(Vector3d min, Vector3d max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
public AABB(Vector3d min, Vector3d max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public Vector3d getMin() {
|
||||
return this.min;
|
||||
}
|
||||
public Vector3d getMin() {
|
||||
return this.min;
|
||||
}
|
||||
|
||||
public Vector3d getMax() {
|
||||
return this.max;
|
||||
}
|
||||
public Vector3d getMax() {
|
||||
return this.max;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,19 +18,19 @@
|
||||
package com.viaversion.viarewind.api.minecraft.math;
|
||||
|
||||
public class Ray3d {
|
||||
Vector3d start;
|
||||
Vector3d dir;
|
||||
Vector3d start;
|
||||
Vector3d dir;
|
||||
|
||||
public Ray3d(Vector3d start, Vector3d dir) {
|
||||
this.start = start;
|
||||
this.dir = dir;
|
||||
}
|
||||
public Ray3d(Vector3d start, Vector3d dir) {
|
||||
this.start = start;
|
||||
this.dir = dir;
|
||||
}
|
||||
|
||||
public Vector3d getStart() {
|
||||
return this.start;
|
||||
}
|
||||
public Vector3d getStart() {
|
||||
return this.start;
|
||||
}
|
||||
|
||||
public Vector3d getDir() {
|
||||
return this.dir;
|
||||
}
|
||||
public Vector3d getDir() {
|
||||
return this.dir;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,40 +19,40 @@ package com.viaversion.viarewind.api.minecraft.math;
|
||||
|
||||
public class RayTracing {
|
||||
|
||||
public static Vector3d trace(Ray3d ray, AABB aabb, double distance) {
|
||||
Vector3d invDir = new Vector3d(1f / ray.dir.x, 1f / ray.dir.y, 1f / ray.dir.z);
|
||||
public static Vector3d trace(Ray3d ray, AABB aabb, double distance) {
|
||||
Vector3d invDir = new Vector3d(1f / ray.dir.x, 1f / ray.dir.y, 1f / ray.dir.z);
|
||||
|
||||
boolean signDirX = invDir.x < 0;
|
||||
boolean signDirY = invDir.y < 0;
|
||||
boolean signDirZ = invDir.z < 0;
|
||||
boolean signDirX = invDir.x < 0;
|
||||
boolean signDirY = invDir.y < 0;
|
||||
boolean signDirZ = invDir.z < 0;
|
||||
|
||||
Vector3d bbox = signDirX ? aabb.max : aabb.min;
|
||||
double tmin = (bbox.x - ray.start.x) * invDir.x;
|
||||
bbox = signDirX ? aabb.min : aabb.max;
|
||||
double tmax = (bbox.x - ray.start.x) * invDir.x;
|
||||
bbox = signDirY ? aabb.max : aabb.min;
|
||||
double tymin = (bbox.y - ray.start.y) * invDir.y;
|
||||
bbox = signDirY ? aabb.min : aabb.max;
|
||||
double tymax = (bbox.y - ray.start.y) * invDir.y;
|
||||
Vector3d bbox = signDirX ? aabb.max : aabb.min;
|
||||
double tmin = (bbox.x - ray.start.x) * invDir.x;
|
||||
bbox = signDirX ? aabb.min : aabb.max;
|
||||
double tmax = (bbox.x - ray.start.x) * invDir.x;
|
||||
bbox = signDirY ? aabb.max : aabb.min;
|
||||
double tymin = (bbox.y - ray.start.y) * invDir.y;
|
||||
bbox = signDirY ? aabb.min : aabb.max;
|
||||
double tymax = (bbox.y - ray.start.y) * invDir.y;
|
||||
|
||||
if (tmin > tymax || tymin > tmax) return null;
|
||||
if (tmin > tymax || tymin > tmax) return null;
|
||||
|
||||
if (tymin > tmin) tmin = tymin;
|
||||
if (tymin > tmin) tmin = tymin;
|
||||
|
||||
if (tymax < tmax) tmax = tymax;
|
||||
if (tymax < tmax) tmax = tymax;
|
||||
|
||||
bbox = signDirZ ? aabb.max : aabb.min;
|
||||
double tzmin = (bbox.z - ray.start.z) * invDir.z;
|
||||
bbox = signDirZ ? aabb.min : aabb.max;
|
||||
double tzmax = (bbox.z - ray.start.z) * invDir.z;
|
||||
bbox = signDirZ ? aabb.max : aabb.min;
|
||||
double tzmin = (bbox.z - ray.start.z) * invDir.z;
|
||||
bbox = signDirZ ? aabb.min : aabb.max;
|
||||
double tzmax = (bbox.z - ray.start.z) * invDir.z;
|
||||
|
||||
if (tmin > tzmax || tzmin > tmax) return null;
|
||||
if (tmin > tzmax || tzmin > tmax) return null;
|
||||
|
||||
if (tzmin > tmin) tmin = tzmin;
|
||||
if (tzmin > tmin) tmin = tzmin;
|
||||
|
||||
if (tzmax < tmax) tmax = tzmax;
|
||||
if (tzmax < tmax) tmax = tzmax;
|
||||
|
||||
return tmin <= distance && tmax > 0 ? ray.start.clone().add(ray.dir.clone().normalize().multiply(tmin)) : null;
|
||||
}
|
||||
return tmin <= distance && tmax > 0 ? ray.start.clone().add(ray.dir.clone().normalize().multiply(tmin)) : null;
|
||||
}
|
||||
|
||||
}
|
||||
+63
-67
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,87 +17,83 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.api.minecraft.math;
|
||||
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.EntityTracker1_9;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.Vector;
|
||||
|
||||
@Deprecated // ?????????
|
||||
public class RelativeMoveUtil {
|
||||
|
||||
public static Vector[] calculateRelativeMoves(UserConnection user, int entityId, int relX, int relY, int relZ) {
|
||||
EntityTracker1_9 tracker = user.getEntityTracker(Protocol1_9To1_8.class);
|
||||
public static Vector[] calculateRelativeMoves(EntityTracker1_9 tracker, int entityId, int relX, int relY, int relZ) {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
Vector offset = tracker.getEntityOffset(entityId);
|
||||
if (offset != null) {
|
||||
relX += offset.blockX();
|
||||
relY += offset.blockY();
|
||||
relZ += offset.blockZ();
|
||||
}
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
Vector offset = tracker.getEntityOffset(entityId);
|
||||
if (offset != null) {
|
||||
relX += offset.blockX();
|
||||
relY += offset.blockY();
|
||||
relZ += offset.blockZ();
|
||||
}
|
||||
if (relX > Short.MAX_VALUE) {
|
||||
x = relX - Short.MAX_VALUE;
|
||||
relX = Short.MAX_VALUE;
|
||||
} else if (relX < Short.MIN_VALUE) {
|
||||
x = relX - Short.MIN_VALUE;
|
||||
relX = Short.MIN_VALUE;
|
||||
} else {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (relX > Short.MAX_VALUE) {
|
||||
x = relX - Short.MAX_VALUE;
|
||||
relX = Short.MAX_VALUE;
|
||||
} else if (relX < Short.MIN_VALUE) {
|
||||
x = relX - Short.MIN_VALUE;
|
||||
relX = Short.MIN_VALUE;
|
||||
} else {
|
||||
x = 0;
|
||||
}
|
||||
if (relY > Short.MAX_VALUE) {
|
||||
y = relY - Short.MAX_VALUE;
|
||||
relY = Short.MAX_VALUE;
|
||||
} else if (relY < Short.MIN_VALUE) {
|
||||
y = relY - Short.MIN_VALUE;
|
||||
relY = Short.MIN_VALUE;
|
||||
} else {
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (relY > Short.MAX_VALUE) {
|
||||
y = relY - Short.MAX_VALUE;
|
||||
relY = Short.MAX_VALUE;
|
||||
} else if (relY < Short.MIN_VALUE) {
|
||||
y = relY - Short.MIN_VALUE;
|
||||
relY = Short.MIN_VALUE;
|
||||
} else {
|
||||
y = 0;
|
||||
}
|
||||
if (relZ > Short.MAX_VALUE) {
|
||||
z = relZ - Short.MAX_VALUE;
|
||||
relZ = Short.MAX_VALUE;
|
||||
} else if (relZ < Short.MIN_VALUE) {
|
||||
z = relZ - Short.MIN_VALUE;
|
||||
relZ = Short.MIN_VALUE;
|
||||
} else {
|
||||
z = 0;
|
||||
}
|
||||
|
||||
if (relZ > Short.MAX_VALUE) {
|
||||
z = relZ - Short.MAX_VALUE;
|
||||
relZ = Short.MAX_VALUE;
|
||||
} else if (relZ < Short.MIN_VALUE) {
|
||||
z = relZ - Short.MIN_VALUE;
|
||||
relZ = Short.MIN_VALUE;
|
||||
} else {
|
||||
z = 0;
|
||||
}
|
||||
int sentRelX, sentRelY, sentRelZ;
|
||||
Vector[] moves;
|
||||
|
||||
int sentRelX, sentRelY, sentRelZ;
|
||||
Vector[] moves;
|
||||
if (relX > Byte.MAX_VALUE * 128 || relX < Byte.MIN_VALUE * 128 || relY > Byte.MAX_VALUE * 128 || relY < Byte.MIN_VALUE * 128 || relZ > Byte.MAX_VALUE * 128 || relZ < Byte.MIN_VALUE * 128) {
|
||||
byte relX1 = (byte) (relX / 256);
|
||||
byte relX2 = (byte) (Math.round((relX - relX1 * 128) / 128f));
|
||||
byte relY1 = (byte) (relY / 256);
|
||||
byte relY2 = (byte) (Math.round((relY - relY1 * 128) / 128f));
|
||||
byte relZ1 = (byte) (relZ / 256);
|
||||
byte relZ2 = (byte) (Math.round((relZ - relZ1 * 128) / 128f));
|
||||
|
||||
if (relX > Byte.MAX_VALUE * 128 || relX < Byte.MIN_VALUE * 128 || relY > Byte.MAX_VALUE * 128 || relY < Byte.MIN_VALUE * 128 || relZ > Byte.MAX_VALUE * 128 || relZ < Byte.MIN_VALUE * 128) {
|
||||
byte relX1 = (byte) (relX / 256);
|
||||
byte relX2 = (byte) (Math.round((relX - relX1 * 128) / 128f));
|
||||
byte relY1 = (byte) (relY / 256);
|
||||
byte relY2 = (byte) (Math.round((relY - relY1 * 128) / 128f));
|
||||
byte relZ1 = (byte) (relZ / 256);
|
||||
byte relZ2 = (byte) (Math.round((relZ - relZ1 * 128) / 128f));
|
||||
sentRelX = relX1 + relX2;
|
||||
sentRelY = relY1 + relY2;
|
||||
sentRelZ = relZ1 + relZ2;
|
||||
|
||||
sentRelX = relX1 + relX2;
|
||||
sentRelY = relY1 + relY2;
|
||||
sentRelZ = relZ1 + relZ2;
|
||||
moves = new Vector[]{new Vector(relX1, relY1, relZ1), new Vector(relX2, relY2, relZ2)};
|
||||
} else {
|
||||
sentRelX = Math.round(relX / 128f);
|
||||
sentRelY = Math.round(relY / 128f);
|
||||
sentRelZ = Math.round(relZ / 128f);
|
||||
|
||||
moves = new Vector[]{new Vector(relX1, relY1, relZ1), new Vector(relX2, relY2, relZ2)};
|
||||
} else {
|
||||
sentRelX = Math.round(relX / 128f);
|
||||
sentRelY = Math.round(relY / 128f);
|
||||
sentRelZ = Math.round(relZ / 128f);
|
||||
moves = new Vector[]{new Vector(sentRelX, sentRelY, sentRelZ)};
|
||||
}
|
||||
|
||||
moves = new Vector[]{new Vector(sentRelX, sentRelY, sentRelZ)};
|
||||
}
|
||||
x = x + relX - sentRelX * 128;
|
||||
y = y + relY - sentRelY * 128;
|
||||
z = z + relZ - sentRelZ * 128;
|
||||
|
||||
x = x + relX - sentRelX * 128;
|
||||
y = y + relY - sentRelY * 128;
|
||||
z = z + relZ - sentRelZ * 128;
|
||||
tracker.setEntityOffset(entityId, new Vector(x, y, z));
|
||||
|
||||
tracker.setEntityOffset(entityId, new Vector(x, y, z));
|
||||
|
||||
return moves;
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,109 +20,109 @@ package com.viaversion.viarewind.api.minecraft.math;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Vector3d {
|
||||
double x, y, z;
|
||||
double x, y, z;
|
||||
|
||||
public Vector3d(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
public Vector3d(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public Vector3d() {
|
||||
}
|
||||
public Vector3d() {
|
||||
}
|
||||
|
||||
public void set(Vector3d vec) {
|
||||
this.x = vec.x;
|
||||
this.y = vec.y;
|
||||
this.z = vec.z;
|
||||
}
|
||||
public void set(Vector3d vec) {
|
||||
this.x = vec.x;
|
||||
this.y = vec.y;
|
||||
this.z = vec.z;
|
||||
}
|
||||
|
||||
public Vector3d set(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
return this;
|
||||
}
|
||||
public Vector3d set(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3d multiply(double a) {
|
||||
this.x *= a;
|
||||
this.y *= a;
|
||||
this.z *= a;
|
||||
return this;
|
||||
}
|
||||
public Vector3d multiply(double a) {
|
||||
this.x *= a;
|
||||
this.y *= a;
|
||||
this.z *= a;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3d add(Vector3d vec) {
|
||||
this.x += vec.x;
|
||||
this.y += vec.y;
|
||||
this.z += vec.z;
|
||||
return this;
|
||||
}
|
||||
public Vector3d add(Vector3d vec) {
|
||||
this.x += vec.x;
|
||||
this.y += vec.y;
|
||||
this.z += vec.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3d substract(Vector3d vec) {
|
||||
this.x -= vec.x;
|
||||
this.y -= vec.y;
|
||||
this.z -= vec.z;
|
||||
return this;
|
||||
}
|
||||
public Vector3d substract(Vector3d vec) {
|
||||
this.x -= vec.x;
|
||||
this.y -= vec.y;
|
||||
this.z -= vec.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double length() {
|
||||
return Math.sqrt(lengthSquared());
|
||||
}
|
||||
public double length() {
|
||||
return Math.sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
public double lengthSquared() {
|
||||
return this.x * this.x + this.y * this.y + this.z * this.z;
|
||||
}
|
||||
public double lengthSquared() {
|
||||
return this.x * this.x + this.y * this.y + this.z * this.z;
|
||||
}
|
||||
|
||||
public Vector3d normalize() {
|
||||
double length = length();
|
||||
multiply(1.0 / length);
|
||||
return this;
|
||||
}
|
||||
public Vector3d normalize() {
|
||||
double length = length();
|
||||
multiply(1.0 / length);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3d clone() {
|
||||
return new Vector3d(this.x, this.y, this.z);
|
||||
}
|
||||
@Override
|
||||
public Vector3d clone() {
|
||||
return new Vector3d(this.x, this.y, this.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Vector3d vector3d = (Vector3d) o;
|
||||
return Double.compare(vector3d.x, x) == 0 && Double.compare(vector3d.y, y) == 0 && Double.compare(vector3d.z, z) == 0;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Vector3d vector3d = (Vector3d) o;
|
||||
return Double.compare(vector3d.x, x) == 0 && Double.compare(vector3d.y, y) == 0 && Double.compare(vector3d.z, z) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Vector3d{" + "x=" + x + ", y=" + y + ", z=" + z + '}';
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Vector3d{" + "x=" + x + ", y=" + y + ", z=" + z + '}';
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return this.x;
|
||||
}
|
||||
public double getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return this.y;
|
||||
}
|
||||
public void setX(double x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return this.z;
|
||||
}
|
||||
public double getY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
public void setX(double x) {
|
||||
this.x = x;
|
||||
}
|
||||
public void setY(double y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public void setY(double y) {
|
||||
this.y = y;
|
||||
}
|
||||
public double getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
public void setZ(double z) {
|
||||
this.z = z;
|
||||
}
|
||||
public void setZ(double z) {
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,8 +23,8 @@ import io.netty.handler.codec.MessageToByteEncoder;
|
||||
|
||||
public class ForwardMessageToByteEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) {
|
||||
out.writeBytes(msg);
|
||||
}
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) {
|
||||
out.writeBytes(msg);
|
||||
}
|
||||
}
|
||||
+12
-12
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -26,17 +26,17 @@ import com.viaversion.viaversion.libs.gson.JsonObject;
|
||||
|
||||
public class VRBlockItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType, T extends BackwardsProtocol<C, ?, ?, S>> extends LegacyBlockItemRewriter<C, S, T> {
|
||||
|
||||
protected VRBlockItemRewriter(T protocol, String name) {
|
||||
super(protocol, name);
|
||||
}
|
||||
protected VRBlockItemRewriter(T protocol, String name) {
|
||||
super(protocol, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsonObject readMappingsFile(String name) {
|
||||
return RewindMappingDataLoader.INSTANCE.loadFromDataDir(name);
|
||||
}
|
||||
@Override
|
||||
protected JsonObject readMappingsFile(String name) {
|
||||
return RewindMappingDataLoader.INSTANCE.loadFromDataDir(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nbtTagName() {
|
||||
return "VR|" + protocol.getClass().getSimpleName();
|
||||
}
|
||||
@Override
|
||||
public String nbtTagName() {
|
||||
return "VR|" + protocol.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -31,36 +31,36 @@ import com.viaversion.viaversion.data.entity.EntityTrackerBase;
|
||||
|
||||
public abstract class VREntityRewriter<C extends ClientboundPacketType, T extends BackwardsProtocol<C, ?, ?, ?>> extends LegacyEntityRewriter<C, T> {
|
||||
|
||||
public VREntityRewriter(T protocol) {
|
||||
super(protocol, EntityDataTypes1_8.STRING, EntityDataTypes1_8.BYTE);
|
||||
}
|
||||
public VREntityRewriter(T protocol) {
|
||||
super(protocol, EntityDataTypes1_8.STRING, EntityDataTypes1_8.BYTE);
|
||||
}
|
||||
|
||||
public VREntityRewriter(T protocol, EntityDataType displayType, EntityDataType displayVisibilityType) {
|
||||
super(protocol, displayType, displayVisibilityType);
|
||||
}
|
||||
public VREntityRewriter(T protocol, EntityDataType displayType, EntityDataType displayVisibilityType) {
|
||||
super(protocol, displayType, displayVisibilityType);
|
||||
}
|
||||
|
||||
protected void removeEntities(final UserConnection connection, final int[] entities) {
|
||||
final EntityTrackerBase tracker = tracker(connection);
|
||||
for (int entityId : entities) {
|
||||
tracker.removeEntity(entityId);
|
||||
}
|
||||
}
|
||||
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);
|
||||
};
|
||||
}
|
||||
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 getDisplayVisibilityDataValue() {
|
||||
return (byte) 1;
|
||||
}
|
||||
@Override
|
||||
protected Object getDisplayVisibilityDataValue() {
|
||||
return (byte) 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean alwaysShowOriginalMobName() {
|
||||
return ViaRewind.getConfig().alwaysShowOriginalMobName();
|
||||
}
|
||||
@Override
|
||||
protected boolean alwaysShowOriginalMobName() {
|
||||
return ViaRewind.getConfig().alwaysShowOriginalMobName();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,23 +22,23 @@ import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class IntArrayType extends Type<int[]> {
|
||||
|
||||
public IntArrayType() {
|
||||
super(int[].class);
|
||||
}
|
||||
public IntArrayType() {
|
||||
super(int[].class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] read(ByteBuf byteBuf) {
|
||||
byte size = byteBuf.readByte();
|
||||
int[] array = new int[size];
|
||||
for (byte i = 0; i < size; i++) {
|
||||
array[i] = byteBuf.readInt();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
@Override
|
||||
public int[] read(ByteBuf byteBuf) {
|
||||
byte size = byteBuf.readByte();
|
||||
int[] array = new int[size];
|
||||
for (byte i = 0; i < size; i++) {
|
||||
array[i] = byteBuf.readInt();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf byteBuf, int[] array) {
|
||||
byteBuf.writeByte(array.length);
|
||||
for (int i : array) byteBuf.writeInt(i);
|
||||
}
|
||||
@Override
|
||||
public void write(ByteBuf byteBuf, int[] array) {
|
||||
byteBuf.writeByte(array.length);
|
||||
for (int i : array) byteBuf.writeInt(i);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,34 +20,33 @@ package com.viaversion.viarewind.api.type;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
public class PositionVarYType<T extends Number> extends Type<BlockPosition> {
|
||||
|
||||
private final Type<T> yType;
|
||||
private final IntFunction<T> toY;
|
||||
private final Type<T> yType;
|
||||
private final IntFunction<T> toY;
|
||||
|
||||
public PositionVarYType(final Type<T> yType, final IntFunction<T> toY) {
|
||||
super(BlockPosition.class);
|
||||
public PositionVarYType(final Type<T> yType, final IntFunction<T> toY) {
|
||||
super(BlockPosition.class);
|
||||
|
||||
this.yType = yType;
|
||||
this.toY = toY;
|
||||
}
|
||||
this.yType = yType;
|
||||
this.toY = toY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosition read(ByteBuf buffer) {
|
||||
final int x = buffer.readInt();
|
||||
final int y = yType.read(buffer).intValue();
|
||||
final int z = buffer.readInt();
|
||||
@Override
|
||||
public BlockPosition read(ByteBuf buffer) {
|
||||
final int x = buffer.readInt();
|
||||
final int y = yType.read(buffer).intValue();
|
||||
final int z = buffer.readInt();
|
||||
|
||||
return new BlockPosition(x, y, z);
|
||||
}
|
||||
return new BlockPosition(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, BlockPosition value) {
|
||||
buffer.writeInt(value.x());
|
||||
yType.write(buffer, this.toY.apply(value.y()));
|
||||
buffer.writeInt(value.z());
|
||||
}
|
||||
@Override
|
||||
public void write(ByteBuf buffer, BlockPosition value) {
|
||||
buffer.writeInt(value.x());
|
||||
yType.write(buffer, this.toY.apply(value.y()));
|
||||
buffer.writeInt(value.z());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,18 +17,17 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.api.type;
|
||||
|
||||
import com.viaversion.viarewind.api.type.item.NBTType;
|
||||
import com.viaversion.viarewind.api.type.item.ItemArrayType;
|
||||
import com.viaversion.viarewind.api.type.item.ItemType;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viarewind.api.type.entitydata.EntityDataListType;
|
||||
import com.viaversion.viarewind.api.type.entitydata.EntityDataType;
|
||||
import com.viaversion.viarewind.api.type.item.ItemArrayType;
|
||||
import com.viaversion.viarewind.api.type.item.ItemType;
|
||||
import com.viaversion.viarewind.api.type.item.NBTType;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -36,16 +35,16 @@ import java.util.List;
|
||||
*/
|
||||
public class RewindTypes {
|
||||
|
||||
public static final Type<int[]> INT_ARRAY = new IntArrayType(); // Integer array with byte as length indicator
|
||||
public static final Type<int[]> INT_ARRAY = new IntArrayType(); // Integer array with byte as length indicator
|
||||
|
||||
public static final Type<BlockPosition> SHORT_POSITION = new PositionVarYType<>(Types.SHORT, value -> (short) value);
|
||||
public static final Type<BlockPosition> INT_POSITION = new PositionVarYType<>(Types.INT, value -> value);
|
||||
public static final Type<BlockPosition> BYTE_POSITION = new PositionVarYType<>(Types.BYTE, value -> (byte) value);
|
||||
public static final Type<BlockPosition> U_BYTE_POSITION = new PositionVarYType<>(Types.UNSIGNED_BYTE, value -> (short) value);
|
||||
public static final Type<BlockPosition> SHORT_POSITION = new PositionVarYType<>(Types.SHORT, value -> (short) value);
|
||||
public static final Type<BlockPosition> INT_POSITION = new PositionVarYType<>(Types.INT, value -> value);
|
||||
public static final Type<BlockPosition> BYTE_POSITION = new PositionVarYType<>(Types.BYTE, value -> (byte) value);
|
||||
public static final Type<BlockPosition> U_BYTE_POSITION = new PositionVarYType<>(Types.UNSIGNED_BYTE, value -> (short) value);
|
||||
|
||||
public static final Type<CompoundTag> COMPRESSED_NBT = new NBTType();
|
||||
public static final Type<Item> COMPRESSED_NBT_ITEM = new ItemType();
|
||||
public static final Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType();
|
||||
public static final Type<CompoundTag> COMPRESSED_NBT = new NBTType();
|
||||
public static final Type<Item> COMPRESSED_NBT_ITEM = new ItemType();
|
||||
public static final Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType();
|
||||
|
||||
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);
|
||||
|
||||
+82
-75
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,95 +17,102 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.api.type.chunk;
|
||||
|
||||
import com.viaversion.viarewind.api.compression.ThreadLocalCompressionProvider;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DataFormatException;
|
||||
|
||||
|
||||
public class BulkChunkType1_7_6 extends Type<Chunk[]> {
|
||||
|
||||
public static final BulkChunkType1_7_6 TYPE = new BulkChunkType1_7_6();
|
||||
public static final BulkChunkType1_7_6 TYPE = new BulkChunkType1_7_6();
|
||||
|
||||
public BulkChunkType1_7_6() {
|
||||
super(Chunk[].class);
|
||||
}
|
||||
public BulkChunkType1_7_6() {
|
||||
super(Chunk[].class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk[] read(ByteBuf byteBuf) {
|
||||
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/ChunkBulk1_7_6Type.java
|
||||
}
|
||||
@Override
|
||||
public Chunk[] read(ByteBuf byteBuf) {
|
||||
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/ChunkBulk1_7_6Type.java
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf byteBuf, Chunk[] chunks) {
|
||||
final int chunkCount = chunks.length;
|
||||
final int[] chunkX = new int[chunkCount];
|
||||
final int[] chunkZ = new int[chunkCount];
|
||||
final short[] primaryBitMask = new short[chunkCount];
|
||||
final short[] additionalBitMask = new short[chunkCount];
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Chunk[] chunks) {
|
||||
final int chunkCount = chunks.length;
|
||||
final int[] addBitMasks = new int[chunkCount];
|
||||
int totalSize = 0;
|
||||
boolean anySkyLight = false;
|
||||
|
||||
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);
|
||||
final byte[] data = chunkData.key();
|
||||
dataArrays[i] = data;
|
||||
dataSize += data.length;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to serialize chunk", e);
|
||||
}
|
||||
chunkX[i] = chunk.getX();
|
||||
chunkZ[i] = chunk.getZ();
|
||||
primaryBitMask[i] = (short) chunk.getBitmask();
|
||||
additionalBitMask[i] = chunkData.value();
|
||||
}
|
||||
|
||||
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;
|
||||
for (Chunk chunk : chunks) {
|
||||
if (ChunkType1_7_6.hasSkyLight(chunk)) {
|
||||
anySkyLight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final Deflater deflater = new Deflater();
|
||||
byte[] compressedData;
|
||||
int compressedSize;
|
||||
try {
|
||||
deflater.setInput(data, 0, data.length);
|
||||
deflater.finish();
|
||||
compressedData = new byte[data.length];
|
||||
compressedSize = deflater.deflate(compressedData);
|
||||
} finally {
|
||||
deflater.end();
|
||||
}
|
||||
for (int i = 0; i < chunkCount; i++) {
|
||||
Chunk chunk = chunks[i];
|
||||
addBitMasks[i] = ChunkType1_7_6.getAddBitMask(chunk);
|
||||
boolean biomes = chunk.isFullChunk() && chunk.getBiomeData() != null;
|
||||
|
||||
byteBuf.writeShort(chunkCount);
|
||||
byteBuf.writeInt(compressedSize);
|
||||
totalSize += ChunkType1_7_6.calcSize(
|
||||
chunk.getBitmask(),
|
||||
addBitMasks[i],
|
||||
anySkyLight,
|
||||
biomes
|
||||
);
|
||||
}
|
||||
|
||||
boolean skyLight = false;
|
||||
for (Chunk chunk : chunks) {
|
||||
for (ChunkSection section : chunk.getSections()) {
|
||||
if (section != null && section.getLight().hasSkyLight()) {
|
||||
skyLight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
final ByteBuf uncompressed = buffer.alloc().buffer(totalSize);
|
||||
|
||||
byteBuf.writeBoolean(skyLight); // hasSkyLight
|
||||
byteBuf.writeBytes(compressedData, 0, compressedSize);
|
||||
try {
|
||||
for (int i = 0; i < chunkCount; i++) {
|
||||
Chunk chunk = chunks[i];
|
||||
boolean biomes = chunk.isFullChunk() && chunk.getBiomeData() != null;
|
||||
|
||||
for (int i = 0; i < chunkCount; i++) {
|
||||
byteBuf.writeInt(chunkX[i]);
|
||||
byteBuf.writeInt(chunkZ[i]);
|
||||
byteBuf.writeShort(primaryBitMask[i]);
|
||||
byteBuf.writeShort(additionalBitMask[i]);
|
||||
}
|
||||
}
|
||||
ChunkType1_7_6.serialize(
|
||||
chunk,
|
||||
uncompressed,
|
||||
addBitMasks[i],
|
||||
anySkyLight,
|
||||
biomes
|
||||
);
|
||||
}
|
||||
|
||||
buffer.writeShort(chunkCount);
|
||||
|
||||
// Reserve 4 bytes for the compressed size
|
||||
final int sizeIndex = buffer.writerIndex();
|
||||
buffer.writeInt(0); // Placeholder for compressed size
|
||||
|
||||
buffer.writeBoolean(anySkyLight);
|
||||
|
||||
// Write compressed data directly to output buffer
|
||||
final int compressedStart = buffer.writerIndex();
|
||||
try {
|
||||
ThreadLocalCompressionProvider.deflate(uncompressed, buffer);
|
||||
} catch (DataFormatException e) {
|
||||
throw new RuntimeException("Failed to compress bulk chunk data", e);
|
||||
}
|
||||
final int compressedSize = buffer.writerIndex() - compressedStart;
|
||||
|
||||
// Go back and write the compressed size
|
||||
final int endIndex = buffer.writerIndex();
|
||||
buffer.writerIndex(sizeIndex);
|
||||
buffer.writeInt(compressedSize);
|
||||
buffer.writerIndex(endIndex);
|
||||
} finally {
|
||||
uncompressed.release();
|
||||
}
|
||||
|
||||
for (int i = 0; i < chunkCount; i++) {
|
||||
Chunk chunk = chunks[i];
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
buffer.writeShort(chunk.getBitmask());
|
||||
buffer.writeShort(addBitMasks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+161
-133
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,163 +17,191 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.api.type.chunk;
|
||||
|
||||
import com.viaversion.viarewind.api.minecraft.ExtendedBlockStorage;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.*;
|
||||
import com.viaversion.viarewind.api.compression.ThreadLocalCompressionProvider;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DataFormatException;
|
||||
|
||||
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();
|
||||
public static final ChunkType1_7_6 TYPE = new ChunkType1_7_6();
|
||||
|
||||
public ChunkType1_7_6() {
|
||||
super(Chunk.class);
|
||||
}
|
||||
public ChunkType1_7_6() {
|
||||
super(Chunk.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk read(ByteBuf byteBuf) {
|
||||
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/Chunk1_7_6Type.java
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf output, Chunk chunk) {
|
||||
Pair<byte[], Short> chunkData;
|
||||
try {
|
||||
chunkData = serialize(chunk);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Unable to serialize chunk", e);
|
||||
}
|
||||
final byte[] data = chunkData.key();
|
||||
final short additionalBitMask = chunkData.value();
|
||||
|
||||
final Deflater deflater = new Deflater();
|
||||
byte[] compressedData;
|
||||
int compressedSize;
|
||||
try {
|
||||
deflater.setInput(data, 0, data.length);
|
||||
deflater.finish();
|
||||
compressedData = new byte[data.length];
|
||||
compressedSize = deflater.deflate(compressedData);
|
||||
} finally {
|
||||
deflater.end();
|
||||
}
|
||||
|
||||
output.writeInt(chunk.getX());
|
||||
output.writeInt(chunk.getZ());
|
||||
output.writeBoolean(chunk.isFullChunk());
|
||||
output.writeShort(chunk.getBitmask());
|
||||
output.writeShort(additionalBitMask);
|
||||
output.writeInt(compressedSize);
|
||||
output.writeBytes(compressedData, 0, compressedSize);
|
||||
}
|
||||
|
||||
public static Pair<byte[], Short> serialize(final Chunk chunk) throws IOException {
|
||||
final ExtendedBlockStorage[] storageArrays = new ExtendedBlockStorage[16];
|
||||
for (int i = 0; i < storageArrays.length; i++) {
|
||||
final ChunkSection section = chunk.getSections()[i];
|
||||
if (section != null) {
|
||||
final ExtendedBlockStorage storage = storageArrays[i] = new ExtendedBlockStorage(section.getLight().hasSkyLight());
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
final int flatBlock = section.palette(PaletteType.BLOCKS).idAt(x, y, z);
|
||||
storage.setBlockId(x, y, z, flatBlock >> 4);
|
||||
storage.setBlockMetadata(x, y, z, flatBlock & 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
storage.getBlockLightArray().setHandle(section.getLight().getBlockLight());
|
||||
if (section.getLight().hasSkyLight()) {
|
||||
storage.getSkyLightArray().setHandle(section.getLight().getSkyLight());
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Chunk read(ByteBuf byteBuf) {
|
||||
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/Chunk1_7_6Type.java
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Chunk chunk) {
|
||||
final int bitmask = chunk.getBitmask();
|
||||
final int addBitmask = getAddBitMask(chunk);
|
||||
final boolean hasSkyLight = hasSkyLight(chunk);
|
||||
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;
|
||||
final int size = calcSize(bitmask, addBitmask, hasSkyLight, biomes);
|
||||
final ByteBuf uncompressed = buffer.alloc().buffer(size);
|
||||
|
||||
for (int i = 0; i < storageArrays.length; i++) {
|
||||
if ((chunk.getBitmask() & 1 << i) != 0) {
|
||||
final byte[] blockLSBArray = storageArrays[i].getBlockLSBArray();
|
||||
System.arraycopy(blockLSBArray, 0, output, index, blockLSBArray.length);
|
||||
index += blockLSBArray.length;
|
||||
}
|
||||
}
|
||||
try {
|
||||
serialize(chunk, uncompressed, addBitmask, hasSkyLight, biomes);
|
||||
|
||||
for (int i = 0; i < storageArrays.length; i++) {
|
||||
if ((chunk.getBitmask() & 1 << i) != 0) {
|
||||
final byte[] blockMetadataArray = storageArrays[i].getBlockMetadataArray().getHandle();
|
||||
System.arraycopy(blockMetadataArray, 0, output, index, blockMetadataArray.length);
|
||||
index += blockMetadataArray.length;
|
||||
}
|
||||
}
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
buffer.writeBoolean(chunk.isFullChunk());
|
||||
buffer.writeShort(bitmask);
|
||||
buffer.writeShort(addBitmask);
|
||||
|
||||
for (int i = 0; i < storageArrays.length; i++) {
|
||||
if ((chunk.getBitmask() & 1 << i) != 0) {
|
||||
final byte[] blockLightArray = storageArrays[i].getBlockLightArray().getHandle();
|
||||
System.arraycopy(blockLightArray, 0, output, index, blockLightArray.length);
|
||||
index += blockLightArray.length;
|
||||
}
|
||||
}
|
||||
// Reserve 4 bytes for the compressed size
|
||||
final int sizeIndex = buffer.writerIndex();
|
||||
buffer.writeInt(0); // Placeholder for compressed size
|
||||
|
||||
for (int i = 0; i < storageArrays.length; i++) {
|
||||
if ((chunk.getBitmask() & 1 << i) != 0 && storageArrays[i].getSkyLightArray() != null) {
|
||||
final byte[] skyLightArray = storageArrays[i].getSkyLightArray().getHandle();
|
||||
System.arraycopy(skyLightArray, 0, output, index, skyLightArray.length);
|
||||
index += skyLightArray.length;
|
||||
}
|
||||
}
|
||||
// Write compressed data directly to output buffer
|
||||
final int compressedStart = buffer.writerIndex();
|
||||
try {
|
||||
ThreadLocalCompressionProvider.deflate(uncompressed, buffer);
|
||||
} catch (DataFormatException e) {
|
||||
throw new RuntimeException("Failed to compress chunk data", e);
|
||||
}
|
||||
final int compressedSize = buffer.writerIndex() - compressedStart;
|
||||
|
||||
short additionalBitMask = 0;
|
||||
for (int i = 0; i < storageArrays.length; i++) {
|
||||
if ((chunk.getBitmask() & 1 << i) != 0 && storageArrays[i].hasBlockMSBArray()) {
|
||||
additionalBitMask |= (short) (1 << i);
|
||||
final byte[] blockMSBArray = storageArrays[i].getOrCreateBlockMSBArray().getHandle();
|
||||
System.arraycopy(blockMSBArray, 0, output, index, blockMSBArray.length);
|
||||
index += blockMSBArray.length;
|
||||
}
|
||||
}
|
||||
// Go back and write the compressed size
|
||||
final int endIndex = buffer.writerIndex();
|
||||
buffer.writerIndex(sizeIndex);
|
||||
buffer.writeInt(compressedSize);
|
||||
buffer.writerIndex(endIndex);
|
||||
} finally {
|
||||
uncompressed.release();
|
||||
}
|
||||
}
|
||||
|
||||
if (biomes) {
|
||||
for (int biome : chunk.getBiomeData()) {
|
||||
output[index++] = (byte) biome;
|
||||
}
|
||||
}
|
||||
public static void serialize(Chunk chunk, ByteBuf output, int addBitmask, boolean writeSkyLight, boolean biomes) {
|
||||
final ChunkSection[] sections = chunk.getSections();
|
||||
final int bitmask = chunk.getBitmask();
|
||||
|
||||
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
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((bitmask & (1 << i)) != 0) {
|
||||
final ChunkSection section = sections[i];
|
||||
final DataPalette palette = section.palette(PaletteType.BLOCKS);
|
||||
for (int j = 0; j < SIZE; j++) {
|
||||
final int block = palette.idAt(j);
|
||||
output.writeByte((block >> 4) & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (biomes) {
|
||||
totalSize += 256;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((bitmask & (1 << i)) != 0) {
|
||||
final ChunkSection section = sections[i];
|
||||
final DataPalette palette = section.palette(PaletteType.BLOCKS);
|
||||
for (int j = 0; j < ChunkSection.SIZE; j += 2) {
|
||||
final int meta1 = palette.idAt(j) & 0xF;
|
||||
final int meta2 = palette.idAt(j + 1) & 0xF;
|
||||
output.writeByte(meta1 | (meta2 << 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((bitmask & (1 << i)) != 0) {
|
||||
final byte[] blockLight = sections[i].getLight().getBlockLight();
|
||||
output.writeBytes(blockLight);
|
||||
}
|
||||
}
|
||||
|
||||
if (writeSkyLight) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((bitmask & (1 << i)) != 0) {
|
||||
if (sections[i].getLight().hasSkyLight()) {
|
||||
final byte[] skyLight = sections[i].getLight().getSkyLight();
|
||||
output.writeBytes(skyLight);
|
||||
} else {
|
||||
// Write empty skylight data
|
||||
output.writeZero(LIGHT_LENGTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (addBitmask != 0) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((bitmask & (1 << i)) != 0 && (addBitmask & (1 << i)) != 0) {
|
||||
final ChunkSection section = sections[i];
|
||||
final DataPalette palette = section.palette(PaletteType.BLOCKS);
|
||||
for (int j = 0; j < SIZE; j += 2) {
|
||||
final int add1 = (palette.idAt(j) >> 12) & 0xF;
|
||||
final int add2 = (palette.idAt(j + 1) >> 12) & 0xF;
|
||||
output.writeByte(add1 | (add2 << 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (biomes && chunk.getBiomeData() != null) {
|
||||
final int[] biomeData = chunk.getBiomeData();
|
||||
for (int biome : biomeData) {
|
||||
output.writeByte(biome);
|
||||
}
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
public static int calcSize(int bitmask, int addBitmask, boolean hasSkyLight, boolean biomes) {
|
||||
int size = 0;
|
||||
int sections = Integer.bitCount(bitmask);
|
||||
|
||||
size += sections * SIZE;
|
||||
size += sections * (SIZE / 2);
|
||||
size += sections * LIGHT_LENGTH;
|
||||
|
||||
if (hasSkyLight) {
|
||||
size += sections * LIGHT_LENGTH;
|
||||
}
|
||||
|
||||
if (addBitmask != 0) {
|
||||
size += Integer.bitCount(addBitmask) * (SIZE / 2);
|
||||
}
|
||||
|
||||
if (biomes) {
|
||||
size += 256;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public static int getAddBitMask(Chunk chunk) {
|
||||
int addBitMask = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((chunk.getBitmask() & (1 << i)) != 0) {
|
||||
final ChunkSection section = chunk.getSections()[i];
|
||||
final DataPalette palette = section.palette(PaletteType.BLOCKS);
|
||||
for (int j = 0; j < SIZE; j++) {
|
||||
final int id = palette.idAt(j);
|
||||
if ((id >> 12) != 0) {
|
||||
addBitMask |= (1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return addBitMask;
|
||||
}
|
||||
|
||||
public static boolean hasSkyLight(Chunk chunk) {
|
||||
for (ChunkSection section : chunk.getSections()) {
|
||||
if (section != null && section.getLight().hasSkyLight()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+28
-29
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,41 +22,40 @@ import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListTypeTemplate;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EntityDataListType extends EntityDataListTypeTemplate {
|
||||
|
||||
private final Type<EntityData> type;
|
||||
private final Type<EntityData> type;
|
||||
|
||||
public EntityDataListType(Type<EntityData> type) {
|
||||
this.type = type;
|
||||
}
|
||||
public EntityDataListType(Type<EntityData> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EntityData> read(ByteBuf buffer) {
|
||||
ArrayList<EntityData> entityData = new ArrayList<>();
|
||||
@Override
|
||||
public List<EntityData> read(ByteBuf buffer) {
|
||||
ArrayList<EntityData> entityData = new ArrayList<>();
|
||||
|
||||
EntityData data;
|
||||
do {
|
||||
data = type.read(buffer);
|
||||
if (data != null) {
|
||||
entityData.add(data);
|
||||
}
|
||||
} while (data != null);
|
||||
EntityData data;
|
||||
do {
|
||||
data = type.read(buffer);
|
||||
if (data != null) {
|
||||
entityData.add(data);
|
||||
}
|
||||
} while (data != null);
|
||||
|
||||
return entityData;
|
||||
}
|
||||
return entityData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, List<EntityData> entityData) {
|
||||
for (EntityData meta : entityData) {
|
||||
type.write(buffer, meta);
|
||||
}
|
||||
if (entityData.isEmpty()) {
|
||||
type.write(buffer, new EntityData(0, EntityDataTypes1_7_6_10.BYTE, (byte) 0));
|
||||
}
|
||||
buffer.writeByte(127);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void write(ByteBuf buffer, List<EntityData> entityData) {
|
||||
for (EntityData meta : entityData) {
|
||||
type.write(buffer, meta);
|
||||
}
|
||||
if (entityData.isEmpty()) {
|
||||
type.write(buffer, new EntityData(0, EntityDataTypes1_7_6_10.BYTE, (byte) 0));
|
||||
}
|
||||
buffer.writeByte(127);
|
||||
}
|
||||
}
|
||||
+19
-19
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,23 +23,23 @@ import com.viaversion.viaversion.api.type.types.entitydata.EntityDataTypeTemplat
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class EntityDataType extends EntityDataTypeTemplate {
|
||||
@Override
|
||||
public EntityData read(ByteBuf buffer) {
|
||||
byte item = buffer.readByte();
|
||||
if (item == 127) {
|
||||
return null;
|
||||
} else {
|
||||
int typeID = (item & 224) >> 5;
|
||||
EntityDataTypes1_7_6_10 type = EntityDataTypes1_7_6_10.byId(typeID);
|
||||
int id = item & 31;
|
||||
return new EntityData(id, type, type.type().read(buffer));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public EntityData read(ByteBuf buffer) {
|
||||
byte item = buffer.readByte();
|
||||
if (item == 127) {
|
||||
return null;
|
||||
} else {
|
||||
int typeID = (item & 224) >> 5;
|
||||
EntityDataTypes1_7_6_10 type = EntityDataTypes1_7_6_10.byId(typeID);
|
||||
int id = item & 31;
|
||||
return new EntityData(id, type, type.type().read(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, EntityData meta) {
|
||||
int item = (meta.dataType().typeId() << 5 | meta.id() & 31) & 255;
|
||||
buffer.writeByte(item);
|
||||
meta.dataType().type().write(buffer, meta.getValue());
|
||||
}
|
||||
@Override
|
||||
public void write(ByteBuf buffer, EntityData meta) {
|
||||
int item = (meta.dataType().typeId() << 5 | meta.id() & 31) & 255;
|
||||
buffer.writeByte(item);
|
||||
meta.dataType().type().write(buffer, meta.getValue());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,26 +25,26 @@ import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class ItemArrayType extends Type<Item[]> {
|
||||
|
||||
public ItemArrayType() {
|
||||
super(Item[].class);
|
||||
}
|
||||
public ItemArrayType() {
|
||||
super(Item[].class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] read(ByteBuf buffer) {
|
||||
int amount = Types.SHORT.readPrimitive(buffer);
|
||||
Item[] items = new Item[amount];
|
||||
@Override
|
||||
public Item[] read(ByteBuf buffer) {
|
||||
int amount = Types.SHORT.readPrimitive(buffer);
|
||||
Item[] items = new Item[amount];
|
||||
|
||||
for (int i = 0; i < amount; ++i) {
|
||||
items[i] = RewindTypes.COMPRESSED_NBT_ITEM.read(buffer);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
for (int i = 0; i < amount; ++i) {
|
||||
items[i] = RewindTypes.COMPRESSED_NBT_ITEM.read(buffer);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Item[] items) {
|
||||
Types.SHORT.writePrimitive(buffer, (short) items.length);
|
||||
for (Item item : items) {
|
||||
RewindTypes.COMPRESSED_NBT_ITEM.write(buffer, item);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Item[] items) {
|
||||
Types.SHORT.writePrimitive(buffer, (short) items.length);
|
||||
for (Item item : items) {
|
||||
RewindTypes.COMPRESSED_NBT_ITEM.write(buffer, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,33 +25,33 @@ import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class ItemType extends Type<Item> {
|
||||
|
||||
public ItemType() {
|
||||
super(Item.class);
|
||||
}
|
||||
public ItemType() {
|
||||
super(Item.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item read(ByteBuf buffer) {
|
||||
short id = buffer.readShort();
|
||||
if (id < 0) {
|
||||
return null;
|
||||
}
|
||||
Item item = new DataItem();
|
||||
item.setIdentifier(id);
|
||||
item.setAmount(buffer.readByte());
|
||||
item.setData(buffer.readShort());
|
||||
item.setTag(RewindTypes.COMPRESSED_NBT.read(buffer));
|
||||
return item;
|
||||
}
|
||||
@Override
|
||||
public Item read(ByteBuf buffer) {
|
||||
short id = buffer.readShort();
|
||||
if (id < 0) {
|
||||
return null;
|
||||
}
|
||||
Item item = new DataItem();
|
||||
item.setIdentifier(id);
|
||||
item.setAmount(buffer.readByte());
|
||||
item.setData(buffer.readShort());
|
||||
item.setTag(RewindTypes.COMPRESSED_NBT.read(buffer));
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Item item) {
|
||||
if (item == null) {
|
||||
buffer.writeShort(-1);
|
||||
} else {
|
||||
buffer.writeShort(item.identifier());
|
||||
buffer.writeByte(item.amount());
|
||||
buffer.writeShort(item.data());
|
||||
RewindTypes.COMPRESSED_NBT.write(buffer, item.tag());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Item item) {
|
||||
if (item == null) {
|
||||
buffer.writeShort(-1);
|
||||
} else {
|
||||
buffer.writeShort(item.identifier());
|
||||
buffer.writeByte(item.amount());
|
||||
buffer.writeShort(item.data());
|
||||
RewindTypes.COMPRESSED_NBT.write(buffer, item.tag());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,57 +17,56 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.api.type.item;
|
||||
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.io.NBTIO;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class NBTType extends Type<CompoundTag> {
|
||||
public NBTType() {
|
||||
super(CompoundTag.class);
|
||||
}
|
||||
public NBTType() {
|
||||
super(CompoundTag.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag read(ByteBuf buffer) {
|
||||
short length = buffer.readShort();
|
||||
if (length <= 0) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public CompoundTag read(ByteBuf buffer) {
|
||||
short length = buffer.readShort();
|
||||
if (length <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ByteBuf compressed = buffer.readSlice(length);
|
||||
ByteBuf compressed = buffer.readSlice(length);
|
||||
|
||||
try (GZIPInputStream gzipStream = new GZIPInputStream(new ByteBufInputStream(compressed))) {
|
||||
return NBTIO.reader(CompoundTag.class).named().read(gzipStream);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
try (GZIPInputStream gzipStream = new GZIPInputStream(new ByteBufInputStream(compressed))) {
|
||||
return NBTIO.reader(CompoundTag.class).named().read(gzipStream);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, CompoundTag nbt) {
|
||||
if (nbt == null) {
|
||||
buffer.writeShort(-1);
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void write(ByteBuf buffer, CompoundTag nbt) {
|
||||
if (nbt == null) {
|
||||
buffer.writeShort(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuf compressedBuf = buffer.alloc().buffer();
|
||||
try {
|
||||
try (GZIPOutputStream gzipStream = new GZIPOutputStream(new ByteBufOutputStream(compressedBuf))) {
|
||||
NBTIO.writer().named().write(gzipStream, nbt);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
ByteBuf compressedBuf = buffer.alloc().buffer();
|
||||
try {
|
||||
try (GZIPOutputStream gzipStream = new GZIPOutputStream(new ByteBufOutputStream(compressedBuf))) {
|
||||
NBTIO.writer().named().write(gzipStream, nbt);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
buffer.writeShort(compressedBuf.readableBytes());
|
||||
buffer.writeBytes(compressedBuf);
|
||||
} finally {
|
||||
compressedBuf.release();
|
||||
}
|
||||
}
|
||||
buffer.writeShort(compressedBuf.readableBytes());
|
||||
buffer.writeBytes(compressedBuf);
|
||||
} finally {
|
||||
compressedBuf.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
-75
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -27,90 +27,89 @@ import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Protocol1_7_6_10To1_7_2_5 extends AbstractProtocol<ClientboundPackets1_7_2_5, ClientboundPackets1_7_2_5, ServerboundPackets1_7_2_5, ServerboundPackets1_7_2_5> {
|
||||
|
||||
public static final ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<>(Types.STRING) {
|
||||
@Override
|
||||
public String transform(PacketWrapper wrapper, String s) {
|
||||
return s.replace("-", "");
|
||||
}
|
||||
};
|
||||
public static final ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<>(Types.STRING) {
|
||||
@Override
|
||||
public String transform(PacketWrapper wrapper, String s) {
|
||||
return s.replace("-", "");
|
||||
}
|
||||
};
|
||||
|
||||
public Protocol1_7_6_10To1_7_2_5() {
|
||||
super(ClientboundPackets1_7_2_5.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class);
|
||||
}
|
||||
public Protocol1_7_6_10To1_7_2_5() {
|
||||
super(ClientboundPackets1_7_2_5.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_FINISHED, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING, REMOVE_DASHES); // Uuid
|
||||
map(Types.STRING); // Name
|
||||
}
|
||||
});
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_FINISHED, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING, REMOVE_DASHES); // Uuid
|
||||
map(Types.STRING); // Name
|
||||
}
|
||||
});
|
||||
|
||||
this.registerClientbound(ClientboundPackets1_7_2_5.ADD_PLAYER, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.VAR_INT); // Entity id
|
||||
map(Types.STRING, REMOVE_DASHES); // Uuid
|
||||
map(Types.STRING); // Name
|
||||
handler(wrapper -> {
|
||||
final int size = wrapper.read(Types.VAR_INT); // Data count
|
||||
for (int i = 0; i < size; i++) {
|
||||
wrapper.read(Types.STRING); // Data name
|
||||
wrapper.read(Types.STRING); // Data value
|
||||
wrapper.read(Types.STRING); // Data signature
|
||||
}
|
||||
});
|
||||
map(Types.INT); // X
|
||||
map(Types.INT); // Y
|
||||
map(Types.INT); // Z
|
||||
map(Types.BYTE); // Yaw
|
||||
map(Types.BYTE); // Pitch
|
||||
map(Types.SHORT); // Item in hand
|
||||
map(RewindTypes.ENTITY_DATA_LIST1_7); // Entity data
|
||||
}
|
||||
});
|
||||
this.registerClientbound(ClientboundPackets1_7_2_5.ADD_PLAYER, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.VAR_INT); // Entity id
|
||||
map(Types.STRING, REMOVE_DASHES); // Uuid
|
||||
map(Types.STRING); // Name
|
||||
handler(wrapper -> {
|
||||
final int size = wrapper.read(Types.VAR_INT); // Data count
|
||||
for (int i = 0; i < size; i++) {
|
||||
wrapper.read(Types.STRING); // Data name
|
||||
wrapper.read(Types.STRING); // Data value
|
||||
wrapper.read(Types.STRING); // Data signature
|
||||
}
|
||||
});
|
||||
map(Types.INT); // X
|
||||
map(Types.INT); // Y
|
||||
map(Types.INT); // Z
|
||||
map(Types.BYTE); // Yaw
|
||||
map(Types.BYTE); // Pitch
|
||||
map(Types.SHORT); // Item in hand
|
||||
map(RewindTypes.ENTITY_DATA_LIST1_7); // Entity data
|
||||
}
|
||||
});
|
||||
|
||||
this.registerClientbound(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING); // Team name
|
||||
map(Types.BYTE); // Mode
|
||||
handler(wrapper -> {
|
||||
final byte mode = wrapper.get(Types.BYTE, 0);
|
||||
if (mode == 0 || mode == 2) { // Team is created or information is updated
|
||||
wrapper.passthrough(Types.STRING); // Team display name
|
||||
wrapper.passthrough(Types.STRING); // Team prefix
|
||||
wrapper.passthrough(Types.STRING); // Team suffix
|
||||
wrapper.passthrough(Types.BYTE); // Friendly fire
|
||||
}
|
||||
if (mode == 0 || mode == 3 || mode == 4) { // Team is created, player is added or player is removed
|
||||
List<String> entryList = new ArrayList<>();
|
||||
final int size = wrapper.read(Types.SHORT);
|
||||
for (int i = 0; i < size; i++) {
|
||||
entryList.add(wrapper.read(Types.STRING));
|
||||
}
|
||||
this.registerClientbound(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING); // Team name
|
||||
map(Types.BYTE); // Mode
|
||||
handler(wrapper -> {
|
||||
final byte mode = wrapper.get(Types.BYTE, 0);
|
||||
if (mode == 0 || mode == 2) { // Team is created or information is updated
|
||||
wrapper.passthrough(Types.STRING); // Team display name
|
||||
wrapper.passthrough(Types.STRING); // Team prefix
|
||||
wrapper.passthrough(Types.STRING); // Team suffix
|
||||
wrapper.passthrough(Types.BYTE); // Friendly fire
|
||||
}
|
||||
if (mode == 0 || mode == 3 || mode == 4) { // Team is created, player is added or player is removed
|
||||
List<String> entryList = new ArrayList<>();
|
||||
final int size = wrapper.read(Types.SHORT);
|
||||
for (int i = 0; i < size; i++) {
|
||||
entryList.add(wrapper.read(Types.STRING));
|
||||
}
|
||||
|
||||
entryList = entryList.stream()
|
||||
.map(it -> it.length() > 16 ? it.substring(0, 16) : it) // trim to 16 characters
|
||||
.distinct() // remove duplicates
|
||||
.collect(Collectors.toList());
|
||||
entryList = entryList.stream()
|
||||
.map(it -> it.length() > 16 ? it.substring(0, 16) : it) // trim to 16 characters
|
||||
.distinct() // remove duplicates
|
||||
.collect(Collectors.toList());
|
||||
|
||||
wrapper.write(Types.SHORT, (short) entryList.size());
|
||||
for (String entry : entryList) {
|
||||
wrapper.write(Types.STRING, entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
wrapper.write(Types.SHORT, (short) entryList.size());
|
||||
for (String entry : entryList) {
|
||||
wrapper.write(Types.STRING, entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+74
-74
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,79 +20,79 @@ package com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
|
||||
public enum ClientboundPackets1_7_2_5 implements ClientboundPacketType {
|
||||
KEEP_ALIVE, // 0x00
|
||||
LOGIN, // 0x01
|
||||
CHAT, // 0x02
|
||||
SET_TIME, // 0x03
|
||||
SET_EQUIPPED_ITEM, // 0x04
|
||||
SET_DEFAULT_SPAWN_POSITION, // 0x05
|
||||
SET_HEALTH, // 0x06
|
||||
RESPAWN, // 0x07
|
||||
PLAYER_POSITION, // 0x08
|
||||
SET_CARRIED_ITEM, // 0x09
|
||||
PLAYER_SLEEP, // 0x0A
|
||||
ANIMATE, // 0x0B
|
||||
ADD_PLAYER, // 0x0C
|
||||
TAKE_ITEM_ENTITY, // 0x0D
|
||||
ADD_ENTITY, // 0x0E
|
||||
ADD_MOB, // 0x0F
|
||||
ADD_PAINTING, // 0x10
|
||||
ADD_EXPERIENCE_ORB, // 0x11
|
||||
SET_ENTITY_MOTION, // 0x12
|
||||
REMOVE_ENTITIES, // 0x13
|
||||
MOVE_ENTITY, // 0x14
|
||||
MOVE_ENTITY_POS, // 0x15
|
||||
MOVE_ENTITY_ROT, // 0x16
|
||||
MOVE_ENTITY_POS_ROT, // 0x17
|
||||
TELEPORT_ENTITY, // 0x18
|
||||
ROTATE_HEAD, // 0x19
|
||||
ENTITY_EVENT, // 0x1A
|
||||
SET_ENTITY_LINK, // 0x1B
|
||||
SET_ENTITY_DATA, // 0x1C
|
||||
UPDATE_MOB_EFFECT, // 0x1D
|
||||
REMOVE_MOB_EFFECT, // 0x1E
|
||||
SET_EXPERIENCE, // 0x1F
|
||||
UPDATE_ATTRIBUTES, // 0x20
|
||||
LEVEL_CHUNK, // 0x21
|
||||
CHUNK_BLOCKS_UPDATE, // 0x22
|
||||
BLOCK_UPDATE, // 0x23
|
||||
BLOCK_EVENT, // 0x24
|
||||
BLOCK_DESTRUCTION, // 0x25
|
||||
MAP_BULK_CHUNK, // 0x26
|
||||
EXPLODE, // 0x27
|
||||
LEVEL_EVENT, // 0x28
|
||||
CUSTOM_SOUND, // 0x29
|
||||
LEVEL_PARTICLES, // 0x2A
|
||||
GAME_EVENT, // 0x2B
|
||||
ADD_GLOBAL_ENTITY, // 0x2C
|
||||
OPEN_SCREEN, // 0x2D
|
||||
CONTAINER_CLOSE, // 0x2E
|
||||
CONTAINER_SET_SLOT, // 0x2F
|
||||
CONTAINER_SET_CONTENT, // 0x30
|
||||
CONTAINER_SET_DATA, // 0x31
|
||||
CONTAINER_ACK, // 0x32
|
||||
UPDATE_SIGN, // 0x33
|
||||
MAP_ITEM_DATA, // 0x34
|
||||
BLOCK_ENTITY_DATA, // 0x35
|
||||
OPEN_SIGN_EDITOR, // 0x36
|
||||
AWARD_STATS, // 0x37
|
||||
PLAYER_INFO, // 0x38
|
||||
PLAYER_ABILITIES, // 0x39
|
||||
COMMAND_SUGGESTIONS, // 0x3A
|
||||
SET_OBJECTIVE, // 0x3B
|
||||
SET_SCORE, // 0x3C
|
||||
SET_DISPLAY_OBJECTIVE, // 0x3D
|
||||
SET_PLAYER_TEAM, // 0x3E
|
||||
CUSTOM_PAYLOAD, // 0x3F
|
||||
DISCONNECT; // 0x40
|
||||
KEEP_ALIVE, // 0x00
|
||||
LOGIN, // 0x01
|
||||
CHAT, // 0x02
|
||||
SET_TIME, // 0x03
|
||||
SET_EQUIPPED_ITEM, // 0x04
|
||||
SET_DEFAULT_SPAWN_POSITION, // 0x05
|
||||
SET_HEALTH, // 0x06
|
||||
RESPAWN, // 0x07
|
||||
PLAYER_POSITION, // 0x08
|
||||
SET_CARRIED_ITEM, // 0x09
|
||||
PLAYER_SLEEP, // 0x0A
|
||||
ANIMATE, // 0x0B
|
||||
ADD_PLAYER, // 0x0C
|
||||
TAKE_ITEM_ENTITY, // 0x0D
|
||||
ADD_ENTITY, // 0x0E
|
||||
ADD_MOB, // 0x0F
|
||||
ADD_PAINTING, // 0x10
|
||||
ADD_EXPERIENCE_ORB, // 0x11
|
||||
SET_ENTITY_MOTION, // 0x12
|
||||
REMOVE_ENTITIES, // 0x13
|
||||
MOVE_ENTITY, // 0x14
|
||||
MOVE_ENTITY_POS, // 0x15
|
||||
MOVE_ENTITY_ROT, // 0x16
|
||||
MOVE_ENTITY_POS_ROT, // 0x17
|
||||
TELEPORT_ENTITY, // 0x18
|
||||
ROTATE_HEAD, // 0x19
|
||||
ENTITY_EVENT, // 0x1A
|
||||
SET_ENTITY_LINK, // 0x1B
|
||||
SET_ENTITY_DATA, // 0x1C
|
||||
UPDATE_MOB_EFFECT, // 0x1D
|
||||
REMOVE_MOB_EFFECT, // 0x1E
|
||||
SET_EXPERIENCE, // 0x1F
|
||||
UPDATE_ATTRIBUTES, // 0x20
|
||||
LEVEL_CHUNK, // 0x21
|
||||
CHUNK_BLOCKS_UPDATE, // 0x22
|
||||
BLOCK_UPDATE, // 0x23
|
||||
BLOCK_EVENT, // 0x24
|
||||
BLOCK_DESTRUCTION, // 0x25
|
||||
MAP_BULK_CHUNK, // 0x26
|
||||
EXPLODE, // 0x27
|
||||
LEVEL_EVENT, // 0x28
|
||||
CUSTOM_SOUND, // 0x29
|
||||
LEVEL_PARTICLES, // 0x2A
|
||||
GAME_EVENT, // 0x2B
|
||||
ADD_GLOBAL_ENTITY, // 0x2C
|
||||
OPEN_SCREEN, // 0x2D
|
||||
CONTAINER_CLOSE, // 0x2E
|
||||
CONTAINER_SET_SLOT, // 0x2F
|
||||
CONTAINER_SET_CONTENT, // 0x30
|
||||
CONTAINER_SET_DATA, // 0x31
|
||||
CONTAINER_ACK, // 0x32
|
||||
UPDATE_SIGN, // 0x33
|
||||
MAP_ITEM_DATA, // 0x34
|
||||
BLOCK_ENTITY_DATA, // 0x35
|
||||
OPEN_SIGN_EDITOR, // 0x36
|
||||
AWARD_STATS, // 0x37
|
||||
PLAYER_INFO, // 0x38
|
||||
PLAYER_ABILITIES, // 0x39
|
||||
COMMAND_SUGGESTIONS, // 0x3A
|
||||
SET_OBJECTIVE, // 0x3B
|
||||
SET_SCORE, // 0x3C
|
||||
SET_DISPLAY_OBJECTIVE, // 0x3D
|
||||
SET_PLAYER_TEAM, // 0x3E
|
||||
CUSTOM_PAYLOAD, // 0x3F
|
||||
DISCONNECT; // 0x40
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return ordinal();
|
||||
}
|
||||
@Override
|
||||
public int getId() {
|
||||
return ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
@Override
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
+33
-33
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,38 +20,38 @@ package com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
|
||||
public enum ServerboundPackets1_7_2_5 implements ServerboundPacketType {
|
||||
KEEP_ALIVE, // 0x00
|
||||
CHAT, // 0x01
|
||||
INTERACT, // 0x02
|
||||
MOVE_PLAYER_STATUS_ONLY, // 0x03
|
||||
MOVE_PLAYER_POS, // 0x04
|
||||
MOVE_PLAYER_ROT, // 0x05
|
||||
MOVE_PLAYER_POS_ROT, // 0x06
|
||||
PLAYER_ACTION, // 0x07
|
||||
USE_ITEM_ON, // 0x08
|
||||
SET_CARRIED_ITEM, // 0x09
|
||||
SWING, // 0x0A
|
||||
PLAYER_COMMAND, // 0x0B
|
||||
PLAYER_INPUT, // 0x0C
|
||||
CONTAINER_CLOSE, // 0x0D
|
||||
CONTAINER_CLICK, // 0x0E
|
||||
CONTAINER_ACK, // 0x0F
|
||||
SET_CREATIVE_MODE_SLOT, // 0x10
|
||||
CONTAINER_BUTTON_CLICK, // 0x11
|
||||
SIGN_UPDATE, // 0x12
|
||||
PLAYER_ABILITIES, // 0x13
|
||||
COMMAND_SUGGESTION, // 0x14
|
||||
CLIENT_INFORMATION, // 0x15
|
||||
CLIENT_COMMAND, // 0x16
|
||||
CUSTOM_PAYLOAD; // 0x17
|
||||
KEEP_ALIVE, // 0x00
|
||||
CHAT, // 0x01
|
||||
INTERACT, // 0x02
|
||||
MOVE_PLAYER_STATUS_ONLY, // 0x03
|
||||
MOVE_PLAYER_POS, // 0x04
|
||||
MOVE_PLAYER_ROT, // 0x05
|
||||
MOVE_PLAYER_POS_ROT, // 0x06
|
||||
PLAYER_ACTION, // 0x07
|
||||
USE_ITEM_ON, // 0x08
|
||||
SET_CARRIED_ITEM, // 0x09
|
||||
SWING, // 0x0A
|
||||
PLAYER_COMMAND, // 0x0B
|
||||
PLAYER_INPUT, // 0x0C
|
||||
CONTAINER_CLOSE, // 0x0D
|
||||
CONTAINER_CLICK, // 0x0E
|
||||
CONTAINER_ACK, // 0x0F
|
||||
SET_CREATIVE_MODE_SLOT, // 0x10
|
||||
CONTAINER_BUTTON_CLICK, // 0x11
|
||||
SIGN_UPDATE, // 0x12
|
||||
PLAYER_ABILITIES, // 0x13
|
||||
COMMAND_SUGGESTION, // 0x14
|
||||
CLIENT_INFORMATION, // 0x15
|
||||
CLIENT_COMMAND, // 0x16
|
||||
CUSTOM_PAYLOAD; // 0x17
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return ordinal();
|
||||
}
|
||||
@Override
|
||||
public int getId() {
|
||||
return ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
@Override
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
+103
-96
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,13 +22,23 @@ import com.viaversion.viarewind.ViaRewind;
|
||||
import com.viaversion.viarewind.api.data.RewindMappingData;
|
||||
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.viarewind.protocol.v1_8to1_7_6_10.rewriter.EntityPacketRewriter1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter.*;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.CompressionHandlerProvider;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression.TrackingCompressionHandlerProvider;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.*;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter.BlockItemPacketRewriter1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter.EntityPacketRewriter1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter.PlayerPacketRewriter1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter.ScoreboardPacketRewriter1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter.WorldPacketRewriter1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.CompressionStatusTracker;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.EntityTracker1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.GameProfileStorage;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.InventoryTracker;
|
||||
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.viarewind.protocol.v1_8to1_7_6_10.storage.WorldBorderEmulator;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.task.WorldBorderUpdateTask;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolStorables;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
|
||||
@@ -42,118 +52,115 @@ import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
|
||||
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ServerboundPackets1_8;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Protocol1_8To1_7_6_10 extends BackwardsProtocol<ClientboundPackets1_8, ClientboundPackets1_7_2_5, ServerboundPackets1_8, ServerboundPackets1_7_2_5> {
|
||||
|
||||
public static final RewindMappingData MAPPINGS = new RewindMappingData("1.8", "1.7.10");
|
||||
public static final RewindMappingData MAPPINGS = new RewindMappingData("1.8", "1.7.10");
|
||||
|
||||
private final BlockItemPacketRewriter1_8 itemRewriter = new BlockItemPacketRewriter1_8(this);
|
||||
private final EntityPacketRewriter1_8 entityRewriter = new EntityPacketRewriter1_8(this);
|
||||
private final BlockItemPacketRewriter1_8 itemRewriter = new BlockItemPacketRewriter1_8(this);
|
||||
private final EntityPacketRewriter1_8 entityRewriter = new EntityPacketRewriter1_8(this);
|
||||
|
||||
public Protocol1_8To1_7_6_10() {
|
||||
super(ClientboundPackets1_8.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_8.class, ServerboundPackets1_7_2_5.class);
|
||||
}
|
||||
public Protocol1_8To1_7_6_10() {
|
||||
super(ClientboundPackets1_8.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_8.class, ServerboundPackets1_7_2_5.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
itemRewriter.register();
|
||||
entityRewriter.register();
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
itemRewriter.register();
|
||||
entityRewriter.register();
|
||||
|
||||
new PlayerPacketRewriter1_8(this).register();
|
||||
new ScoreboardPacketRewriter1_8(this).register();
|
||||
new WorldPacketRewriter1_8(this).register();
|
||||
new PlayerPacketRewriter1_8(this).register();
|
||||
new ScoreboardPacketRewriter1_8(this).register();
|
||||
new WorldPacketRewriter1_8(this).register();
|
||||
|
||||
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING); // server hash
|
||||
map(Types.BYTE_ARRAY_PRIMITIVE, Types.SHORT_BYTE_ARRAY); // public key
|
||||
map(Types.BYTE_ARRAY_PRIMITIVE, Types.SHORT_BYTE_ARRAY); // verification token
|
||||
}
|
||||
});
|
||||
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_COMPRESSION, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
handler(wrapper -> {
|
||||
final int threshold = wrapper.read(Types.VAR_INT);
|
||||
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING); // server hash
|
||||
map(Types.BYTE_ARRAY_PRIMITIVE, Types.SHORT_BYTE_ARRAY); // public key
|
||||
map(Types.BYTE_ARRAY_PRIMITIVE, Types.SHORT_BYTE_ARRAY); // verification token
|
||||
}
|
||||
});
|
||||
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_COMPRESSION, this::handleCompression);
|
||||
this.registerClientbound(ClientboundPackets1_8.SET_COMPRESSION, null, this::handleCompression);
|
||||
this.registerClientbound(ClientboundPackets1_8.KEEP_ALIVE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.VAR_INT, Types.INT); // id
|
||||
}
|
||||
});
|
||||
|
||||
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onHandleLoginCompressionPacket(wrapper.user(), threshold);
|
||||
wrapper.cancel();
|
||||
});
|
||||
}
|
||||
});
|
||||
this.cancelClientbound(ClientboundPackets1_8.SET_COMPRESSION); // unused
|
||||
this.registerClientbound(ClientboundPackets1_8.KEEP_ALIVE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.VAR_INT, Types.INT); // id
|
||||
}
|
||||
});
|
||||
this.registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.SHORT_BYTE_ARRAY, Types.BYTE_ARRAY_PRIMITIVE); // shared secret
|
||||
map(Types.SHORT_BYTE_ARRAY, Types.BYTE_ARRAY_PRIMITIVE); // verification token
|
||||
}
|
||||
});
|
||||
|
||||
this.registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.SHORT_BYTE_ARRAY, Types.BYTE_ARRAY_PRIMITIVE); // shared secret
|
||||
map(Types.SHORT_BYTE_ARRAY, Types.BYTE_ARRAY_PRIMITIVE); // verification token
|
||||
}
|
||||
});
|
||||
this.registerServerbound(ServerboundPackets1_7_2_5.KEEP_ALIVE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT, Types.VAR_INT); // id
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.registerServerbound(ServerboundPackets1_7_2_5.KEEP_ALIVE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT, Types.VAR_INT); // id
|
||||
}
|
||||
});
|
||||
}
|
||||
private void handleCompression(final PacketWrapper wrapper) {
|
||||
wrapper.cancel();
|
||||
final int threshold = wrapper.read(Types.VAR_INT);
|
||||
|
||||
@Override
|
||||
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws CancelException {
|
||||
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onTransformPacket(packetWrapper.user());
|
||||
Via.getManager().getProviders().get(CompressionHandlerProvider.class).setCompressionThreshold(wrapper.user(), threshold);
|
||||
}
|
||||
|
||||
super.transform(direction, state, packetWrapper);
|
||||
}
|
||||
@Override
|
||||
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws CancelException {
|
||||
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onTransformPacket(packetWrapper.user());
|
||||
|
||||
@Override
|
||||
public void init(UserConnection connection) {
|
||||
connection.addEntityTracker(this.getClass(), new EntityTracker1_8(connection));
|
||||
connection.addClientWorld(this.getClass(), new ClientWorld());
|
||||
super.transform(direction, state, packetWrapper);
|
||||
}
|
||||
|
||||
connection.put(new InventoryTracker(connection));
|
||||
connection.put(new PlayerSessionStorage(connection));
|
||||
connection.put(new GameProfileStorage(connection));
|
||||
connection.put(new ScoreboardTracker(connection));
|
||||
connection.put(new CompressionStatusTracker(connection));
|
||||
connection.put(new WorldBorderEmulator(connection));
|
||||
}
|
||||
@Override
|
||||
public void init(UserConnection connection) {
|
||||
final ProtocolStorables storables = connection.storables(this);
|
||||
storables.setEntityTracker(new EntityTracker1_8(connection));
|
||||
storables.setClientWorld(new ClientWorld());
|
||||
|
||||
@Override
|
||||
public void register(ViaProviders providers) {
|
||||
providers.register(CompressionHandlerProvider.class, new TrackingCompressionHandlerProvider());
|
||||
connection.put(new InventoryTracker(connection));
|
||||
connection.put(new PlayerSessionStorage(connection));
|
||||
connection.put(new GameProfileStorage(connection));
|
||||
connection.put(new ScoreboardTracker(connection));
|
||||
connection.put(new CompressionStatusTracker(connection));
|
||||
connection.put(new WorldBorderEmulator(connection));
|
||||
}
|
||||
|
||||
if (ViaRewind.getConfig().isEmulateWorldBorder()) {
|
||||
Via.getManager().getScheduler().scheduleRepeating(new WorldBorderUpdateTask(), 0L, 50L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void register(ViaProviders providers) {
|
||||
providers.register(CompressionHandlerProvider.class, new TrackingCompressionHandlerProvider());
|
||||
|
||||
@Override
|
||||
public RewindMappingData getMappingData() {
|
||||
return MAPPINGS;
|
||||
}
|
||||
if (ViaRewind.getConfig().isEmulateWorldBorder()) {
|
||||
Via.getManager().getScheduler().scheduleRepeating(new WorldBorderUpdateTask(), 0L, 50L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockItemPacketRewriter1_8 getItemRewriter() {
|
||||
return itemRewriter;
|
||||
}
|
||||
@Override
|
||||
public RewindMappingData getMappingData() {
|
||||
return MAPPINGS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPacketRewriter1_8 getEntityRewriter() {
|
||||
return entityRewriter;
|
||||
}
|
||||
@Override
|
||||
public BlockItemPacketRewriter1_8 getItemRewriter() {
|
||||
return itemRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMappingDataToLoad() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public EntityPacketRewriter1_8 getEntityRewriter() {
|
||||
return entityRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMappingDataToLoad() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+425
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.data;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.Protocol1_8To1_7_6_10;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.item.DataItem;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntMap;
|
||||
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntOpenHashMap;
|
||||
import com.viaversion.viaversion.libs.gson.JsonArray;
|
||||
import com.viaversion.viaversion.libs.gson.JsonElement;
|
||||
import com.viaversion.viaversion.libs.gson.JsonObject;
|
||||
import com.viaversion.viaversion.util.ComponentUtil;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import com.viaversion.viaversion.util.SerializerVersion;
|
||||
|
||||
// TODO move this into a ComponentRewriter
|
||||
@Deprecated
|
||||
public final class ChatItemRewriter {
|
||||
|
||||
private static final Object2IntMap<String> NAME_TO_ID = new Object2IntOpenHashMap<>(336);
|
||||
|
||||
static {
|
||||
NAME_TO_ID.put("stone", 1);
|
||||
NAME_TO_ID.put("grass", 2);
|
||||
NAME_TO_ID.put("dirt", 3);
|
||||
NAME_TO_ID.put("cobblestone", 4);
|
||||
NAME_TO_ID.put("planks", 5);
|
||||
NAME_TO_ID.put("sapling", 6);
|
||||
NAME_TO_ID.put("bedrock", 7);
|
||||
NAME_TO_ID.put("sand", 12);
|
||||
NAME_TO_ID.put("gravel", 13);
|
||||
NAME_TO_ID.put("gold_ore", 14);
|
||||
NAME_TO_ID.put("iron_ore", 15);
|
||||
NAME_TO_ID.put("coal_ore", 16);
|
||||
NAME_TO_ID.put("log", 17);
|
||||
NAME_TO_ID.put("leaves", 18);
|
||||
NAME_TO_ID.put("sponge", 19);
|
||||
NAME_TO_ID.put("glass", 20);
|
||||
NAME_TO_ID.put("lapis_ore", 21);
|
||||
NAME_TO_ID.put("lapis_block", 22);
|
||||
NAME_TO_ID.put("dispenser", 23);
|
||||
NAME_TO_ID.put("sandstone", 24);
|
||||
NAME_TO_ID.put("noteblock", 25);
|
||||
NAME_TO_ID.put("golden_rail", 27);
|
||||
NAME_TO_ID.put("detector_rail", 28);
|
||||
NAME_TO_ID.put("sticky_piston", 29);
|
||||
NAME_TO_ID.put("web", 30);
|
||||
NAME_TO_ID.put("tallgrass", 31);
|
||||
NAME_TO_ID.put("deadbush", 32);
|
||||
NAME_TO_ID.put("piston", 33);
|
||||
NAME_TO_ID.put("wool", 35);
|
||||
NAME_TO_ID.put("yellow_flower", 37);
|
||||
NAME_TO_ID.put("red_flower", 38);
|
||||
NAME_TO_ID.put("brown_mushroom", 39);
|
||||
NAME_TO_ID.put("red_mushroom", 40);
|
||||
NAME_TO_ID.put("gold_block", 41);
|
||||
NAME_TO_ID.put("iron_block", 42);
|
||||
NAME_TO_ID.put("stone_slab", 44);
|
||||
NAME_TO_ID.put("brick_block", 45);
|
||||
NAME_TO_ID.put("tnt", 46);
|
||||
NAME_TO_ID.put("bookshelf", 47);
|
||||
NAME_TO_ID.put("mossy_cobblestone", 48);
|
||||
NAME_TO_ID.put("obsidian", 49);
|
||||
NAME_TO_ID.put("torch", 50);
|
||||
NAME_TO_ID.put("mob_spawner", 52);
|
||||
NAME_TO_ID.put("oak_stairs", 53);
|
||||
NAME_TO_ID.put("chest", 54);
|
||||
NAME_TO_ID.put("diamond_ore", 56);
|
||||
NAME_TO_ID.put("diamond_block", 57);
|
||||
NAME_TO_ID.put("crafting_table", 58);
|
||||
NAME_TO_ID.put("farmland", 60);
|
||||
NAME_TO_ID.put("furnace", 61);
|
||||
NAME_TO_ID.put("ladder", 65);
|
||||
NAME_TO_ID.put("rail", 66);
|
||||
NAME_TO_ID.put("stone_stairs", 67);
|
||||
NAME_TO_ID.put("lever", 69);
|
||||
NAME_TO_ID.put("stone_pressure_plate", 70);
|
||||
NAME_TO_ID.put("wooden_pressure_plate", 72);
|
||||
NAME_TO_ID.put("redstone_ore", 73);
|
||||
NAME_TO_ID.put("redstone_torch", 76);
|
||||
NAME_TO_ID.put("stone_button", 77);
|
||||
NAME_TO_ID.put("snow_layer", 78);
|
||||
NAME_TO_ID.put("ice", 79);
|
||||
NAME_TO_ID.put("snow", 80);
|
||||
NAME_TO_ID.put("cactus", 81);
|
||||
NAME_TO_ID.put("clay", 82);
|
||||
NAME_TO_ID.put("jukebox", 84);
|
||||
NAME_TO_ID.put("fence", 85);
|
||||
NAME_TO_ID.put("pumpkin", 86);
|
||||
NAME_TO_ID.put("netherrack", 87);
|
||||
NAME_TO_ID.put("soul_sand", 88);
|
||||
NAME_TO_ID.put("glowstone", 89);
|
||||
NAME_TO_ID.put("lit_pumpkin", 91);
|
||||
NAME_TO_ID.put("stained_glass", 95);
|
||||
NAME_TO_ID.put("trapdoor", 96);
|
||||
NAME_TO_ID.put("monster_egg", 97);
|
||||
NAME_TO_ID.put("stonebrick", 98);
|
||||
NAME_TO_ID.put("brown_mushroom_block", 99);
|
||||
NAME_TO_ID.put("red_mushroom_block", 100);
|
||||
NAME_TO_ID.put("iron_bars", 101);
|
||||
NAME_TO_ID.put("glass_pane", 102);
|
||||
NAME_TO_ID.put("melon_block", 103);
|
||||
NAME_TO_ID.put("vine", 106);
|
||||
NAME_TO_ID.put("fence_gate", 107);
|
||||
NAME_TO_ID.put("brick_stairs", 108);
|
||||
NAME_TO_ID.put("stone_brick_stairs", 109);
|
||||
NAME_TO_ID.put("mycelium", 110);
|
||||
NAME_TO_ID.put("waterlily", 111);
|
||||
NAME_TO_ID.put("nether_brick", 112);
|
||||
NAME_TO_ID.put("nether_brick_fence", 113);
|
||||
NAME_TO_ID.put("nether_brick_stairs", 114);
|
||||
NAME_TO_ID.put("enchanting_table", 116);
|
||||
NAME_TO_ID.put("end_portal_frame", 120);
|
||||
NAME_TO_ID.put("end_stone", 121);
|
||||
NAME_TO_ID.put("dragon_egg", 122);
|
||||
NAME_TO_ID.put("redstone_lamp", 123);
|
||||
NAME_TO_ID.put("wooden_slab", 126);
|
||||
NAME_TO_ID.put("sandstone_stairs", 128);
|
||||
NAME_TO_ID.put("emerald_ore", 129);
|
||||
NAME_TO_ID.put("ender_chest", 130);
|
||||
NAME_TO_ID.put("tripwire_hook", 131);
|
||||
NAME_TO_ID.put("emerald_block", 133);
|
||||
NAME_TO_ID.put("spruce_stairs", 134);
|
||||
NAME_TO_ID.put("birch_stairs", 135);
|
||||
NAME_TO_ID.put("jungle_stairs", 136);
|
||||
NAME_TO_ID.put("command_block", 137);
|
||||
NAME_TO_ID.put("beacon", 138);
|
||||
NAME_TO_ID.put("cobblestone_wall", 139);
|
||||
NAME_TO_ID.put("wooden_button", 143);
|
||||
NAME_TO_ID.put("anvil", 145);
|
||||
NAME_TO_ID.put("trapped_chest", 146);
|
||||
NAME_TO_ID.put("light_weighted_pressure_plate", 147);
|
||||
NAME_TO_ID.put("heavy_weighted_pressure_plate", 148);
|
||||
NAME_TO_ID.put("daylight_detector", 151);
|
||||
NAME_TO_ID.put("redstone_block", 152);
|
||||
NAME_TO_ID.put("quartz_ore", 153);
|
||||
NAME_TO_ID.put("hopper", 154);
|
||||
NAME_TO_ID.put("quartz_block", 155);
|
||||
NAME_TO_ID.put("quartz_stairs", 156);
|
||||
NAME_TO_ID.put("activator_rail", 157);
|
||||
NAME_TO_ID.put("dropper", 158);
|
||||
NAME_TO_ID.put("stained_hardened_clay", 159);
|
||||
NAME_TO_ID.put("stained_glass_pane", 160);
|
||||
NAME_TO_ID.put("leaves2", 161);
|
||||
NAME_TO_ID.put("log2", 162);
|
||||
NAME_TO_ID.put("acacia_stairs", 163);
|
||||
NAME_TO_ID.put("dark_oak_stairs", 164);
|
||||
NAME_TO_ID.put("slime", 165);
|
||||
NAME_TO_ID.put("barrier", 166);
|
||||
NAME_TO_ID.put("iron_trapdoor", 167);
|
||||
NAME_TO_ID.put("prismarine", 168);
|
||||
NAME_TO_ID.put("sea_lantern", 169);
|
||||
NAME_TO_ID.put("hay_block", 170);
|
||||
NAME_TO_ID.put("carpet", 171);
|
||||
NAME_TO_ID.put("hardened_clay", 172);
|
||||
NAME_TO_ID.put("coal_block", 173);
|
||||
NAME_TO_ID.put("packed_ice", 174);
|
||||
NAME_TO_ID.put("double_plant", 175);
|
||||
NAME_TO_ID.put("red_sandstone", 179);
|
||||
NAME_TO_ID.put("red_sandstone_stairs", 180);
|
||||
NAME_TO_ID.put("stone_slab2", 182);
|
||||
NAME_TO_ID.put("spruce_fence_gate", 183);
|
||||
NAME_TO_ID.put("birch_fence_gate", 184);
|
||||
NAME_TO_ID.put("jungle_fence_gate", 185);
|
||||
NAME_TO_ID.put("dark_oak_fence_gate", 186);
|
||||
NAME_TO_ID.put("acacia_fence_gate", 187);
|
||||
NAME_TO_ID.put("spruce_fence", 188);
|
||||
NAME_TO_ID.put("birch_fence", 189);
|
||||
NAME_TO_ID.put("jungle_fence", 190);
|
||||
NAME_TO_ID.put("dark_oak_fence", 191);
|
||||
NAME_TO_ID.put("acacia_fence", 192);
|
||||
NAME_TO_ID.put("iron_shovel", 256);
|
||||
NAME_TO_ID.put("iron_pickaxe", 257);
|
||||
NAME_TO_ID.put("iron_axe", 258);
|
||||
NAME_TO_ID.put("flint_and_steel", 259);
|
||||
NAME_TO_ID.put("apple", 260);
|
||||
NAME_TO_ID.put("bow", 261);
|
||||
NAME_TO_ID.put("arrow", 262);
|
||||
NAME_TO_ID.put("coal", 263);
|
||||
NAME_TO_ID.put("diamond", 264);
|
||||
NAME_TO_ID.put("iron_ingot", 265);
|
||||
NAME_TO_ID.put("gold_ingot", 266);
|
||||
NAME_TO_ID.put("iron_sword", 267);
|
||||
NAME_TO_ID.put("wooden_sword", 268);
|
||||
NAME_TO_ID.put("wooden_shovel", 269);
|
||||
NAME_TO_ID.put("wooden_pickaxe", 270);
|
||||
NAME_TO_ID.put("wooden_axe", 271);
|
||||
NAME_TO_ID.put("stone_sword", 272);
|
||||
NAME_TO_ID.put("stone_shovel", 273);
|
||||
NAME_TO_ID.put("stone_pickaxe", 274);
|
||||
NAME_TO_ID.put("stone_axe", 275);
|
||||
NAME_TO_ID.put("diamond_sword", 276);
|
||||
NAME_TO_ID.put("diamond_shovel", 277);
|
||||
NAME_TO_ID.put("diamond_pickaxe", 278);
|
||||
NAME_TO_ID.put("diamond_axe", 279);
|
||||
NAME_TO_ID.put("stick", 280);
|
||||
NAME_TO_ID.put("bowl", 281);
|
||||
NAME_TO_ID.put("mushroom_stew", 282);
|
||||
NAME_TO_ID.put("golden_sword", 283);
|
||||
NAME_TO_ID.put("golden_shovel", 284);
|
||||
NAME_TO_ID.put("golden_pickaxe", 285);
|
||||
NAME_TO_ID.put("golden_axe", 286);
|
||||
NAME_TO_ID.put("string", 287);
|
||||
NAME_TO_ID.put("feather", 288);
|
||||
NAME_TO_ID.put("gunpowder", 289);
|
||||
NAME_TO_ID.put("wooden_hoe", 290);
|
||||
NAME_TO_ID.put("stone_hoe", 291);
|
||||
NAME_TO_ID.put("iron_hoe", 292);
|
||||
NAME_TO_ID.put("diamond_hoe", 293);
|
||||
NAME_TO_ID.put("golden_hoe", 294);
|
||||
NAME_TO_ID.put("wheat_seeds", 295);
|
||||
NAME_TO_ID.put("wheat", 296);
|
||||
NAME_TO_ID.put("bread", 297);
|
||||
NAME_TO_ID.put("leather_helmet", 298);
|
||||
NAME_TO_ID.put("leather_chestplate", 299);
|
||||
NAME_TO_ID.put("leather_leggings", 300);
|
||||
NAME_TO_ID.put("leather_boots", 301);
|
||||
NAME_TO_ID.put("chainmail_helmet", 302);
|
||||
NAME_TO_ID.put("chainmail_chestplate", 303);
|
||||
NAME_TO_ID.put("chainmail_leggings", 304);
|
||||
NAME_TO_ID.put("chainmail_boots", 305);
|
||||
NAME_TO_ID.put("iron_helmet", 306);
|
||||
NAME_TO_ID.put("iron_chestplate", 307);
|
||||
NAME_TO_ID.put("iron_leggings", 308);
|
||||
NAME_TO_ID.put("iron_boots", 309);
|
||||
NAME_TO_ID.put("diamond_helmet", 310);
|
||||
NAME_TO_ID.put("diamond_chestplate", 311);
|
||||
NAME_TO_ID.put("diamond_leggings", 312);
|
||||
NAME_TO_ID.put("diamond_boots", 313);
|
||||
NAME_TO_ID.put("golden_helmet", 314);
|
||||
NAME_TO_ID.put("golden_chestplate", 315);
|
||||
NAME_TO_ID.put("golden_leggings", 316);
|
||||
NAME_TO_ID.put("golden_boots", 317);
|
||||
NAME_TO_ID.put("flint", 318);
|
||||
NAME_TO_ID.put("porkchop", 319);
|
||||
NAME_TO_ID.put("cooked_porkchop", 320);
|
||||
NAME_TO_ID.put("painting", 321);
|
||||
NAME_TO_ID.put("golden_apple", 322);
|
||||
NAME_TO_ID.put("sign", 323);
|
||||
NAME_TO_ID.put("wooden_door", 324);
|
||||
NAME_TO_ID.put("bucket", 325);
|
||||
NAME_TO_ID.put("water_bucket", 326);
|
||||
NAME_TO_ID.put("lava_bucket", 327);
|
||||
NAME_TO_ID.put("minecart", 328);
|
||||
NAME_TO_ID.put("saddle", 329);
|
||||
NAME_TO_ID.put("iron_door", 330);
|
||||
NAME_TO_ID.put("redstone", 331);
|
||||
NAME_TO_ID.put("snowball", 332);
|
||||
NAME_TO_ID.put("boat", 333);
|
||||
NAME_TO_ID.put("leather", 334);
|
||||
NAME_TO_ID.put("milk_bucket", 335);
|
||||
NAME_TO_ID.put("brick", 336);
|
||||
NAME_TO_ID.put("clay_ball", 337);
|
||||
NAME_TO_ID.put("reeds", 338);
|
||||
NAME_TO_ID.put("paper", 339);
|
||||
NAME_TO_ID.put("book", 340);
|
||||
NAME_TO_ID.put("slime_ball", 341);
|
||||
NAME_TO_ID.put("chest_minecart", 342);
|
||||
NAME_TO_ID.put("furnace_minecart", 343);
|
||||
NAME_TO_ID.put("egg", 344);
|
||||
NAME_TO_ID.put("compass", 345);
|
||||
NAME_TO_ID.put("fishing_rod", 346);
|
||||
NAME_TO_ID.put("clock", 347);
|
||||
NAME_TO_ID.put("glowstone_dust", 348);
|
||||
NAME_TO_ID.put("fish", 349);
|
||||
NAME_TO_ID.put("cooked_fish", 350);
|
||||
NAME_TO_ID.put("dye", 351);
|
||||
NAME_TO_ID.put("bone", 352);
|
||||
NAME_TO_ID.put("sugar", 353);
|
||||
NAME_TO_ID.put("cake", 354);
|
||||
NAME_TO_ID.put("bed", 355);
|
||||
NAME_TO_ID.put("repeater", 356);
|
||||
NAME_TO_ID.put("cookie", 357);
|
||||
NAME_TO_ID.put("filled_map", 358);
|
||||
NAME_TO_ID.put("shears", 359);
|
||||
NAME_TO_ID.put("melon", 360);
|
||||
NAME_TO_ID.put("pumpkin_seeds", 361);
|
||||
NAME_TO_ID.put("melon_seeds", 362);
|
||||
NAME_TO_ID.put("beef", 363);
|
||||
NAME_TO_ID.put("cooked_beef", 364);
|
||||
NAME_TO_ID.put("chicken", 365);
|
||||
NAME_TO_ID.put("cooked_chicken", 366);
|
||||
NAME_TO_ID.put("rotten_flesh", 367);
|
||||
NAME_TO_ID.put("ender_pearl", 368);
|
||||
NAME_TO_ID.put("blaze_rod", 369);
|
||||
NAME_TO_ID.put("ghast_tear", 370);
|
||||
NAME_TO_ID.put("gold_nugget", 371);
|
||||
NAME_TO_ID.put("nether_wart", 372);
|
||||
NAME_TO_ID.put("potion", 373);
|
||||
NAME_TO_ID.put("glass_bottle", 374);
|
||||
NAME_TO_ID.put("spider_eye", 375);
|
||||
NAME_TO_ID.put("fermented_spider_eye", 376);
|
||||
NAME_TO_ID.put("blaze_powder", 377);
|
||||
NAME_TO_ID.put("magma_cream", 378);
|
||||
NAME_TO_ID.put("brewing_stand", 379);
|
||||
NAME_TO_ID.put("cauldron", 380);
|
||||
NAME_TO_ID.put("ender_eye", 381);
|
||||
NAME_TO_ID.put("speckled_melon", 382);
|
||||
NAME_TO_ID.put("spawn_egg", 383);
|
||||
NAME_TO_ID.put("experience_bottle", 384);
|
||||
NAME_TO_ID.put("fire_charge", 385);
|
||||
NAME_TO_ID.put("writable_book", 386);
|
||||
NAME_TO_ID.put("written_book", 387);
|
||||
NAME_TO_ID.put("emerald", 388);
|
||||
NAME_TO_ID.put("item_frame", 389);
|
||||
NAME_TO_ID.put("flower_pot", 390);
|
||||
NAME_TO_ID.put("carrot", 391);
|
||||
NAME_TO_ID.put("potato", 392);
|
||||
NAME_TO_ID.put("baked_potato", 393);
|
||||
NAME_TO_ID.put("poisonous_potato", 394);
|
||||
NAME_TO_ID.put("map", 395);
|
||||
NAME_TO_ID.put("golden_carrot", 396);
|
||||
NAME_TO_ID.put("skull", 397);
|
||||
NAME_TO_ID.put("carrot_on_a_stick", 398);
|
||||
NAME_TO_ID.put("nether_star", 399);
|
||||
NAME_TO_ID.put("pumpkin_pie", 400);
|
||||
NAME_TO_ID.put("fireworks", 401);
|
||||
NAME_TO_ID.put("firework_charge", 402);
|
||||
NAME_TO_ID.put("enchanted_book", 403);
|
||||
NAME_TO_ID.put("comparator", 404);
|
||||
NAME_TO_ID.put("netherbrick", 405);
|
||||
NAME_TO_ID.put("quartz", 406);
|
||||
NAME_TO_ID.put("tnt_minecart", 407);
|
||||
NAME_TO_ID.put("hopper_minecart", 408);
|
||||
NAME_TO_ID.put("prismarine_shard", 409);
|
||||
NAME_TO_ID.put("prismarine_crystals", 410);
|
||||
NAME_TO_ID.put("rabbit", 411);
|
||||
NAME_TO_ID.put("cooked_rabbit", 412);
|
||||
NAME_TO_ID.put("rabbit_stew", 413);
|
||||
NAME_TO_ID.put("rabbit_foot", 414);
|
||||
NAME_TO_ID.put("rabbit_hide", 415);
|
||||
NAME_TO_ID.put("armor_stand", 416);
|
||||
NAME_TO_ID.put("iron_horse_armor", 417);
|
||||
NAME_TO_ID.put("golden_horse_armor", 418);
|
||||
NAME_TO_ID.put("diamond_horse_armor", 419);
|
||||
NAME_TO_ID.put("lead", 420);
|
||||
NAME_TO_ID.put("name_tag", 421);
|
||||
NAME_TO_ID.put("command_block_minecart", 422);
|
||||
NAME_TO_ID.put("mutton", 423);
|
||||
NAME_TO_ID.put("cooked_mutton", 424);
|
||||
NAME_TO_ID.put("banner", 425);
|
||||
NAME_TO_ID.put("spruce_door", 427);
|
||||
NAME_TO_ID.put("birch_door", 428);
|
||||
NAME_TO_ID.put("jungle_door", 429);
|
||||
NAME_TO_ID.put("acacia_door", 430);
|
||||
NAME_TO_ID.put("dark_oak_door", 431);
|
||||
NAME_TO_ID.put("record_13", 2256);
|
||||
NAME_TO_ID.put("record_cat", 2257);
|
||||
NAME_TO_ID.put("record_blocks", 2258);
|
||||
NAME_TO_ID.put("record_chirp", 2259);
|
||||
NAME_TO_ID.put("record_far", 2260);
|
||||
NAME_TO_ID.put("record_mall", 2261);
|
||||
NAME_TO_ID.put("record_mellohi", 2262);
|
||||
NAME_TO_ID.put("record_stal", 2263);
|
||||
NAME_TO_ID.put("record_strad", 2264);
|
||||
NAME_TO_ID.put("record_ward", 2265);
|
||||
NAME_TO_ID.put("record_11", 2266);
|
||||
NAME_TO_ID.put("record_wait", 2267);
|
||||
}
|
||||
|
||||
public static void toClient(final Protocol1_8To1_7_6_10 protocol, final UserConnection connection, JsonElement element) {
|
||||
if (element instanceof final JsonObject obj) {
|
||||
if (obj.has("hoverEvent")) {
|
||||
if (!(obj.get("hoverEvent") instanceof final JsonObject hoverEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hoverEvent.has("action") || !hoverEvent.has("value")) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String type = hoverEvent.get("action").getAsString();
|
||||
if (!type.equals("show_item")) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CompoundTag compound = ComponentUtil.deserializeLegacyShowItem(hoverEvent.get("value"), SerializerVersion.V1_8);
|
||||
final int identifier;
|
||||
final String stringId = compound.getString("id");
|
||||
if (stringId != null) {
|
||||
identifier = NAME_TO_ID.getOrDefault(Key.stripMinecraftNamespace(stringId), compound.getShort("id"));
|
||||
} else {
|
||||
identifier = compound.getShort("id");
|
||||
}
|
||||
final CompoundTag itemTag = compound.getCompoundTag("tag");
|
||||
|
||||
final Item dataItem = new DataItem(identifier, (byte) 1, (short) 0, itemTag);
|
||||
protocol.getItemRewriter().handleItemToClient(connection, dataItem);
|
||||
|
||||
compound.putInt("id", dataItem.identifier());
|
||||
if (dataItem.tag() != itemTag) {
|
||||
compound.put("tag", dataItem.tag());
|
||||
}
|
||||
hoverEvent.addProperty("value", SerializerVersion.V1_7.toSNBT(compound));
|
||||
} else if (obj.has("extra")) {
|
||||
toClient(protocol, connection, obj.get("extra"));
|
||||
} else if (obj.has("translate") && obj.has("with")) {
|
||||
toClient(protocol, connection, obj.get("with"));
|
||||
}
|
||||
} else if (element instanceof final JsonArray array) {
|
||||
for (JsonElement value : array) {
|
||||
toClient(protocol, connection, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.data;
|
||||
|
||||
import com.viaversion.viaversion.libs.gson.JsonArray;
|
||||
import com.viaversion.viaversion.libs.gson.JsonElement;
|
||||
import com.viaversion.viaversion.libs.gson.JsonObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChatNewlineRewriter {
|
||||
private static final String[] STYLE_KEYS = {
|
||||
"color",
|
||||
"bold",
|
||||
"italic",
|
||||
"underlined",
|
||||
"strikethrough",
|
||||
"obfuscated",
|
||||
"clickEvent",
|
||||
"hoverEvent",
|
||||
"insertion"
|
||||
};
|
||||
|
||||
public static List<JsonObject> splitChatComponentByNewline(JsonElement element) {
|
||||
return splitChatComponentByNewline(element, new JsonObject());
|
||||
}
|
||||
|
||||
private static List<JsonObject> splitChatComponentByNewline(JsonElement element, JsonObject inheritedStyle) {
|
||||
List<JsonObject> results = new ArrayList<>();
|
||||
if (element == null || element.isJsonNull()) {
|
||||
return results;
|
||||
}
|
||||
|
||||
if (element.isJsonPrimitive()) {
|
||||
String text = element.getAsString();
|
||||
for (String part : text.split("\n", -1)) {
|
||||
JsonObject obj = inheritedStyle.deepCopy();
|
||||
obj.addProperty("text", part);
|
||||
results.add(obj);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
if (element.isJsonArray()) {
|
||||
List<JsonObject> currentLine = new ArrayList<>();
|
||||
JsonObject siblingStyle = inheritedStyle;
|
||||
boolean foundRoot = false;
|
||||
|
||||
for (JsonElement child : element.getAsJsonArray()) {
|
||||
List<JsonObject> splitParts = splitChatComponentByNewline(child, siblingStyle);
|
||||
for (int i = 0; i < splitParts.size(); i++) {
|
||||
currentLine.add(splitParts.get(i));
|
||||
if (i < splitParts.size() - 1) {
|
||||
results.add(mergeLine(currentLine));
|
||||
currentLine.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundRoot && child != null && !child.isJsonNull()) {
|
||||
siblingStyle = rootStyle(inheritedStyle, child);
|
||||
foundRoot = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentLine.isEmpty()) {
|
||||
results.add(mergeLine(currentLine));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
if (!element.isJsonObject()) {
|
||||
return results;
|
||||
}
|
||||
|
||||
JsonObject obj = element.getAsJsonObject();
|
||||
|
||||
// Build the style for this node: inherit first, then override with this object's style
|
||||
JsonObject currentStyle = mergeStyle(inheritedStyle, obj);
|
||||
|
||||
// Gather components in order: base text then extra array
|
||||
List<JsonElement> ordered = new ArrayList<>();
|
||||
if (obj.has("text")) {
|
||||
ordered.add(obj.get("text"));
|
||||
}
|
||||
if (obj.has("extra") && obj.get("extra").isJsonArray()) {
|
||||
for (JsonElement extra : obj.getAsJsonArray("extra")) {
|
||||
ordered.add(extra);
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no text/extra, return a single object with the style
|
||||
if (ordered.isEmpty()) {
|
||||
JsonObject baseComponent = copyComponentWithoutExtra(obj, currentStyle);
|
||||
results.add(baseComponent != null ? baseComponent : currentStyle);
|
||||
return results;
|
||||
}
|
||||
|
||||
// Build lines by concatenating split pieces
|
||||
List<JsonObject> currentLine = new ArrayList<>();
|
||||
if (!obj.has("text")) {
|
||||
JsonObject baseComponent = copyComponentWithoutExtra(obj, currentStyle);
|
||||
if (baseComponent != null) {
|
||||
currentLine.add(baseComponent);
|
||||
}
|
||||
}
|
||||
for (JsonElement part : ordered) {
|
||||
if (part == null || part.isJsonNull()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (part.isJsonPrimitive()) {
|
||||
String text = part.getAsString();
|
||||
String[] split = text.split("\n", -1);
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
JsonObject piece = currentStyle.deepCopy();
|
||||
piece.addProperty("text", split[i]);
|
||||
currentLine.add(piece);
|
||||
|
||||
if (i < split.length - 1) {
|
||||
results.add(mergeLine(currentLine));
|
||||
currentLine.clear();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (part.isJsonObject() || part.isJsonArray()) {
|
||||
List<JsonObject> splitParts = splitChatComponentByNewline(part, currentStyle);
|
||||
for (int i = 0; i < splitParts.size(); i++) {
|
||||
currentLine.add(splitParts.get(i));
|
||||
if (i < splitParts.size() - 1) {
|
||||
results.add(mergeLine(currentLine));
|
||||
currentLine.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentLine.isEmpty()) {
|
||||
results.add(mergeLine(currentLine));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static JsonObject rootStyle(JsonObject inheritedStyle, JsonElement element) {
|
||||
if (element == null || element.isJsonNull()) {
|
||||
return inheritedStyle;
|
||||
}
|
||||
if (element.isJsonObject()) {
|
||||
return mergeStyle(inheritedStyle, element.getAsJsonObject());
|
||||
}
|
||||
if (element.isJsonArray()) {
|
||||
for (JsonElement child : element.getAsJsonArray()) {
|
||||
if (child != null && !child.isJsonNull()) {
|
||||
return rootStyle(inheritedStyle, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return inheritedStyle;
|
||||
}
|
||||
|
||||
private static JsonObject mergeStyle(JsonObject inheritedStyle, JsonObject obj) {
|
||||
JsonObject currentStyle = inheritedStyle.deepCopy();
|
||||
for (String key : STYLE_KEYS) {
|
||||
if (obj.has(key)) {
|
||||
currentStyle.add(key, obj.get(key).deepCopy());
|
||||
}
|
||||
}
|
||||
return currentStyle;
|
||||
}
|
||||
|
||||
private static JsonObject copyComponentWithoutExtra(JsonObject obj, JsonObject currentStyle) {
|
||||
JsonObject component = currentStyle.deepCopy();
|
||||
for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if ("extra".equals(key) || isStyleKey(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
component.add(key, entry.getValue().deepCopy());
|
||||
}
|
||||
return component.size() == currentStyle.size() ? null : component;
|
||||
}
|
||||
|
||||
private static boolean isStyleKey(String key) {
|
||||
for (String styleKey : STYLE_KEYS) {
|
||||
if (styleKey.equals(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static JsonObject mergeLine(List<JsonObject> lineParts) {
|
||||
if (lineParts.isEmpty()) {
|
||||
JsonObject empty = new JsonObject();
|
||||
empty.addProperty("text", "");
|
||||
return empty;
|
||||
}
|
||||
|
||||
JsonObject first = lineParts.get(0);
|
||||
if (lineParts.size() == 1) {
|
||||
return first;
|
||||
}
|
||||
|
||||
JsonObject merged = new JsonObject();
|
||||
merged.addProperty("text", "");
|
||||
|
||||
JsonArray extra = new JsonArray();
|
||||
for (JsonObject linePart : lineParts) {
|
||||
extra.add(linePart);
|
||||
}
|
||||
merged.add("extra", extra);
|
||||
return merged;
|
||||
}
|
||||
}
|
||||
+170
-138
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,194 +22,226 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_8;
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.*;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.ABSTRACT_AGEABLE;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.ABSTRACT_MINECART;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.ARMOR_STAND;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.ARROW;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.BAT;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.BLAZE;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.BOAT;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.CREEPER;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.ENDERMAN;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.END_CRYSTAL;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.ENTITY;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.FIREWORK_ROCKET;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.FURNACE_MINECART;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.GHAST;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.GUARDIAN;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.HORSE;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.IRON_GOLEM;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.ITEM;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.ITEM_FRAME;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.LIVING_ENTITY;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.LIVING_ENTITY_BASE;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.OCELOT;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.PIG;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.PLAYER;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.SHEEP;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.SKELETON;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.SLIME;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.SPIDER;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.TAMABLE_ANIMAL;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.VILLAGER;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.WITCH;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.WITHER;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.WOLF;
|
||||
import static com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8.EntityType.ZOMBIE;
|
||||
|
||||
public enum EntityDataIndex1_7_6_10 {
|
||||
|
||||
ENTITY_FLAGS(ENTITY, 0, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ENTITY_AIR(ENTITY, 1, EntityDataTypes1_7_6_10.SHORT, EntityDataTypes1_8.SHORT),
|
||||
ENTITY_NAME_TAG(ENTITY, -1, null, 2, EntityDataTypes1_8.STRING),
|
||||
ENTITY_NAME_TAG_VISIBILITY(ENTITY, -1, null, 3, EntityDataTypes1_8.BYTE),
|
||||
ENTITY_SILENT(ENTITY, -1, null, 4, EntityDataTypes1_8.BYTE),
|
||||
ENTITY_FLAGS(ENTITY, 0, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ENTITY_AIR(ENTITY, 1, EntityDataTypes1_7_6_10.SHORT, EntityDataTypes1_8.SHORT),
|
||||
ENTITY_NAME_TAG(ENTITY, -1, null, 2, EntityDataTypes1_8.STRING),
|
||||
ENTITY_NAME_TAG_VISIBILITY(ENTITY, -1, null, 3, EntityDataTypes1_8.BYTE),
|
||||
ENTITY_SILENT(ENTITY, -1, null, 4, EntityDataTypes1_8.BYTE),
|
||||
|
||||
LIVING_ENTITY_BASE_HEALTH(LIVING_ENTITY_BASE, 6, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
LIVING_ENTITY_BASE_POTION_EFFECT_COLOR(LIVING_ENTITY_BASE, 7, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
LIVING_ENTITY_BASE_IS_POTION_EFFECT_AMBIENT(LIVING_ENTITY_BASE, 8, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
LIVING_ENTITY_BASE_ARROWS(LIVING_ENTITY_BASE, 9, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
LIVING_ENTITY_BASE_NAME_TAG(LIVING_ENTITY_BASE, 10, EntityDataTypes1_7_6_10.STRING, 2, EntityDataTypes1_8.STRING),
|
||||
LIVING_ENTITY_BASE_NAME_TAG_VISIBILITY(LIVING_ENTITY_BASE, 11, EntityDataTypes1_7_6_10.BYTE, 3, EntityDataTypes1_8.BYTE),
|
||||
LIVING_ENTITY_BASE_HEALTH(LIVING_ENTITY_BASE, 6, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
LIVING_ENTITY_BASE_POTION_EFFECT_COLOR(LIVING_ENTITY_BASE, 7, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
LIVING_ENTITY_BASE_IS_POTION_EFFECT_AMBIENT(LIVING_ENTITY_BASE, 8, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
LIVING_ENTITY_BASE_ARROWS(LIVING_ENTITY_BASE, 9, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
LIVING_ENTITY_BASE_NAME_TAG(LIVING_ENTITY_BASE, 10, EntityDataTypes1_7_6_10.STRING, 2, EntityDataTypes1_8.STRING),
|
||||
LIVING_ENTITY_BASE_NAME_TAG_VISIBILITY(LIVING_ENTITY_BASE, 11, EntityDataTypes1_7_6_10.BYTE, 3, EntityDataTypes1_8.BYTE),
|
||||
|
||||
LIVING_ENTITY_AI(LIVING_ENTITY, -1, null, 15, EntityDataTypes1_8.BYTE),
|
||||
LIVING_ENTITY_AI(LIVING_ENTITY, -1, null, 15, EntityDataTypes1_8.BYTE),
|
||||
|
||||
ABSTRACT_AGEABLE_AGE(ABSTRACT_AGEABLE, 12, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.BYTE),
|
||||
ABSTRACT_AGEABLE_AGE(ABSTRACT_AGEABLE, 12, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.BYTE),
|
||||
|
||||
ARMOR_STAND_FLAGS(ARMOR_STAND, -1, null, 10, EntityDataTypes1_8.BYTE),
|
||||
ARMOR_STAND_HEAD_POSITION(ARMOR_STAND, -1, null, 11, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_BODY_POSITION(ARMOR_STAND, -1, null, 12, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_LEFT_ARM_POSITION(ARMOR_STAND, -1, null, 13, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_RIGHT_ARM_POSITION(ARMOR_STAND, -1, null, 14, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_LEFT_LEG_POSITION(ARMOR_STAND, -1, null, 15, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_RIGHT_LEG_POSITION(ARMOR_STAND, -1, null, 16, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_FLAGS(ARMOR_STAND, -1, null, 10, EntityDataTypes1_8.BYTE),
|
||||
ARMOR_STAND_HEAD_POSITION(ARMOR_STAND, -1, null, 11, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_BODY_POSITION(ARMOR_STAND, -1, null, 12, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_LEFT_ARM_POSITION(ARMOR_STAND, -1, null, 13, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_RIGHT_ARM_POSITION(ARMOR_STAND, -1, null, 14, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_LEFT_LEG_POSITION(ARMOR_STAND, -1, null, 15, EntityDataTypes1_8.ROTATIONS),
|
||||
ARMOR_STAND_RIGHT_LEG_POSITION(ARMOR_STAND, -1, null, 16, EntityDataTypes1_8.ROTATIONS),
|
||||
|
||||
PLAYER_SKIN_FLAGS(PLAYER, 16, EntityDataTypes1_7_6_10.BYTE, 10, EntityDataTypes1_8.BYTE),
|
||||
PLAYER_UNUSED(PLAYER, -1, null, 16, EntityDataTypes1_8.BYTE),
|
||||
PLAYER_ABSORPTION_HEATS(PLAYER, 17, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
PLAYER_SCORE(PLAYER, 18, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
PLAYER_SKIN_FLAGS(PLAYER, 16, EntityDataTypes1_7_6_10.BYTE, 10, EntityDataTypes1_8.BYTE),
|
||||
PLAYER_UNUSED(PLAYER, -1, null, 16, EntityDataTypes1_8.BYTE),
|
||||
PLAYER_ABSORPTION_HEATS(PLAYER, 17, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
PLAYER_SCORE(PLAYER, 18, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
|
||||
HORSE_FLAGS(HORSE, 16, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
HORSE_TYPE(HORSE, 19, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
HORSE_COLOR(HORSE, 20, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
HORSE_OWNER(HORSE, 21, EntityDataTypes1_7_6_10.STRING, EntityDataTypes1_8.STRING),
|
||||
HORSE_ARMOR(HORSE, 22, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
HORSE_FLAGS(HORSE, 16, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
HORSE_TYPE(HORSE, 19, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
HORSE_COLOR(HORSE, 20, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
HORSE_OWNER(HORSE, 21, EntityDataTypes1_7_6_10.STRING, EntityDataTypes1_8.STRING),
|
||||
HORSE_ARMOR(HORSE, 22, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
|
||||
BAT_HANGING(BAT, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
BAT_HANGING(BAT, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
TAMABLE_ANIMAL_FLAGS(TAMABLE_ANIMAL, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
TAMABLE_ANIMAL_OWNER(TAMABLE_ANIMAL, 17, EntityDataTypes1_7_6_10.STRING, EntityDataTypes1_8.STRING),
|
||||
TAMABLE_ANIMAL_FLAGS(TAMABLE_ANIMAL, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
TAMABLE_ANIMAL_OWNER(TAMABLE_ANIMAL, 17, EntityDataTypes1_7_6_10.STRING, EntityDataTypes1_8.STRING),
|
||||
|
||||
OCELOT_TYPE(OCELOT, 18, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
OCELOT_TYPE(OCELOT, 18, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
WOLF_FLAGS(WOLF, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
WOLF_HEALTH(WOLF, 18, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
WOLF_BEGGING(WOLF, 19, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
WOLF_COLLAR_COLOR(WOLF, 20, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
WOLF_FLAGS(WOLF, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
WOLF_HEALTH(WOLF, 18, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
WOLF_BEGGING(WOLF, 19, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
WOLF_COLLAR_COLOR(WOLF, 20, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
PIG_SADDLE(PIG, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
PIG_SADDLE(PIG, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
SHEEP_COLOR_OR_SHEARED(SHEEP, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
SHEEP_COLOR_OR_SHEARED(SHEEP, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
VILLAGER_TYPE(VILLAGER, 16, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
VILLAGER_TYPE(VILLAGER, 16, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
|
||||
ENDERMAN_CARRIED_BLOCK(ENDERMAN, 16, null, EntityDataTypes1_8.SHORT),
|
||||
ENDERMAN_CARRIED_BLOCK_DATA(ENDERMAN, 17, null, EntityDataTypes1_8.BYTE),
|
||||
ENDERMAN_IS_SCREAMING(ENDERMAN, 18, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ENDERMAN_CARRIED_BLOCK(ENDERMAN, 16, null, EntityDataTypes1_8.SHORT),
|
||||
ENDERMAN_CARRIED_BLOCK_DATA(ENDERMAN, 17, null, EntityDataTypes1_8.BYTE),
|
||||
ENDERMAN_IS_SCREAMING(ENDERMAN, 18, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
ZOMBIE_CHILD(ZOMBIE, 12, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ZOMBIE_VILLAGER(ZOMBIE, 13, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ZOMBIE_CONVERTING(ZOMBIE, 14, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ZOMBIE_CHILD(ZOMBIE, 12, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ZOMBIE_VILLAGER(ZOMBIE, 13, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ZOMBIE_CONVERTING(ZOMBIE, 14, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
BLAZE_ON_FIRE(BLAZE, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
BLAZE_ON_FIRE(BLAZE, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
SPIDER_CLIMBING(SPIDER, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
SPIDER_CLIMBING(SPIDER, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
CREEPER_STATE(CREEPER, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
CREEPER_POWERED(CREEPER, 17, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
CREEPER_IGNITED(CREEPER, 18, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
CREEPER_STATE(CREEPER, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
CREEPER_POWERED(CREEPER, 17, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
CREEPER_IGNITED(CREEPER, 18, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
GHAST_STATE(GHAST, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
GHAST_IS_POWERED(GHAST, 17, null, EntityDataTypes1_8.BYTE),
|
||||
GHAST_STATE(GHAST, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
GHAST_IS_POWERED(GHAST, 17, null, EntityDataTypes1_8.BYTE),
|
||||
|
||||
SLIME_SIZE(SLIME, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
SLIME_SIZE(SLIME, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
SKELETON_TYPE(SKELETON, 13, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
SKELETON_TYPE(SKELETON, 13, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
WITCH_AGGRESSIVE(WITCH, 21, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
WITCH_AGGRESSIVE(WITCH, 21, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
IRON_GOLEM_IS_PLAYER_CREATED(IRON_GOLEM, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
IRON_GOLEM_IS_PLAYER_CREATED(IRON_GOLEM, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
WITHER_WATCHED_TARGET_1(WITHER, 17, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
WITHER_WATCHED_TARGET_2(WITHER, 18, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
WITHER_WATCHED_TARGET_3(WITHER, 19, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
WITHER_INVULNERABLE_TIME(WITHER, 20, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
WITHER_WATCHED_TARGET_1(WITHER, 17, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
WITHER_WATCHED_TARGET_2(WITHER, 18, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
WITHER_WATCHED_TARGET_3(WITHER, 19, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
WITHER_INVULNERABLE_TIME(WITHER, 20, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
|
||||
GUARDIAN_FLAGS(GUARDIAN, 16, null, EntityDataTypes1_8.BYTE),
|
||||
GUARDIAN_TARGET(GUARDIAN, 17, null, EntityDataTypes1_8.INT),
|
||||
GUARDIAN_FLAGS(GUARDIAN, 16, null, EntityDataTypes1_8.BYTE),
|
||||
GUARDIAN_TARGET(GUARDIAN, 17, null, EntityDataTypes1_8.INT),
|
||||
|
||||
BOAT_TIME_SINCE_HIT(BOAT, 17, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
BOAT_FORWARD_DIRECTION(BOAT, 18, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
BOAT_DAMAGE_TAKEN(BOAT, 19, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
BOAT_TIME_SINCE_HIT(BOAT, 17, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
BOAT_FORWARD_DIRECTION(BOAT, 18, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
BOAT_DAMAGE_TAKEN(BOAT, 19, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
|
||||
ABSTRACT_MINECART_SHAKING_POWER(ABSTRACT_MINECART, 17, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
ABSTRACT_MINECART_SHAKING_DIRECTION(ABSTRACT_MINECART, 18, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
ABSTRACT_MINECART_DAMAGE_TAKEN(ABSTRACT_MINECART, 19, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
ABSTRACT_MINECART_BLOCK_INSIDE(ABSTRACT_MINECART, 20, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
ABSTRACT_MINECART_BLOCK_Y(ABSTRACT_MINECART, 21, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
ABSTRACT_MINECART_SHOW_BLOCK(ABSTRACT_MINECART, 22, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ABSTRACT_MINECART_SHAKING_POWER(ABSTRACT_MINECART, 17, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
ABSTRACT_MINECART_SHAKING_DIRECTION(ABSTRACT_MINECART, 18, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
ABSTRACT_MINECART_DAMAGE_TAKEN(ABSTRACT_MINECART, 19, EntityDataTypes1_7_6_10.FLOAT, EntityDataTypes1_8.FLOAT),
|
||||
ABSTRACT_MINECART_BLOCK_INSIDE(ABSTRACT_MINECART, 20, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
ABSTRACT_MINECART_BLOCK_Y(ABSTRACT_MINECART, 21, EntityDataTypes1_7_6_10.INT, EntityDataTypes1_8.INT),
|
||||
ABSTRACT_MINECART_SHOW_BLOCK(ABSTRACT_MINECART, 22, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
FURNACE_MINECART_IS_POWERED(FURNACE_MINECART, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
FURNACE_MINECART_IS_POWERED(FURNACE_MINECART, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
ITEM_ITEM(ITEM, 10, EntityDataTypes1_7_6_10.ITEM, EntityDataTypes1_8.ITEM),
|
||||
ITEM_ITEM(ITEM, 10, EntityDataTypes1_7_6_10.ITEM, EntityDataTypes1_8.ITEM),
|
||||
|
||||
ARROW_IS_CRITICAL(ARROW, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
ARROW_IS_CRITICAL(ARROW, 16, EntityDataTypes1_7_6_10.BYTE, EntityDataTypes1_8.BYTE),
|
||||
|
||||
FIREWORK_ROCKET_INFO(FIREWORK_ROCKET, 8, EntityDataTypes1_7_6_10.ITEM, EntityDataTypes1_8.ITEM),
|
||||
FIREWORK_ROCKET_INFO(FIREWORK_ROCKET, 8, EntityDataTypes1_7_6_10.ITEM, EntityDataTypes1_8.ITEM),
|
||||
|
||||
ITEM_FRAME_ITEM(ITEM_FRAME, 2, EntityDataTypes1_7_6_10.ITEM, 8, EntityDataTypes1_8.ITEM),
|
||||
ITEM_FRAME_ROTATION(ITEM_FRAME, 3, EntityDataTypes1_7_6_10.BYTE, 9, EntityDataTypes1_8.BYTE),
|
||||
ITEM_FRAME_ITEM(ITEM_FRAME, 2, EntityDataTypes1_7_6_10.ITEM, 8, EntityDataTypes1_8.ITEM),
|
||||
ITEM_FRAME_ROTATION(ITEM_FRAME, 3, EntityDataTypes1_7_6_10.BYTE, 9, EntityDataTypes1_8.BYTE),
|
||||
|
||||
END_CRYSTAL_HEALTH(END_CRYSTAL, 8, EntityDataTypes1_7_6_10.INT, 9, EntityDataTypes1_8.INT);
|
||||
END_CRYSTAL_HEALTH(END_CRYSTAL, 8, EntityDataTypes1_7_6_10.INT, 9, EntityDataTypes1_8.INT);
|
||||
|
||||
private static final HashMap<Pair<EntityTypes1_8.EntityType, Integer>, EntityDataIndex1_7_6_10> ENTITY_DATA_REWRITES = new HashMap<>();
|
||||
private static final HashMap<Pair<EntityTypes1_8.EntityType, Integer>, EntityDataIndex1_7_6_10> ENTITY_DATA_REWRITES = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (EntityDataIndex1_7_6_10 index : EntityDataIndex1_7_6_10.values()) {
|
||||
ENTITY_DATA_REWRITES.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
|
||||
}
|
||||
}
|
||||
static {
|
||||
for (EntityDataIndex1_7_6_10 index : EntityDataIndex1_7_6_10.values()) {
|
||||
ENTITY_DATA_REWRITES.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
|
||||
}
|
||||
}
|
||||
|
||||
private final EntityTypes1_8.EntityType clazz;
|
||||
private final int newIndex;
|
||||
private final EntityDataTypes1_8 newType;
|
||||
private final EntityDataTypes1_7_6_10 oldType;
|
||||
private final int index;
|
||||
private final EntityTypes1_8.EntityType clazz;
|
||||
private final int newIndex;
|
||||
private final EntityDataTypes1_8 newType;
|
||||
private final EntityDataTypes1_7_6_10 oldType;
|
||||
private final int index;
|
||||
|
||||
EntityDataIndex1_7_6_10(EntityTypes1_8.EntityType type, int index, EntityDataTypes1_7_6_10 oldType, EntityDataTypes1_8 newType) {
|
||||
this.clazz = type;
|
||||
this.index = index;
|
||||
this.newIndex = index;
|
||||
this.oldType = oldType;
|
||||
this.newType = newType;
|
||||
}
|
||||
EntityDataIndex1_7_6_10(EntityTypes1_8.EntityType type, int index, EntityDataTypes1_7_6_10 oldType, EntityDataTypes1_8 newType) {
|
||||
this.clazz = type;
|
||||
this.index = index;
|
||||
this.newIndex = index;
|
||||
this.oldType = oldType;
|
||||
this.newType = newType;
|
||||
}
|
||||
|
||||
EntityDataIndex1_7_6_10(EntityTypes1_8.EntityType type, int index, EntityDataTypes1_7_6_10 oldType, int newIndex, EntityDataTypes1_8 newType) {
|
||||
this.clazz = type;
|
||||
this.index = index;
|
||||
this.oldType = oldType;
|
||||
this.newIndex = newIndex;
|
||||
this.newType = newType;
|
||||
}
|
||||
EntityDataIndex1_7_6_10(EntityTypes1_8.EntityType type, int index, EntityDataTypes1_7_6_10 oldType, int newIndex, EntityDataTypes1_8 newType) {
|
||||
this.clazz = type;
|
||||
this.index = index;
|
||||
this.oldType = oldType;
|
||||
this.newIndex = newIndex;
|
||||
this.newType = newType;
|
||||
}
|
||||
|
||||
private static Optional<EntityDataIndex1_7_6_10> getIndex(EntityType type, int index) {
|
||||
final Pair<EntityType, Integer> pair = new Pair<>(type, index);
|
||||
return Optional.ofNullable(ENTITY_DATA_REWRITES.get(pair));
|
||||
}
|
||||
private static Optional<EntityDataIndex1_7_6_10> getIndex(EntityType type, int index) {
|
||||
final Pair<EntityType, Integer> pair = new Pair<>(type, index);
|
||||
return Optional.ofNullable(ENTITY_DATA_REWRITES.get(pair));
|
||||
}
|
||||
|
||||
public EntityTypes1_8.EntityType getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
public static EntityDataIndex1_7_6_10 searchIndex(EntityType type, int index) {
|
||||
EntityType currentType = type;
|
||||
do {
|
||||
Optional<EntityDataIndex1_7_6_10> optMeta = getIndex(currentType, index);
|
||||
|
||||
public int getNewIndex() {
|
||||
return newIndex;
|
||||
}
|
||||
if (optMeta.isPresent()) {
|
||||
return optMeta.get();
|
||||
}
|
||||
|
||||
public EntityDataTypes1_8 getNewType() {
|
||||
return newType;
|
||||
}
|
||||
currentType = currentType.getParent();
|
||||
} while (currentType != null);
|
||||
|
||||
public EntityDataTypes1_7_6_10 getOldType() {
|
||||
return oldType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
public EntityTypes1_8.EntityType getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public static EntityDataIndex1_7_6_10 searchIndex(EntityType type, int index) {
|
||||
EntityType currentType = type;
|
||||
do {
|
||||
Optional<EntityDataIndex1_7_6_10> optMeta = getIndex(currentType, index);
|
||||
public int getNewIndex() {
|
||||
return newIndex;
|
||||
}
|
||||
|
||||
if (optMeta.isPresent()) {
|
||||
return optMeta.get();
|
||||
}
|
||||
public EntityDataTypes1_8 getNewType() {
|
||||
return newType;
|
||||
}
|
||||
|
||||
currentType = currentType.getParent();
|
||||
} while (currentType != null);
|
||||
public EntityDataTypes1_7_6_10 getOldType() {
|
||||
return oldType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
+69
-68
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,77 +20,78 @@ package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.data;
|
||||
import java.util.HashMap;
|
||||
|
||||
public enum Particles1_8 {
|
||||
EXPLOSION_NORMAL("explode"),
|
||||
EXPLOSION_LARGE("largeexplode"),
|
||||
EXPLOSION_HUGE("hugeexplosion"),
|
||||
FIREWORKS_SPARK("fireworksSpark"),
|
||||
WATER_BUBBLE("bubble"),
|
||||
WATER_SPLASH("splash"),
|
||||
WATER_WAKE("wake"),
|
||||
SUSPENDED("suspended"),
|
||||
SUSPENDED_DEPTH("depthsuspend"),
|
||||
CRIT("crit"),
|
||||
CRIT_MAGIC("magicCrit"),
|
||||
SMOKE_NORMAL("smoke"),
|
||||
SMOKE_LARGE("largesmoke"),
|
||||
SPELL("spell"),
|
||||
SPELL_INSTANT("instantSpell"),
|
||||
SPELL_MOB("mobSpell"),
|
||||
SPELL_MOB_AMBIENT("mobSpellAmbient"),
|
||||
SPELL_WITCH("witchMagic"),
|
||||
DRIP_WATER("dripWater"),
|
||||
DRIP_LAVA("dripLava"),
|
||||
VILLAGER_ANGRY("angryVillager"),
|
||||
VILLAGER_HAPPY("happyVillager"),
|
||||
TOWN_AURA("townaura"),
|
||||
NOTE("note"),
|
||||
PORTAL("portal"),
|
||||
ENCHANTMENT_TABLE("enchantmenttable"),
|
||||
FLAME("flame"),
|
||||
LAVA("lava"),
|
||||
FOOTSTEP("footstep"),
|
||||
CLOUD("cloud"),
|
||||
REDSTONE("reddust"),
|
||||
SNOWBALL("snowballpoof"),
|
||||
SNOW_SHOVEL("snowshovel"),
|
||||
SLIME("slime"),
|
||||
HEART("heart"),
|
||||
BARRIER("barrier"),
|
||||
ICON_CRACK("iconcrack", 2),
|
||||
BLOCK_CRACK("blockcrack", 1),
|
||||
BLOCK_DUST("blockdust", 1),
|
||||
WATER_DROP("droplet"),
|
||||
ITEM_TAKE("take"),
|
||||
MOB_APPEARANCE("mobappearance");
|
||||
EXPLOSION_NORMAL("explode"),
|
||||
EXPLOSION_LARGE("largeexplode"),
|
||||
EXPLOSION_HUGE("hugeexplosion"),
|
||||
FIREWORKS_SPARK("fireworksSpark"),
|
||||
WATER_BUBBLE("bubble"),
|
||||
WATER_SPLASH("splash"),
|
||||
WATER_WAKE("wake"),
|
||||
SUSPENDED("suspended"),
|
||||
SUSPENDED_DEPTH("depthsuspend"),
|
||||
CRIT("crit"),
|
||||
CRIT_MAGIC("magicCrit"),
|
||||
SMOKE_NORMAL("smoke"),
|
||||
SMOKE_LARGE("largesmoke"),
|
||||
SPELL("spell"),
|
||||
SPELL_INSTANT("instantSpell"),
|
||||
SPELL_MOB("mobSpell"),
|
||||
SPELL_MOB_AMBIENT("mobSpellAmbient"),
|
||||
SPELL_WITCH("witchMagic"),
|
||||
DRIP_WATER("dripWater"),
|
||||
DRIP_LAVA("dripLava"),
|
||||
VILLAGER_ANGRY("angryVillager"),
|
||||
VILLAGER_HAPPY("happyVillager"),
|
||||
TOWN_AURA("townaura"),
|
||||
NOTE("note"),
|
||||
PORTAL("portal"),
|
||||
ENCHANTMENT_TABLE("enchantmenttable"),
|
||||
FLAME("flame"),
|
||||
LAVA("lava"),
|
||||
FOOTSTEP("footstep"),
|
||||
CLOUD("cloud"),
|
||||
REDSTONE("reddust"),
|
||||
SNOWBALL("snowballpoof"),
|
||||
SNOW_SHOVEL("snowshovel"),
|
||||
SLIME("slime"),
|
||||
HEART("heart"),
|
||||
BARRIER("barrier"),
|
||||
ICON_CRACK("iconcrack", 2),
|
||||
BLOCK_CRACK("blockcrack", 1),
|
||||
BLOCK_DUST("blockdust", 1),
|
||||
WATER_DROP("droplet"),
|
||||
ITEM_TAKE("take"),
|
||||
MOB_APPEARANCE("mobappearance");
|
||||
|
||||
public final String name;
|
||||
public final int extra;
|
||||
private static final HashMap<String, Particles1_8> particleMap = new HashMap<>();
|
||||
private static final HashMap<String, Particles1_8> particleMap = new HashMap<>();
|
||||
|
||||
Particles1_8(String name) {
|
||||
this(name, 0);
|
||||
}
|
||||
static {
|
||||
Particles1_8[] particles = values();
|
||||
|
||||
Particles1_8(String name, int extra) {
|
||||
this.name = name;
|
||||
this.extra = extra;
|
||||
}
|
||||
for (Particles1_8 particle : particles) {
|
||||
particleMap.put(particle.name, particle);
|
||||
}
|
||||
}
|
||||
|
||||
public static Particles1_8 find(String part) {
|
||||
return particleMap.get(part);
|
||||
}
|
||||
public final String name;
|
||||
public final int extra;
|
||||
|
||||
public static Particles1_8 find(int id) {
|
||||
if (id < 0) return null;
|
||||
Particles1_8[] values = Particles1_8.values();
|
||||
return id >= values.length ? null : values[id];
|
||||
}
|
||||
Particles1_8(String name) {
|
||||
this(name, 0);
|
||||
}
|
||||
|
||||
static {
|
||||
Particles1_8[] particles = values();
|
||||
Particles1_8(String name, int extra) {
|
||||
this.name = name;
|
||||
this.extra = extra;
|
||||
}
|
||||
|
||||
for (Particles1_8 particle : particles) {
|
||||
particleMap.put(particle.name, particle);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static Particles1_8 find(String part) {
|
||||
return particleMap.get(part);
|
||||
}
|
||||
|
||||
public static Particles1_8 find(int id) {
|
||||
if (id < 0) return null;
|
||||
Particles1_8[] values = Particles1_8.values();
|
||||
return id >= values.length ? null : values[id];
|
||||
}
|
||||
}
|
||||
+89
-47
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,7 @@ 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.viarewind.protocol.v1_8to1_7_6_10.storage.EntityTracker1_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;
|
||||
@@ -46,8 +47,13 @@ public class VirtualHologramEntity {
|
||||
private String name = null;
|
||||
private float yaw, pitch;
|
||||
private float headYaw;
|
||||
private byte flags = 0;
|
||||
private byte armorStandFlags = 0;
|
||||
private boolean small = false;
|
||||
private boolean marker = false;
|
||||
private boolean sneaking = false;
|
||||
private boolean gravity = false;
|
||||
private byte alwaysShowNametag;
|
||||
|
||||
public VirtualHologramEntity(final UserConnection user, final int entityId) {
|
||||
this.user = user;
|
||||
@@ -60,7 +66,7 @@ public class VirtualHologramEntity {
|
||||
this.locY = y;
|
||||
this.locZ = z;
|
||||
|
||||
updateLocation(false);
|
||||
updateLocation();
|
||||
}
|
||||
|
||||
public void setRelativePosition(final double x, final double y, final double z) {
|
||||
@@ -69,7 +75,7 @@ public class VirtualHologramEntity {
|
||||
this.locY += y;
|
||||
this.locZ += z;
|
||||
|
||||
updateLocation(false);
|
||||
updateLocation();
|
||||
}
|
||||
|
||||
public void setRotation(final float yaw, final float pitch) {
|
||||
@@ -78,14 +84,14 @@ public class VirtualHologramEntity {
|
||||
this.headYaw = yaw;
|
||||
this.pitch = pitch;
|
||||
|
||||
updateLocation(false);
|
||||
updateLocation();
|
||||
}
|
||||
|
||||
public void setHeadYaw(float yaw) {
|
||||
if (this.headYaw == yaw) return;
|
||||
this.headYaw = yaw;
|
||||
|
||||
updateLocation(false);
|
||||
updateLocation();
|
||||
}
|
||||
|
||||
public void syncState(final EntityPacketRewriter1_8 entityRewriter, final List<EntityData> entityDataList) {
|
||||
@@ -96,27 +102,31 @@ public class VirtualHologramEntity {
|
||||
}
|
||||
|
||||
// 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() == 3 && entityData.dataType() == EntityDataTypes1_8.BYTE) {
|
||||
alwaysShowNametag = ((Number) entityData.getValue()).byteValue();
|
||||
} else if (entityData.id() == 10 && entityData.dataType() == EntityDataTypes1_8.BYTE) {
|
||||
armorStandFlags = ((Number) entityData.getValue()).byteValue();
|
||||
}
|
||||
}
|
||||
final boolean invisible = (flags & 0x20) != 0;
|
||||
sneaking = (flags & 0x02) != 0;
|
||||
small = (armorStandFlags & 0x01) != 0;
|
||||
marker = (armorStandFlags & 0x10) != 0;
|
||||
gravity = (armorStandFlags & 0x02) == 0;
|
||||
|
||||
State prevState = currentState;
|
||||
if (invisible && name != null) {
|
||||
if (invisible && name != null && alwaysShowNametag == 1) {
|
||||
currentState = State.HOLOGRAM;
|
||||
} else {
|
||||
} else if (gravity) {
|
||||
currentState = State.ZOMBIE;
|
||||
} else {
|
||||
currentState = State.ZOMBIE_NO_GRAVITY;
|
||||
}
|
||||
|
||||
if (currentState != prevState) {
|
||||
@@ -124,11 +134,11 @@ public class VirtualHologramEntity {
|
||||
sendSpawnPacket(entityRewriter);
|
||||
} else {
|
||||
sendEntityDataUpdate(entityRewriter);
|
||||
updateLocation(false);
|
||||
updateLocation();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLocation(final boolean remount) {
|
||||
private void updateLocation() {
|
||||
if (entityIds == null) {
|
||||
return;
|
||||
}
|
||||
@@ -141,27 +151,37 @@ public class VirtualHologramEntity {
|
||||
entityHeadLook.write(Types.BYTE, (byte) ((headYaw / 360f) * 256));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
} else if (currentState == State.HOLOGRAM || currentState == State.ZOMBIE_NO_GRAVITY) {
|
||||
// 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
|
||||
teleportEntity(entityIds[1], locX, (locY + getOffset()), locZ, 0, 0); // Squid
|
||||
}
|
||||
}
|
||||
|
||||
if (remount) {
|
||||
teleportEntity(entityIds[1], locX, locY + 56.75, locZ, 0, 0); // Horse
|
||||
private double getOffset() {
|
||||
if (currentState == State.HOLOGRAM) {
|
||||
double baseOffset = 54.35;
|
||||
|
||||
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 (marker) {
|
||||
return baseOffset;
|
||||
} else if (small) {
|
||||
return baseOffset + 0.9875;
|
||||
} else {
|
||||
return baseOffset + (0.9875 * 2);
|
||||
}
|
||||
} else if (currentState == State.ZOMBIE_NO_GRAVITY) {
|
||||
// 1.7 ride stack offset sum: Squid (0.95 * 0.75) + Zombie (1.8 * 0.75) = 2.0625
|
||||
// By starting at -2.0625, we zero out the 1.7 passenger height so we can apply 1.8's offsets.
|
||||
double baseOffset = -2.0625;
|
||||
|
||||
if (marker) {
|
||||
// 1.8 Marker ArmorStand height is 0.0 -> mounted offset 0.0
|
||||
return baseOffset;
|
||||
} else {
|
||||
// 1.8 Normal ArmorStand height is 1.975 -> mounted offset 1.975 * 0.75 = 1.48125
|
||||
return baseOffset + 1.48125;
|
||||
}
|
||||
} else {
|
||||
return -0.4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +223,7 @@ public class VirtualHologramEntity {
|
||||
}
|
||||
final PacketWrapper setEntityData = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_DATA, user);
|
||||
|
||||
if (currentState == State.ZOMBIE) {
|
||||
if (currentState == State.ZOMBIE || currentState == State.ZOMBIE_NO_GRAVITY) {
|
||||
writeZombieMeta(entityRewriter, setEntityData);
|
||||
} else if (currentState == State.HOLOGRAM) {
|
||||
writeHologramMeta(setEntityData);
|
||||
@@ -247,13 +267,14 @@ public class VirtualHologramEntity {
|
||||
}
|
||||
|
||||
private void writeHologramMeta(PacketWrapper wrapper) {
|
||||
wrapper.write(Types.INT, entityIds[1]);
|
||||
wrapper.write(Types.INT, entityIds[0]);
|
||||
|
||||
// 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.ENTITY_FLAGS.getIndex(), EntityDataTypes1_7_6_10.BYTE, (byte) (sneaking ? 2 : 0)));
|
||||
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));
|
||||
entityDataList.add(new EntityData(EntityDataIndex1_7_6_10.LIVING_ENTITY_BASE_NAME_TAG_VISIBILITY.getIndex(), EntityDataTypes1_7_6_10.BYTE, alwaysShowNametag));
|
||||
|
||||
wrapper.write(RewindTypes.ENTITY_DATA_LIST1_7, entityDataList);
|
||||
}
|
||||
@@ -266,31 +287,45 @@ public class VirtualHologramEntity {
|
||||
spawnEntity(entityId, EntityTypes1_8.EntityType.ZOMBIE.getId(), locX, locY, locZ, new ArrayList<>());
|
||||
|
||||
entityIds = new int[]{entityId};
|
||||
} else if (currentState == State.HOLOGRAM) {
|
||||
} else if (currentState == State.ZOMBIE_NO_GRAVITY || currentState == State.HOLOGRAM) {
|
||||
final int[] entityIds = {entityId, additionalEntityId()};
|
||||
|
||||
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);
|
||||
|
||||
final List<EntityData> squidEntityData = new ArrayList<>();
|
||||
squidEntityData.add(new EntityData(0, EntityDataTypes1_8.BYTE, (byte) 32));
|
||||
|
||||
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<>());
|
||||
if (currentState == State.HOLOGRAM) {
|
||||
spawnEntity(entityIds[0], EntityTypes1_8.EntityType.HORSE.getId(), locX, locY + (getOffset() + 0.68), locZ, new ArrayList<>());
|
||||
} else {
|
||||
spawnEntity(entityIds[0], EntityTypes1_8.EntityType.ZOMBIE.getId(), locX, locY, locZ, new ArrayList<>());
|
||||
}
|
||||
|
||||
spawnEntity(entityIds[1], EntityTypes1_8.EntityType.SQUID.getId(), locX, locY + getOffset(), locZ, squidEntityData);
|
||||
|
||||
this.entityIds = entityIds;
|
||||
}
|
||||
|
||||
for (int extraId : entityIds) {
|
||||
if (extraId != entityId) {
|
||||
((EntityTracker1_8) user.getEntityTracker(Protocol1_8To1_7_6_10.class)).setExtraHologramId(entityId, extraId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sendEntityDataUpdate(entityRewriter);
|
||||
updateLocation(true);
|
||||
if (entityIds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentState == State.ZOMBIE) {
|
||||
updateLocation();
|
||||
} else {
|
||||
final PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_LINK, user);
|
||||
attach.write(Types.INT, entityIds[0]);
|
||||
attach.write(Types.INT, entityIds[1]);
|
||||
attach.write(Types.BOOLEAN, false);
|
||||
|
||||
attach.send(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
}
|
||||
|
||||
public AABB getBoundingBox() {
|
||||
@@ -311,6 +346,13 @@ public class VirtualHologramEntity {
|
||||
if (entityIds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int extraId : entityIds) {
|
||||
if (extraId != entityId) {
|
||||
((EntityTracker1_8) user.getEntityTracker(Protocol1_8To1_7_6_10.class)).removeExtraHologramId(extraId);
|
||||
}
|
||||
}
|
||||
|
||||
final PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.REMOVE_ENTITIES, user);
|
||||
despawn.write(Types.BYTE, (byte) entityIds.length);
|
||||
for (int id : entityIds) {
|
||||
@@ -321,6 +363,6 @@ public class VirtualHologramEntity {
|
||||
}
|
||||
|
||||
private enum State {
|
||||
HOLOGRAM, ZOMBIE
|
||||
HOLOGRAM, ZOMBIE, ZOMBIE_NO_GRAVITY
|
||||
}
|
||||
}
|
||||
+10
-12
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,21 +20,19 @@ package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.CompressionStatusTracker;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.platform.providers.Provider;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
|
||||
public abstract class CompressionHandlerProvider implements Provider {
|
||||
|
||||
public abstract void onHandleLoginCompressionPacket(UserConnection user, int threshold);
|
||||
public abstract void onTransformPacket(UserConnection user);
|
||||
public abstract void setCompressionThreshold(UserConnection user, int threshold);
|
||||
|
||||
public abstract ChannelHandler getEncoder(int threshold);
|
||||
public abstract ChannelHandler getDecoder(int threshold);
|
||||
public abstract void onTransformPacket(UserConnection user);
|
||||
|
||||
public boolean isCompressionEnabled(UserConnection user) {
|
||||
return user.get(CompressionStatusTracker.class).removeCompression;
|
||||
}
|
||||
|
||||
public void setCompressionEnabled(UserConnection user, boolean enabled) {
|
||||
user.get(CompressionStatusTracker.class).removeCompression = enabled;
|
||||
}
|
||||
public boolean isRemoveCompression(UserConnection user) {
|
||||
return user.get(CompressionStatusTracker.class).removeCompression;
|
||||
}
|
||||
|
||||
public void setRemoveCompression(UserConnection user, boolean enabled) {
|
||||
user.get(CompressionStatusTracker.class).removeCompression = enabled;
|
||||
}
|
||||
}
|
||||
+58
-59
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,7 +18,6 @@
|
||||
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider;
|
||||
|
||||
import com.viaversion.viaversion.api.platform.providers.Provider;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@@ -26,74 +25,74 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
// TODO I believe this should be a storage?
|
||||
public abstract class TitleRenderProvider implements Provider {
|
||||
protected Map<UUID, Integer> fadeIn = new HashMap<>();
|
||||
protected Map<UUID, Integer> stay = new HashMap<>();
|
||||
protected Map<UUID, Integer> fadeOut = new HashMap<>();
|
||||
protected Map<UUID, String> titles = new HashMap<>();
|
||||
protected Map<UUID, String> subTitles = new HashMap<>();
|
||||
protected Map<UUID, AtomicInteger> times = new HashMap<>();
|
||||
protected Map<UUID, Integer> fadeIn = new HashMap<>();
|
||||
protected Map<UUID, Integer> stay = new HashMap<>();
|
||||
protected Map<UUID, Integer> fadeOut = new HashMap<>();
|
||||
protected Map<UUID, String> titles = new HashMap<>();
|
||||
protected Map<UUID, String> subTitles = new HashMap<>();
|
||||
protected Map<UUID, AtomicInteger> times = new HashMap<>();
|
||||
|
||||
public void setTimings(UUID uuid, int fadeIn, int stay, int fadeOut) {
|
||||
setFadeIn(uuid, fadeIn);
|
||||
setStay(uuid, stay);
|
||||
setFadeOut(uuid, fadeOut);
|
||||
public void setTimings(UUID uuid, int fadeIn, int stay, int fadeOut) {
|
||||
setFadeIn(uuid, fadeIn);
|
||||
setStay(uuid, stay);
|
||||
setFadeOut(uuid, fadeOut);
|
||||
|
||||
AtomicInteger time = getTime(uuid);
|
||||
if (time.get() > 0) time.set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
|
||||
}
|
||||
AtomicInteger time = getTime(uuid);
|
||||
if (time.get() > 0) time.set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
|
||||
}
|
||||
|
||||
public void reset(UUID uuid) {
|
||||
this.titles.remove(uuid);
|
||||
this.subTitles.remove(uuid);
|
||||
getTime(uuid).set(0);
|
||||
fadeIn.remove(uuid);
|
||||
stay.remove(uuid);
|
||||
fadeOut.remove(uuid);
|
||||
}
|
||||
public void reset(UUID uuid) {
|
||||
this.titles.remove(uuid);
|
||||
this.subTitles.remove(uuid);
|
||||
getTime(uuid).set(0);
|
||||
fadeIn.remove(uuid);
|
||||
stay.remove(uuid);
|
||||
fadeOut.remove(uuid);
|
||||
}
|
||||
|
||||
public void setTitle(UUID uuid, String title) {
|
||||
this.titles.put(uuid, title);
|
||||
getTime(uuid).set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
|
||||
}
|
||||
public void setTitle(UUID uuid, String title) {
|
||||
this.titles.put(uuid, title);
|
||||
getTime(uuid).set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
|
||||
}
|
||||
|
||||
public void setSubTitle(UUID uuid, String subTitle) {
|
||||
this.subTitles.put(uuid, subTitle);
|
||||
}
|
||||
public void setSubTitle(UUID uuid, String subTitle) {
|
||||
this.subTitles.put(uuid, subTitle);
|
||||
}
|
||||
|
||||
public void clear(UUID uuid) {
|
||||
this.titles.remove(uuid);
|
||||
this.subTitles.remove(uuid);
|
||||
getTime(uuid).set(0);
|
||||
}
|
||||
public void clear(UUID uuid) {
|
||||
this.titles.remove(uuid);
|
||||
this.subTitles.remove(uuid);
|
||||
getTime(uuid).set(0);
|
||||
}
|
||||
|
||||
public AtomicInteger getTime(UUID uuid) {
|
||||
return times.computeIfAbsent(uuid, key -> new AtomicInteger(0));
|
||||
}
|
||||
public AtomicInteger getTime(UUID uuid) {
|
||||
return times.computeIfAbsent(uuid, key -> new AtomicInteger(0));
|
||||
}
|
||||
|
||||
public int getFadeIn(UUID uuid) {
|
||||
return fadeIn.getOrDefault(uuid, 10);
|
||||
}
|
||||
public int getFadeIn(UUID uuid) {
|
||||
return fadeIn.getOrDefault(uuid, 10);
|
||||
}
|
||||
|
||||
public int getStay(UUID uuid) {
|
||||
return stay.getOrDefault(uuid, 70);
|
||||
}
|
||||
public int getStay(UUID uuid) {
|
||||
return stay.getOrDefault(uuid, 70);
|
||||
}
|
||||
|
||||
public int getFadeOut(UUID uuid) {
|
||||
return fadeOut.getOrDefault(uuid, 20);
|
||||
}
|
||||
public int getFadeOut(UUID uuid) {
|
||||
return fadeOut.getOrDefault(uuid, 20);
|
||||
}
|
||||
|
||||
public void setFadeIn(UUID uuid, int fadeIn) {
|
||||
if (fadeIn >= 0) this.fadeIn.put(uuid, fadeIn);
|
||||
else this.fadeIn.remove(uuid);
|
||||
}
|
||||
public void setFadeIn(UUID uuid, int fadeIn) {
|
||||
if (fadeIn >= 0) this.fadeIn.put(uuid, fadeIn);
|
||||
else this.fadeIn.remove(uuid);
|
||||
}
|
||||
|
||||
public void setStay(UUID uuid, int stay) {
|
||||
if (stay >= 0) this.stay.put(uuid, stay);
|
||||
else this.stay.remove(uuid);
|
||||
}
|
||||
public void setStay(UUID uuid, int stay) {
|
||||
if (stay >= 0) this.stay.put(uuid, stay);
|
||||
else this.stay.remove(uuid);
|
||||
}
|
||||
|
||||
public void setFadeOut(UUID uuid, int fadeOut) {
|
||||
if (fadeOut >= 0) this.fadeOut.put(uuid, fadeOut);
|
||||
else this.fadeOut.remove(uuid);
|
||||
}
|
||||
public void setFadeOut(UUID uuid, int fadeOut) {
|
||||
if (fadeOut >= 0) this.fadeOut.put(uuid, fadeOut);
|
||||
else this.fadeOut.remove(uuid);
|
||||
}
|
||||
}
|
||||
+34
-39
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,56 +17,51 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression;
|
||||
|
||||
import com.viaversion.viarewind.api.compression.ThreadLocalCompressionProvider;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
public class CompressionDecoder extends MessageToMessageDecoder<ByteBuf> {
|
||||
private final Inflater inflater = new Inflater();
|
||||
|
||||
private final int threshold;
|
||||
private int threshold;
|
||||
|
||||
public CompressionDecoder(final int threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
public CompressionDecoder(final int threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
if (!in.isReadable()) return;
|
||||
public void setThreshold(final int threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
int outLength = Types.VAR_INT.readPrimitive(in);
|
||||
if (outLength == 0) {
|
||||
out.add(in.readBytes(in.readableBytes()));
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
if (!in.isReadable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (outLength < this.threshold) {
|
||||
throw new DecoderException("Badly compressed packet - size of " + outLength + " is below server threshold of " + this.threshold);
|
||||
} else if (outLength > 2097152) {
|
||||
throw new DecoderException("Badly compressed packet - size of " + outLength + " is larger than protocol maximum of " + 2097152);
|
||||
}
|
||||
int outLength = Types.VAR_INT.readPrimitive(in);
|
||||
if (outLength == 0) {
|
||||
out.add(in.readBytes(in.readableBytes()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (outLength < this.threshold) {
|
||||
throw new DecoderException("Badly compressed packet - size of " + outLength + " is below server threshold of " + this.threshold);
|
||||
} else if (outLength > 2097152) {
|
||||
throw new DecoderException("Badly compressed packet - size of " + outLength + " is larger than protocol maximum of " + 2097152);
|
||||
}
|
||||
|
||||
ByteBuf output = ctx.alloc().buffer(outLength);
|
||||
try {
|
||||
ThreadLocalCompressionProvider.inflate(in, output, outLength);
|
||||
out.add(output.retain());
|
||||
} finally {
|
||||
output.release();
|
||||
}
|
||||
}
|
||||
|
||||
ByteBuf temp = in;
|
||||
if (!in.hasArray()) {
|
||||
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
|
||||
} else {
|
||||
in.retain();
|
||||
}
|
||||
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer(outLength, outLength);
|
||||
try {
|
||||
this.inflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
|
||||
output.writerIndex(output.writerIndex() + this.inflater.inflate(output.array(), output.arrayOffset(), outLength));
|
||||
out.add(output.retain());
|
||||
} finally {
|
||||
output.release();
|
||||
temp.release();
|
||||
this.inflater.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-40
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,54 +17,35 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.compression;
|
||||
|
||||
import com.viaversion.viarewind.api.compression.ThreadLocalCompressionProvider;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
private final Deflater deflater = new Deflater();
|
||||
|
||||
private final int threshold;
|
||||
private int threshold;
|
||||
|
||||
public CompressionEncoder(final int threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
public CompressionEncoder(final int threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
|
||||
int frameLength = in.readableBytes();
|
||||
if (frameLength < this.threshold) {
|
||||
out.writeByte(0); // VarInt
|
||||
out.writeBytes(in);
|
||||
return;
|
||||
}
|
||||
public void setThreshold(final int threshold) {
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
Types.VAR_INT.writePrimitive(out, frameLength);
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
|
||||
int frameLength = in.readableBytes();
|
||||
if (frameLength < this.threshold) {
|
||||
out.writeByte(0); // VarInt
|
||||
out.writeBytes(in);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuf temp = in;
|
||||
if (!in.hasArray()) {
|
||||
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
|
||||
} else {
|
||||
in.retain();
|
||||
}
|
||||
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer();
|
||||
try {
|
||||
this.deflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
|
||||
deflater.finish();
|
||||
Types.VAR_INT.writePrimitive(out, frameLength);
|
||||
ThreadLocalCompressionProvider.deflate(in, out);
|
||||
}
|
||||
|
||||
while (!deflater.finished()) {
|
||||
output.ensureWritable(4096);
|
||||
output.writerIndex(output.writerIndex() + this.deflater.deflate(output.array(), output.arrayOffset() + output.writerIndex(), output.writableBytes()));
|
||||
}
|
||||
out.writeBytes(output);
|
||||
} finally {
|
||||
output.release();
|
||||
temp.release();
|
||||
this.deflater.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
-39
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,52 +23,57 @@ import com.viaversion.viarewind.api.minecraft.netty.ForwardMessageToByteEncoder;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.CompressionHandlerProvider;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
|
||||
public class TrackingCompressionHandlerProvider extends CompressionHandlerProvider {
|
||||
|
||||
@Override
|
||||
public void onHandleLoginCompressionPacket(UserConnection user, int threshold) {
|
||||
final ChannelPipeline pipeline = user.getChannel().pipeline();
|
||||
if (user.isClientSide()) {
|
||||
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
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void setCompressionThreshold(UserConnection user, int threshold) {
|
||||
final ChannelPipeline pipeline = user.getChannel().pipeline();
|
||||
if (!user.isClientSide() || threshold < 0) {
|
||||
setRemoveCompression(user, true); // We need to remove compression for 1.7 clients
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransformPacket(UserConnection user) {
|
||||
if (isCompressionEnabled(user)) {
|
||||
final ChannelPipeline pipeline = user.getChannel().pipeline();
|
||||
final String compressHandlerName = ViaRewind.getPlatform().compressHandlerName();
|
||||
final CompressionEncoder encoder = (CompressionEncoder) pipeline.get(compressHandlerName);
|
||||
if (encoder != null) {
|
||||
encoder.setThreshold(threshold);
|
||||
} else {
|
||||
pipeline.addBefore(Via.getManager().getInjector().getEncoderName(), compressHandlerName, new CompressionEncoder(threshold));
|
||||
}
|
||||
|
||||
String compressor = null;
|
||||
String decompressor = null;
|
||||
if (pipeline.get(ViaRewind.getPlatform().compressHandlerName()) != null) {
|
||||
compressor = ViaRewind.getPlatform().compressHandlerName();
|
||||
decompressor = ViaRewind.getPlatform().decompressHandlerName();
|
||||
}
|
||||
final String decompressHandlerName = ViaRewind.getPlatform().decompressHandlerName();
|
||||
final CompressionDecoder decoder = (CompressionDecoder) pipeline.get(decompressHandlerName);
|
||||
if (decoder != null) {
|
||||
decoder.setThreshold(threshold);
|
||||
} else {
|
||||
pipeline.addBefore(Via.getManager().getInjector().getDecoderName(), decompressHandlerName, new CompressionDecoder(threshold));
|
||||
}
|
||||
}
|
||||
|
||||
if (compressor != null) { // We can neutralize the effect of compressor to the client
|
||||
pipeline.replace(decompressor, decompressor, new EmptyChannelHandler());
|
||||
pipeline.replace(compressor, compressor, new ForwardMessageToByteEncoder());
|
||||
} else {
|
||||
throw new IllegalStateException("Couldn't remove compression for 1.7!");
|
||||
}
|
||||
@Override
|
||||
public void onTransformPacket(UserConnection user) {
|
||||
if (isRemoveCompression(user)) {
|
||||
final ChannelPipeline pipeline = user.getChannel().pipeline();
|
||||
|
||||
setCompressionEnabled(user, false);
|
||||
}
|
||||
}
|
||||
String compressor = null;
|
||||
String decompressor = null;
|
||||
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
|
||||
pipeline.replace(decompressor, decompressor, new EmptyChannelHandler());
|
||||
pipeline.replace(compressor, compressor, new ForwardMessageToByteEncoder());
|
||||
} else {
|
||||
throw new IllegalStateException("Couldn't remove compression for 1.7!");
|
||||
}
|
||||
|
||||
setRemoveCompression(user, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler getEncoder(int threshold) {
|
||||
return new CompressionEncoder(threshold);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler getDecoder(int threshold) {
|
||||
return new CompressionDecoder(threshold);
|
||||
}
|
||||
}
|
||||
+240
-239
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,304 +17,305 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.ListTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
|
||||
import com.viaversion.viarewind.api.rewriter.VRBlockItemRewriter;
|
||||
import com.viaversion.viarewind.api.type.RewindTypes;
|
||||
import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ServerboundPackets1_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.storage.EntityTracker1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.GameProfileStorage;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.InventoryTracker;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.PlayerSessionStorage;
|
||||
import com.viaversion.viarewind.api.type.RewindTypes;
|
||||
import com.viaversion.viarewind.utils.ChatUtil;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.libs.gson.JsonElement;
|
||||
import com.viaversion.nbt.tag.*;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BlockItemPacketRewriter1_8 extends VRBlockItemRewriter<ClientboundPackets1_8, ServerboundPackets1_7_2_5, Protocol1_8To1_7_6_10> {
|
||||
|
||||
private LegacyEnchantmentRewriter enchantmentRewriter;
|
||||
private LegacyEnchantmentRewriter enchantmentRewriter;
|
||||
|
||||
public BlockItemPacketRewriter1_8(Protocol1_8To1_7_6_10 protocol) {
|
||||
super(protocol, "1.8");
|
||||
}
|
||||
public BlockItemPacketRewriter1_8(Protocol1_8To1_7_6_10 protocol) {
|
||||
super(protocol, "1.8");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocol.registerClientbound(ClientboundPackets1_8.OPEN_SCREEN, wrapper -> {
|
||||
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocol.registerClientbound(ClientboundPackets1_8.OPEN_SCREEN, wrapper -> {
|
||||
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
|
||||
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE); // Window id
|
||||
final short windowTypeId = InventoryTracker.getInventoryType(wrapper.read(Types.STRING)); // Window type
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE); // Window id
|
||||
final short windowTypeId = InventoryTracker.getInventoryType(wrapper.read(Types.STRING)); // Window type
|
||||
|
||||
windowTracker.getWindowTypeMap().put(windowId, windowTypeId);
|
||||
wrapper.write(Types.UNSIGNED_BYTE, windowTypeId); // Window type id
|
||||
windowTracker.getWindowTypeMap().put(windowId, windowTypeId);
|
||||
wrapper.write(Types.UNSIGNED_BYTE, windowTypeId); // Window type id
|
||||
|
||||
final JsonElement titleComponent = wrapper.read(Types.COMPONENT); // Title
|
||||
String title = ChatUtil.jsonToLegacy(titleComponent);
|
||||
title = ChatUtil.removeUnusedColor(title, '8');
|
||||
if (title.length() > 32) {
|
||||
title = title.substring(0, 32);
|
||||
}
|
||||
wrapper.write(Types.STRING, title); // Window title
|
||||
final JsonElement titleComponent = wrapper.read(Types.COMPONENT); // Title
|
||||
String title = ChatUtil.jsonToLegacy(titleComponent);
|
||||
title = ChatUtil.removeUnusedColor(title, '8');
|
||||
if (title.length() > 32) {
|
||||
title = title.substring(0, 32);
|
||||
}
|
||||
wrapper.write(Types.STRING, title); // Window title
|
||||
|
||||
wrapper.passthrough(Types.UNSIGNED_BYTE); // Slots
|
||||
wrapper.write(Types.BOOLEAN, true); // Use provided window title
|
||||
wrapper.passthrough(Types.UNSIGNED_BYTE); // Slots
|
||||
wrapper.write(Types.BOOLEAN, true); // Use provided window title
|
||||
|
||||
if (windowTypeId == 11) { // Horse
|
||||
wrapper.passthrough(Types.INT); // Entity id
|
||||
}
|
||||
});
|
||||
if (windowTypeId == 11) { // Horse
|
||||
wrapper.passthrough(Types.INT); // Entity id
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CONTAINER_CLOSE, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE); // Window id
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CONTAINER_CLOSE, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE); // Window id
|
||||
|
||||
wrapper.user().get(InventoryTracker.class).remove(windowId);
|
||||
});
|
||||
wrapper.user().get(InventoryTracker.class).remove(windowId);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CONTAINER_SET_SLOT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE); // Window id
|
||||
map(Types.SHORT); // Slot
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CONTAINER_SET_SLOT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE); // Window id
|
||||
map(Types.SHORT); // Slot
|
||||
|
||||
handler(wrapper -> {
|
||||
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) {
|
||||
wrapper.cancel();
|
||||
} else if (slot >= 2) {
|
||||
wrapper.set(Types.SHORT, 0, (short) (slot - 1));
|
||||
}
|
||||
}
|
||||
});
|
||||
handler(wrapper -> {
|
||||
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) {
|
||||
wrapper.cancel();
|
||||
} else if (slot >= 2) {
|
||||
wrapper.set(Types.SHORT, 0, (short) (slot - 1));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
map(Types.ITEM1_8, RewindTypes.COMPRESSED_NBT_ITEM); // item
|
||||
handler(wrapper -> handleItemToClient(wrapper.user(), wrapper.get(RewindTypes.COMPRESSED_NBT_ITEM, 0)));
|
||||
map(Types.ITEM1_8, RewindTypes.COMPRESSED_NBT_ITEM); // item
|
||||
handler(wrapper -> handleItemToClient(wrapper.user(), wrapper.get(RewindTypes.COMPRESSED_NBT_ITEM, 0)));
|
||||
|
||||
handler(wrapper -> {
|
||||
final byte windowId = wrapper.get(Types.BYTE, 0);
|
||||
if (windowId != 0) {
|
||||
return;
|
||||
}
|
||||
final short slot = wrapper.get(Types.SHORT, 0);
|
||||
if (slot < 5 || slot > 8) {
|
||||
return;
|
||||
}
|
||||
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
|
||||
final Item item = wrapper.get(RewindTypes.COMPRESSED_NBT_ITEM, 0);
|
||||
playerSession.setPlayerEquipment(wrapper.user().getProtocolInfo().getUuid(), item, 8 - slot);
|
||||
handler(wrapper -> {
|
||||
final byte windowId = wrapper.get(Types.BYTE, 0);
|
||||
if (windowId != 0) {
|
||||
return;
|
||||
}
|
||||
final short slot = wrapper.get(Types.SHORT, 0);
|
||||
if (slot < 5 || slot > 8) {
|
||||
return;
|
||||
}
|
||||
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
|
||||
final Item item = wrapper.get(RewindTypes.COMPRESSED_NBT_ITEM, 0);
|
||||
playerSession.setPlayerEquipment(wrapper.user().getProtocolInfo().getUuid(), item, 8 - slot);
|
||||
|
||||
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_7_6_10.class);
|
||||
if (tracker.isSpectator()) { // Spectator mode didn't exist in 1.7.10
|
||||
wrapper.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(protocol);
|
||||
if (tracker.isSpectator()) { // Spectator mode didn't exist in 1.7.10
|
||||
wrapper.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CONTAINER_SET_CONTENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.UNSIGNED_BYTE); // Window id
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CONTAINER_SET_CONTENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.UNSIGNED_BYTE); // Window id
|
||||
|
||||
// remap enchantment table items
|
||||
handler(wrapper -> {
|
||||
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Types.UNSIGNED_BYTE, 0));
|
||||
// remap enchantment table items
|
||||
handler(wrapper -> {
|
||||
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Types.UNSIGNED_BYTE, 0));
|
||||
|
||||
Item[] items = wrapper.read(Types.ITEM1_8_SHORT_ARRAY);
|
||||
if (windowType == 4) { // Enchantment Table
|
||||
Item[] old = items;
|
||||
items = new Item[old.length - 1];
|
||||
items[0] = old[0];
|
||||
System.arraycopy(old, 2, items, 1, old.length - 2);
|
||||
}
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
items[i] = handleItemToClient(wrapper.user(), items[i]);
|
||||
}
|
||||
wrapper.write(RewindTypes.COMPRESSED_NBT_ITEM_ARRAY, items); // Items
|
||||
});
|
||||
Item[] items = wrapper.read(Types.ITEM1_8_SHORT_ARRAY);
|
||||
if (windowType == 4) { // Enchantment Table
|
||||
Item[] old = items;
|
||||
items = new Item[old.length - 1];
|
||||
items[0] = old[0];
|
||||
System.arraycopy(old, 2, items, 1, old.length - 2);
|
||||
}
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
items[i] = handleItemToClient(wrapper.user(), items[i]);
|
||||
}
|
||||
wrapper.write(RewindTypes.COMPRESSED_NBT_ITEM_ARRAY, items); // Items
|
||||
});
|
||||
|
||||
handler(wrapper -> {
|
||||
final short windowId = wrapper.get(Types.UNSIGNED_BYTE, 0);
|
||||
if (windowId != 0) {
|
||||
return;
|
||||
}
|
||||
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_7_6_10.class);
|
||||
final UUID userId = wrapper.user().getProtocolInfo().getUuid();
|
||||
handler(wrapper -> {
|
||||
final short windowId = wrapper.get(Types.UNSIGNED_BYTE, 0);
|
||||
if (windowId != 0) {
|
||||
return;
|
||||
}
|
||||
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(protocol);
|
||||
final UUID userId = wrapper.user().getProtocolInfo().getUuid();
|
||||
|
||||
final Item[] items = wrapper.get(RewindTypes.COMPRESSED_NBT_ITEM_ARRAY, 0);
|
||||
for (int i = 5; i < 9; i++) {
|
||||
wrapper.user().get(PlayerSessionStorage.class).setPlayerEquipment(userId, items[i], 8 - i);
|
||||
if (tracker.isSpectator()) {
|
||||
items[i] = null;
|
||||
}
|
||||
}
|
||||
if (tracker.isSpectator()) {
|
||||
final GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(userId);
|
||||
if (profile != null) {
|
||||
items[5] = profile.getSkull();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
final Item[] items = wrapper.get(RewindTypes.COMPRESSED_NBT_ITEM_ARRAY, 0);
|
||||
for (int i = 5; i < 9; i++) {
|
||||
wrapper.user().get(PlayerSessionStorage.class).setPlayerEquipment(userId, items[i], 8 - i);
|
||||
if (tracker.isSpectator()) {
|
||||
items[i] = null;
|
||||
}
|
||||
}
|
||||
if (tracker.isSpectator()) {
|
||||
final GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(userId);
|
||||
if (profile != null) {
|
||||
items[5] = profile.getSkull();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CONTAINER_SET_DATA, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.UNSIGNED_BYTE); // Window id
|
||||
map(Types.SHORT); // Progress bar id
|
||||
map(Types.SHORT); // Progress bar value
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CONTAINER_SET_DATA, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.UNSIGNED_BYTE); // Window id
|
||||
map(Types.SHORT); // Progress bar id
|
||||
map(Types.SHORT); // Progress bar value
|
||||
|
||||
handler(wrapper -> {
|
||||
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
|
||||
handler(wrapper -> {
|
||||
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
|
||||
|
||||
final short windowId = wrapper.get(Types.UNSIGNED_BYTE, 0);
|
||||
final short windowType = windowTracker.get(windowId);
|
||||
final short windowId = wrapper.get(Types.UNSIGNED_BYTE, 0);
|
||||
final short windowType = windowTracker.get(windowId);
|
||||
|
||||
final short progressBarId = wrapper.get(Types.SHORT, 0);
|
||||
short progress = wrapper.get(Types.SHORT, 1);
|
||||
final short progressBarId = wrapper.get(Types.SHORT, 0);
|
||||
short progress = wrapper.get(Types.SHORT, 1);
|
||||
|
||||
if (windowType == 2) { // Furnace
|
||||
// TODO | Proper methods (getOrCreate)=
|
||||
final InventoryTracker.FurnaceData furnace = windowTracker.getFurnaceData().computeIfAbsent(windowId, x -> new InventoryTracker.FurnaceData());
|
||||
if (progressBarId == 0 || progressBarId == 1) {
|
||||
if (progressBarId == 0) {
|
||||
furnace.fuelLeft = progress;
|
||||
} else {
|
||||
furnace.maxFuel = progress;
|
||||
}
|
||||
if (furnace.maxFuel == 0) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
progress = (short) (200 * furnace.fuelLeft / furnace.maxFuel);
|
||||
wrapper.set(Types.SHORT, 0, (short) 1);
|
||||
wrapper.set(Types.SHORT, 1, progress);
|
||||
} else if (progressBarId == 2 || progressBarId == 3) {
|
||||
if (progressBarId == 2) {
|
||||
furnace.progress = progress;
|
||||
} else {
|
||||
furnace.maxProgress = progress;
|
||||
}
|
||||
if (furnace.maxProgress == 0) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
progress = (short) (200 * furnace.progress / furnace.maxProgress);
|
||||
wrapper.set(Types.SHORT, 0, (short) 0);
|
||||
wrapper.set(Types.SHORT, 1, progress);
|
||||
}
|
||||
} else if (windowType == 4 && progressBarId > 2) { // Enchanting Table
|
||||
wrapper.cancel();
|
||||
} else if (windowType == 8) { // Anvil
|
||||
windowTracker.levelCost = progress;
|
||||
windowTracker.anvilId = windowId;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (windowType == 2) { // Furnace
|
||||
// TODO | Proper methods (getOrCreate)=
|
||||
final InventoryTracker.FurnaceData furnace = windowTracker.getFurnaceData().computeIfAbsent(windowId, x -> new InventoryTracker.FurnaceData());
|
||||
if (progressBarId == 0 || progressBarId == 1) {
|
||||
if (progressBarId == 0) {
|
||||
furnace.fuelLeft = progress;
|
||||
} else {
|
||||
furnace.maxFuel = progress;
|
||||
}
|
||||
if (furnace.maxFuel == 0) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
progress = (short) (200 * furnace.fuelLeft / furnace.maxFuel);
|
||||
wrapper.set(Types.SHORT, 0, (short) 1);
|
||||
wrapper.set(Types.SHORT, 1, progress);
|
||||
} else if (progressBarId == 2 || progressBarId == 3) {
|
||||
if (progressBarId == 2) {
|
||||
furnace.progress = progress;
|
||||
} else {
|
||||
furnace.maxProgress = progress;
|
||||
}
|
||||
if (furnace.maxProgress == 0) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
progress = (short) (200 * furnace.progress / furnace.maxProgress);
|
||||
wrapper.set(Types.SHORT, 0, (short) 0);
|
||||
wrapper.set(Types.SHORT, 1, progress);
|
||||
}
|
||||
} else if (windowType == 4 && progressBarId > 2) { // Enchanting Table
|
||||
wrapper.cancel();
|
||||
} else if (windowType == 8) { // Anvil
|
||||
windowTracker.levelCost = progress;
|
||||
windowTracker.anvilId = windowId;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_7_2_5.CONTAINER_CLOSE, wrapper -> {
|
||||
final byte windowId = wrapper.passthrough(Types.BYTE);
|
||||
protocol.registerServerbound(ServerboundPackets1_7_2_5.CONTAINER_CLOSE, wrapper -> {
|
||||
final byte windowId = wrapper.passthrough(Types.BYTE);
|
||||
|
||||
wrapper.user().get(InventoryTracker.class).remove(windowId);
|
||||
});
|
||||
wrapper.user().get(InventoryTracker.class).remove(windowId);
|
||||
});
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_7_2_5.CONTAINER_CLICK, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE); // Window id
|
||||
map(Types.SHORT); // Slot
|
||||
handler(wrapper -> {
|
||||
final byte windowId = wrapper.get(Types.BYTE, 0); // Window id
|
||||
final short slot = wrapper.get(Types.SHORT, 0);
|
||||
protocol.registerServerbound(ServerboundPackets1_7_2_5.CONTAINER_CLICK, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE); // Window id
|
||||
map(Types.SHORT); // Slot
|
||||
handler(wrapper -> {
|
||||
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);
|
||||
if (windowType == 4) { // Enchantment Table
|
||||
if (slot > 0) {
|
||||
wrapper.set(Types.SHORT, 0, (short) (slot + 1));
|
||||
}
|
||||
}
|
||||
});
|
||||
map(Types.BYTE); // Button
|
||||
map(Types.SHORT); // Action number
|
||||
map(Types.BYTE); // Mode
|
||||
map(RewindTypes.COMPRESSED_NBT_ITEM, Types.ITEM1_8); // Clicked item
|
||||
final short windowType = wrapper.user().get(InventoryTracker.class).get(windowId);
|
||||
if (windowType == 4) { // Enchantment Table
|
||||
if (slot > 0) {
|
||||
wrapper.set(Types.SHORT, 0, (short) (slot + 1));
|
||||
}
|
||||
}
|
||||
});
|
||||
map(Types.BYTE); // Button
|
||||
map(Types.SHORT); // Action number
|
||||
map(Types.BYTE); // Mode
|
||||
map(RewindTypes.COMPRESSED_NBT_ITEM, Types.ITEM1_8); // Clicked item
|
||||
|
||||
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Types.ITEM1_8, 0)));
|
||||
}
|
||||
});
|
||||
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Types.ITEM1_8, 0)));
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_7_2_5.SET_CREATIVE_MODE_SLOT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.SHORT); // Slot
|
||||
map(RewindTypes.COMPRESSED_NBT_ITEM, Types.ITEM1_8); // Item
|
||||
protocol.registerServerbound(ServerboundPackets1_7_2_5.SET_CREATIVE_MODE_SLOT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.SHORT); // Slot
|
||||
map(RewindTypes.COMPRESSED_NBT_ITEM, Types.ITEM1_8); // Item
|
||||
|
||||
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Types.ITEM1_8, 0)));
|
||||
}
|
||||
});
|
||||
}
|
||||
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Types.ITEM1_8, 0)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerRewrites() {
|
||||
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName(), false);
|
||||
enchantmentRewriter.registerEnchantment(8, "§7Depth Strider");
|
||||
}
|
||||
@Override
|
||||
protected void registerRewrites() {
|
||||
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName(), false);
|
||||
enchantmentRewriter.registerEnchantment(8, "§7Depth Strider");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item handleItemToClient(UserConnection connection, Item item) {
|
||||
if (item == null) return null;
|
||||
super.handleItemToClient(connection, item);
|
||||
@Override
|
||||
public Item handleItemToClient(UserConnection connection, Item item) {
|
||||
if (item == null) return null;
|
||||
super.handleItemToClient(connection, item);
|
||||
|
||||
CompoundTag tag = item.tag();
|
||||
if (tag == null) return item;
|
||||
CompoundTag tag = item.tag();
|
||||
if (tag == null) return item;
|
||||
|
||||
enchantmentRewriter.handleToClient(item);
|
||||
enchantmentRewriter.handleToClient(item);
|
||||
|
||||
if (item.identifier() == 387) {
|
||||
final ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
|
||||
if (pages == null) return item;
|
||||
if (item.identifier() == 387) {
|
||||
final ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
|
||||
if (pages == null) return item;
|
||||
|
||||
final ListTag<StringTag> oldPages = new ListTag<>(StringTag.class);
|
||||
tag.put(nbtTagName() + "|pages", oldPages);
|
||||
final ListTag<StringTag> oldPages = new ListTag<>(StringTag.class);
|
||||
tag.put(nbtTagName() + "|pages", oldPages);
|
||||
|
||||
for (StringTag page : pages) {
|
||||
final String value = page.getValue();
|
||||
oldPages.add(new StringTag(value));
|
||||
page.setValue(ChatUtil.jsonToLegacy(value));
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
for (StringTag page : pages) {
|
||||
final String value = page.getValue();
|
||||
oldPages.add(new StringTag(value));
|
||||
page.setValue(ChatUtil.jsonToLegacy(value));
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item handleItemToServer(UserConnection connection, Item item) {
|
||||
if (item == null) return null;
|
||||
super.handleItemToServer(connection, item);
|
||||
@Override
|
||||
public Item handleItemToServer(UserConnection connection, Item item) {
|
||||
if (item == null) return null;
|
||||
super.handleItemToServer(connection, item);
|
||||
|
||||
final CompoundTag tag = item.tag();
|
||||
if (tag == null) return item;
|
||||
final CompoundTag tag = item.tag();
|
||||
if (tag == null) return item;
|
||||
|
||||
enchantmentRewriter.handleToServer(item);
|
||||
enchantmentRewriter.handleToServer(item);
|
||||
|
||||
if (item.identifier() == 387) {
|
||||
final ListTag<StringTag> oldPages = tag.getListTag(nbtTagName() + "|pages", StringTag.class);
|
||||
if (oldPages != null) {
|
||||
tag.remove("pages");
|
||||
tag.put("pages", oldPages);
|
||||
}
|
||||
}
|
||||
if (item.identifier() == 387) {
|
||||
final ListTag<StringTag> oldPages = tag.getListTag(nbtTagName() + "|pages", StringTag.class);
|
||||
if (oldPages != null) {
|
||||
tag.remove("pages");
|
||||
tag.put("pages", oldPages);
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
+661
-657
File diff suppressed because it is too large.
Load diff
+749
-658
File diff suppressed because it is too large.
Load diff
+216
-198
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,7 @@ package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter;
|
||||
|
||||
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.storage.EntityTracker1_8;
|
||||
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;
|
||||
@@ -26,227 +27,244 @@ 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ScoreboardPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10> {
|
||||
|
||||
public ScoreboardPacketRewriter1_8(Protocol1_8To1_7_6_10 protocol) {
|
||||
super(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) {
|
||||
wrapper.set(Types.STRING, 0, name = name.substring(0, 16));
|
||||
}
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocol.registerClientbound(ClientboundPackets1_8.SET_OBJECTIVE, wrapper -> {
|
||||
String name = wrapper.passthrough(Types.STRING);
|
||||
if (name.length() > 16) {
|
||||
wrapper.set(Types.STRING, 0, name = name.substring(0, 16));
|
||||
}
|
||||
|
||||
final byte mode = wrapper.read(Types.BYTE);
|
||||
ScoreboardTracker scoreboard = wrapper.user().get(ScoreboardTracker.class);
|
||||
if (mode == 0) {
|
||||
if (scoreboard.objectiveExists(name)) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
scoreboard.addObjective(name);
|
||||
} else if (mode == 1) {
|
||||
if (!scoreboard.objectiveExists(name)) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
if (scoreboard.getColorIndependentSidebar() != null) {
|
||||
String username = wrapper.user().getProtocolInfo().getUsername();
|
||||
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
|
||||
if (color.isPresent()) {
|
||||
String sidebar = scoreboard.getColorDependentSidebar().get(color.get());
|
||||
if (name.equals(sidebar)) {
|
||||
final PacketWrapper sidebarPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user());
|
||||
sidebarPacket.write(Types.BYTE, (byte) 1);
|
||||
sidebarPacket.write(Types.STRING, scoreboard.getColorIndependentSidebar());
|
||||
sidebarPacket.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
scoreboard.removeObjective(name);
|
||||
} else if (mode == 2) {
|
||||
if (!scoreboard.objectiveExists(name)) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
final byte mode = wrapper.read(Types.BYTE);
|
||||
ScoreboardTracker scoreboard = wrapper.user().get(ScoreboardTracker.class);
|
||||
if (mode == 0) {
|
||||
if (scoreboard.objectiveExists(name)) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
scoreboard.addObjective(name);
|
||||
} else if (mode == 1) {
|
||||
if (!scoreboard.objectiveExists(name)) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
if (scoreboard.getColorIndependentSidebar() != null) {
|
||||
String username = wrapper.user().getProtocolInfo().getUsername();
|
||||
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
|
||||
if (color.isPresent()) {
|
||||
String sidebar = scoreboard.getColorDependentSidebar().get(color.get());
|
||||
if (name.equals(sidebar)) {
|
||||
final PacketWrapper sidebarPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user());
|
||||
sidebarPacket.write(Types.BYTE, (byte) 1);
|
||||
sidebarPacket.write(Types.STRING, scoreboard.getColorIndependentSidebar());
|
||||
sidebarPacket.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
scoreboard.removeObjective(name);
|
||||
} else if (mode == 2) {
|
||||
if (!scoreboard.objectiveExists(name)) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == 0 || mode == 2) {
|
||||
String displayName = wrapper.passthrough(Types.STRING);
|
||||
if (displayName.length() > 32) {
|
||||
wrapper.set(Types.STRING, 1, displayName.substring(0, 32));
|
||||
}
|
||||
wrapper.read(Types.STRING);
|
||||
} else {
|
||||
wrapper.write(Types.STRING, "");
|
||||
}
|
||||
wrapper.write(Types.BYTE, mode);
|
||||
});
|
||||
if (mode == 0 || mode == 2) {
|
||||
String displayName = wrapper.passthrough(Types.STRING);
|
||||
if (displayName.length() > 32) {
|
||||
wrapper.set(Types.STRING, 1, displayName.substring(0, 32));
|
||||
}
|
||||
wrapper.read(Types.STRING);
|
||||
} else {
|
||||
wrapper.write(Types.STRING, "");
|
||||
}
|
||||
wrapper.write(Types.BYTE, mode);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.SET_SCORE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING); // Name
|
||||
map(Types.VAR_INT, Types.BYTE); // Mode
|
||||
handler(wrapper -> {
|
||||
ScoreboardTracker scoreboard = wrapper.user().get(ScoreboardTracker.class);
|
||||
String name = wrapper.get(Types.STRING, 0);
|
||||
byte mode = wrapper.get(Types.BYTE, 0);
|
||||
protocol.registerClientbound(ClientboundPackets1_8.SET_SCORE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING); // Name
|
||||
map(Types.VAR_INT, Types.BYTE); // Mode
|
||||
handler(wrapper -> {
|
||||
ScoreboardTracker scoreboard = wrapper.user().get(ScoreboardTracker.class);
|
||||
String name = wrapper.get(Types.STRING, 0);
|
||||
byte mode = wrapper.get(Types.BYTE, 0);
|
||||
|
||||
if (mode == 1) {
|
||||
name = scoreboard.removeTeamForScore(name);
|
||||
} else {
|
||||
name = scoreboard.sendTeamForScore(name);
|
||||
}
|
||||
if (mode == 1) {
|
||||
name = scoreboard.removeTeamForScore(name);
|
||||
} else {
|
||||
name = scoreboard.sendTeamForScore(name);
|
||||
}
|
||||
|
||||
if (name.length() > 16) {
|
||||
name = ChatColorUtil.stripColor(name);
|
||||
if (name.length() > 16) {
|
||||
name = name.substring(0, 16);
|
||||
}
|
||||
}
|
||||
wrapper.set(Types.STRING, 0, name);
|
||||
if (name.length() > 16) {
|
||||
name = ChatColorUtil.stripColor(name);
|
||||
if (name.length() > 16) {
|
||||
name = name.substring(0, 16);
|
||||
}
|
||||
}
|
||||
wrapper.set(Types.STRING, 0, name);
|
||||
|
||||
String objective = wrapper.read(Types.STRING);
|
||||
if (objective.length() > 16) {
|
||||
objective = objective.substring(0, 16);
|
||||
}
|
||||
String objective = wrapper.read(Types.STRING);
|
||||
if (objective.length() > 16) {
|
||||
objective = objective.substring(0, 16);
|
||||
}
|
||||
|
||||
if (mode != 1) {
|
||||
int score = wrapper.read(Types.VAR_INT);
|
||||
wrapper.write(Types.STRING, objective);
|
||||
wrapper.write(Types.INT, score);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (mode != 1) {
|
||||
int score = wrapper.read(Types.VAR_INT);
|
||||
wrapper.write(Types.STRING, objective);
|
||||
wrapper.write(Types.INT, score);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.SET_DISPLAY_OBJECTIVE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE); // Position
|
||||
map(Types.STRING); // Score name
|
||||
handler(wrapper -> {
|
||||
byte position = wrapper.get(Types.BYTE, 0);
|
||||
String name = wrapper.get(Types.STRING, 0);
|
||||
ScoreboardTracker scoreboard = wrapper.user().get(ScoreboardTracker.class);
|
||||
if (position > 2) { // team specific sidebar
|
||||
byte receiverTeamColor = (byte) (position - 3);
|
||||
scoreboard.getColorDependentSidebar().put(receiverTeamColor, name);
|
||||
protocol.registerClientbound(ClientboundPackets1_8.SET_DISPLAY_OBJECTIVE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE); // Position
|
||||
map(Types.STRING); // Score name
|
||||
handler(wrapper -> {
|
||||
byte position = wrapper.get(Types.BYTE, 0);
|
||||
String name = wrapper.get(Types.STRING, 0);
|
||||
ScoreboardTracker scoreboard = wrapper.user().get(ScoreboardTracker.class);
|
||||
if (position > 2) { // team specific sidebar
|
||||
byte receiverTeamColor = (byte) (position - 3);
|
||||
scoreboard.getColorDependentSidebar().put(receiverTeamColor, name);
|
||||
|
||||
String username = wrapper.user().getProtocolInfo().getUsername();
|
||||
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
|
||||
if (color.isPresent() && color.get() == receiverTeamColor) {
|
||||
position = 1;
|
||||
} else {
|
||||
position = -1;
|
||||
}
|
||||
} else if (position == 1) { // team independent sidebar
|
||||
scoreboard.setColorIndependentSidebar(name);
|
||||
String username = wrapper.user().getProtocolInfo().getUsername();
|
||||
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
|
||||
if (color.isPresent() && scoreboard.getColorDependentSidebar().containsKey(color.get())) {
|
||||
position = -1;
|
||||
}
|
||||
}
|
||||
if (position == -1) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
wrapper.set(Types.BYTE, 0, position);
|
||||
});
|
||||
}
|
||||
});
|
||||
String username = wrapper.user().getProtocolInfo().getUsername();
|
||||
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
|
||||
if (color.isPresent() && color.get() == receiverTeamColor) {
|
||||
position = 1;
|
||||
} else {
|
||||
position = -1;
|
||||
}
|
||||
} else if (position == 1) { // team independent sidebar
|
||||
scoreboard.setColorIndependentSidebar(name);
|
||||
String username = wrapper.user().getProtocolInfo().getUsername();
|
||||
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
|
||||
if (color.isPresent() && scoreboard.getColorDependentSidebar().containsKey(color.get())) {
|
||||
position = -1;
|
||||
}
|
||||
}
|
||||
if (position == -1) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
wrapper.set(Types.BYTE, 0, position);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.SET_PLAYER_TEAM, wrapper -> {
|
||||
final String team = wrapper.passthrough(Types.STRING);
|
||||
if (team == null) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
protocol.registerClientbound(ClientboundPackets1_8.SET_PLAYER_TEAM, wrapper -> {
|
||||
final String team = wrapper.passthrough(Types.STRING);
|
||||
if (team == null) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
final ScoreboardTracker scoreboard = wrapper.user().get(ScoreboardTracker.class);
|
||||
final ScoreboardTracker scoreboard = wrapper.user().get(ScoreboardTracker.class);
|
||||
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(protocol);
|
||||
|
||||
final byte mode = wrapper.passthrough(Types.BYTE);
|
||||
if (mode != 0 && !scoreboard.teamExists(team)) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
} else if (mode == 0 && scoreboard.teamExists(team)) {
|
||||
scoreboard.removeTeam(team);
|
||||
final byte mode = wrapper.passthrough(Types.BYTE);
|
||||
if (mode != 0 && !scoreboard.teamExists(team)) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
} else if (mode == 0 && scoreboard.teamExists(team)) {
|
||||
scoreboard.removeTeam(team);
|
||||
|
||||
final PacketWrapper removeTeam = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, wrapper.user());
|
||||
removeTeam.write(Types.STRING, team);
|
||||
removeTeam.write(Types.BYTE, (byte) 1);
|
||||
removeTeam.send(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
final PacketWrapper removeTeam = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, wrapper.user());
|
||||
removeTeam.write(Types.STRING, team);
|
||||
removeTeam.write(Types.BYTE, (byte) 1);
|
||||
removeTeam.send(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
|
||||
if (mode == 0) {
|
||||
scoreboard.addTeam(team);
|
||||
} else if (mode == 1) {
|
||||
scoreboard.removeTeam(team);
|
||||
}
|
||||
if (mode == 0) {
|
||||
scoreboard.addTeam(team);
|
||||
} else if (mode == 1) {
|
||||
// Team removed, nametag visibility might have changed
|
||||
for (final String member : scoreboard.getTeamMembers(team)) {
|
||||
tracker.checkNametagVisbility(member);
|
||||
}
|
||||
scoreboard.removeTeam(team);
|
||||
}
|
||||
|
||||
if (mode == 0 || mode == 2) {
|
||||
wrapper.passthrough(Types.STRING); // Display name
|
||||
wrapper.passthrough(Types.STRING); // Prefix
|
||||
wrapper.passthrough(Types.STRING); // Suffix
|
||||
wrapper.passthrough(Types.BYTE); // Friendly fire
|
||||
wrapper.read(Types.STRING); // Name tag visibility
|
||||
byte color = wrapper.read(Types.BYTE);
|
||||
if (mode == 2 && scoreboard.getTeamColor(team).get() != color) {
|
||||
final String sidebar = scoreboard.getColorDependentSidebar().get(color);
|
||||
if (mode == 0 || mode == 2) {
|
||||
wrapper.passthrough(Types.STRING); // Display name
|
||||
wrapper.passthrough(Types.STRING); // Prefix
|
||||
wrapper.passthrough(Types.STRING); // Suffix
|
||||
wrapper.passthrough(Types.BYTE); // Friendly fire
|
||||
final String nameTagVisibility = wrapper.read(Types.STRING);
|
||||
final String previousVisibility = scoreboard.getTeamNameTagVisibility(team);
|
||||
scoreboard.setTeamNameTagVisibility(team, nameTagVisibility);
|
||||
byte color = wrapper.read(Types.BYTE);
|
||||
if (mode == 2 && scoreboard.getTeamColor(team).get() != color) {
|
||||
final String sidebar = scoreboard.getColorDependentSidebar().get(color);
|
||||
|
||||
final PacketWrapper sidebarPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user());
|
||||
sidebarPacket.write(Types.BYTE, (byte) 1);
|
||||
sidebarPacket.write(Types.STRING, sidebar == null ? "" : sidebar);
|
||||
sidebarPacket.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
scoreboard.setTeamColor(team, color);
|
||||
}
|
||||
if (mode == 0 || mode == 3 || mode == 4) {
|
||||
byte color = scoreboard.getTeamColor(team).get();
|
||||
String[] entries = wrapper.read(Types.STRING_ARRAY);
|
||||
List<String> entryList = new ArrayList<>();
|
||||
final PacketWrapper sidebarPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user());
|
||||
sidebarPacket.write(Types.BYTE, (byte) 1);
|
||||
sidebarPacket.write(Types.STRING, sidebar == null ? "" : sidebar);
|
||||
sidebarPacket.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
scoreboard.setTeamColor(team, color);
|
||||
|
||||
for (String entry : entries) {
|
||||
String username = wrapper.user().getProtocolInfo().getUsername();
|
||||
// Re-evaluate nametag visibility for all team members when visibility changes
|
||||
if (mode == 2 && !nameTagVisibility.equals(previousVisibility)) {
|
||||
for (final String member : scoreboard.getTeamMembers(team)) {
|
||||
tracker.checkNametagVisbility(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mode == 0 || mode == 3 || mode == 4) {
|
||||
byte color = scoreboard.getTeamColor(team).get();
|
||||
String[] entries = wrapper.read(Types.STRING_ARRAY);
|
||||
List<String> entryList = new ArrayList<>();
|
||||
|
||||
if (mode == 4) {
|
||||
if (!scoreboard.isPlayerInTeam(entry, team)) {
|
||||
continue;
|
||||
}
|
||||
scoreboard.removePlayerFromTeam(entry, team);
|
||||
if (entry.equals(username)) {
|
||||
final PacketWrapper sidebarPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user());
|
||||
sidebarPacket.write(Types.BYTE, (byte) 1);
|
||||
sidebarPacket.write(Types.STRING, scoreboard.getColorIndependentSidebar() == null ? "" : scoreboard.getColorIndependentSidebar());
|
||||
sidebarPacket.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
} else {
|
||||
scoreboard.addPlayerToTeam(entry, team);
|
||||
if (entry.equals(username) && scoreboard.getColorDependentSidebar().containsKey(color)) {
|
||||
final PacketWrapper displayObjective = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user());
|
||||
displayObjective.write(Types.BYTE, (byte) 1);
|
||||
displayObjective.write(Types.STRING, scoreboard.getColorDependentSidebar().get(color));
|
||||
displayObjective.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
}
|
||||
entryList.add(entry);
|
||||
}
|
||||
for (String entry : entries) {
|
||||
String username = wrapper.user().getProtocolInfo().getUsername();
|
||||
|
||||
wrapper.write(Types.SHORT, (short) entryList.size());
|
||||
for (String entry : entryList) {
|
||||
wrapper.write(Types.STRING, entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (mode == 4) {
|
||||
if (!scoreboard.isPlayerInTeam(entry, team)) {
|
||||
continue;
|
||||
}
|
||||
scoreboard.removePlayerFromTeam(entry, team);
|
||||
// Player left team, nametag visibility may change
|
||||
tracker.checkNametagVisbility(entry);
|
||||
if (entry.equals(username)) {
|
||||
final PacketWrapper sidebarPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user());
|
||||
sidebarPacket.write(Types.BYTE, (byte) 1);
|
||||
sidebarPacket.write(Types.STRING, scoreboard.getColorIndependentSidebar() == null ? "" : scoreboard.getColorIndependentSidebar());
|
||||
sidebarPacket.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
} else {
|
||||
scoreboard.addPlayerToTeam(entry, team);
|
||||
// Player joined team, nametag visibility may change
|
||||
tracker.checkNametagVisbility(entry);
|
||||
if (entry.equals(username) && scoreboard.getColorDependentSidebar().containsKey(color)) {
|
||||
final PacketWrapper displayObjective = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user());
|
||||
displayObjective.write(Types.BYTE, (byte) 1);
|
||||
displayObjective.write(Types.STRING, scoreboard.getColorDependentSidebar().get(color));
|
||||
displayObjective.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
}
|
||||
entryList.add(entry);
|
||||
}
|
||||
|
||||
wrapper.write(Types.SHORT, (short) entryList.size());
|
||||
for (String entry : entryList) {
|
||||
wrapper.write(Types.STRING, entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+222
-222
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,14 +17,15 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.rewriter;
|
||||
|
||||
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.WorldBorderEmulator;
|
||||
import com.viaversion.viarewind.api.type.chunk.ChunkType1_7_6;
|
||||
import com.viaversion.viarewind.api.type.chunk.BulkChunkType1_7_6;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.data.Particles1_8;
|
||||
import com.viaversion.viarewind.api.type.RewindTypes;
|
||||
import com.viaversion.viarewind.api.type.chunk.BulkChunkType1_7_6;
|
||||
import com.viaversion.viarewind.api.type.chunk.ChunkType1_7_6;
|
||||
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.Particles1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.WorldBorderEmulator;
|
||||
import com.viaversion.viarewind.utils.ChatUtil;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
@@ -33,261 +34,260 @@ 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;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_8;
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
import com.viaversion.viaversion.util.ChatColorUtil;
|
||||
import com.viaversion.viaversion.util.IdAndData;
|
||||
|
||||
public class WorldPacketRewriter1_8 extends RewriterBase<Protocol1_8To1_7_6_10> {
|
||||
|
||||
public WorldPacketRewriter1_8(Protocol1_8To1_7_6_10 protocol) {
|
||||
super(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().getClientWorld(Protocol1_8To1_7_6_10.class);
|
||||
final Chunk chunk = wrapper.read(ChunkType1_8.forEnvironment(world.getEnvironment()));
|
||||
protocol.getItemRewriter().handleChunk(chunk);
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocol.registerClientbound(ClientboundPackets1_8.LEVEL_CHUNK, wrapper -> {
|
||||
final ClientWorld world = wrapper.user().storables(protocol).clientWorld();
|
||||
final Chunk chunk = wrapper.read(ChunkType1_8.forEnvironment(world.getEnvironment()));
|
||||
protocol.getItemRewriter().handleChunk(chunk);
|
||||
|
||||
wrapper.write(ChunkType1_7_6.TYPE, chunk);
|
||||
});
|
||||
wrapper.write(ChunkType1_7_6.TYPE, chunk);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_UPDATE, new PacketHandlers() {
|
||||
@Override
|
||||
protected void register() {
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.U_BYTE_POSITION); // Position
|
||||
handler(wrapper -> {
|
||||
int data = wrapper.read(Types.VAR_INT); // Block data
|
||||
data = protocol.getItemRewriter().handleBlockId(data);
|
||||
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_UPDATE, new PacketHandlers() {
|
||||
@Override
|
||||
protected void register() {
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.U_BYTE_POSITION); // Position
|
||||
handler(wrapper -> {
|
||||
int data = wrapper.read(Types.VAR_INT); // Block data
|
||||
data = protocol.getItemRewriter().handleBlockId(data);
|
||||
|
||||
wrapper.write(Types.VAR_INT, IdAndData.getId(data)); // Block id
|
||||
wrapper.write(Types.UNSIGNED_BYTE, (short) IdAndData.getData(data)); // Block data
|
||||
});
|
||||
}
|
||||
});
|
||||
wrapper.write(Types.VAR_INT, IdAndData.getId(data)); // Block id
|
||||
wrapper.write(Types.UNSIGNED_BYTE, (short) IdAndData.getData(data)); // Block data
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CHUNK_BLOCKS_UPDATE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Chunk x
|
||||
map(Types.INT); // Chunk z
|
||||
protocol.registerClientbound(ClientboundPackets1_8.CHUNK_BLOCKS_UPDATE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Chunk x
|
||||
map(Types.INT); // Chunk z
|
||||
|
||||
handler(wrapper -> {
|
||||
final BlockChangeRecord[] records = wrapper.read(Types.BLOCK_CHANGE_ARRAY);
|
||||
handler(wrapper -> {
|
||||
final BlockChangeRecord[] records = wrapper.read(Types.BLOCK_CHANGE_ARRAY);
|
||||
|
||||
wrapper.write(Types.SHORT, (short) records.length); // Record count
|
||||
wrapper.write(Types.INT, records.length * 4); // Data array length (position + block id)
|
||||
wrapper.write(Types.SHORT, (short) records.length); // Record count
|
||||
wrapper.write(Types.INT, records.length * 4); // Data array length (position + block id)
|
||||
|
||||
for (BlockChangeRecord record : records) {
|
||||
wrapper.write(Types.SHORT, (short) (record.getSectionX() << 12 | record.getSectionZ() << 8 | record.getY())); // Position
|
||||
wrapper.write(Types.SHORT, (short) protocol.getItemRewriter().handleBlockId(record.getBlockId())); // Block id
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
for (BlockChangeRecord record : records) {
|
||||
wrapper.write(Types.SHORT, (short) (record.getSectionX() << 12 | record.getSectionZ() << 8 | record.getY())); // Position
|
||||
wrapper.write(Types.SHORT, (short) protocol.getItemRewriter().handleBlockId(record.getBlockId())); // Block id
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_EVENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.SHORT_POSITION); // Position
|
||||
map(Types.UNSIGNED_BYTE); // Type
|
||||
map(Types.UNSIGNED_BYTE); // Data
|
||||
map(Types.VAR_INT); // Block id
|
||||
}
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_EVENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.SHORT_POSITION); // Position
|
||||
map(Types.UNSIGNED_BYTE); // Type
|
||||
map(Types.UNSIGNED_BYTE); // Data
|
||||
map(Types.VAR_INT); // Block id
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_DESTRUCTION, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.VAR_INT); // Entity id
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.INT_POSITION); // Position
|
||||
map(Types.BYTE); // Progress
|
||||
}
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_DESTRUCTION, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.VAR_INT); // Entity id
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.INT_POSITION); // Position
|
||||
map(Types.BYTE); // Progress
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.MAP_BULK_CHUNK, wrapper -> {
|
||||
final Chunk[] chunks = wrapper.read(BulkChunkType1_8.TYPE);
|
||||
for (Chunk chunk : chunks) {
|
||||
protocol.getItemRewriter().handleChunk(chunk);
|
||||
}
|
||||
protocol.registerClientbound(ClientboundPackets1_8.MAP_BULK_CHUNK, wrapper -> {
|
||||
final Chunk[] chunks = wrapper.read(BulkChunkType1_8.TYPE);
|
||||
for (Chunk chunk : chunks) {
|
||||
protocol.getItemRewriter().handleChunk(chunk);
|
||||
}
|
||||
|
||||
wrapper.write(BulkChunkType1_7_6.TYPE, chunks);
|
||||
});
|
||||
wrapper.write(BulkChunkType1_7_6.TYPE, chunks);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.LEVEL_EVENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Effect id
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.BYTE_POSITION); // Position
|
||||
map(Types.INT); // Data
|
||||
map(Types.BOOLEAN); // Disable relative volume
|
||||
}
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_8.LEVEL_EVENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Effect id
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.BYTE_POSITION); // Position
|
||||
map(Types.INT); // Data
|
||||
map(Types.BOOLEAN); // Disable relative volume
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.LEVEL_PARTICLES, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
handler(wrapper -> {
|
||||
final int particleId = wrapper.read(Types.INT); // Particle id
|
||||
Particles1_8 particle = Particles1_8.find(particleId);
|
||||
if (particle == null) {
|
||||
particle = Particles1_8.CRIT;
|
||||
}
|
||||
wrapper.write(Types.STRING, particle.name); // Particle name
|
||||
protocol.registerClientbound(ClientboundPackets1_8.LEVEL_PARTICLES, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
handler(wrapper -> {
|
||||
final int particleId = wrapper.read(Types.INT); // Particle id
|
||||
Particles1_8 particle = Particles1_8.find(particleId);
|
||||
if (particle == null) {
|
||||
particle = Particles1_8.CRIT;
|
||||
}
|
||||
wrapper.write(Types.STRING, particle.name); // Particle name
|
||||
|
||||
});
|
||||
read(Types.BOOLEAN); // Long distance
|
||||
map(Types.FLOAT); // X
|
||||
map(Types.FLOAT); // Y
|
||||
map(Types.FLOAT); // Z
|
||||
map(Types.FLOAT); // Offset x
|
||||
map(Types.FLOAT); // Offset y
|
||||
map(Types.FLOAT); // Offset z
|
||||
map(Types.FLOAT); // Particle data
|
||||
map(Types.INT); // Particle count
|
||||
handler(wrapper -> {
|
||||
String name = wrapper.get(Types.STRING, 0);
|
||||
Particles1_8 particle = Particles1_8.find(name);
|
||||
});
|
||||
read(Types.BOOLEAN); // Long distance
|
||||
map(Types.FLOAT); // X
|
||||
map(Types.FLOAT); // Y
|
||||
map(Types.FLOAT); // Z
|
||||
map(Types.FLOAT); // Offset x
|
||||
map(Types.FLOAT); // Offset y
|
||||
map(Types.FLOAT); // Offset z
|
||||
map(Types.FLOAT); // Particle data
|
||||
map(Types.INT); // Particle count
|
||||
handler(wrapper -> {
|
||||
String name = wrapper.get(Types.STRING, 0);
|
||||
Particles1_8 particle = Particles1_8.find(name);
|
||||
|
||||
if (particle == Particles1_8.ICON_CRACK || particle == Particles1_8.BLOCK_CRACK || particle == Particles1_8.BLOCK_DUST) {
|
||||
int id = wrapper.read(Types.VAR_INT);
|
||||
int data = particle == Particles1_8.ICON_CRACK ? wrapper.read(Types.VAR_INT) : id / 4096;
|
||||
id %= 4096;
|
||||
if (id >= 256 && id <= 422 || id >= 2256 && id <= 2267) { //item
|
||||
particle = Particles1_8.ICON_CRACK;
|
||||
} else if (id >= 0 && id <= 164 || id >= 170 && id <= 175) {
|
||||
if (particle == Particles1_8.ICON_CRACK)
|
||||
particle = Particles1_8.BLOCK_CRACK;
|
||||
} else {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
name = particle.name + "_" + id + "_" + data;
|
||||
}
|
||||
if (particle == Particles1_8.ICON_CRACK || particle == Particles1_8.BLOCK_CRACK || particle == Particles1_8.BLOCK_DUST) {
|
||||
int id = wrapper.read(Types.VAR_INT);
|
||||
int data = particle == Particles1_8.ICON_CRACK ? wrapper.read(Types.VAR_INT) : id / 4096;
|
||||
id %= 4096;
|
||||
if (id >= 256 && id <= 422 || id >= 2256 && id <= 2267) { //item
|
||||
particle = Particles1_8.ICON_CRACK;
|
||||
} else if (id >= 0 && id <= 164 || id >= 170 && id <= 175) {
|
||||
if (particle == Particles1_8.ICON_CRACK)
|
||||
particle = Particles1_8.BLOCK_CRACK;
|
||||
} else {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
name = particle.name + "_" + id + "_" + data;
|
||||
}
|
||||
|
||||
wrapper.set(Types.STRING, 0, name);
|
||||
});
|
||||
}
|
||||
});
|
||||
wrapper.set(Types.STRING, 0, name);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.SHORT_POSITION); // position
|
||||
handler(wrapper -> {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
String line = wrapper.read(Types.STRING);
|
||||
line = ChatUtil.jsonToLegacy(line);
|
||||
line = ChatUtil.removeUnusedColor(line, '0');
|
||||
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.SHORT_POSITION); // position
|
||||
handler(wrapper -> {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
String line = wrapper.read(Types.STRING);
|
||||
line = ChatUtil.jsonToLegacy(line);
|
||||
line = ChatUtil.removeUnusedColor(line, '0');
|
||||
|
||||
if (line.length() > 15) {
|
||||
line = ChatColorUtil.stripColor(line);
|
||||
if (line.length() > 15) line = line.substring(0, 15);
|
||||
}
|
||||
wrapper.write(Types.STRING, line);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (line.length() > 15) {
|
||||
line = ChatColorUtil.stripColor(line);
|
||||
if (line.length() > 15) line = line.substring(0, 15);
|
||||
}
|
||||
wrapper.write(Types.STRING, line);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper -> {
|
||||
wrapper.cancel();
|
||||
final int id = wrapper.read(Types.VAR_INT);
|
||||
final byte scale = wrapper.read(Types.BYTE);
|
||||
protocol.registerClientbound(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper -> {
|
||||
wrapper.cancel();
|
||||
final int id = wrapper.read(Types.VAR_INT);
|
||||
final byte scale = wrapper.read(Types.BYTE);
|
||||
|
||||
final int iconCount = wrapper.read(Types.VAR_INT);
|
||||
byte[] icons = new byte[iconCount * 4];
|
||||
for (int i = 0; i < iconCount; i++) {
|
||||
final int directionAndType = wrapper.read(Types.BYTE);
|
||||
final int iconCount = wrapper.read(Types.VAR_INT);
|
||||
byte[] icons = new byte[iconCount * 4];
|
||||
for (int i = 0; i < iconCount; i++) {
|
||||
final int directionAndType = wrapper.read(Types.BYTE);
|
||||
|
||||
icons[i * 4] = (byte) (directionAndType >> 4 & 0xF);
|
||||
icons[i * 4 + 1] = wrapper.read(Types.BYTE); // x
|
||||
icons[i * 4 + 2] = wrapper.read(Types.BYTE); // z
|
||||
icons[i * 4 + 3] = (byte) (directionAndType & 0xF);
|
||||
}
|
||||
final short columns = wrapper.read(Types.UNSIGNED_BYTE);
|
||||
if (columns > 0) {
|
||||
final short rows = wrapper.read(Types.UNSIGNED_BYTE);
|
||||
final short x = wrapper.read(Types.UNSIGNED_BYTE);
|
||||
final short z = wrapper.read(Types.UNSIGNED_BYTE);
|
||||
icons[i * 4] = (byte) (directionAndType >> 4 & 0xF);
|
||||
icons[i * 4 + 1] = wrapper.read(Types.BYTE); // x
|
||||
icons[i * 4 + 2] = wrapper.read(Types.BYTE); // z
|
||||
icons[i * 4 + 3] = (byte) (directionAndType & 0xF);
|
||||
}
|
||||
final short columns = wrapper.read(Types.UNSIGNED_BYTE);
|
||||
if (columns > 0) {
|
||||
final short rows = wrapper.read(Types.UNSIGNED_BYTE);
|
||||
final short x = wrapper.read(Types.UNSIGNED_BYTE);
|
||||
final short z = wrapper.read(Types.UNSIGNED_BYTE);
|
||||
|
||||
final byte[] data = wrapper.read(Types.BYTE_ARRAY_PRIMITIVE);
|
||||
for (int column = 0; column < columns; column++) {
|
||||
byte[] columnData = new byte[rows + 3];
|
||||
columnData[0] = 0;
|
||||
columnData[1] = (byte) (x + column);
|
||||
columnData[2] = (byte) z;
|
||||
final byte[] data = wrapper.read(Types.BYTE_ARRAY_PRIMITIVE);
|
||||
for (int column = 0; column < columns; column++) {
|
||||
byte[] columnData = new byte[rows + 3];
|
||||
columnData[0] = 0;
|
||||
columnData[1] = (byte) (x + column);
|
||||
columnData[2] = (byte) z;
|
||||
|
||||
for (int i = 0; i < rows; i++) {
|
||||
columnData[i + 3] = data[column + i * columns];
|
||||
}
|
||||
for (int i = 0; i < rows; i++) {
|
||||
columnData[i + 3] = data[column + i * columns];
|
||||
}
|
||||
|
||||
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper.user());
|
||||
mapData.write(Types.VAR_INT, id); // map id
|
||||
mapData.write(Types.SHORT, (short) columnData.length); // data length
|
||||
mapData.write(new FixedByteArrayType(columnData.length), columnData); // data
|
||||
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper.user());
|
||||
mapData.write(Types.VAR_INT, id); // map id
|
||||
mapData.write(Types.SHORT, (short) columnData.length); // data length
|
||||
mapData.write(new FixedByteArrayType(columnData.length), columnData); // data
|
||||
|
||||
mapData.send(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
}
|
||||
mapData.send(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
}
|
||||
|
||||
if (iconCount > 0) {
|
||||
final byte[] iconData = new byte[iconCount * 3 + 1];
|
||||
iconData[0] = 1;
|
||||
for (int i = 0; i < iconCount; i++) {
|
||||
iconData[i * 3 + 1] = (byte) (icons[i * 4] << 4 | icons[i * 4 + 3] & 0xF);
|
||||
iconData[i * 3 + 2] = icons[i * 4 + 1];
|
||||
iconData[i * 3 + 3] = icons[i * 4 + 2];
|
||||
}
|
||||
if (iconCount > 0) {
|
||||
final byte[] iconData = new byte[iconCount * 3 + 1];
|
||||
iconData[0] = 1;
|
||||
for (int i = 0; i < iconCount; i++) {
|
||||
iconData[i * 3 + 1] = (byte) (icons[i * 4] << 4 | icons[i * 4 + 3] & 0xF);
|
||||
iconData[i * 3 + 2] = icons[i * 4 + 1];
|
||||
iconData[i * 3 + 3] = icons[i * 4 + 2];
|
||||
}
|
||||
|
||||
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper.user());
|
||||
mapData.write(Types.VAR_INT, id); // map id
|
||||
mapData.write(Types.SHORT, (short) iconData.length); // data length
|
||||
mapData.write(new FixedByteArrayType(iconData.length), iconData); // data
|
||||
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper.user());
|
||||
mapData.write(Types.VAR_INT, id); // map id
|
||||
mapData.write(Types.SHORT, (short) iconData.length); // data length
|
||||
mapData.write(new FixedByteArrayType(iconData.length), iconData); // data
|
||||
|
||||
mapData.send(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
mapData.send(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
|
||||
// Update scale
|
||||
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper.user());
|
||||
mapData.write(Types.VAR_INT, id); // map id
|
||||
mapData.write(Types.SHORT, (short) 2); // data length
|
||||
mapData.write(new FixedByteArrayType(2), new byte[]{2, scale}); // data
|
||||
// Update scale
|
||||
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_ITEM_DATA, wrapper.user());
|
||||
mapData.write(Types.VAR_INT, id); // map id
|
||||
mapData.write(Types.SHORT, (short) 2); // data length
|
||||
mapData.write(new FixedByteArrayType(2), new byte[]{2, scale}); // data
|
||||
|
||||
mapData.send(Protocol1_8To1_7_6_10.class);
|
||||
});
|
||||
mapData.send(Protocol1_8To1_7_6_10.class);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ENTITY_DATA, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.SHORT_POSITION); // position
|
||||
map(Types.UNSIGNED_BYTE); // action
|
||||
map(Types.NAMED_COMPOUND_TAG, RewindTypes.COMPRESSED_NBT); // nbt
|
||||
}
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ENTITY_DATA, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BLOCK_POSITION1_8, RewindTypes.SHORT_POSITION); // position
|
||||
map(Types.UNSIGNED_BYTE); // action
|
||||
map(Types.NAMED_COMPOUND_TAG, RewindTypes.COMPRESSED_NBT); // nbt
|
||||
}
|
||||
});
|
||||
|
||||
protocol.cancelClientbound(ClientboundPackets1_8.CHANGE_DIFFICULTY);
|
||||
protocol.cancelClientbound(ClientboundPackets1_8.CHANGE_DIFFICULTY);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_8.SET_BORDER, null, wrapper -> {
|
||||
final WorldBorderEmulator emulator = wrapper.user().get(WorldBorderEmulator.class);
|
||||
wrapper.cancel();
|
||||
protocol.registerClientbound(ClientboundPackets1_8.SET_BORDER, null, wrapper -> {
|
||||
final WorldBorderEmulator emulator = wrapper.user().get(WorldBorderEmulator.class);
|
||||
wrapper.cancel();
|
||||
|
||||
final int action = wrapper.read(Types.VAR_INT);
|
||||
if (action == 0) { // set size
|
||||
emulator.setSize(wrapper.read(Types.DOUBLE)); // radius
|
||||
} else if (action == 1) { // lerp size
|
||||
emulator.lerpSize(wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE), wrapper.read(Types.VAR_LONG)); // old radius, new radius, speed
|
||||
} else if (action == 2) { // set center
|
||||
emulator.setCenter(wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE)); // x, z
|
||||
} else if (action == 3) { // initialize
|
||||
emulator.init(
|
||||
wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE), // x, z
|
||||
wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE), // old radius, new radius
|
||||
wrapper.read(Types.VAR_LONG) // speed
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
final int action = wrapper.read(Types.VAR_INT);
|
||||
if (action == 0) { // set size
|
||||
emulator.setSize(wrapper.read(Types.DOUBLE)); // radius
|
||||
} else if (action == 1) { // lerp size
|
||||
emulator.lerpSize(wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE), wrapper.read(Types.VAR_LONG)); // old radius, new radius, speed
|
||||
} else if (action == 2) { // set center
|
||||
emulator.setCenter(wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE)); // x, z
|
||||
} else if (action == 3) { // initialize
|
||||
emulator.init(
|
||||
wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE), // x, z
|
||||
wrapper.read(Types.DOUBLE), wrapper.read(Types.DOUBLE), // old radius, new radius
|
||||
wrapper.read(Types.VAR_LONG) // speed
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,9 +24,9 @@ import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
* @see com.viaversion.viarewind.protocol.v1_8to1_7_6_10.provider.CompressionHandlerProvider
|
||||
*/
|
||||
public class CompressionStatusTracker extends StoredObject {
|
||||
public boolean removeCompression = false;
|
||||
public boolean removeCompression = false;
|
||||
|
||||
public CompressionStatusTracker(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
public CompressionStatusTracker(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
}
|
||||
+132
-8
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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_7_6_10to1_7_2_5.packet.ServerboundPa
|
||||
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.VirtualHologramEntity;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_8;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
|
||||
@@ -36,16 +37,27 @@ import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
|
||||
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntMap;
|
||||
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntOpenHashMap;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.viaversion.viarewind.api.minecraft.entitydata.EntityDataTypes1_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;
|
||||
|
||||
public class EntityTracker1_8 extends EntityTrackerBase {
|
||||
|
||||
private final Int2ObjectMap<VirtualHologramEntity> holograms = new Int2ObjectArrayMap<>();
|
||||
private final Int2IntMap extraHologramIds = new Int2IntArrayMap();
|
||||
private final Int2IntMap vehicles = new Int2IntArrayMap();
|
||||
private final Int2ObjectMap<UUID> entityIdToUUID = new Int2ObjectArrayMap<>();
|
||||
private final Object2IntMap<UUID> entityUUIDToId = new Object2IntOpenHashMap<>();
|
||||
private final Int2IntMap playerNametagHiderEntities = new Int2IntArrayMap();
|
||||
|
||||
private final List<EntityData> entityData = new ArrayList<>();
|
||||
|
||||
@@ -57,35 +69,41 @@ public class EntityTracker1_8 extends EntityTrackerBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntity(int id, EntityType type) {
|
||||
super.addEntity(id, type);
|
||||
public TrackedEntity addEntity(int id, EntityType type) {
|
||||
if (type == EntityTypes1_8.EntityType.ARMOR_STAND) {
|
||||
holograms.put(id, new VirtualHologramEntity(user(), id));
|
||||
}
|
||||
return super.addEntity(id, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEntity(int entityId) {
|
||||
super.removeEntity(entityId);
|
||||
|
||||
public TrackedEntity removeEntity(int entityId) {
|
||||
final VirtualHologramEntity hologram = holograms.get(entityId);
|
||||
if (hologram != null) {
|
||||
hologram.deleteEntity();
|
||||
holograms.remove(entityId);
|
||||
}
|
||||
|
||||
if (playerNametagHiderEntities.containsKey(entityId)) {
|
||||
despawnNametagHiderEntity(entityId);
|
||||
}
|
||||
|
||||
if (entityIdToUUID.containsKey(entityId)) {
|
||||
final UUID playerId = entityIdToUUID.remove(entityId);
|
||||
|
||||
entityUUIDToId.removeInt(playerId);
|
||||
user().get(PlayerSessionStorage.class).getPlayerEquipment().remove(playerId);
|
||||
}
|
||||
return super.removeEntity(entityId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearEntities() {
|
||||
super.clearEntities();
|
||||
holograms.clear();
|
||||
extraHologramIds.clear();
|
||||
vehicles.clear();
|
||||
playerNametagHiderEntities.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,6 +170,11 @@ public class EntityTracker1_8 extends EntityTrackerBase {
|
||||
} else {
|
||||
vehicles.put(vehicleId, passengerId);
|
||||
}
|
||||
|
||||
// Re-evaluate nametag visibility when a player entity's passenger changes
|
||||
if (vehicleId != -1 && entityIdToUUID.containsKey(vehicleId)) {
|
||||
checkNametagVisibility(vehicleId);
|
||||
}
|
||||
}
|
||||
|
||||
protected void attachEntity(final int target) {
|
||||
@@ -182,10 +205,111 @@ public class EntityTracker1_8 extends EntityTrackerBase {
|
||||
}
|
||||
}
|
||||
|
||||
public void checkNametagVisibility(final int entityId) {
|
||||
if (!entityIdToUUID.containsKey(entityId)) {
|
||||
return;
|
||||
}
|
||||
final boolean shouldHide = isPlayerNametagHidden(entityId);
|
||||
final boolean hasServerPassenger = getPassenger(entityId) != -1;
|
||||
final boolean hasSkull = playerNametagHiderEntities.containsKey(entityId);
|
||||
|
||||
if (shouldHide && !hasServerPassenger && !hasSkull) {
|
||||
spawnNametagHiderEntity(entityId);
|
||||
} else if ((!shouldHide || hasServerPassenger) && hasSkull) {
|
||||
despawnNametagHiderEntity(entityId);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkNametagVisbility(final String username) {
|
||||
final GameProfileStorage profileStorage = user().get(GameProfileStorage.class);
|
||||
final List<GameProfileStorage.GameProfile> profiles = profileStorage.get(username, false);
|
||||
|
||||
for (GameProfileStorage.GameProfile profile : profiles) {
|
||||
final int entityId = getPlayerEntityId(profile.uuid);
|
||||
if (entityId == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkNametagVisibility(entityId);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPlayerNametagHidden(final int entityId) {
|
||||
final UUID uuid = entityIdToUUID.get(entityId);
|
||||
if (uuid == null) {
|
||||
return false;
|
||||
}
|
||||
final GameProfileStorage profileStorage = user().get(GameProfileStorage.class);
|
||||
final GameProfileStorage.GameProfile profile = profileStorage.get(uuid);
|
||||
if (profile == null) {
|
||||
return false;
|
||||
}
|
||||
return user().get(ScoreboardTracker.class).isNametagHidden(profile.name);
|
||||
}
|
||||
|
||||
private int getNametagHiderEntityId(final int playerEntityId) {
|
||||
return Integer.MAX_VALUE - 32000 - playerEntityId;
|
||||
}
|
||||
|
||||
private void spawnNametagHiderEntity(final int playerEntityId) {
|
||||
final int entityId = getNametagHiderEntityId(playerEntityId);
|
||||
playerNametagHiderEntities.put(playerEntityId, entityId);
|
||||
|
||||
final List<EntityData> mobData = new ArrayList<>();
|
||||
mobData.add(new EntityData(0, EntityDataTypes1_7_6_10.BYTE, (byte) 0x20));
|
||||
mobData.add(new EntityData(16, EntityDataTypes1_7_6_10.BYTE, (byte) 0));
|
||||
|
||||
final PacketWrapper spawnMob = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_MOB, user());
|
||||
spawnMob.write(Types.VAR_INT, entityId);
|
||||
spawnMob.write(Types.UNSIGNED_BYTE, (short) EntityTypes1_8.EntityType.MAGMA_CUBE.getId());
|
||||
spawnMob.write(Types.INT, 0); // X
|
||||
spawnMob.write(Types.INT, 0); // Y
|
||||
spawnMob.write(Types.INT, 0); // Z
|
||||
spawnMob.write(Types.BYTE, (byte) 0); // Yaw
|
||||
spawnMob.write(Types.BYTE, (byte) 0); // Pitch
|
||||
spawnMob.write(Types.BYTE, (byte) 0); // Head yaw
|
||||
spawnMob.write(Types.SHORT, (short) 0); // Velocity x
|
||||
spawnMob.write(Types.SHORT, (short) 0); // Velocity y
|
||||
spawnMob.write(Types.SHORT, (short) 0); // Velocity z
|
||||
spawnMob.write(RewindTypes.ENTITY_DATA_LIST1_7, mobData);
|
||||
spawnMob.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
|
||||
final PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_LINK, user());
|
||||
attach.write(Types.INT, entityId);
|
||||
attach.write(Types.INT, playerEntityId);
|
||||
attach.write(Types.BOOLEAN, false);
|
||||
attach.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
|
||||
private void despawnNametagHiderEntity(final int playerEntityId) {
|
||||
if (!playerNametagHiderEntities.containsKey(playerEntityId)) return;
|
||||
final int mobId = playerNametagHiderEntities.remove(playerEntityId);
|
||||
|
||||
final PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.REMOVE_ENTITIES, user());
|
||||
despawn.write(Types.BYTE, (byte) 1);
|
||||
despawn.write(Types.INT, mobId);
|
||||
despawn.scheduleSend(Protocol1_8To1_7_6_10.class);
|
||||
}
|
||||
|
||||
public Int2ObjectMap<VirtualHologramEntity> getHolograms() {
|
||||
return holograms;
|
||||
}
|
||||
|
||||
public void setExtraHologramId(final int entityId, final int extraId) {
|
||||
extraHologramIds.put(extraId, entityId);
|
||||
}
|
||||
|
||||
public void removeExtraHologramId(int extraId) {
|
||||
extraHologramIds.remove(extraId);
|
||||
}
|
||||
|
||||
public int getHologramIdWithExtra(final int id) {
|
||||
if (holograms.containsKey(id)) {
|
||||
return id;
|
||||
}
|
||||
return extraHologramIds.getOrDefault(id, -1);
|
||||
}
|
||||
|
||||
public boolean isSpectator() {
|
||||
return clientEntityGameMode == 3;
|
||||
}
|
||||
|
||||
+104
-98
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,129 +17,135 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.ListTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
import com.viaversion.viarewind.utils.ChatUtil;
|
||||
import com.viaversion.viaversion.api.connection.StoredObject;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.item.DataItem;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.ListTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
import com.viaversion.viaversion.util.ChatColorUtil;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GameProfileStorage extends StoredObject {
|
||||
private final Map<UUID, GameProfile> properties = new HashMap<>();
|
||||
private final Map<UUID, GameProfile> properties = new HashMap<>();
|
||||
private final ListMultimap<String, GameProfile> nameToProfile = ArrayListMultimap.create();
|
||||
|
||||
public GameProfileStorage(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
public GameProfileStorage(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
public GameProfile put(UUID uuid, String name) {
|
||||
GameProfile gameProfile = new GameProfile(uuid, name);
|
||||
properties.put(uuid, gameProfile);
|
||||
return gameProfile;
|
||||
}
|
||||
public GameProfile put(UUID uuid, String name, String displayName, int ping, int gamemode) {
|
||||
GameProfile gameProfile = new GameProfile(uuid, name, displayName, ping, gamemode);
|
||||
properties.put(uuid, gameProfile);
|
||||
nameToProfile.put(name, gameProfile);
|
||||
return gameProfile;
|
||||
}
|
||||
|
||||
public GameProfile get(UUID uuid) {
|
||||
return properties.get(uuid);
|
||||
}
|
||||
public GameProfile get(UUID uuid) {
|
||||
return properties.get(uuid);
|
||||
}
|
||||
|
||||
public GameProfile get(String name, boolean ignoreCase) {
|
||||
if (ignoreCase) name = name.toLowerCase();
|
||||
public List<GameProfile> get(String name, boolean ignoreCase) {
|
||||
if (ignoreCase) name = name.toLowerCase();
|
||||
return nameToProfile.get(name);
|
||||
}
|
||||
|
||||
for (GameProfile profile : properties.values()) {
|
||||
if (profile.name == null) continue;
|
||||
public List<GameProfile> getAllWithPrefix(String prefix, boolean ignoreCase) {
|
||||
if (ignoreCase) prefix = prefix.toLowerCase();
|
||||
|
||||
String n = ignoreCase ? profile.name.toLowerCase() : profile.name;
|
||||
ArrayList<GameProfile> profiles = new ArrayList<>();
|
||||
|
||||
if (n.equals(name)) {
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
for (GameProfile profile : properties.values()) {
|
||||
if (profile.name == null) continue;
|
||||
|
||||
public List<GameProfile> getAllWithPrefix(String prefix, boolean ignoreCase) {
|
||||
if (ignoreCase) prefix = prefix.toLowerCase();
|
||||
String n = ignoreCase ? profile.name.toLowerCase() : profile.name;
|
||||
|
||||
ArrayList<GameProfile> profiles = new ArrayList<>();
|
||||
if (n.startsWith(prefix)) profiles.add(profile);
|
||||
}
|
||||
|
||||
for (GameProfile profile : properties.values()) {
|
||||
if (profile.name == null) continue;
|
||||
return profiles;
|
||||
}
|
||||
|
||||
String n = ignoreCase ? profile.name.toLowerCase() : profile.name;
|
||||
|
||||
if (n.startsWith(prefix)) profiles.add(profile);
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
public GameProfile remove(UUID uuid) {
|
||||
return properties.remove(uuid);
|
||||
}
|
||||
public GameProfile remove(UUID uuid) {
|
||||
GameProfile removedProfile = properties.remove(uuid);
|
||||
if (removedProfile != null) {
|
||||
nameToProfile.get(removedProfile.name).remove(removedProfile);
|
||||
}
|
||||
return removedProfile;
|
||||
}
|
||||
|
||||
|
||||
public static class GameProfile {
|
||||
public final String name;
|
||||
public final UUID uuid;
|
||||
public String displayName;
|
||||
public int ping;
|
||||
public List<Property> properties = new ArrayList<>();
|
||||
public int gamemode = 0;
|
||||
public static class GameProfile {
|
||||
public final UUID uuid;
|
||||
public final String name;
|
||||
public String displayName;
|
||||
public List<Property> properties = new ArrayList<>();
|
||||
public int ping;
|
||||
public int gamemode = 0;
|
||||
|
||||
public GameProfile(UUID uuid, String name) {
|
||||
this.name = name;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
public GameProfile(UUID uuid, String name, String displayName, int ping, int gamemode) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
this.displayName = displayName;
|
||||
this.ping = ping;
|
||||
this.gamemode = gamemode;
|
||||
}
|
||||
|
||||
public Item getSkull() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
CompoundTag ownerTag = new CompoundTag();
|
||||
tag.put("SkullOwner", ownerTag);
|
||||
ownerTag.put("Id", new StringTag(uuid.toString()));
|
||||
CompoundTag properties = new CompoundTag();
|
||||
ownerTag.put("Properties", properties);
|
||||
ListTag textures = new ListTag(CompoundTag.class);
|
||||
properties.put("textures", textures);
|
||||
for (Property property : this.properties) {
|
||||
if (property.name.equals("textures")) {
|
||||
CompoundTag textureTag = new CompoundTag();
|
||||
textureTag.put("Value", new StringTag(property.value));
|
||||
if (property.signature != null) {
|
||||
textureTag.put("Signature", new StringTag(property.signature));
|
||||
}
|
||||
textures.add(textureTag);
|
||||
}
|
||||
}
|
||||
public Item getSkull() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
CompoundTag ownerTag = new CompoundTag();
|
||||
tag.put("SkullOwner", ownerTag);
|
||||
ownerTag.put("Id", new StringTag(uuid.toString()));
|
||||
CompoundTag properties = new CompoundTag();
|
||||
ownerTag.put("Properties", properties);
|
||||
ListTag textures = new ListTag(CompoundTag.class);
|
||||
properties.put("textures", textures);
|
||||
for (Property property : this.properties) {
|
||||
if (property.name.equals("textures")) {
|
||||
CompoundTag textureTag = new CompoundTag();
|
||||
textureTag.put("Value", new StringTag(property.value));
|
||||
if (property.signature != null) {
|
||||
textureTag.put("Signature", new StringTag(property.signature));
|
||||
}
|
||||
textures.add(textureTag);
|
||||
}
|
||||
}
|
||||
|
||||
return new DataItem(397, (byte) 1, (short) 3, tag);
|
||||
}
|
||||
return new DataItem(397, (byte) 1, (short) 3, tag);
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
String displayName = this.displayName == null ? name : this.displayName;
|
||||
if (displayName.length() > 16) displayName = ChatUtil.removeUnusedColor(displayName, 'f');
|
||||
if (displayName.length() > 16) displayName = ChatColorUtil.stripColor(displayName);
|
||||
if (displayName.length() > 16) displayName = displayName.substring(0, 16);
|
||||
return displayName;
|
||||
}
|
||||
public String getLegacyDisplayName() {
|
||||
String displayName = this.displayName == null ? name : this.displayName;
|
||||
if (displayName.length() > 16) displayName = ChatUtil.removeUnusedColor(displayName, 'f');
|
||||
if (displayName.length() > 16) displayName = ChatColorUtil.stripColor(displayName);
|
||||
if (displayName.length() > 16) displayName = displayName.substring(0, 16);
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
}
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Property {
|
||||
public final String name;
|
||||
public final String value;
|
||||
public final String signature;
|
||||
public static class Property {
|
||||
public final String name;
|
||||
public final String value;
|
||||
public final String signature;
|
||||
|
||||
public Property(String name, String value, String signature) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.signature = signature;
|
||||
}
|
||||
}
|
||||
public Property(String name, String value, String signature) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.signature = signature;
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
-47
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,66 +19,65 @@ package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.StoredObject;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class InventoryTracker extends StoredObject {
|
||||
public static final Map<String, Integer> WINDOW_TYPE_REGISTRY = new HashMap<>();
|
||||
public static final Map<String, Integer> WINDOW_TYPE_REGISTRY = new HashMap<>();
|
||||
|
||||
static {
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:container", 0);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:chest", 0);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:crafting_table", 1);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:furnace", 2);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:dispenser", 3);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:enchanting_table", 4);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:brewing_stand", 5);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:villager", 6);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:beacon", 7);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:anvil", 8);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:hopper", 9);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:dropper", 10);
|
||||
WINDOW_TYPE_REGISTRY.put("EntityHorse", 11);
|
||||
}
|
||||
static {
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:container", 0);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:chest", 0);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:crafting_table", 1);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:furnace", 2);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:dispenser", 3);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:enchanting_table", 4);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:brewing_stand", 5);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:villager", 6);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:beacon", 7);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:anvil", 8);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:hopper", 9);
|
||||
WINDOW_TYPE_REGISTRY.put("minecraft:dropper", 10);
|
||||
WINDOW_TYPE_REGISTRY.put("EntityHorse", 11);
|
||||
}
|
||||
|
||||
private final HashMap<Short, Short> windowTypeMap = new HashMap<>();
|
||||
private final HashMap<Short, FurnaceData> furnaceData = new HashMap<>();
|
||||
private final HashMap<Short, Short> windowTypeMap = new HashMap<>();
|
||||
private final HashMap<Short, FurnaceData> furnaceData = new HashMap<>();
|
||||
|
||||
public short levelCost = 0;
|
||||
public short anvilId = -1;
|
||||
public short levelCost = 0;
|
||||
public short anvilId = -1;
|
||||
|
||||
public InventoryTracker(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
public InventoryTracker(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
public short get(short windowId) {
|
||||
return windowTypeMap.getOrDefault(windowId, (short) -1);
|
||||
}
|
||||
public static short getInventoryType(String name) {
|
||||
return WINDOW_TYPE_REGISTRY.getOrDefault(name, -1).shortValue();
|
||||
}
|
||||
|
||||
public void remove(short windowId) {
|
||||
windowTypeMap.remove(windowId);
|
||||
furnaceData.remove(windowId);
|
||||
}
|
||||
public short get(short windowId) {
|
||||
return windowTypeMap.getOrDefault(windowId, (short) -1);
|
||||
}
|
||||
|
||||
public static short getInventoryType(String name) {
|
||||
return WINDOW_TYPE_REGISTRY.getOrDefault(name, -1).shortValue();
|
||||
}
|
||||
public void remove(short windowId) {
|
||||
windowTypeMap.remove(windowId);
|
||||
furnaceData.remove(windowId);
|
||||
}
|
||||
|
||||
public HashMap<Short, Short> getWindowTypeMap() {
|
||||
return windowTypeMap;
|
||||
}
|
||||
public HashMap<Short, Short> getWindowTypeMap() {
|
||||
return windowTypeMap;
|
||||
}
|
||||
|
||||
public HashMap<Short, FurnaceData> getFurnaceData() {
|
||||
return furnaceData;
|
||||
}
|
||||
public HashMap<Short, FurnaceData> getFurnaceData() {
|
||||
return furnaceData;
|
||||
}
|
||||
|
||||
public static class FurnaceData {
|
||||
public static class FurnaceData {
|
||||
|
||||
public short fuelLeft = 0;
|
||||
public short maxFuel = 0;
|
||||
public short progress = 0;
|
||||
public short maxProgress = 200;
|
||||
}
|
||||
public short fuelLeft = 0;
|
||||
public short maxFuel = 0;
|
||||
public short progress = 0;
|
||||
public short maxProgress = 200;
|
||||
}
|
||||
|
||||
}
|
||||
+53
-54
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,78 +20,77 @@ package com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage;
|
||||
import com.viaversion.viaversion.api.connection.StoredObject;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerSessionStorage extends StoredObject {
|
||||
|
||||
// Player abilities
|
||||
public boolean sprinting, allowFly, flying, invincible, creative;
|
||||
public float flySpeed, walkSpeed;
|
||||
// Player inventory
|
||||
private final Map<UUID, Item[]> playerEquipment = new HashMap<>();
|
||||
|
||||
// Player position, rotation and data
|
||||
private double posX, posY, posZ;
|
||||
public double receivedPosY;
|
||||
public float yaw, pitch;
|
||||
public boolean onGround;
|
||||
// Player abilities
|
||||
public boolean sprinting, allowFly, flying, invincible, creative;
|
||||
public float flySpeed, walkSpeed;
|
||||
public double receivedPosY;
|
||||
public float yaw, pitch;
|
||||
public boolean onGround;
|
||||
|
||||
// Player inventory
|
||||
private final Map<UUID, Item[]> playerEquipment = new HashMap<>();
|
||||
// Player position, rotation and data
|
||||
private double posX, posY, posZ;
|
||||
|
||||
public PlayerSessionStorage(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
public PlayerSessionStorage(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
public byte combineAbilities() {
|
||||
byte flags = 0;
|
||||
public byte combineAbilities() {
|
||||
byte flags = 0;
|
||||
|
||||
if (invincible) flags |= 8;
|
||||
if (allowFly) flags |= 4;
|
||||
if (flying) flags |= 2;
|
||||
if (creative) flags |= 1;
|
||||
if (invincible) flags |= 8;
|
||||
if (allowFly) flags |= 4;
|
||||
if (flying) flags |= 2;
|
||||
if (creative) flags |= 1;
|
||||
|
||||
return flags;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
public double getPosX() {
|
||||
return posX;
|
||||
}
|
||||
public double getPosX() {
|
||||
return posX;
|
||||
}
|
||||
|
||||
public double getPosY() {
|
||||
return posY;
|
||||
}
|
||||
public double getPosY() {
|
||||
return posY;
|
||||
}
|
||||
|
||||
public double getPosZ() {
|
||||
return posZ;
|
||||
}
|
||||
public double getPosZ() {
|
||||
return posZ;
|
||||
}
|
||||
|
||||
public void setPos(double x, double y, double z) {
|
||||
posX = x;
|
||||
posY = y;
|
||||
posZ = z;
|
||||
}
|
||||
public void setPos(double x, double y, double z) {
|
||||
posX = x;
|
||||
posY = y;
|
||||
posZ = z;
|
||||
}
|
||||
|
||||
public Item getPlayerEquipment(final UUID uuid, final int slot) {
|
||||
final Item[] items = playerEquipment.get(uuid);
|
||||
if (items == null || slot < 0 || slot >= items.length) {
|
||||
return null;
|
||||
}
|
||||
public Item getPlayerEquipment(final UUID uuid, final int slot) {
|
||||
final Item[] items = playerEquipment.get(uuid);
|
||||
if (items == null || slot < 0 || slot >= items.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return items[slot];
|
||||
}
|
||||
return items[slot];
|
||||
}
|
||||
|
||||
public void setPlayerEquipment(final UUID uuid, final Item equipment, final int slot) {
|
||||
final Item[] items = playerEquipment.computeIfAbsent(uuid, it -> new Item[5]);
|
||||
if (slot < 0 || slot >= items.length) {
|
||||
return;
|
||||
}
|
||||
public void setPlayerEquipment(final UUID uuid, final Item equipment, final int slot) {
|
||||
final Item[] items = playerEquipment.computeIfAbsent(uuid, it -> new Item[5]);
|
||||
if (slot < 0 || slot >= items.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
items[slot] = equipment;
|
||||
}
|
||||
items[slot] = equipment;
|
||||
}
|
||||
|
||||
public Map<UUID, Item[]> getPlayerEquipment() {
|
||||
return playerEquipment;
|
||||
}
|
||||
public Map<UUID, Item[]> getPlayerEquipment() {
|
||||
return playerEquipment;
|
||||
}
|
||||
}
|
||||
+164
-131
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,163 +23,196 @@ import com.viaversion.viaversion.api.connection.StoredObject;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ScoreboardTracker extends StoredObject {
|
||||
private final HashMap<String, List<String>> teams = new HashMap<>();
|
||||
private final HashSet<String> objectives = new HashSet<>();
|
||||
private final HashMap<String, ScoreTeam> scoreTeams = new HashMap<>();
|
||||
private final HashMap<String, Byte> teamColors = new HashMap<>();
|
||||
private final HashSet<String> scoreTeamNames = new HashSet<>();
|
||||
private String colorIndependentSidebar;
|
||||
private final HashMap<Byte, String> colorDependentSidebar = new HashMap<>();
|
||||
private final HashMap<String, List<String>> teams = new HashMap<>();
|
||||
private final HashSet<String> objectives = new HashSet<>();
|
||||
private final HashMap<String, ScoreTeam> scoreTeams = new HashMap<>();
|
||||
private final HashMap<String, Byte> teamColors = new HashMap<>();
|
||||
private final HashSet<String> scoreTeamNames = new HashSet<>();
|
||||
private final HashMap<Byte, String> colorDependentSidebar = new HashMap<>();
|
||||
private final HashMap<String, String> teamNameTagVisibilities = new HashMap<>();
|
||||
private String colorIndependentSidebar;
|
||||
|
||||
public ScoreboardTracker(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
public ScoreboardTracker(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
public void addPlayerToTeam(String player, String team) {
|
||||
teams.computeIfAbsent(team, key -> new ArrayList<>()).add(player);
|
||||
}
|
||||
public void addPlayerToTeam(String player, String team) {
|
||||
teams.computeIfAbsent(team, key -> new ArrayList<>()).add(player);
|
||||
}
|
||||
|
||||
public void setTeamColor(String team, Byte color) {
|
||||
teamColors.put(team, color);
|
||||
}
|
||||
public void setTeamColor(String team, Byte color) {
|
||||
teamColors.put(team, color);
|
||||
}
|
||||
|
||||
public Optional<Byte> getTeamColor(String team) {
|
||||
return Optional.ofNullable(teamColors.get(team));
|
||||
}
|
||||
public Optional<Byte> getTeamColor(String team) {
|
||||
return Optional.ofNullable(teamColors.get(team));
|
||||
}
|
||||
|
||||
public void addTeam(String team) {
|
||||
teams.computeIfAbsent(team, key -> new ArrayList<>());
|
||||
}
|
||||
public void addTeam(String team) {
|
||||
teams.computeIfAbsent(team, key -> new ArrayList<>());
|
||||
}
|
||||
|
||||
public void removeTeam(String team) {
|
||||
teams.remove(team);
|
||||
scoreTeams.remove(team);
|
||||
teamColors.remove(team);
|
||||
}
|
||||
public void removeTeam(String team) {
|
||||
teams.remove(team);
|
||||
scoreTeams.remove(team);
|
||||
teamColors.remove(team);
|
||||
teamNameTagVisibilities.remove(team);
|
||||
}
|
||||
|
||||
public boolean teamExists(String team) {
|
||||
return teams.containsKey(team);
|
||||
}
|
||||
public boolean teamExists(String team) {
|
||||
return teams.containsKey(team);
|
||||
}
|
||||
|
||||
public void removePlayerFromTeam(String player, String team) {
|
||||
List<String> teamPlayers = teams.get(team);
|
||||
if (teamPlayers != null) teamPlayers.remove(player);
|
||||
}
|
||||
public void removePlayerFromTeam(String player, String team) {
|
||||
List<String> teamPlayers = teams.get(team);
|
||||
if (teamPlayers != null) teamPlayers.remove(player);
|
||||
}
|
||||
|
||||
public boolean isPlayerInTeam(String player, String team) {
|
||||
List<String> teamPlayers = teams.get(team);
|
||||
return teamPlayers != null && teamPlayers.contains(player);
|
||||
}
|
||||
public boolean isPlayerInTeam(String player, String team) {
|
||||
List<String> teamPlayers = teams.get(team);
|
||||
return teamPlayers != null && teamPlayers.contains(player);
|
||||
}
|
||||
|
||||
public boolean isPlayerInTeam(String player) {
|
||||
for (List<String> teamPlayers : teams.values()) {
|
||||
if (teamPlayers.contains(player)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean isPlayerInTeam(String player) {
|
||||
for (List<String> teamPlayers : teams.values()) {
|
||||
if (teamPlayers.contains(player)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Optional<Byte> getPlayerTeamColor(String player) {
|
||||
Optional<String> team = getTeam(player);
|
||||
return team.isPresent() ? getTeamColor(team.get()) : Optional.empty();
|
||||
}
|
||||
public Optional<Byte> getPlayerTeamColor(String player) {
|
||||
Optional<String> team = getTeam(player);
|
||||
return team.isPresent() ? getTeamColor(team.get()) : Optional.empty();
|
||||
}
|
||||
|
||||
public Optional<String> getTeam(String player) {
|
||||
for (Map.Entry<String, List<String>> entry : teams.entrySet())
|
||||
if (entry.getValue().contains(player))
|
||||
return Optional.of(entry.getKey());
|
||||
return Optional.empty();
|
||||
}
|
||||
public Optional<String> getTeam(String player) {
|
||||
for (Map.Entry<String, List<String>> entry : teams.entrySet())
|
||||
if (entry.getValue().contains(player))
|
||||
return Optional.of(entry.getKey());
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public void addObjective(String name) {
|
||||
objectives.add(name);
|
||||
}
|
||||
public void setTeamNameTagVisibility(String team, String visibility) {
|
||||
teamNameTagVisibilities.put(team, visibility);
|
||||
}
|
||||
|
||||
public void removeObjective(String name) {
|
||||
objectives.remove(name);
|
||||
colorDependentSidebar.values().remove(name);
|
||||
if (name.equals(colorIndependentSidebar)) {
|
||||
colorIndependentSidebar = null;
|
||||
}
|
||||
}
|
||||
public String getTeamNameTagVisibility(String team) {
|
||||
return teamNameTagVisibilities.getOrDefault(team, "always");
|
||||
}
|
||||
|
||||
public boolean objectiveExists(String name) {
|
||||
return objectives.contains(name);
|
||||
}
|
||||
public boolean isNametagHidden(String username) {
|
||||
for (Map.Entry<String, List<String>> entry : teams.entrySet()) {
|
||||
if (entry.getValue().contains(username)) {
|
||||
return "never".equalsIgnoreCase(teamNameTagVisibilities.getOrDefault(entry.getKey(), "always"));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String sendTeamForScore(String score) {
|
||||
if (score.length() <= 16) return score;
|
||||
if (scoreTeams.containsKey(score)) return scoreTeams.get(score).name;
|
||||
int l = 16;
|
||||
int i = Math.min(16, score.length() - 16);
|
||||
String name = score.substring(i, i + l);
|
||||
while (scoreTeamNames.contains(name) || teams.containsKey(name)) {
|
||||
i--;
|
||||
while (score.length() - l - i > 16) {
|
||||
l--;
|
||||
if (l < 1) return score;
|
||||
i = Math.min(16, score.length() - l);
|
||||
}
|
||||
name = score.substring(i, i + l);
|
||||
}
|
||||
String prefix = score.substring(0, i);
|
||||
String suffix = i + l >= score.length() ? "" : score.substring(i + l);
|
||||
public List<String> getTeamMembers(String team) {
|
||||
return teams.getOrDefault(team, new ArrayList<>());
|
||||
}
|
||||
|
||||
ScoreTeam scoreTeam = new ScoreTeam(name, prefix, suffix);
|
||||
scoreTeams.put(score, scoreTeam);
|
||||
scoreTeamNames.add(name);
|
||||
public void addObjective(String name) {
|
||||
objectives.add(name);
|
||||
}
|
||||
|
||||
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, getUser());
|
||||
teamPacket.write(Types.STRING, name);
|
||||
teamPacket.write(Types.BYTE, (byte) 0);
|
||||
teamPacket.write(Types.STRING, "ViaRewind");
|
||||
teamPacket.write(Types.STRING, prefix);
|
||||
teamPacket.write(Types.STRING, suffix);
|
||||
teamPacket.write(Types.BYTE, (byte) 0);
|
||||
teamPacket.write(Types.SHORT, (short) 1);
|
||||
teamPacket.write(Types.STRING, name);
|
||||
teamPacket.send(Protocol1_8To1_7_6_10.class);
|
||||
public void removeObjective(String name) {
|
||||
objectives.remove(name);
|
||||
colorDependentSidebar.values().remove(name);
|
||||
if (name.equals(colorIndependentSidebar)) {
|
||||
colorIndependentSidebar = null;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
public boolean objectiveExists(String name) {
|
||||
return objectives.contains(name);
|
||||
}
|
||||
|
||||
public String removeTeamForScore(String score) {
|
||||
ScoreTeam scoreTeam = scoreTeams.remove(score);
|
||||
if (scoreTeam == null) return score;
|
||||
scoreTeamNames.remove(scoreTeam.name);
|
||||
public String sendTeamForScore(String score) {
|
||||
if (score.length() <= 16) return score;
|
||||
if (scoreTeams.containsKey(score)) return scoreTeams.get(score).name;
|
||||
|
||||
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, getUser());
|
||||
teamPacket.write(Types.STRING, scoreTeam.name);
|
||||
teamPacket.write(Types.BYTE, (byte) 1);
|
||||
teamPacket.send(Protocol1_8To1_7_6_10.class);
|
||||
// Find the longest window score[i, i+l) that:
|
||||
// - is not already claimed as a team name
|
||||
// - keeps prefix (score[0,i)) at most 16 chars i <= 16
|
||||
// - keeps suffix (score[i+l, end)) at most 16 chars score.length()-l-i <= 16
|
||||
for (int l = 16; l >= 1; l--) {
|
||||
final int iMax = Math.min(16, score.length() - l);
|
||||
final int iMin = Math.max(0, score.length() - l - 16);
|
||||
for (int i = iMax; i >= iMin; i--) {
|
||||
final String name = score.substring(i, i + l);
|
||||
if (scoreTeamNames.contains(name) || teams.containsKey(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return scoreTeam.name;
|
||||
}
|
||||
final String prefix = score.substring(0, i);
|
||||
final String suffix = i + l >= score.length() ? "" : score.substring(i + l);
|
||||
|
||||
public String getColorIndependentSidebar() {
|
||||
return this.colorIndependentSidebar;
|
||||
}
|
||||
final ScoreTeam scoreTeam = new ScoreTeam(name, prefix, suffix);
|
||||
scoreTeams.put(score, scoreTeam);
|
||||
scoreTeamNames.add(name);
|
||||
|
||||
public HashMap<Byte, String> getColorDependentSidebar() {
|
||||
return this.colorDependentSidebar;
|
||||
}
|
||||
final PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, getUser());
|
||||
teamPacket.write(Types.STRING, name);
|
||||
teamPacket.write(Types.BYTE, (byte) 0);
|
||||
teamPacket.write(Types.STRING, "ViaRewind");
|
||||
teamPacket.write(Types.STRING, prefix);
|
||||
teamPacket.write(Types.STRING, suffix);
|
||||
teamPacket.write(Types.BYTE, (byte) 0);
|
||||
teamPacket.write(Types.SHORT, (short) 1);
|
||||
teamPacket.write(Types.STRING, name);
|
||||
teamPacket.send(Protocol1_8To1_7_6_10.class);
|
||||
|
||||
public void setColorIndependentSidebar(String colorIndependentSidebar) {
|
||||
this.colorIndependentSidebar = colorIndependentSidebar;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ScoreTeam {
|
||||
private final String prefix;
|
||||
private final String suffix;
|
||||
private final String name;
|
||||
return score;
|
||||
}
|
||||
|
||||
public ScoreTeam(String name, String prefix, String suffix) {
|
||||
this.prefix = prefix;
|
||||
this.suffix = suffix;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
public String removeTeamForScore(String score) {
|
||||
ScoreTeam scoreTeam = scoreTeams.remove(score);
|
||||
if (scoreTeam == null) return score;
|
||||
scoreTeamNames.remove(scoreTeam.name);
|
||||
|
||||
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_PLAYER_TEAM, getUser());
|
||||
teamPacket.write(Types.STRING, scoreTeam.name);
|
||||
teamPacket.write(Types.BYTE, (byte) 1);
|
||||
teamPacket.send(Protocol1_8To1_7_6_10.class);
|
||||
|
||||
return scoreTeam.name;
|
||||
}
|
||||
|
||||
public String getColorIndependentSidebar() {
|
||||
return this.colorIndependentSidebar;
|
||||
}
|
||||
|
||||
public void setColorIndependentSidebar(String colorIndependentSidebar) {
|
||||
this.colorIndependentSidebar = colorIndependentSidebar;
|
||||
}
|
||||
|
||||
public HashMap<Byte, String> getColorDependentSidebar() {
|
||||
return this.colorDependentSidebar;
|
||||
}
|
||||
|
||||
private static class ScoreTeam {
|
||||
private final String prefix;
|
||||
private final String suffix;
|
||||
private final String name;
|
||||
|
||||
public ScoreTeam(String name, String prefix, String suffix) {
|
||||
this.prefix = prefix;
|
||||
this.suffix = suffix;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
+63
-63
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,87 +21,87 @@ import com.viaversion.viaversion.api.connection.StoredObject;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
|
||||
public class WorldBorderEmulator extends StoredObject {
|
||||
private double x, z;
|
||||
private double oldDiameter, newDiameter;
|
||||
private double x, z;
|
||||
private double oldDiameter, newDiameter;
|
||||
|
||||
private long lerpTime;
|
||||
private long lerpStartTime;
|
||||
private long lerpTime;
|
||||
private long lerpStartTime;
|
||||
|
||||
private boolean init = false;
|
||||
private boolean init = false;
|
||||
|
||||
public WorldBorderEmulator(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
public WorldBorderEmulator(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
public void init(double x, double z, double oldDiameter, double newDiameter, long lerpTime) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
public void init(double x, double z, double oldDiameter, double newDiameter, long lerpTime) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
|
||||
this.oldDiameter = oldDiameter;
|
||||
this.newDiameter = newDiameter;
|
||||
this.oldDiameter = oldDiameter;
|
||||
this.newDiameter = newDiameter;
|
||||
|
||||
this.lerpTime = lerpTime;
|
||||
this.lerpTime = lerpTime;
|
||||
|
||||
init = true;
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
|
||||
public void setCenter(double x, double z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
public void setCenter(double x, double z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public void lerpSize(double oldDiameter, double newDiameter, long lerpTime) {
|
||||
this.oldDiameter = oldDiameter;
|
||||
this.newDiameter = newDiameter;
|
||||
this.lerpTime = lerpTime;
|
||||
this.lerpStartTime = System.currentTimeMillis();
|
||||
}
|
||||
public void lerpSize(double oldDiameter, double newDiameter, long lerpTime) {
|
||||
this.oldDiameter = oldDiameter;
|
||||
this.newDiameter = newDiameter;
|
||||
this.lerpTime = lerpTime;
|
||||
this.lerpStartTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void setSize(double size) {
|
||||
this.oldDiameter = size;
|
||||
this.newDiameter = size;
|
||||
public double getSize() {
|
||||
if (lerpTime == 0) {
|
||||
return newDiameter;
|
||||
}
|
||||
|
||||
this.lerpTime = 0;
|
||||
}
|
||||
double percent = ((double) (System.currentTimeMillis() - lerpStartTime) / (double) (lerpTime));
|
||||
|
||||
public double getSize() {
|
||||
if (lerpTime == 0) {
|
||||
return newDiameter;
|
||||
}
|
||||
// Clamp value
|
||||
if (percent > 1.0D) percent = 1.0d;
|
||||
else if (percent < 0.0D) percent = 0.0d;
|
||||
|
||||
double percent = ((double) (System.currentTimeMillis() - lerpStartTime) / (double) (lerpTime));
|
||||
return oldDiameter + (newDiameter - oldDiameter) * percent;
|
||||
}
|
||||
|
||||
// Clamp value
|
||||
if (percent > 1.0D) percent = 1.0d;
|
||||
else if (percent < 0.0D) percent = 0.0d;
|
||||
public void setSize(double size) {
|
||||
this.oldDiameter = size;
|
||||
this.newDiameter = size;
|
||||
|
||||
return oldDiameter + (newDiameter - oldDiameter) * percent;
|
||||
}
|
||||
this.lerpTime = 0;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public boolean isInit() {
|
||||
return init;
|
||||
}
|
||||
public boolean isInit() {
|
||||
return init;
|
||||
}
|
||||
|
||||
public enum Side {
|
||||
NORTH(0, -1),
|
||||
EAST(1, 0),
|
||||
SOUTH(0, 1),
|
||||
WEST(-1, 0);
|
||||
public enum Side {
|
||||
NORTH(0, -1),
|
||||
EAST(1, 0),
|
||||
SOUTH(0, 1),
|
||||
WEST(-1, 0);
|
||||
|
||||
public final int modX;
|
||||
public final int modZ;
|
||||
public final int modX;
|
||||
public final int modZ;
|
||||
|
||||
Side(int modX, int modZ) {
|
||||
this.modX = modX;
|
||||
this.modZ = modZ;
|
||||
}
|
||||
}
|
||||
Side(int modX, int modZ) {
|
||||
this.modX = modX;
|
||||
this.modZ = modZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
+55
-53
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -26,70 +26,72 @@ import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class WorldBorderUpdateTask implements Runnable {
|
||||
public static final int VIEW_DISTANCE = 16;
|
||||
public static final int VIEW_DISTANCE = 16;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
|
||||
final WorldBorderEmulator worldBorderEmulatorTracker = connection.get(WorldBorderEmulator.class);
|
||||
if (!worldBorderEmulatorTracker.isInit()) continue;
|
||||
@Override
|
||||
public void run() {
|
||||
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
|
||||
final WorldBorderEmulator worldBorderEmulatorTracker = connection.get(WorldBorderEmulator.class);
|
||||
if (worldBorderEmulatorTracker == null) {
|
||||
continue;
|
||||
}
|
||||
if (!worldBorderEmulatorTracker.isInit()) continue;
|
||||
|
||||
final PlayerSessionStorage playerSession = connection.get(PlayerSessionStorage.class);
|
||||
final PlayerSessionStorage playerSession = connection.get(PlayerSessionStorage.class);
|
||||
|
||||
double radius = worldBorderEmulatorTracker.getSize() / 2.0;
|
||||
double radius = worldBorderEmulatorTracker.getSize() / 2.0;
|
||||
|
||||
for (WorldBorderEmulator.Side side : WorldBorderEmulator.Side.values()) {
|
||||
double d;
|
||||
double pos;
|
||||
double center;
|
||||
if (side.modX != 0) {
|
||||
pos = playerSession.getPosZ();
|
||||
center = worldBorderEmulatorTracker.getZ();
|
||||
d = Math.abs(worldBorderEmulatorTracker.getX() + radius * side.modX - playerSession.getPosX());
|
||||
} else {
|
||||
center = worldBorderEmulatorTracker.getX();
|
||||
pos = playerSession.getPosX();
|
||||
d = Math.abs(worldBorderEmulatorTracker.getZ() + radius * side.modZ - playerSession.getPosZ());
|
||||
}
|
||||
if (d >= VIEW_DISTANCE) continue;
|
||||
for (WorldBorderEmulator.Side side : WorldBorderEmulator.Side.values()) {
|
||||
double d;
|
||||
double pos;
|
||||
double center;
|
||||
if (side.modX != 0) {
|
||||
pos = playerSession.getPosZ();
|
||||
center = worldBorderEmulatorTracker.getZ();
|
||||
d = Math.abs(worldBorderEmulatorTracker.getX() + radius * side.modX - playerSession.getPosX());
|
||||
} else {
|
||||
center = worldBorderEmulatorTracker.getX();
|
||||
pos = playerSession.getPosX();
|
||||
d = Math.abs(worldBorderEmulatorTracker.getZ() + radius * side.modZ - playerSession.getPosZ());
|
||||
}
|
||||
if (d >= VIEW_DISTANCE) continue;
|
||||
|
||||
double r = Math.sqrt(VIEW_DISTANCE * VIEW_DISTANCE - d * d);
|
||||
double r = Math.sqrt(VIEW_DISTANCE * VIEW_DISTANCE - d * d);
|
||||
|
||||
double minH = Math.ceil(pos - r);
|
||||
double maxH = Math.floor(pos + r);
|
||||
double minV = Math.ceil(playerSession.getPosY() - r);
|
||||
double maxV = Math.floor(playerSession.getPosY() + r);
|
||||
double minH = Math.ceil(pos - r);
|
||||
double maxH = Math.floor(pos + r);
|
||||
double minV = Math.ceil(playerSession.getPosY() - r);
|
||||
double maxV = Math.floor(playerSession.getPosY() + r);
|
||||
|
||||
if (minH < center - radius) minH = Math.ceil(center - radius);
|
||||
if (maxH > center + radius) maxH = Math.floor(center + radius);
|
||||
if (minV < 0.0) minV = 0.0;
|
||||
if (minH < center - radius) minH = Math.ceil(center - radius);
|
||||
if (maxH > center + radius) maxH = Math.floor(center + radius);
|
||||
if (minV < 0.0) minV = 0.0;
|
||||
|
||||
double centerH = (minH + maxH) / 2.0;
|
||||
double centerV = (minV + maxV) / 2.0;
|
||||
double centerH = (minH + maxH) / 2.0;
|
||||
double centerV = (minV + maxV) / 2.0;
|
||||
|
||||
double particleOffset = 2.5;
|
||||
double particleOffset = 2.5;
|
||||
|
||||
final PacketWrapper spawnParticle = PacketWrapper.create(ClientboundPackets1_8.LEVEL_PARTICLES, connection);
|
||||
spawnParticle.write(Types.STRING, ViaRewind.getConfig().getWorldBorderParticle()); // particle name
|
||||
spawnParticle.write(Types.FLOAT, (float) (side.modX != 0 ? worldBorderEmulatorTracker.getX() + (radius * side.modX) : centerH)); // x
|
||||
spawnParticle.write(Types.FLOAT, (float) centerV); // y
|
||||
spawnParticle.write(Types.FLOAT, (float) (side.modX == 0 ? worldBorderEmulatorTracker.getZ() + (radius * side.modZ) : centerH)); // z
|
||||
spawnParticle.write(Types.FLOAT, (float) (side.modX != 0 ? 0f : (maxH - minH) / particleOffset)); // offset x
|
||||
spawnParticle.write(Types.FLOAT, (float) ((maxV - minV) / particleOffset)); // offset y
|
||||
spawnParticle.write(Types.FLOAT, (float) (side.modX == 0 ? 0f : (maxH - minH) / particleOffset)); // offset z
|
||||
spawnParticle.write(Types.FLOAT, 0F); // particle data
|
||||
spawnParticle.write(Types.INT, (int) Math.floor((maxH - minH) * (maxV - minV) * 0.5));
|
||||
final PacketWrapper spawnParticle = PacketWrapper.create(ClientboundPackets1_8.LEVEL_PARTICLES, connection);
|
||||
spawnParticle.write(Types.STRING, ViaRewind.getConfig().getWorldBorderParticle()); // particle name
|
||||
spawnParticle.write(Types.FLOAT, (float) (side.modX != 0 ? worldBorderEmulatorTracker.getX() + (radius * side.modX) : centerH)); // x
|
||||
spawnParticle.write(Types.FLOAT, (float) centerV); // y
|
||||
spawnParticle.write(Types.FLOAT, (float) (side.modX == 0 ? worldBorderEmulatorTracker.getZ() + (radius * side.modZ) : centerH)); // z
|
||||
spawnParticle.write(Types.FLOAT, (float) (side.modX != 0 ? 0f : (maxH - minH) / particleOffset)); // offset x
|
||||
spawnParticle.write(Types.FLOAT, (float) ((maxV - minV) / particleOffset)); // offset y
|
||||
spawnParticle.write(Types.FLOAT, (float) (side.modX == 0 ? 0f : (maxH - minH) / particleOffset)); // offset z
|
||||
spawnParticle.write(Types.FLOAT, 0F); // particle data
|
||||
spawnParticle.write(Types.INT, (int) Math.floor((maxH - minH) * (maxV - minV) * 0.5));
|
||||
|
||||
try {
|
||||
spawnParticle.send(Protocol1_8To1_7_6_10.class);
|
||||
} catch (Exception e) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send world border particle", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
spawnParticle.send(Protocol1_8To1_7_6_10.class);
|
||||
} catch (Exception e) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send world border particle", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
-63
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,94 +18,110 @@
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8;
|
||||
|
||||
import com.viaversion.viabackwards.api.BackwardsProtocol;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.data.RewindMappingData1_8;
|
||||
import com.viaversion.viarewind.api.data.RewindMappingData;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.provider.InventoryProvider;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.rewriter.BlockItemPacketRewriter1_9;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.rewriter.EntityPacketRewriter1_9;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.rewriter.*;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.*;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.rewriter.PlayerPacketRewriter1_9;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.rewriter.WorldPacketRewriter1_9;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.BlockPlaceDestroyTracker;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.BossBarStorage;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.CommandBlockStateStorage;
|
||||
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.viarewind.protocol.v1_9to1_8.storage.LastTitle;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.WindowTracker;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.task.CooldownIndicatorTask;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.task.LevitationUpdateTask;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolStorables;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ServerboundPackets1_8;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ServerboundPackets1_9;
|
||||
|
||||
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<>(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<>(Types.BYTE) {
|
||||
@Override
|
||||
public Byte transform(PacketWrapper packetWrapper, Float degrees) {
|
||||
return (byte) ((degrees / 360F) * 256);
|
||||
}
|
||||
};
|
||||
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) Math.round(inputValue * 32.0D);
|
||||
}
|
||||
};
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
public static final RewindMappingData1_8 MAPPINGS = new RewindMappingData1_8();
|
||||
public static final RewindMappingData MAPPINGS = new RewindMappingData("1.9", "1.8");
|
||||
|
||||
private final BlockItemPacketRewriter1_9 itemRewriter = new BlockItemPacketRewriter1_9(this);
|
||||
private final EntityPacketRewriter1_9 entityRewriter = new EntityPacketRewriter1_9(this);
|
||||
private final BlockItemPacketRewriter1_9 itemRewriter = new BlockItemPacketRewriter1_9(this);
|
||||
private final EntityPacketRewriter1_9 entityRewriter = new EntityPacketRewriter1_9(this);
|
||||
|
||||
public Protocol1_9To1_8() {
|
||||
super(ClientboundPackets1_9.class, ClientboundPackets1_8.class, ServerboundPackets1_9.class, ServerboundPackets1_8.class);
|
||||
}
|
||||
public Protocol1_9To1_8() {
|
||||
super(ClientboundPackets1_9.class, ClientboundPackets1_8.class, ServerboundPackets1_9.class, ServerboundPackets1_8.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
entityRewriter.register();
|
||||
itemRewriter.register();
|
||||
new PlayerPacketRewriter1_9(this).register();
|
||||
new WorldPacketRewriter1_9(this).register();
|
||||
}
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
entityRewriter.register();
|
||||
itemRewriter.register();
|
||||
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());
|
||||
@Override
|
||||
public void init(UserConnection connection) {
|
||||
final ProtocolStorables storables = connection.storables(this);
|
||||
storables.setEntityTracker(new EntityTracker1_9(connection));
|
||||
storables.setClientWorld(new ClientWorld());
|
||||
|
||||
connection.put(new WindowTracker(connection));
|
||||
connection.put(new LevitationStorage());
|
||||
connection.put(new PlayerPositionTracker());
|
||||
connection.put(new CooldownStorage());
|
||||
connection.put(new BlockPlaceDestroyTracker());
|
||||
connection.put(new BossBarStorage(connection));
|
||||
}
|
||||
connection.put(new WindowTracker(connection));
|
||||
connection.put(new LevitationStorage());
|
||||
connection.put(new PlayerPositionTracker());
|
||||
connection.put(new CooldownStorage());
|
||||
connection.put(new LastTitle());
|
||||
connection.put(new BlockPlaceDestroyTracker());
|
||||
connection.put(new BossBarStorage(connection));
|
||||
connection.put(new CommandBlockStateStorage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(ViaProviders providers) {
|
||||
Via.getManager().getScheduler().scheduleRepeating(new LevitationUpdateTask(), 0L, 50L, TimeUnit.MILLISECONDS);
|
||||
Via.getManager().getScheduler().scheduleRepeating(new CooldownIndicatorTask(), 0L, 50L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
@Override
|
||||
public void register(ViaProviders providers) {
|
||||
providers.register(InventoryProvider.class, new InventoryProvider());
|
||||
|
||||
@Override
|
||||
public RewindMappingData1_8 getMappingData() {
|
||||
return MAPPINGS;
|
||||
}
|
||||
Via.getManager().getScheduler().scheduleRepeating(new LevitationUpdateTask(), 0L, 50L, TimeUnit.MILLISECONDS);
|
||||
Via.getManager().getScheduler().scheduleRepeating(new CooldownIndicatorTask(), 0L, 50L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockItemPacketRewriter1_9 getItemRewriter() {
|
||||
return itemRewriter;
|
||||
}
|
||||
@Override
|
||||
public RewindMappingData getMappingData() {
|
||||
return MAPPINGS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPacketRewriter1_9 getEntityRewriter() {
|
||||
return entityRewriter;
|
||||
}
|
||||
@Override
|
||||
public BlockItemPacketRewriter1_9 getItemRewriter() {
|
||||
return itemRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMappingDataToLoad() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public EntityPacketRewriter1_9 getEntityRewriter() {
|
||||
return entityRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMappingDataToLoad() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+19
-19
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,26 +25,26 @@ import com.viaversion.viaversion.libs.gson.JsonPrimitive;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
|
||||
public class ActionBarVisualization implements CooldownVisualization {
|
||||
private final UserConnection user;
|
||||
private final UserConnection user;
|
||||
|
||||
public ActionBarVisualization(UserConnection user) {
|
||||
this.user = user;
|
||||
}
|
||||
public ActionBarVisualization(UserConnection user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(double progress) throws Exception {
|
||||
sendActionBar(CooldownVisualization.buildProgressText("■", progress));
|
||||
}
|
||||
@Override
|
||||
public void show(double progress) throws Exception {
|
||||
sendActionBar(CooldownVisualization.buildProgressText("■", progress));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() throws Exception {
|
||||
sendActionBar("§r");
|
||||
}
|
||||
@Override
|
||||
public void hide() throws Exception {
|
||||
sendActionBar("§r");
|
||||
}
|
||||
|
||||
private void sendActionBar(final String bar) {
|
||||
PacketWrapper actionBarPacket = PacketWrapper.create(ClientboundPackets1_8.CHAT, user);
|
||||
actionBarPacket.write(Types.COMPONENT, new JsonPrimitive(bar));
|
||||
actionBarPacket.write(Types.BYTE, (byte) 2); // Position - above hotbar
|
||||
actionBarPacket.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
private void sendActionBar(final String bar) {
|
||||
PacketWrapper actionBarPacket = PacketWrapper.create(ClientboundPackets1_8.CHAT, user);
|
||||
actionBarPacket.write(Types.COMPONENT, new JsonPrimitive(bar));
|
||||
actionBarPacket.write(Types.BYTE, (byte) 2); // Position - above hotbar
|
||||
actionBarPacket.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
}
|
||||
+36
-37
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,46 +23,45 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BossBarVisualization implements CooldownVisualization {
|
||||
private final UserConnection user;
|
||||
private UUID bossUUID;
|
||||
private final UserConnection user;
|
||||
private UUID bossUUID;
|
||||
|
||||
public BossBarVisualization(UserConnection user) {
|
||||
this.user = user;
|
||||
}
|
||||
public BossBarVisualization(UserConnection user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(double progress) throws Exception {
|
||||
final PacketWrapper setBossbar = PacketWrapper.create(ClientboundPackets1_9.BOSS_EVENT, user);
|
||||
if (bossUUID == null) {
|
||||
bossUUID = UUID.randomUUID();
|
||||
setBossbar.write(Types.UUID, bossUUID);
|
||||
setBossbar.write(Types.VAR_INT, 0); // Action - add
|
||||
setBossbar.write(Types.COMPONENT, new JsonPrimitive(" ")); // Title
|
||||
setBossbar.write(Types.FLOAT, (float) progress); // Health
|
||||
setBossbar.write(Types.VAR_INT, 0); // Color
|
||||
setBossbar.write(Types.VAR_INT, 0); // Division
|
||||
setBossbar.write(Types.UNSIGNED_BYTE, (short) 0); // Flags
|
||||
} else {
|
||||
setBossbar.write(Types.UUID, bossUUID);
|
||||
setBossbar.write(Types.VAR_INT, 2); // Action - update health
|
||||
setBossbar.write(Types.FLOAT, (float) progress); // Health
|
||||
}
|
||||
setBossbar.send(Protocol1_9To1_8.class, false);
|
||||
}
|
||||
@Override
|
||||
public void show(double progress) throws Exception {
|
||||
final PacketWrapper setBossbar = PacketWrapper.create(ClientboundPackets1_9.BOSS_EVENT, user);
|
||||
if (bossUUID == null) {
|
||||
bossUUID = UUID.randomUUID();
|
||||
setBossbar.write(Types.UUID, bossUUID);
|
||||
setBossbar.write(Types.VAR_INT, 0); // Action - add
|
||||
setBossbar.write(Types.COMPONENT, new JsonPrimitive(" ")); // Title
|
||||
setBossbar.write(Types.FLOAT, (float) progress); // Health
|
||||
setBossbar.write(Types.VAR_INT, 0); // Color
|
||||
setBossbar.write(Types.VAR_INT, 0); // Division
|
||||
setBossbar.write(Types.UNSIGNED_BYTE, (short) 0); // Flags
|
||||
} else {
|
||||
setBossbar.write(Types.UUID, bossUUID);
|
||||
setBossbar.write(Types.VAR_INT, 2); // Action - update health
|
||||
setBossbar.write(Types.FLOAT, (float) progress); // Health
|
||||
}
|
||||
setBossbar.send(Protocol1_9To1_8.class, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() throws Exception {
|
||||
if (bossUUID == null) {
|
||||
return;
|
||||
}
|
||||
final PacketWrapper removeBossbar = PacketWrapper.create(ClientboundPackets1_9.BOSS_EVENT, user);
|
||||
removeBossbar.write(Types.UUID, bossUUID);
|
||||
removeBossbar.write(Types.VAR_INT, 1); // Action - remove
|
||||
removeBossbar.send(Protocol1_9To1_8.class, false);
|
||||
bossUUID = null;
|
||||
}
|
||||
@Override
|
||||
public void hide() throws Exception {
|
||||
if (bossUUID == null) {
|
||||
return;
|
||||
}
|
||||
final PacketWrapper removeBossbar = PacketWrapper.create(ClientboundPackets1_9.BOSS_EVENT, user);
|
||||
removeBossbar.write(Types.UUID, bossUUID);
|
||||
removeBossbar.write(Types.VAR_INT, 1); // Action - remove
|
||||
removeBossbar.send(Protocol1_9To1_8.class, false);
|
||||
bossUUID = null;
|
||||
}
|
||||
}
|
||||
+33
-34
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,44 +22,43 @@ import com.viaversion.viarewind.api.ViaRewindConfig.CooldownIndicator;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
|
||||
public interface CooldownVisualization {
|
||||
void show(double progress) throws Exception;
|
||||
int MAX_PROGRESS_TEXT_LENGTH = 10;
|
||||
|
||||
void hide() throws Exception;
|
||||
static String buildProgressText(String symbol, double cooldown) {
|
||||
int green = (int) Math.floor(((double) MAX_PROGRESS_TEXT_LENGTH) * cooldown);
|
||||
int grey = MAX_PROGRESS_TEXT_LENGTH - green;
|
||||
StringBuilder builder = new StringBuilder("§8");
|
||||
while (green-- > 0) builder.append(symbol);
|
||||
builder.append("§7");
|
||||
while (grey-- > 0) builder.append(symbol);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
void show(double progress) throws Exception;
|
||||
|
||||
int MAX_PROGRESS_TEXT_LENGTH = 10;
|
||||
void hide() throws Exception;
|
||||
|
||||
static String buildProgressText(String symbol, double cooldown) {
|
||||
int green = (int) Math.floor(((double) MAX_PROGRESS_TEXT_LENGTH) * cooldown);
|
||||
int grey = MAX_PROGRESS_TEXT_LENGTH - green;
|
||||
StringBuilder builder = new StringBuilder("§8");
|
||||
while (green-- > 0) builder.append(symbol);
|
||||
builder.append("§7");
|
||||
while (grey-- > 0) builder.append(symbol);
|
||||
return builder.toString();
|
||||
}
|
||||
interface Factory {
|
||||
Factory DISABLED = user -> new DisabledCooldownVisualization();
|
||||
|
||||
interface Factory {
|
||||
CooldownVisualization create(UserConnection user);
|
||||
static Factory fromConfiguration() {
|
||||
try {
|
||||
return fromIndicator(ViaRewind.getConfig().getCooldownIndicator());
|
||||
} catch (IllegalArgumentException e) {
|
||||
ViaRewind.getPlatform().getLogger().warning("Invalid cooldown-indicator setting");
|
||||
return DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
static Factory fromConfiguration() {
|
||||
try {
|
||||
return fromIndicator(ViaRewind.getConfig().getCooldownIndicator());
|
||||
} catch (IllegalArgumentException e) {
|
||||
ViaRewind.getPlatform().getLogger().warning("Invalid cooldown-indicator setting");
|
||||
return DISABLED;
|
||||
}
|
||||
}
|
||||
static Factory fromIndicator(CooldownIndicator indicator) {
|
||||
return switch (indicator) {
|
||||
case TITLE -> TitleCooldownVisualization::new;
|
||||
case BOSS_BAR -> BossBarVisualization::new;
|
||||
case ACTION_BAR -> ActionBarVisualization::new;
|
||||
case DISABLED -> DISABLED;
|
||||
};
|
||||
}
|
||||
|
||||
static Factory fromIndicator(CooldownIndicator indicator) {
|
||||
return switch (indicator) {
|
||||
case TITLE -> TitleCooldownVisualization::new;
|
||||
case BOSS_BAR -> BossBarVisualization::new;
|
||||
case ACTION_BAR -> ActionBarVisualization::new;
|
||||
case DISABLED -> DISABLED;
|
||||
};
|
||||
}
|
||||
|
||||
Factory DISABLED = user -> new DisabledCooldownVisualization();
|
||||
}
|
||||
CooldownVisualization create(UserConnection user);
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,12 +19,12 @@ package com.viaversion.viarewind.protocol.v1_9to1_8.cooldown;
|
||||
|
||||
public class DisabledCooldownVisualization implements CooldownVisualization {
|
||||
|
||||
@Override
|
||||
public void show(double progress) {
|
||||
}
|
||||
@Override
|
||||
public void show(double progress) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
}
|
||||
@Override
|
||||
public void hide() {
|
||||
}
|
||||
|
||||
}
|
||||
+77
-32
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,50 +18,95 @@
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.cooldown;
|
||||
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.LastTitle;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TitleCooldownVisualization implements CooldownVisualization {
|
||||
|
||||
private static final int ACTION_SET_TITLE = 0;
|
||||
private static final int ACTION_SET_SUBTITLE = 1;
|
||||
private static final int ACTION_SET_TIMES_AND_DISPLAY = 2;
|
||||
private static final int ACTION_HIDE = 3;
|
||||
public static final int ACTION_SET_TITLE = 0;
|
||||
public static final int ACTION_SET_SUBTITLE = 1;
|
||||
public static final int ACTION_SET_TIMES_AND_DISPLAY = 2;
|
||||
public static final int ACTION_HIDE = 3;
|
||||
public static final int ACTION_RESET = 4;
|
||||
|
||||
private final UserConnection user;
|
||||
private final UserConnection user;
|
||||
private boolean visible;
|
||||
|
||||
public TitleCooldownVisualization(UserConnection user) {
|
||||
this.user = user;
|
||||
}
|
||||
public TitleCooldownVisualization(UserConnection user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(double progress) throws Exception {
|
||||
final String text = CooldownVisualization.buildProgressText("˙", progress);
|
||||
@Override
|
||||
public void show(double progress) throws Exception {
|
||||
final LastTitle title = this.user.get(LastTitle.class);
|
||||
if (this.visible && title.isVisible()) {
|
||||
this.restoreTitle(title);
|
||||
return;
|
||||
}
|
||||
|
||||
sendTitlePacket(ACTION_SET_TITLE, wrapper -> wrapper.write(Types.COMPONENT, new JsonPrimitive("")));
|
||||
sendTitlePacket(ACTION_SET_SUBTITLE, wrapper -> wrapper.write(Types.COMPONENT, new JsonPrimitive(text)));
|
||||
sendTitlePacket(ACTION_SET_TIMES_AND_DISPLAY, wrapper -> {
|
||||
wrapper.write(Types.INT, 0);
|
||||
wrapper.write(Types.INT, 2);
|
||||
wrapper.write(Types.INT, 5);
|
||||
});
|
||||
}
|
||||
final PacketWrapper setTitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
|
||||
setTitle.write(Types.VAR_INT, ACTION_SET_TITLE);
|
||||
setTitle.write(Types.COMPONENT, new JsonPrimitive(""));
|
||||
setTitle.send(Protocol1_9To1_8.class);
|
||||
|
||||
@Override
|
||||
public void hide() throws Exception {
|
||||
sendTitlePacket(ACTION_HIDE, wrapper -> {});
|
||||
}
|
||||
final PacketWrapper setSubtitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
|
||||
setSubtitle.write(Types.VAR_INT, ACTION_SET_SUBTITLE);
|
||||
setSubtitle.write(Types.COMPONENT, new JsonPrimitive(CooldownVisualization.buildProgressText("˙", progress)));
|
||||
setSubtitle.send(Protocol1_9To1_8.class);
|
||||
|
||||
private void sendTitlePacket(int action, Consumer<PacketWrapper> writer) {
|
||||
final PacketWrapper title = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
|
||||
title.write(Types.VAR_INT, action);
|
||||
writer.accept(title);
|
||||
title.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
final PacketWrapper setTitleTimes = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
|
||||
setTitleTimes.write(Types.VAR_INT, ACTION_SET_TIMES_AND_DISPLAY);
|
||||
setTitleTimes.write(Types.INT, 0);
|
||||
setTitleTimes.write(Types.INT, 2);
|
||||
setTitleTimes.write(Types.INT, 5);
|
||||
setTitleTimes.send(Protocol1_9To1_8.class);
|
||||
this.visible = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() throws Exception {
|
||||
if (!this.visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
final LastTitle title = this.user.get(LastTitle.class);
|
||||
if (title.isVisible()) {
|
||||
this.restoreTitle(title);
|
||||
return;
|
||||
}
|
||||
|
||||
final PacketWrapper hideTitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
|
||||
hideTitle.write(Types.VAR_INT, ACTION_HIDE);
|
||||
hideTitle.send(Protocol1_9To1_8.class);
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
private void restoreTitle(final LastTitle title) {
|
||||
final PacketWrapper setTitleTimes = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
|
||||
setTitleTimes.write(Types.VAR_INT, ACTION_SET_TIMES_AND_DISPLAY);
|
||||
final int[] times = title.remainingTimes();
|
||||
setTitleTimes.write(Types.INT, times[0]);
|
||||
setTitleTimes.write(Types.INT, times[1]);
|
||||
setTitleTimes.write(Types.INT, times[2]);
|
||||
setTitleTimes.send(Protocol1_9To1_8.class);
|
||||
|
||||
if (title.subtitle() != null) {
|
||||
final PacketWrapper setSubtitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
|
||||
setSubtitle.write(Types.VAR_INT, ACTION_SET_SUBTITLE);
|
||||
setSubtitle.write(Types.COMPONENT, title.subtitle());
|
||||
setSubtitle.send(Protocol1_9To1_8.class);
|
||||
}
|
||||
|
||||
final PacketWrapper setTitle = PacketWrapper.create(ClientboundPackets1_8.SET_TITLES, user);
|
||||
setTitle.write(Types.VAR_INT, ACTION_SET_TITLE);
|
||||
setTitle.write(Types.COMPONENT, title.title());
|
||||
setTitle.send(Protocol1_9To1_8.class);
|
||||
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.data;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.NumberTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
|
||||
public final class CommandBlockState {
|
||||
|
||||
public static final int COMMAND_BLOCK_COMMAND_LIMIT = 32500;
|
||||
|
||||
private static final String IMPULSE = "IMPULSE";
|
||||
private static final String REPEAT = "REPEAT";
|
||||
private static final String CHAIN = "CHAIN";
|
||||
private static final String CONDITIONAL = "CONDITIONAL";
|
||||
private static final String UNCONDITIONAL = "UNCONDITIONAL";
|
||||
private static final String ALWAYS_ACTIVE = "ALWAYSACTIVE";
|
||||
private static final String REDSTONE = "REDSTONE";
|
||||
|
||||
private CommandBlockState() {
|
||||
}
|
||||
|
||||
public static boolean isCommandBlock(final int blockState) {
|
||||
return isImpulse(blockState) || isRepeat(blockState) || isChain(blockState);
|
||||
}
|
||||
|
||||
public static void decorateCommand(final CompoundTag tag, final int blockState) {
|
||||
if (tag == null || !isCommandBlock(blockState)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final StringTag commandTag = tag.getStringTag("Command");
|
||||
if (commandTag == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Mode mode = mode(blockState);
|
||||
final boolean conditional = (blockState & 8) != 0;
|
||||
final boolean automatic = booleanTag(tag, "auto");
|
||||
if (mode == Mode.REDSTONE && !conditional && !automatic) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String prefix = mode.prefix + ' ' + (conditional ? CONDITIONAL : UNCONDITIONAL) + ' ' + (automatic ? ALWAYS_ACTIVE : REDSTONE) + ' ';
|
||||
final String command = commandTag.getValue();
|
||||
if (!parseDecoratedCommand(command).prefixed() && prefix.length() + command.length() <= COMMAND_BLOCK_COMMAND_LIMIT) {
|
||||
commandTag.setValue(prefix + command);
|
||||
}
|
||||
}
|
||||
|
||||
public static ParsedCommand parseDecoratedCommand(final String command) {
|
||||
final int first = command.indexOf(' ');
|
||||
if (first == -1) {
|
||||
return ParsedCommand.defaultState(command);
|
||||
}
|
||||
final int second = command.indexOf(' ', first + 1);
|
||||
if (second == -1) {
|
||||
return ParsedCommand.defaultState(command);
|
||||
}
|
||||
final int third = command.indexOf(' ', second + 1);
|
||||
if (third == -1) {
|
||||
return ParsedCommand.defaultState(command);
|
||||
}
|
||||
|
||||
final Mode mode = Mode.fromPrefix(command.substring(0, first));
|
||||
if (mode == null) {
|
||||
return ParsedCommand.defaultState(command);
|
||||
}
|
||||
|
||||
final String conditionalToken = command.substring(first + 1, second);
|
||||
final boolean conditional;
|
||||
if (CONDITIONAL.equalsIgnoreCase(conditionalToken)) {
|
||||
conditional = true;
|
||||
} else if (UNCONDITIONAL.equalsIgnoreCase(conditionalToken)) {
|
||||
conditional = false;
|
||||
} else {
|
||||
return ParsedCommand.defaultState(command);
|
||||
}
|
||||
|
||||
final String automaticToken = command.substring(second + 1, third);
|
||||
final boolean automatic;
|
||||
if (ALWAYS_ACTIVE.equalsIgnoreCase(automaticToken)) {
|
||||
automatic = true;
|
||||
} else if (REDSTONE.equalsIgnoreCase(automaticToken)) {
|
||||
automatic = false;
|
||||
} else {
|
||||
return ParsedCommand.defaultState(command);
|
||||
}
|
||||
|
||||
return new ParsedCommand(command.substring(third + 1), mode.serverName, conditional, automatic, true);
|
||||
}
|
||||
|
||||
private static boolean booleanTag(final CompoundTag tag, final String key) {
|
||||
final NumberTag numberTag = tag.getNumberTag(key);
|
||||
return numberTag != null && numberTag.asByte() != 0;
|
||||
}
|
||||
|
||||
private static Mode mode(final int blockState) {
|
||||
if (isRepeat(blockState)) {
|
||||
return Mode.AUTO;
|
||||
}
|
||||
if (isChain(blockState)) {
|
||||
return Mode.SEQUENCE;
|
||||
}
|
||||
return Mode.REDSTONE;
|
||||
}
|
||||
|
||||
private static boolean isImpulse(final int blockState) {
|
||||
return blockState >= 2192 && blockState <= 2207;
|
||||
}
|
||||
|
||||
private static boolean isRepeat(final int blockState) {
|
||||
return blockState >= 3360 && blockState <= 3375;
|
||||
}
|
||||
|
||||
private static boolean isChain(final int blockState) {
|
||||
return blockState >= 3376 && blockState <= 3391;
|
||||
}
|
||||
|
||||
public record ParsedCommand(String command, String mode, boolean conditional, boolean automatic, boolean prefixed) {
|
||||
|
||||
private static ParsedCommand defaultState(final String command) {
|
||||
return new ParsedCommand(command, Mode.REDSTONE.serverName, false, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
private enum Mode {
|
||||
REDSTONE(IMPULSE, "REDSTONE"),
|
||||
AUTO(REPEAT, "AUTO"),
|
||||
SEQUENCE(CHAIN, "SEQUENCE");
|
||||
|
||||
private final String prefix;
|
||||
private final String serverName;
|
||||
|
||||
Mode(final String prefix, final String serverName) {
|
||||
this.prefix = prefix;
|
||||
this.serverName = serverName;
|
||||
}
|
||||
|
||||
private static Mode fromPrefix(final String prefix) {
|
||||
for (final Mode mode : values()) {
|
||||
if (mode.prefix.equalsIgnoreCase(prefix)) {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
-43
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,49 +21,49 @@ import java.util.HashMap;
|
||||
|
||||
public class EffectIdMappings1_8 {
|
||||
|
||||
private static final HashMap<Integer, Integer> effects = new HashMap<>();
|
||||
private static final HashMap<Integer, Integer> effects = new HashMap<>();
|
||||
|
||||
static {
|
||||
effects.put(1003, 1002);
|
||||
effects.put(1005, 1003);
|
||||
effects.put(1006, 1003);
|
||||
effects.put(1007, 1003);
|
||||
effects.put(1008, 1003);
|
||||
effects.put(1009, 1004);
|
||||
effects.put(1010, 1005);
|
||||
effects.put(1011, 1006);
|
||||
effects.put(1012, 1006);
|
||||
effects.put(1013, 1006);
|
||||
effects.put(1014, 1006);
|
||||
effects.put(1015, 1007);
|
||||
effects.put(1016, 1008);
|
||||
effects.put(1017, 1008);
|
||||
effects.put(1018, 1009);
|
||||
effects.put(1019, 1010);
|
||||
effects.put(1020, 1011);
|
||||
effects.put(1021, 1012);
|
||||
effects.put(1022, 1012);
|
||||
effects.put(1023, 1013);
|
||||
effects.put(1024, 1014);
|
||||
effects.put(1025, 1015);
|
||||
effects.put(1026, 1016);
|
||||
effects.put(1027, 1017);
|
||||
effects.put(1028, 1018);
|
||||
effects.put(1029, 1020);
|
||||
effects.put(1030, 1021);
|
||||
effects.put(1031, 1022);
|
||||
effects.put(1032, -1);
|
||||
effects.put(1033, -1);
|
||||
effects.put(1034, -1);
|
||||
effects.put(1035, -1);
|
||||
effects.put(1036, 1003);
|
||||
effects.put(1037, 1006);
|
||||
static {
|
||||
effects.put(1003, 1002);
|
||||
effects.put(1005, 1003);
|
||||
effects.put(1006, 1003);
|
||||
effects.put(1007, 1003);
|
||||
effects.put(1008, 1003);
|
||||
effects.put(1009, 1004);
|
||||
effects.put(1010, 1005);
|
||||
effects.put(1011, 1006);
|
||||
effects.put(1012, 1006);
|
||||
effects.put(1013, 1006);
|
||||
effects.put(1014, 1006);
|
||||
effects.put(1015, 1007);
|
||||
effects.put(1016, 1008);
|
||||
effects.put(1017, 1008);
|
||||
effects.put(1018, 1009);
|
||||
effects.put(1019, 1010);
|
||||
effects.put(1020, 1011);
|
||||
effects.put(1021, 1012);
|
||||
effects.put(1022, 1012);
|
||||
effects.put(1023, 1013);
|
||||
effects.put(1024, 1014);
|
||||
effects.put(1025, 1015);
|
||||
effects.put(1026, 1016);
|
||||
effects.put(1027, 1017);
|
||||
effects.put(1028, 1018);
|
||||
effects.put(1029, 1020);
|
||||
effects.put(1030, 1021);
|
||||
effects.put(1031, 1022);
|
||||
effects.put(1032, -1);
|
||||
effects.put(1033, -1);
|
||||
effects.put(1034, -1);
|
||||
effects.put(1035, -1);
|
||||
effects.put(1036, 1003);
|
||||
effects.put(1037, 1006);
|
||||
|
||||
effects.put(3000, -1);
|
||||
effects.put(3001, -1);
|
||||
}
|
||||
effects.put(3000, -1);
|
||||
effects.put(3001, -1);
|
||||
}
|
||||
|
||||
public static int getOldId(int id) {
|
||||
return effects.getOrDefault(id, id);
|
||||
}
|
||||
public static int getOldId(int id) {
|
||||
return effects.getOrDefault(id, id);
|
||||
}
|
||||
}
|
||||
+22
-23
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,35 +21,34 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_9;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.data.EntityDataIndex1_9;
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
|
||||
public class EntityDataIndex1_8 {
|
||||
|
||||
private static final HashMap<Pair<EntityTypes1_9.EntityType, Integer>, EntityDataIndex1_9> ENTITY_DATA_REWRITES = new HashMap<>();
|
||||
private static final HashMap<Pair<EntityTypes1_9.EntityType, Integer>, EntityDataIndex1_9> ENTITY_DATA_REWRITES = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (EntityDataIndex1_9 index : EntityDataIndex1_9.values()) {
|
||||
ENTITY_DATA_REWRITES.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
|
||||
}
|
||||
}
|
||||
static {
|
||||
for (EntityDataIndex1_9 index : EntityDataIndex1_9.values()) {
|
||||
ENTITY_DATA_REWRITES.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
|
||||
}
|
||||
}
|
||||
|
||||
private static Optional<EntityDataIndex1_9> getIndex(final EntityType type, final int index) {
|
||||
final Pair<EntityType, Integer> pair = new Pair<>(type, index);
|
||||
return Optional.ofNullable(ENTITY_DATA_REWRITES.get(pair));
|
||||
}
|
||||
private static Optional<EntityDataIndex1_9> getIndex(final EntityType type, final int index) {
|
||||
final Pair<EntityType, Integer> pair = new Pair<>(type, index);
|
||||
return Optional.ofNullable(ENTITY_DATA_REWRITES.get(pair));
|
||||
}
|
||||
|
||||
public static EntityDataIndex1_9 searchIndex(final EntityType type, final int index) {
|
||||
EntityType currentType = type;
|
||||
do {
|
||||
final Optional<EntityDataIndex1_9> optMeta = getIndex(currentType, index);
|
||||
if (optMeta.isPresent()) {
|
||||
return optMeta.get();
|
||||
}
|
||||
currentType = currentType.getParent();
|
||||
} while (currentType != null);
|
||||
return null;
|
||||
}
|
||||
public static EntityDataIndex1_9 searchIndex(final EntityType type, final int index) {
|
||||
EntityType currentType = type;
|
||||
do {
|
||||
final Optional<EntityDataIndex1_9> optMeta = getIndex(currentType, index);
|
||||
if (optMeta.isPresent()) {
|
||||
return optMeta.get();
|
||||
}
|
||||
currentType = currentType.getParent();
|
||||
} while (currentType != null);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+53
-54
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,63 +18,62 @@
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.data;
|
||||
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.data.PotionIdMappings1_9;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
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<>();
|
||||
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); // Map new potion to similar one (luck->leaping)
|
||||
static {
|
||||
POTION_NAME_TO_ID.putAll(PotionIdMappings1_9.POTION_NAME_TO_ID);
|
||||
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");
|
||||
POTION_NAME_INDEX.put("thick", "§rThick Potion");
|
||||
POTION_NAME_INDEX.put("awkward", "§rAwkward Potion");
|
||||
POTION_NAME_INDEX.put("water_splash", "§rSplash Water Bottle");
|
||||
POTION_NAME_INDEX.put("mundane_splash", "§rMundane Splash Potion");
|
||||
POTION_NAME_INDEX.put("thick_splash", "§rThick Splash Potion");
|
||||
POTION_NAME_INDEX.put("awkward_splash", "§rAwkward Splash Potion");
|
||||
POTION_NAME_INDEX.put("water_lingering", "§rLingering Water Bottle");
|
||||
POTION_NAME_INDEX.put("mundane_lingering", "§rMundane Lingering Potion");
|
||||
POTION_NAME_INDEX.put("thick_lingering", "§rThick Lingering Potion");
|
||||
POTION_NAME_INDEX.put("awkward_lingering", "§rAwkward Lingering Potion");
|
||||
POTION_NAME_INDEX.put("night_vision_lingering", "§rLingering Potion of Night Vision");
|
||||
POTION_NAME_INDEX.put("long_night_vision_lingering", "§rLingering Potion of Night Vision");
|
||||
POTION_NAME_INDEX.put("invisibility_lingering", "§rLingering Potion of Invisibility");
|
||||
POTION_NAME_INDEX.put("long_invisibility_lingering", "§rLingering Potion of Invisibility");
|
||||
POTION_NAME_INDEX.put("leaping_lingering", "§rLingering Potion of Leaping");
|
||||
POTION_NAME_INDEX.put("long_leaping_lingering", "§rLingering Potion of Leaping");
|
||||
POTION_NAME_INDEX.put("strong_leaping_lingering", "§rLingering Potion of Leaping");
|
||||
POTION_NAME_INDEX.put("fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
|
||||
POTION_NAME_INDEX.put("long_fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
|
||||
POTION_NAME_INDEX.put("swiftness_lingering", "§rLingering Potion of Swiftness");
|
||||
POTION_NAME_INDEX.put("long_swiftness_lingering", "§rLingering Potion of Swiftness");
|
||||
POTION_NAME_INDEX.put("strong_swiftness_lingering", "§rLingering Potion of Swiftness");
|
||||
POTION_NAME_INDEX.put("slowness_lingering", "§rLingering Potion of Slowness");
|
||||
POTION_NAME_INDEX.put("long_slowness_lingering", "§rLingering Potion of Slowness");
|
||||
POTION_NAME_INDEX.put("water_breathing_lingering", "§rLingering Potion of Water Breathing");
|
||||
POTION_NAME_INDEX.put("long_water_breathing_lingering", "§rLingering Potion of Water Breathing");
|
||||
POTION_NAME_INDEX.put("healing_lingering", "§rLingering Potion of Healing");
|
||||
POTION_NAME_INDEX.put("strong_healing_lingering", "§rLingering Potion of Healing");
|
||||
POTION_NAME_INDEX.put("harming_lingering", "§rLingering Potion of Harming");
|
||||
POTION_NAME_INDEX.put("strong_harming_lingering", "§rLingering Potion of Harming");
|
||||
POTION_NAME_INDEX.put("poison_lingering", "§rLingering Potion of Poisen");
|
||||
POTION_NAME_INDEX.put("long_poison_lingering", "§rLingering Potion of Poisen");
|
||||
POTION_NAME_INDEX.put("strong_poison_lingering", "§rLingering Potion of Poisen");
|
||||
POTION_NAME_INDEX.put("regeneration_lingering", "§rLingering Potion of Regeneration");
|
||||
POTION_NAME_INDEX.put("long_regeneration_lingering", "§rLingering Potion of Regeneration");
|
||||
POTION_NAME_INDEX.put("strong_regeneration_lingering", "§rLingering Potion of Regeneration");
|
||||
POTION_NAME_INDEX.put("strength_lingering", "§rLingering Potion of Strength");
|
||||
POTION_NAME_INDEX.put("long_strength_lingering", "§rLingering Potion of Strength");
|
||||
POTION_NAME_INDEX.put("strong_strength_lingering", "§rLingering Potion of Strength");
|
||||
POTION_NAME_INDEX.put("weakness_lingering", "§rLingering Potion of Weakness");
|
||||
POTION_NAME_INDEX.put("long_weakness_lingering", "§rLingering Potion of Weakness");
|
||||
POTION_NAME_INDEX.put("luck_lingering", "§rLingering Potion of Luck");
|
||||
POTION_NAME_INDEX.put("luck", "§rPotion of Luck");
|
||||
POTION_NAME_INDEX.put("luck_splash", "§rSplash Potion of Luck");
|
||||
}
|
||||
POTION_NAME_INDEX.put("water", "§rWater Bottle");
|
||||
POTION_NAME_INDEX.put("mundane", "§rMundane Potion");
|
||||
POTION_NAME_INDEX.put("thick", "§rThick Potion");
|
||||
POTION_NAME_INDEX.put("awkward", "§rAwkward Potion");
|
||||
POTION_NAME_INDEX.put("water_splash", "§rSplash Water Bottle");
|
||||
POTION_NAME_INDEX.put("mundane_splash", "§rMundane Splash Potion");
|
||||
POTION_NAME_INDEX.put("thick_splash", "§rThick Splash Potion");
|
||||
POTION_NAME_INDEX.put("awkward_splash", "§rAwkward Splash Potion");
|
||||
POTION_NAME_INDEX.put("water_lingering", "§rLingering Water Bottle");
|
||||
POTION_NAME_INDEX.put("mundane_lingering", "§rMundane Lingering Potion");
|
||||
POTION_NAME_INDEX.put("thick_lingering", "§rThick Lingering Potion");
|
||||
POTION_NAME_INDEX.put("awkward_lingering", "§rAwkward Lingering Potion");
|
||||
POTION_NAME_INDEX.put("night_vision_lingering", "§rLingering Potion of Night Vision");
|
||||
POTION_NAME_INDEX.put("long_night_vision_lingering", "§rLingering Potion of Night Vision");
|
||||
POTION_NAME_INDEX.put("invisibility_lingering", "§rLingering Potion of Invisibility");
|
||||
POTION_NAME_INDEX.put("long_invisibility_lingering", "§rLingering Potion of Invisibility");
|
||||
POTION_NAME_INDEX.put("leaping_lingering", "§rLingering Potion of Leaping");
|
||||
POTION_NAME_INDEX.put("long_leaping_lingering", "§rLingering Potion of Leaping");
|
||||
POTION_NAME_INDEX.put("strong_leaping_lingering", "§rLingering Potion of Leaping");
|
||||
POTION_NAME_INDEX.put("fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
|
||||
POTION_NAME_INDEX.put("long_fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
|
||||
POTION_NAME_INDEX.put("swiftness_lingering", "§rLingering Potion of Swiftness");
|
||||
POTION_NAME_INDEX.put("long_swiftness_lingering", "§rLingering Potion of Swiftness");
|
||||
POTION_NAME_INDEX.put("strong_swiftness_lingering", "§rLingering Potion of Swiftness");
|
||||
POTION_NAME_INDEX.put("slowness_lingering", "§rLingering Potion of Slowness");
|
||||
POTION_NAME_INDEX.put("long_slowness_lingering", "§rLingering Potion of Slowness");
|
||||
POTION_NAME_INDEX.put("water_breathing_lingering", "§rLingering Potion of Water Breathing");
|
||||
POTION_NAME_INDEX.put("long_water_breathing_lingering", "§rLingering Potion of Water Breathing");
|
||||
POTION_NAME_INDEX.put("healing_lingering", "§rLingering Potion of Healing");
|
||||
POTION_NAME_INDEX.put("strong_healing_lingering", "§rLingering Potion of Healing");
|
||||
POTION_NAME_INDEX.put("harming_lingering", "§rLingering Potion of Harming");
|
||||
POTION_NAME_INDEX.put("strong_harming_lingering", "§rLingering Potion of Harming");
|
||||
POTION_NAME_INDEX.put("poison_lingering", "§rLingering Potion of Poisen");
|
||||
POTION_NAME_INDEX.put("long_poison_lingering", "§rLingering Potion of Poisen");
|
||||
POTION_NAME_INDEX.put("strong_poison_lingering", "§rLingering Potion of Poisen");
|
||||
POTION_NAME_INDEX.put("regeneration_lingering", "§rLingering Potion of Regeneration");
|
||||
POTION_NAME_INDEX.put("long_regeneration_lingering", "§rLingering Potion of Regeneration");
|
||||
POTION_NAME_INDEX.put("strong_regeneration_lingering", "§rLingering Potion of Regeneration");
|
||||
POTION_NAME_INDEX.put("strength_lingering", "§rLingering Potion of Strength");
|
||||
POTION_NAME_INDEX.put("long_strength_lingering", "§rLingering Potion of Strength");
|
||||
POTION_NAME_INDEX.put("strong_strength_lingering", "§rLingering Potion of Strength");
|
||||
POTION_NAME_INDEX.put("weakness_lingering", "§rLingering Potion of Weakness");
|
||||
POTION_NAME_INDEX.put("long_weakness_lingering", "§rLingering Potion of Weakness");
|
||||
POTION_NAME_INDEX.put("luck_lingering", "§rLingering Potion of Luck");
|
||||
POTION_NAME_INDEX.put("luck", "§rPotion of Luck");
|
||||
POTION_NAME_INDEX.put("luck_splash", "§rSplash Potion of Luck");
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.data;
|
||||
|
||||
import com.viaversion.viarewind.api.data.RewindMappingDataLoader;
|
||||
import com.viaversion.viaversion.libs.fastutil.objects.ObjectArrayList;
|
||||
import com.viaversion.viaversion.libs.fastutil.objects.ObjectList;
|
||||
import com.viaversion.viaversion.libs.gson.JsonArray;
|
||||
import com.viaversion.viaversion.libs.gson.JsonElement;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
|
||||
public final class RewindMappingData1_8 extends com.viaversion.viarewind.api.data.RewindMappingData {
|
||||
|
||||
private final ObjectList<String> sounds = new ObjectArrayList<>();
|
||||
|
||||
public RewindMappingData1_8() {
|
||||
super("1.9.4", "1.8");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadExtras(CompoundTag data) {
|
||||
super.loadExtras(data);
|
||||
|
||||
final JsonArray sounds = RewindMappingDataLoader.INSTANCE.loadData("sounds-1.9.json").getAsJsonArray("sounds");
|
||||
for (final JsonElement sound : sounds) {
|
||||
this.sounds.add(sound.getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
public String soundName(final int soundId) {
|
||||
return sounds.get(soundId);
|
||||
}
|
||||
}
|
||||
+184
-182
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,224 +28,226 @@ 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 java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class WitherBossBar implements BossBar {
|
||||
|
||||
private static int highestId = Integer.MAX_VALUE - 10000;
|
||||
private static int highestId = Integer.MAX_VALUE - 10000;
|
||||
|
||||
private final UUID uuid;
|
||||
private String title;
|
||||
private float health;
|
||||
private boolean visible = false;
|
||||
private final UUID uuid;
|
||||
private final UserConnection connection;
|
||||
private final int entityId = highestId++;
|
||||
private String title;
|
||||
private float health;
|
||||
private boolean visible = false;
|
||||
private double locX, locY, locZ;
|
||||
|
||||
private final UserConnection connection;
|
||||
public WitherBossBar(UserConnection connection, UUID uuid, String title, float health) {
|
||||
this.connection = connection;
|
||||
this.uuid = uuid;
|
||||
this.title = title;
|
||||
this.health = health;
|
||||
}
|
||||
|
||||
private final int entityId = highestId++;
|
||||
private double locX, locY, locZ;
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public WitherBossBar(UserConnection connection, UUID uuid, String title, float health) {
|
||||
this.connection = connection;
|
||||
this.uuid = uuid;
|
||||
this.title = title;
|
||||
this.health = health;
|
||||
}
|
||||
@Override
|
||||
public BossBar setTitle(String title) {
|
||||
this.title = title;
|
||||
if (this.visible) {
|
||||
updateEntityData();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
@Override
|
||||
public float getHealth() {
|
||||
return health;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar setTitle(String title) {
|
||||
this.title = title;
|
||||
if (this.visible) {
|
||||
updateEntityData();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public BossBar setHealth(float health) {
|
||||
this.health = health;
|
||||
if (this.health <= 0) {
|
||||
this.health = 0.0001f;
|
||||
}
|
||||
if (this.visible) {
|
||||
updateEntityData();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getHealth() {
|
||||
return health;
|
||||
}
|
||||
@Override
|
||||
public BossColor getColor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar setHealth(float health) {
|
||||
this.health = health;
|
||||
if (this.health <= 0) {
|
||||
this.health = 0.0001f;
|
||||
}
|
||||
if (this.visible) {
|
||||
updateEntityData();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public BossBar setColor(BossColor bossColor) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support color");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossColor getColor() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public BossStyle getStyle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar setColor(BossColor bossColor) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support color");
|
||||
}
|
||||
@Override
|
||||
public BossBar setStyle(BossStyle bossStyle) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support styles");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossStyle getStyle() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public BossBar addPlayer(UUID uuid) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar setStyle(BossStyle bossStyle) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support styles");
|
||||
}
|
||||
@Override
|
||||
public BossBar addConnection(UserConnection userConnection) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar addPlayer(UUID uuid) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
@Override
|
||||
public BossBar removePlayer(UUID uuid) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar addConnection(UserConnection userConnection) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
@Override
|
||||
public BossBar removeConnection(UserConnection userConnection) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar removePlayer(UUID uuid) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
@Override
|
||||
public BossBar addFlag(BossFlag bossFlag) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support flags");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar removeConnection(UserConnection userConnection) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
@Override
|
||||
public BossBar removeFlag(BossFlag bossFlag) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support flags");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar addFlag(BossFlag bossFlag) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support flags");
|
||||
}
|
||||
@Override
|
||||
public boolean hasFlag(BossFlag bossFlag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar removeFlag(BossFlag bossFlag) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support flags");
|
||||
}
|
||||
@Override
|
||||
public Set<UUID> getPlayers() {
|
||||
return Collections.singleton(connection.getProtocolInfo().getUuid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFlag(BossFlag bossFlag) {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public Set<UserConnection> getConnections() {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getPlayers() {
|
||||
return Collections.singleton(connection.getProtocolInfo().getUuid());
|
||||
}
|
||||
@Override
|
||||
public BossBar show() {
|
||||
if (!this.visible) {
|
||||
addWither();
|
||||
this.visible = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UserConnection> getConnections() {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
|
||||
}
|
||||
@Override
|
||||
public BossBar hide() {
|
||||
if (this.visible) {
|
||||
removeWither();
|
||||
this.visible = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar show() {
|
||||
if (!this.visible) {
|
||||
addWither();
|
||||
this.visible = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar hide() {
|
||||
if (this.visible) {
|
||||
removeWither();
|
||||
this.visible = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public UUID getId() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
public void setLocation(double x, double y, double z) {
|
||||
locX = x;
|
||||
locY = y;
|
||||
locZ = z;
|
||||
updateLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getId() {
|
||||
return this.uuid;
|
||||
}
|
||||
private void addWither() {
|
||||
final PacketWrapper addMob = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_MOB, this.connection);
|
||||
addMob.write(Types.VAR_INT, entityId);
|
||||
addMob.write(Types.UNSIGNED_BYTE, (short) 64);
|
||||
addMob.write(Types.INT, (int) (locX * 32D));
|
||||
addMob.write(Types.INT, (int) (locY * 32D));
|
||||
addMob.write(Types.INT, (int) (locZ * 32D));
|
||||
addMob.write(Types.BYTE, (byte) 0);
|
||||
addMob.write(Types.BYTE, (byte) 0);
|
||||
addMob.write(Types.BYTE, (byte) 0);
|
||||
addMob.write(Types.SHORT, (short) 0);
|
||||
addMob.write(Types.SHORT, (short) 0);
|
||||
addMob.write(Types.SHORT, (short) 0);
|
||||
|
||||
public void setLocation(double x, double y, double z) {
|
||||
locX = x;
|
||||
locY = y;
|
||||
locZ = z;
|
||||
updateLocation();
|
||||
}
|
||||
final List<EntityData> entityData = new ArrayList<>();
|
||||
entityData.add(new EntityData(0, EntityDataTypes1_8.BYTE, (byte) 0x20));
|
||||
entityData.add(new EntityData(2, EntityDataTypes1_8.STRING, title));
|
||||
entityData.add(new EntityData(3, EntityDataTypes1_8.BYTE, (byte) 1));
|
||||
entityData.add(new EntityData(6, EntityDataTypes1_8.FLOAT, health * 300f));
|
||||
entityData.add(new EntityData(20, EntityDataTypes1_8.INT, 880));
|
||||
|
||||
private void addWither() {
|
||||
final PacketWrapper addMob = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_MOB, this.connection);
|
||||
addMob.write(Types.VAR_INT, entityId);
|
||||
addMob.write(Types.UNSIGNED_BYTE, (short) 64);
|
||||
addMob.write(Types.INT, (int) (locX * 32D));
|
||||
addMob.write(Types.INT, (int) (locY * 32D));
|
||||
addMob.write(Types.INT, (int) (locZ * 32D));
|
||||
addMob.write(Types.BYTE, (byte) 0);
|
||||
addMob.write(Types.BYTE, (byte) 0);
|
||||
addMob.write(Types.BYTE, (byte) 0);
|
||||
addMob.write(Types.SHORT, (short) 0);
|
||||
addMob.write(Types.SHORT, (short) 0);
|
||||
addMob.write(Types.SHORT, (short) 0);
|
||||
addMob.write(Types.ENTITY_DATA_LIST1_8, entityData);
|
||||
addMob.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
|
||||
final List<EntityData> entityData = new ArrayList<>();
|
||||
entityData.add(new EntityData(0, EntityDataTypes1_8.BYTE, (byte) 0x20));
|
||||
entityData.add(new EntityData(2, EntityDataTypes1_8.STRING, title));
|
||||
entityData.add(new EntityData(3, EntityDataTypes1_8.BYTE, (byte) 1));
|
||||
entityData.add(new EntityData(6, EntityDataTypes1_8.FLOAT, health * 300f));
|
||||
private void updateLocation() {
|
||||
final PacketWrapper teleportEntity = PacketWrapper.create(ClientboundPackets1_7_2_5.TELEPORT_ENTITY, this.connection);
|
||||
teleportEntity.write(Types.VAR_INT, entityId);
|
||||
teleportEntity.write(Types.INT, (int) (locX * 32D));
|
||||
teleportEntity.write(Types.INT, (int) (locY * 32D));
|
||||
teleportEntity.write(Types.INT, (int) (locZ * 32D));
|
||||
teleportEntity.write(Types.BYTE, (byte) 0);
|
||||
teleportEntity.write(Types.BYTE, (byte) 0);
|
||||
teleportEntity.write(Types.BOOLEAN, false);
|
||||
teleportEntity.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
|
||||
addMob.write(Types.ENTITY_DATA_LIST1_8, entityData);
|
||||
addMob.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
private void updateEntityData() {
|
||||
final PacketWrapper setEntityData = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_DATA, this.connection);
|
||||
setEntityData.write(Types.VAR_INT, entityId);
|
||||
|
||||
private void updateLocation() {
|
||||
final PacketWrapper teleportEntity = PacketWrapper.create(ClientboundPackets1_7_2_5.TELEPORT_ENTITY, this.connection);
|
||||
teleportEntity.write(Types.VAR_INT, entityId);
|
||||
teleportEntity.write(Types.INT, (int) (locX * 32D));
|
||||
teleportEntity.write(Types.INT, (int) (locY * 32D));
|
||||
teleportEntity.write(Types.INT, (int) (locZ * 32D));
|
||||
teleportEntity.write(Types.BYTE, (byte) 0);
|
||||
teleportEntity.write(Types.BYTE, (byte) 0);
|
||||
teleportEntity.write(Types.BOOLEAN, false);
|
||||
teleportEntity.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
final List<EntityData> entityData = new ArrayList<>();
|
||||
entityData.add(new EntityData(2, EntityDataTypes1_8.STRING, title));
|
||||
entityData.add(new EntityData(6, EntityDataTypes1_8.FLOAT, health * 300f));
|
||||
|
||||
private void updateEntityData() {
|
||||
final PacketWrapper setEntityData = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_DATA, this.connection);
|
||||
setEntityData.write(Types.VAR_INT, entityId);
|
||||
setEntityData.write(Types.ENTITY_DATA_LIST1_8, entityData);
|
||||
setEntityData.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
|
||||
final List<EntityData> entityData = new ArrayList<>();
|
||||
entityData.add(new EntityData(2, EntityDataTypes1_8.STRING, title));
|
||||
entityData.add(new EntityData(6, EntityDataTypes1_8.FLOAT, health * 300f));
|
||||
private void removeWither() {
|
||||
final PacketWrapper removeEntity = PacketWrapper.create(ClientboundPackets1_7_2_5.REMOVE_ENTITIES, this.connection);
|
||||
removeEntity.write(Types.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
|
||||
removeEntity.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
|
||||
setEntityData.write(Types.ENTITY_DATA_LIST1_8, entityData);
|
||||
setEntityData.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
public void setPlayerLocation(double posX, double posY, double posZ, float yaw, float pitch) {
|
||||
double yawR = Math.toRadians(yaw);
|
||||
double pitchR = Math.toRadians(pitch);
|
||||
|
||||
private void removeWither() {
|
||||
final PacketWrapper removeEntity = PacketWrapper.create(ClientboundPackets1_7_2_5.REMOVE_ENTITIES, this.connection);
|
||||
removeEntity.write(Types.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
|
||||
removeEntity.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
posX -= Math.cos(pitchR) * Math.sin(yawR) * 48;
|
||||
posY -= Math.sin(pitchR) * 48;
|
||||
posZ += Math.cos(pitchR) * Math.cos(yawR) * 48;
|
||||
|
||||
public void setPlayerLocation(double posX, double posY, double posZ, float yaw, float pitch) {
|
||||
double yawR = Math.toRadians(yaw);
|
||||
double pitchR = Math.toRadians(pitch);
|
||||
|
||||
posX -= Math.cos(pitchR) * Math.sin(yawR) * 48;
|
||||
posY -= Math.sin(pitchR) * 48;
|
||||
posZ += Math.cos(pitchR) * Math.cos(yawR) * 48;
|
||||
|
||||
setLocation(posX, posY, posZ);
|
||||
}
|
||||
setLocation(posX, posY, posZ);
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.provider;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.platform.providers.Provider;
|
||||
|
||||
public class InventoryProvider implements Provider {
|
||||
|
||||
public boolean hasElytra(final UserConnection connection) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+359
-260
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,324 +17,423 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.rewriter;
|
||||
|
||||
import com.viaversion.nbt.tag.ByteTag;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.IntTag;
|
||||
import com.viaversion.nbt.tag.ListTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
|
||||
import com.viaversion.viarewind.api.rewriter.VRBlockItemRewriter;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.data.PotionIdMappings1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.CommandBlockStateStorage;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.WindowTracker;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.nbt.tag.*;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.data.EntityIds1_8;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.data.PotionIdMappings1_9;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ServerboundPackets1_8;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class BlockItemPacketRewriter1_9 extends VRBlockItemRewriter<ClientboundPackets1_9, ServerboundPackets1_8, Protocol1_9To1_8> {
|
||||
|
||||
public final Set<String> VALID_ATTRIBUTES = new HashSet<>();
|
||||
public final Set<String> VALID_ATTRIBUTES = new HashSet<>();
|
||||
|
||||
private LegacyEnchantmentRewriter enchantmentRewriter;
|
||||
private LegacyEnchantmentRewriter enchantmentRewriter;
|
||||
|
||||
public BlockItemPacketRewriter1_9(Protocol1_9To1_8 protocol) {
|
||||
super(protocol, "1.9");
|
||||
public BlockItemPacketRewriter1_9(Protocol1_9To1_8 protocol) {
|
||||
super(protocol, "1.9");
|
||||
|
||||
VALID_ATTRIBUTES.add("generic.maxHealth");
|
||||
VALID_ATTRIBUTES.add("generic.followRange");
|
||||
VALID_ATTRIBUTES.add("generic.knockbackResistance");
|
||||
VALID_ATTRIBUTES.add("generic.movementSpeed");
|
||||
VALID_ATTRIBUTES.add("generic.attackDamage");
|
||||
VALID_ATTRIBUTES.add("horse.jumpStrength");
|
||||
VALID_ATTRIBUTES.add("zombie.spawnReinforcements");
|
||||
}
|
||||
VALID_ATTRIBUTES.add("generic.maxHealth");
|
||||
VALID_ATTRIBUTES.add("generic.followRange");
|
||||
VALID_ATTRIBUTES.add("generic.knockbackResistance");
|
||||
VALID_ATTRIBUTES.add("generic.movementSpeed");
|
||||
VALID_ATTRIBUTES.add("generic.attackDamage");
|
||||
VALID_ATTRIBUTES.add("horse.jumpStrength");
|
||||
VALID_ATTRIBUTES.add("zombie.spawnReinforcements");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
registerBlockChange(ClientboundPackets1_9.BLOCK_UPDATE);
|
||||
registerMultiBlockChange(ClientboundPackets1_9.CHUNK_BLOCKS_UPDATE);
|
||||
registerSetCreativeModeSlot(ServerboundPackets1_8.SET_CREATIVE_MODE_SLOT);
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_UPDATE, wrapper -> {
|
||||
final BlockPosition position = wrapper.passthrough(Types.BLOCK_POSITION1_8);
|
||||
final int blockState = wrapper.passthrough(Types.VAR_INT);
|
||||
wrapper.user().get(CommandBlockStateStorage.class).storeOrRemove(position, blockState);
|
||||
wrapper.set(Types.VAR_INT, 0, handleBlockId(blockState));
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_CLOSE, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CHUNK_BLOCKS_UPDATE, wrapper -> {
|
||||
final int chunkX = wrapper.passthrough(Types.INT);
|
||||
final int chunkZ = wrapper.passthrough(Types.INT);
|
||||
final BlockChangeRecord[] records = wrapper.passthrough(Types.BLOCK_CHANGE_ARRAY);
|
||||
final CommandBlockStateStorage storage = wrapper.user().get(CommandBlockStateStorage.class);
|
||||
|
||||
final WindowTracker tracker = wrapper.user().get(WindowTracker.class);
|
||||
for (BlockChangeRecord record : records) {
|
||||
final int blockState = record.getBlockId();
|
||||
final BlockPosition position = new BlockPosition((chunkX << 4) + record.getSectionX(), record.getY(), (chunkZ << 4) + record.getSectionZ());
|
||||
storage.storeOrRemove(position, blockState);
|
||||
record.setBlockId(handleBlockId(blockState));
|
||||
}
|
||||
});
|
||||
registerSetCreativeModeSlot(ServerboundPackets1_8.SET_CREATIVE_MODE_SLOT);
|
||||
|
||||
final String windowType = tracker.get(windowId);
|
||||
if (windowType != null && windowType.equalsIgnoreCase("minecraft:enchanting_table")) {
|
||||
tracker.clearEnchantmentProperties();
|
||||
}
|
||||
tracker.remove(windowId);
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_CLOSE, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.OPEN_SCREEN, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
final String windowType = wrapper.passthrough(Types.STRING);
|
||||
final WindowTracker tracker = wrapper.user().get(WindowTracker.class);
|
||||
|
||||
wrapper.user().get(WindowTracker.class).put(windowId, windowType);
|
||||
});
|
||||
final String windowType = tracker.get(windowId);
|
||||
if (windowType != null && windowType.equalsIgnoreCase("minecraft:enchanting_table")) {
|
||||
tracker.clearEnchantmentProperties();
|
||||
}
|
||||
tracker.remove(windowId);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_SET_CONTENT, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
protocol.registerClientbound(ClientboundPackets1_9.OPEN_SCREEN, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
final String windowType = wrapper.passthrough(Types.STRING);
|
||||
wrapper.passthrough(Types.COMPONENT); // title
|
||||
final short slotCount = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
|
||||
Item[] items = wrapper.read(Types.ITEM1_8_SHORT_ARRAY);
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
items[i] = handleItemToClient(wrapper.user(), items[i]);
|
||||
}
|
||||
final WindowTracker tracker = wrapper.user().get(WindowTracker.class);
|
||||
tracker.put(windowId, windowType);
|
||||
tracker.openWindow(windowId, windowType, slotCount);
|
||||
});
|
||||
|
||||
if (windowId == 0 && items.length == 46) {
|
||||
Item[] old = items;
|
||||
items = new Item[45];
|
||||
System.arraycopy(old, 0, items, 0, 45);
|
||||
} else {
|
||||
final String type = wrapper.user().get(WindowTracker.class).get(windowId);
|
||||
if (type != null && type.equalsIgnoreCase("minecraft:brewing_stand")) {
|
||||
System.arraycopy(items, 0, wrapper.user().get(WindowTracker.class).getBrewingItems(windowId), 0, 4);
|
||||
WindowTracker.updateBrewingStand(wrapper.user(), items[4], windowId);
|
||||
Item[] old = items;
|
||||
items = new Item[old.length - 1];
|
||||
System.arraycopy(old, 0, items, 0, 4);
|
||||
System.arraycopy(old, 5, items, 4, old.length - 5);
|
||||
}
|
||||
}
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_SET_CONTENT, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
|
||||
wrapper.write(Types.ITEM1_8_SHORT_ARRAY, items);
|
||||
});
|
||||
Item[] items = wrapper.read(Types.ITEM1_8_SHORT_ARRAY);
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
items[i] = handleItemToClient(wrapper.user(), items[i]);
|
||||
}
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_SET_SLOT, wrapper -> {
|
||||
final byte windowId = wrapper.passthrough(Types.BYTE);
|
||||
final short slot = wrapper.passthrough(Types.SHORT);
|
||||
final Item item = wrapper.passthrough(Types.ITEM1_8);
|
||||
if (windowId == 0 && items.length == 46) {
|
||||
Item[] old = items;
|
||||
items = new Item[45];
|
||||
System.arraycopy(old, 0, items, 0, 45);
|
||||
} else {
|
||||
final String type = wrapper.user().get(WindowTracker.class).get(windowId);
|
||||
if (type != null && type.equalsIgnoreCase("minecraft:brewing_stand")) {
|
||||
System.arraycopy(items, 0, wrapper.user().get(WindowTracker.class).getBrewingItems(windowId), 0, 4);
|
||||
WindowTracker.updateBrewingStand(wrapper.user(), items[4], windowId);
|
||||
Item[] old = items;
|
||||
items = new Item[old.length - 1];
|
||||
System.arraycopy(old, 0, items, 0, 4);
|
||||
System.arraycopy(old, 5, items, 4, old.length - 5);
|
||||
}
|
||||
}
|
||||
|
||||
handleItemToClient(wrapper.user(), item);
|
||||
if (windowId == 0 && slot == 45) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
final WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
|
||||
final String windowType = windowTracker.get(windowId);
|
||||
if (windowType != null && windowType.equalsIgnoreCase("minecraft:brewing_stand")) {
|
||||
if (slot > 4) {
|
||||
wrapper.set(Types.SHORT, 0, (short) (slot - 1));
|
||||
} else if (slot == 4) {
|
||||
wrapper.cancel();
|
||||
WindowTracker.updateBrewingStand(wrapper.user(), wrapper.get(Types.ITEM1_8, 0), windowId);
|
||||
} else {
|
||||
windowTracker.getBrewingItems(windowId)[slot] = wrapper.get(Types.ITEM1_8, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
wrapper.write(Types.ITEM1_8_SHORT_ARRAY, items);
|
||||
});
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_8.CONTAINER_CLOSE, wrapper -> {
|
||||
final byte windowId = wrapper.passthrough(Types.BYTE);
|
||||
wrapper.user().get(WindowTracker.class).remove(windowId);
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_SET_SLOT, wrapper -> {
|
||||
final byte windowId = wrapper.passthrough(Types.BYTE);
|
||||
final short slot = wrapper.passthrough(Types.SHORT);
|
||||
final Item item = wrapper.passthrough(Types.ITEM1_8);
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_8.CONTAINER_CLICK, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE); // Window id
|
||||
map(Types.SHORT); // Slot
|
||||
map(Types.BYTE); // Button
|
||||
map(Types.SHORT); // Action number
|
||||
map(Types.BYTE, Types.VAR_INT); // Mode
|
||||
map(Types.ITEM1_8); // Clicked item
|
||||
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Types.ITEM1_8, 0)));
|
||||
handler(wrapper -> {
|
||||
final byte windowId = wrapper.get(Types.BYTE, 0);
|
||||
final String windowType = wrapper.user().get(WindowTracker.class).get(windowId);
|
||||
handleItemToClient(wrapper.user(), item);
|
||||
if (windowId == -2) {
|
||||
// 1.8 has no window -2 (set a player-inv slot by raw index, ignoring the open container) — retarget it.
|
||||
final WindowTracker tracker = wrapper.user().get(WindowTracker.class);
|
||||
final short openWindow = tracker.openWindowId();
|
||||
if (openWindow != 0) {
|
||||
// Foreign container open: 1.8 only applies player-inv changes through it (main=size.., hotbar=size+27..).
|
||||
final int size = tracker.openWindowSize();
|
||||
final int containerSlot;
|
||||
if (slot >= 0 && slot <= 8) {
|
||||
containerSlot = size + 27 + slot;
|
||||
} else if (slot >= 9 && slot <= 35) {
|
||||
containerSlot = size + slot - 9;
|
||||
} else { // armor/offhand: no slot in a foreign container
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
wrapper.set(Types.BYTE, 0, (byte) openWindow);
|
||||
wrapper.set(Types.SHORT, 0, (short) containerSlot);
|
||||
return;
|
||||
}
|
||||
|
||||
if (windowType != null && windowType.equalsIgnoreCase("minecraft:brewing_stand")) {
|
||||
final short slot = wrapper.get(Types.SHORT, 0);
|
||||
if (slot > 3) {
|
||||
wrapper.set(Types.SHORT, 0, (short) (slot + 1));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// Otherwise window 0 with the menu slot.
|
||||
final int windowSlot;
|
||||
if (slot >= 0 && slot <= 8) {
|
||||
windowSlot = slot + 36;
|
||||
} else if (slot >= 9 && slot <= 35) {
|
||||
windowSlot = slot;
|
||||
} else if (slot >= 36 && slot <= 39) {
|
||||
windowSlot = 44 - slot;
|
||||
} else { // offhand/body/saddle: no 1.8 equivalent
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
wrapper.set(Types.BYTE, 0, (byte) 0);
|
||||
wrapper.set(Types.SHORT, 0, (short) windowSlot);
|
||||
return;
|
||||
}
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_SET_DATA, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
short key = wrapper.read(Types.SHORT);
|
||||
short value = wrapper.read(Types.SHORT);
|
||||
if (windowId == 0 && slot == 45) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
final WindowTracker tracker = wrapper.user().get(WindowTracker.class);
|
||||
final String windowType = tracker.get(windowId);
|
||||
if (windowType != null && windowType.equalsIgnoreCase("minecraft:enchanting_table")) {
|
||||
if (key >= 4 && key <= 6) { // Store enchantment ids
|
||||
tracker.putEnchantmentProperty(key, value);
|
||||
wrapper.cancel();
|
||||
} else if (key >= 7 && key <= 9) { // Mix levels with tracked ids
|
||||
key -= 3;
|
||||
final short property = tracker.getEnchantmentValue(key);
|
||||
value = (short) (property | (value << 8));
|
||||
}
|
||||
}
|
||||
wrapper.write(Types.SHORT, key);
|
||||
wrapper.write(Types.SHORT, value);
|
||||
});
|
||||
}
|
||||
final WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
|
||||
final String windowType = windowTracker.get(windowId);
|
||||
if (windowType != null && windowType.equalsIgnoreCase("minecraft:brewing_stand")) {
|
||||
if (slot > 4) {
|
||||
wrapper.set(Types.SHORT, 0, (short) (slot - 1));
|
||||
} else if (slot == 4) {
|
||||
wrapper.cancel();
|
||||
WindowTracker.updateBrewingStand(wrapper.user(), wrapper.get(Types.ITEM1_8, 0), windowId);
|
||||
} else {
|
||||
windowTracker.getBrewingItems(windowId)[slot] = wrapper.get(Types.ITEM1_8, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
protected void registerRewrites() {
|
||||
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName());
|
||||
enchantmentRewriter.registerEnchantment(9, "§7Frost Walker");
|
||||
enchantmentRewriter.registerEnchantment(70, "§7Mending");
|
||||
}
|
||||
protocol.registerServerbound(ServerboundPackets1_8.CONTAINER_CLOSE, wrapper -> {
|
||||
final byte windowId = wrapper.passthrough(Types.BYTE);
|
||||
wrapper.user().get(WindowTracker.class).remove(windowId);
|
||||
});
|
||||
|
||||
@Override
|
||||
public Item handleItemToClient(UserConnection connection, Item item) {
|
||||
if (item == null) return null;
|
||||
super.handleItemToClient(connection, item);
|
||||
protocol.registerServerbound(ServerboundPackets1_8.CONTAINER_CLICK, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE); // Window id
|
||||
map(Types.SHORT); // Slot
|
||||
map(Types.BYTE); // Button
|
||||
map(Types.SHORT); // Action number
|
||||
map(Types.BYTE, Types.VAR_INT); // Mode
|
||||
map(Types.ITEM1_8); // Clicked item
|
||||
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Types.ITEM1_8, 0)));
|
||||
handler(wrapper -> {
|
||||
final byte windowId = wrapper.get(Types.BYTE, 0);
|
||||
final String windowType = wrapper.user().get(WindowTracker.class).get(windowId);
|
||||
|
||||
CompoundTag tag = item.tag();
|
||||
enchantmentRewriter.handleToClient(item);
|
||||
if (windowType != null && windowType.equalsIgnoreCase("minecraft:brewing_stand")) {
|
||||
final short slot = wrapper.get(Types.SHORT, 0);
|
||||
if (slot > 3) {
|
||||
wrapper.set(Types.SHORT, 0, (short) (slot + 1));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
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");
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_SET_DATA, wrapper -> {
|
||||
final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE);
|
||||
short key = wrapper.read(Types.SHORT);
|
||||
short value = wrapper.read(Types.SHORT);
|
||||
|
||||
if (displayTag == null) { // Remove the display tag again if it was only added to emulate unbreakable
|
||||
tag.put("display", displayTag = new CompoundTag());
|
||||
tag.put(nbtTagName() + "|noDisplay", new ByteTag(true));
|
||||
}
|
||||
final WindowTracker tracker = wrapper.user().get(WindowTracker.class);
|
||||
final String windowType = tracker.get(windowId);
|
||||
if (windowType != null && windowType.equalsIgnoreCase("minecraft:enchanting_table")) {
|
||||
if (key >= 4 && key <= 6) { // Store enchantment ids
|
||||
tracker.putEnchantmentProperty(key, value);
|
||||
wrapper.cancel();
|
||||
} else if (key >= 7 && key <= 9) { // Mix levels with tracked ids
|
||||
key -= 3;
|
||||
final short property = tracker.getEnchantmentValue(key);
|
||||
value = (short) (property | (value << 8));
|
||||
}
|
||||
}
|
||||
wrapper.write(Types.SHORT, key);
|
||||
wrapper.write(Types.SHORT, value);
|
||||
});
|
||||
}
|
||||
|
||||
ListTag<StringTag> loreTag = displayTag.getListTag("Lore", StringTag.class);
|
||||
if (loreTag == null) {
|
||||
displayTag.put("Lore", loreTag = new ListTag<>(StringTag.class));
|
||||
}
|
||||
loreTag.add(new StringTag("§9Unbreakable"));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void registerRewrites() {
|
||||
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName());
|
||||
enchantmentRewriter.registerEnchantment(9, "§7Frost Walker");
|
||||
enchantmentRewriter.registerEnchantment(70, "§7Mending");
|
||||
}
|
||||
|
||||
if (item.identifier() == 383 && item.data() == 0) { // Spawn eggs
|
||||
int data = 0;
|
||||
final CompoundTag entityTag = tag == null ? null : tag.getCompoundTag("EntityTag");
|
||||
if (entityTag != null) {
|
||||
final StringTag idTag = entityTag.getStringTag("id");
|
||||
if (idTag != null) {
|
||||
final String id = idTag.getValue();
|
||||
if (EntityIds1_8.ENTITY_NAME_TO_ID.containsKey(id)) {
|
||||
data = EntityIds1_8.ENTITY_NAME_TO_ID.get(id);
|
||||
} else if (displayTag == null) {
|
||||
tag.put("display", displayTag = new CompoundTag());
|
||||
tag.put(nbtTagName() + "|noDisplay", new ByteTag(true));
|
||||
displayTag.put("Name", new StringTag("§rSpawn " + id));
|
||||
}
|
||||
}
|
||||
}
|
||||
item.setData((short) data);
|
||||
}
|
||||
@Override
|
||||
public Item handleItemToClient(UserConnection connection, Item item) {
|
||||
if (item == null) return null;
|
||||
final int originalId = item.identifier();
|
||||
super.handleItemToClient(connection, item);
|
||||
|
||||
// Potion, splash potion, lingering potion
|
||||
final boolean potion = item.identifier() == 373;
|
||||
final boolean splashPotion = item.identifier() == 438;
|
||||
final boolean lingeringPotion = item.identifier() == 441;
|
||||
CompoundTag tag = item.tag();
|
||||
enchantmentRewriter.handleToClient(item);
|
||||
|
||||
if (potion || splashPotion || lingeringPotion) {
|
||||
int data = 0;
|
||||
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)) {
|
||||
data = PotionIdMappings1_8.POTION_NAME_TO_ID.get(potionName);
|
||||
}
|
||||
if (splashPotion) {
|
||||
potionName += "_splash";
|
||||
} else if (lingeringPotion) {
|
||||
potionName += "_lingering";
|
||||
}
|
||||
// Don't override custom name
|
||||
if ((displayTag == null || !displayTag.contains("Name")) && PotionIdMappings1_8.POTION_NAME_INDEX.containsKey(potionName)) {
|
||||
tag.put("display", displayTag = new CompoundTag());
|
||||
tag.put(nbtTagName() + "|noDisplay", new ByteTag(true));
|
||||
displayTag.put("Name", new StringTag(PotionIdMappings1_8.POTION_NAME_INDEX.get(potionName)));
|
||||
}
|
||||
}
|
||||
if (splashPotion || lingeringPotion) { // Convert splash and lingering potions to normal potions
|
||||
item.setIdentifier(373);
|
||||
data += 8192;
|
||||
}
|
||||
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");
|
||||
|
||||
item.setData((short) data);
|
||||
}
|
||||
if (displayTag == null) { // Remove the display tag again if it was only added to emulate unbreakable
|
||||
tag.put("display", displayTag = new CompoundTag());
|
||||
tag.put(nbtTagName() + "|noDisplay", new ByteTag(true));
|
||||
}
|
||||
|
||||
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 -> {
|
||||
final StringTag nameTag = entries.getStringTag("AttributeName");
|
||||
return nameTag != null && !VALID_ATTRIBUTES.contains(nameTag.getValue());
|
||||
});
|
||||
}
|
||||
ListTag<StringTag> loreTag = displayTag.getListTag("Lore", StringTag.class);
|
||||
if (loreTag == null) {
|
||||
displayTag.put("Lore", loreTag = new ListTag<>(StringTag.class));
|
||||
}
|
||||
loreTag.add(new StringTag("§9Unbreakable"));
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
if (item.identifier() == 383 && item.data() == 0) { // Spawn eggs
|
||||
int data = 0;
|
||||
final CompoundTag entityTag = tag == null ? null : tag.getCompoundTag("EntityTag");
|
||||
if (entityTag != null) {
|
||||
final StringTag idTag = entityTag.getStringTag("id");
|
||||
if (idTag != null) {
|
||||
final String id = idTag.getValue();
|
||||
if (EntityIds1_8.ENTITY_NAME_TO_ID.containsKey(id)) {
|
||||
data = EntityIds1_8.ENTITY_NAME_TO_ID.get(id);
|
||||
} else if (displayTag == null) {
|
||||
tag.put("display", displayTag = new CompoundTag());
|
||||
tag.put(nbtTagName() + "|noDisplay", new ByteTag(true));
|
||||
displayTag.put("Name", new StringTag("§rSpawn " + id));
|
||||
}
|
||||
}
|
||||
}
|
||||
item.setData((short) data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item handleItemToServer(UserConnection connection, Item item) {
|
||||
if (item == null) return null;
|
||||
super.handleItemToServer(connection, item);
|
||||
// Potion, splash potion, lingering potion
|
||||
final boolean potion = item.identifier() == 373;
|
||||
final boolean splashPotion = item.identifier() == 438;
|
||||
final boolean lingeringPotion = item.identifier() == 441;
|
||||
|
||||
CompoundTag tag = item.tag();
|
||||
if (potion || splashPotion || lingeringPotion) {
|
||||
int data = 0;
|
||||
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)) {
|
||||
data = PotionIdMappings1_8.POTION_NAME_TO_ID.get(potionName);
|
||||
}
|
||||
if (splashPotion) {
|
||||
potionName += "_splash";
|
||||
} else if (lingeringPotion) {
|
||||
potionName += "_lingering";
|
||||
}
|
||||
// Don't override custom name
|
||||
if ((displayTag == null || !displayTag.contains("Name")) && PotionIdMappings1_8.POTION_NAME_INDEX.containsKey(potionName)) {
|
||||
tag.put("display", displayTag = new CompoundTag());
|
||||
tag.put(nbtTagName() + "|noDisplay", new ByteTag(true));
|
||||
displayTag.put("Name", new StringTag(PotionIdMappings1_8.POTION_NAME_INDEX.get(potionName)));
|
||||
}
|
||||
}
|
||||
if (splashPotion || lingeringPotion) { // Convert splash and lingering potions to normal potions
|
||||
item.setIdentifier(373);
|
||||
data += 8192;
|
||||
}
|
||||
|
||||
enchantmentRewriter.handleToServer(item);
|
||||
item.setData((short) data);
|
||||
}
|
||||
|
||||
if (item.identifier() == 383 && item.data() != 0) { // Spawn eggs
|
||||
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);
|
||||
}
|
||||
item.setData((short) 0);
|
||||
}
|
||||
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 -> {
|
||||
final StringTag nameTag = entries.getStringTag("AttributeName");
|
||||
return nameTag != null && !VALID_ATTRIBUTES.contains(nameTag.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
if (item.identifier() == 373 && (tag == null || !tag.contains("Potion"))) { // Potions
|
||||
// Colors the fake leather armor for an elytra gray
|
||||
if (originalId == 443) {
|
||||
if (tag == null) {
|
||||
item.setTag(tag = new CompoundTag());
|
||||
}
|
||||
CompoundTag display = tag.getCompoundTag("display");
|
||||
if (display == null) {
|
||||
tag.put("display", display = new CompoundTag());
|
||||
}
|
||||
display.put("color", new IntTag(0x737373)); // Gray
|
||||
tag.put(nbtTagName() + "|noDisplay", new ByteTag(true));
|
||||
}
|
||||
|
||||
// Makes the fake banner for a shield brown if it has no banner patterns
|
||||
if (originalId == 442) {
|
||||
final CompoundTag blockEntityTag = tag == null ? null : tag.getCompoundTag("BlockEntityTag");
|
||||
final ListTag<CompoundTag> patterns = blockEntityTag == null ? null : blockEntityTag.getListTag("Patterns", CompoundTag.class);
|
||||
if (patterns == null || patterns.isEmpty()) {
|
||||
item.setData((short) 3); // Brown
|
||||
if (tag == null) {
|
||||
item.setTag(tag = new CompoundTag());
|
||||
}
|
||||
tag.put(nbtTagName() + "|noData", new ByteTag(true));
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item handleItemToServer(UserConnection connection, Item item) {
|
||||
if (item == null) return null;
|
||||
super.handleItemToServer(connection, item);
|
||||
|
||||
CompoundTag tag = item.tag();
|
||||
|
||||
enchantmentRewriter.handleToServer(item);
|
||||
|
||||
if (item.identifier() == 383 && item.data() != 0) { // Spawn eggs
|
||||
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);
|
||||
}
|
||||
item.setData((short) 0);
|
||||
}
|
||||
|
||||
if (item.identifier() == 373) { // Potions
|
||||
// Restore the splash id even when a Potion tag is present (e.g. items re-sent by a creative mode client)
|
||||
if (item.data() >= 16384) {
|
||||
item.setIdentifier(438);
|
||||
item.setData((short) (item.data() - 8192));
|
||||
}
|
||||
item.setIdentifier(438);
|
||||
item.setData((short) (item.data() - 8192));
|
||||
}
|
||||
|
||||
if (tag == null) {
|
||||
item.setTag(tag = new CompoundTag());
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
tag.put("Unbreakable", unbreakableTag);
|
||||
}
|
||||
final Tag attributeModifiersTag = tag.remove(nbtTagName() + "|AttributeModifiers");
|
||||
if (attributeModifiersTag != null) {
|
||||
tag.put("AttributeModifiers", attributeModifiersTag);
|
||||
}
|
||||
if (tag == null) {
|
||||
return item;
|
||||
}
|
||||
if (tag.remove(nbtTagName() + "|noData") != null) {
|
||||
item.setData((short) 0);
|
||||
}
|
||||
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) {
|
||||
tag.put("Unbreakable", unbreakableTag);
|
||||
}
|
||||
final Tag attributeModifiersTag = tag.remove(nbtTagName() + "|AttributeModifiers");
|
||||
if (attributeModifiersTag != null) {
|
||||
tag.put("AttributeModifiers", attributeModifiersTag);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
+604
-519
File diff suppressed because it is too large.
Load diff
+509
-422
File diff suppressed because it is too large.
Load diff
+250
-209
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,10 +17,14 @@
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.rewriter;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
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.CommandBlockState;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.data.EffectIdMappings1_8;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.storage.CommandBlockStateStorage;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.api.minecraft.Environment;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.BaseChunk;
|
||||
@@ -37,235 +41,272 @@ import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_8;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_9_1;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class WorldPacketRewriter1_9 extends RewriterBase<Protocol1_9To1_8> {
|
||||
|
||||
public WorldPacketRewriter1_9(Protocol1_9To1_8 protocol) {
|
||||
super(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() {
|
||||
map(Types.BLOCK_POSITION1_8); // Position
|
||||
map(Types.UNSIGNED_BYTE); // Action
|
||||
map(Types.NAMED_COMPOUND_TAG); // Tag
|
||||
handler(wrapper -> {
|
||||
final CompoundTag tag = wrapper.get(Types.NAMED_COMPOUND_TAG, 0);
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_ENTITY_DATA, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BLOCK_POSITION1_8); // Position
|
||||
map(Types.UNSIGNED_BYTE); // Action
|
||||
map(Types.NAMED_COMPOUND_TAG); // Tag
|
||||
handler(wrapper -> {
|
||||
final CompoundTag tag = wrapper.get(Types.NAMED_COMPOUND_TAG, 0);
|
||||
final short action = wrapper.get(Types.UNSIGNED_BYTE, 0);
|
||||
|
||||
if (tag.remove("SpawnData") instanceof CompoundTag spawnData) {
|
||||
final Tag id = spawnData.remove("id");
|
||||
if (id instanceof StringTag) {
|
||||
tag.put("EntityId", id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (action == 2) {
|
||||
final BlockPosition position = wrapper.get(Types.BLOCK_POSITION1_8, 0);
|
||||
CommandBlockState.decorateCommand(tag, wrapper.user().get(CommandBlockStateStorage.class).state(position));
|
||||
}
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_EVENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BLOCK_POSITION1_8); // Position
|
||||
map(Types.UNSIGNED_BYTE); // Byte 1 (depending on block type)
|
||||
map(Types.UNSIGNED_BYTE); // Byte 2 (depending on block type)
|
||||
map(Types.VAR_INT); // Block
|
||||
handler(wrapper -> {
|
||||
final int block = wrapper.get(Types.VAR_INT, 0);
|
||||
if (block >= 219 && block <= 234) {
|
||||
wrapper.set(Types.VAR_INT, 0, 130);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (tag.remove("SpawnData") instanceof CompoundTag spawnData) {
|
||||
final Tag id = spawnData.remove("id");
|
||||
if (id instanceof StringTag) {
|
||||
tag.put("EntityId", id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CUSTOM_SOUND, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING); // Sound name
|
||||
handler(wrapper -> {
|
||||
String name = wrapper.get(Types.STRING, 0);
|
||||
name = protocol.getMappingData().getMappedNamedSound(name);
|
||||
if (name == null) {
|
||||
wrapper.cancel();
|
||||
} else {
|
||||
wrapper.set(Types.STRING, 0, name);
|
||||
}
|
||||
});
|
||||
read(Types.VAR_INT); // Sound category
|
||||
map(Types.INT); // Effect position x
|
||||
map(Types.INT); // Effect position y
|
||||
map(Types.INT); // Effect position z
|
||||
map(Types.FLOAT); // Volume
|
||||
map(Types.UNSIGNED_BYTE); // Pitch
|
||||
}
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_EVENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BLOCK_POSITION1_8); // Position
|
||||
map(Types.UNSIGNED_BYTE); // Byte 1 (depending on block type)
|
||||
map(Types.UNSIGNED_BYTE); // Byte 2 (depending on block type)
|
||||
map(Types.VAR_INT); // Block
|
||||
handler(wrapper -> {
|
||||
final int block = wrapper.get(Types.VAR_INT, 0);
|
||||
if (block >= 219 && block <= 234) {
|
||||
wrapper.set(Types.VAR_INT, 0, 130);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.FORGET_LEVEL_CHUNK, ClientboundPackets1_8.LEVEL_CHUNK, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
handler(wrapper -> {
|
||||
final Environment environment = wrapper.user().getClientWorld(Protocol1_9To1_8.class).getEnvironment();
|
||||
protocol.registerClientbound(ClientboundPackets1_9.CUSTOM_SOUND, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING); // Sound name
|
||||
handler(wrapper -> {
|
||||
String name = wrapper.get(Types.STRING, 0);
|
||||
name = protocol.getMappingData().getMappedNamedSound(name);
|
||||
if (name == null) {
|
||||
return;
|
||||
}
|
||||
if (!name.isEmpty()) {
|
||||
wrapper.set(Types.STRING, 0, name);
|
||||
} else {
|
||||
wrapper.cancel();
|
||||
}
|
||||
});
|
||||
read(Types.VAR_INT); // Sound category
|
||||
map(Types.INT); // Effect position x
|
||||
map(Types.INT); // Effect position y
|
||||
map(Types.INT); // Effect position z
|
||||
map(Types.FLOAT); // Volume
|
||||
map(Types.UNSIGNED_BYTE); // Pitch
|
||||
}
|
||||
});
|
||||
|
||||
final int chunkX = wrapper.read(Types.INT);
|
||||
final int chunkZ = wrapper.read(Types.INT);
|
||||
protocol.registerClientbound(ClientboundPackets1_9.FORGET_LEVEL_CHUNK, ClientboundPackets1_8.LEVEL_CHUNK, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
handler(wrapper -> {
|
||||
final Environment environment = wrapper.user().storables(protocol).clientWorld().getEnvironment();
|
||||
final CommandBlockStateStorage commandBlockStates = wrapper.user().get(CommandBlockStateStorage.class);
|
||||
|
||||
wrapper.write(ChunkType1_8.forEnvironment(environment), new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], null, new ArrayList<>()));
|
||||
});
|
||||
}
|
||||
});
|
||||
final int chunkX = wrapper.read(Types.INT);
|
||||
final int chunkZ = wrapper.read(Types.INT);
|
||||
commandBlockStates.unloadChunk(chunkX, chunkZ);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.LEVEL_CHUNK, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
handler(wrapper -> {
|
||||
final Environment environment = wrapper.user().getClientWorld(Protocol1_9To1_8.class).getEnvironment();
|
||||
wrapper.write(ChunkType1_8.forEnvironment(environment), new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], null, new ArrayList<>()));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Chunk chunk = wrapper.read(ChunkType1_9_1.forEnvironment(environment));
|
||||
protocol.registerClientbound(ClientboundPackets1_9.LEVEL_CHUNK, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
handler(wrapper -> {
|
||||
final Environment environment = wrapper.user().storables(protocol).clientWorld().getEnvironment();
|
||||
final CommandBlockStateStorage commandBlockStates = wrapper.user().get(CommandBlockStateStorage.class);
|
||||
|
||||
for (ChunkSection section : chunk.getSections()) {
|
||||
if (section == null) continue;
|
||||
DataPalette palette = section.palette(PaletteType.BLOCKS);
|
||||
for (int i = 0; i < palette.size(); i++) {
|
||||
int block = palette.idByIndex(i);
|
||||
int replacedBlock = protocol.getItemRewriter().handleBlockId(block);
|
||||
palette.setIdByIndex(i, replacedBlock);
|
||||
}
|
||||
}
|
||||
Chunk chunk = wrapper.read(ChunkType1_9_1.forEnvironment(environment));
|
||||
final Chunk originalChunk = chunk;
|
||||
|
||||
if (chunk.isFullChunk() && chunk.getBitmask() == 0) { // This would be an unload packet for 1.8 clients. Just set one air section
|
||||
boolean skylight = environment == Environment.NORMAL;
|
||||
ChunkSection[] sections = new ChunkSection[16];
|
||||
ChunkSection section = new ChunkSectionImpl(true);
|
||||
sections[0] = section;
|
||||
section.palette(PaletteType.BLOCKS).addId(0);
|
||||
if (skylight) section.getLight().setSkyLight(new byte[2048]);
|
||||
chunk = new BaseChunk(chunk.getX(), chunk.getZ(), true, false, 1, sections, chunk.getBiomeData(), chunk.getBlockEntities());
|
||||
}
|
||||
chunk.getBlockEntities().forEach(nbt -> {
|
||||
if (!nbt.contains("x") || !nbt.contains("y") || !nbt.contains("z")) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.write(ChunkType1_8.forEnvironment(environment), chunk);
|
||||
final BlockPosition position = new BlockPosition((int) nbt.get("x").getValue(), (int) nbt.get("y").getValue(), (int) nbt.get("z").getValue());
|
||||
final int blockState = blockStateAt(originalChunk, position);
|
||||
if (CommandBlockState.isCommandBlock(blockState)) {
|
||||
commandBlockStates.storeOrRemove(position, blockState);
|
||||
CommandBlockState.decorateCommand(nbt, blockState);
|
||||
}
|
||||
});
|
||||
|
||||
chunk.getBlockEntities().forEach(nbt -> {
|
||||
if (!nbt.contains("x") || !nbt.contains("y") || !nbt.contains("z") || !nbt.contains("id")) {
|
||||
return;
|
||||
}
|
||||
BlockPosition position = new BlockPosition((int) nbt.get("x").getValue(), (int) nbt.get("y").getValue(), (int) nbt.get("z").getValue());
|
||||
String id = (String) nbt.get("id").getValue();
|
||||
for (ChunkSection section : chunk.getSections()) {
|
||||
if (section == null) continue;
|
||||
DataPalette palette = section.palette(PaletteType.BLOCKS);
|
||||
for (int i = 0; i < palette.size(); i++) {
|
||||
int block = palette.idByIndex(i);
|
||||
int replacedBlock = protocol.getItemRewriter().handleBlockId(block);
|
||||
palette.setIdByIndex(i, replacedBlock);
|
||||
}
|
||||
}
|
||||
|
||||
short action;
|
||||
switch (id) {
|
||||
case "minecraft:mob_spawner":
|
||||
action = 1;
|
||||
break;
|
||||
case "minecraft:command_block":
|
||||
action = 2;
|
||||
break;
|
||||
case "minecraft:beacon":
|
||||
action = 3;
|
||||
break;
|
||||
case "minecraft:skull":
|
||||
action = 4;
|
||||
break;
|
||||
case "minecraft:flower_pot":
|
||||
action = 5;
|
||||
break;
|
||||
case "minecraft:banner":
|
||||
action = 6;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (chunk.isFullChunk() && chunk.getBitmask() == 0) { // This would be an unload packet for 1.8 clients. Just set one air section
|
||||
boolean skylight = environment == Environment.NORMAL;
|
||||
ChunkSection[] sections = new ChunkSection[16];
|
||||
ChunkSection section = new ChunkSectionImpl(true);
|
||||
sections[0] = section;
|
||||
section.palette(PaletteType.BLOCKS).addId(0);
|
||||
if (skylight) section.getLight().setSkyLight(new byte[2048]);
|
||||
chunk = new BaseChunk(chunk.getX(), chunk.getZ(), true, false, 1, sections, chunk.getBiomeData(), chunk.getBlockEntities());
|
||||
}
|
||||
|
||||
final PacketWrapper blockEntityData = PacketWrapper.create(ClientboundPackets1_9.BLOCK_ENTITY_DATA, wrapper.user());
|
||||
blockEntityData.write(Types.BLOCK_POSITION1_8, position);
|
||||
blockEntityData.write(Types.UNSIGNED_BYTE, action);
|
||||
blockEntityData.write(Types.NAMED_COMPOUND_TAG, nbt);
|
||||
blockEntityData.scheduleSend(Protocol1_9To1_8.class, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
wrapper.write(ChunkType1_8.forEnvironment(environment), chunk);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.LEVEL_EVENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Effect id
|
||||
map(Types.BLOCK_POSITION1_8); // Position
|
||||
map(Types.INT); // data
|
||||
map(Types.BOOLEAN); // disable relative volume
|
||||
handler(wrapper -> {
|
||||
int id = wrapper.get(Types.INT, 0);
|
||||
id = EffectIdMappings1_8.getOldId(id);
|
||||
if (id == -1) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
wrapper.set(Types.INT, 0, id);
|
||||
if (id == 2001) {
|
||||
int replacedBlock = protocol.getItemRewriter().handleBlockId(wrapper.get(Types.INT, 1));
|
||||
wrapper.set(Types.INT, 1, replacedBlock);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
chunk.getBlockEntities().forEach(nbt -> {
|
||||
if (!nbt.contains("x") || !nbt.contains("y") || !nbt.contains("z") || !nbt.contains("id")) {
|
||||
return;
|
||||
}
|
||||
BlockPosition position = new BlockPosition((int) nbt.get("x").getValue(), (int) nbt.get("y").getValue(), (int) nbt.get("z").getValue());
|
||||
String id = (String) nbt.get("id").getValue();
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.LEVEL_PARTICLES, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Particle id
|
||||
handler(wrapper -> {
|
||||
int id = wrapper.get(Types.INT, 0);
|
||||
if (id > 41 && !ViaRewind.getConfig().isReplaceParticles()) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
if (id == 42) { // Dragon Breath
|
||||
wrapper.set(Types.INT, 0, 24); // Portal
|
||||
} else if (id == 43) { // End Rod
|
||||
wrapper.set(Types.INT, 0, 3); // Firework Spark
|
||||
} else if (id == 44) { // Damage Indicator
|
||||
wrapper.set(Types.INT, 0, 34); // Heart
|
||||
} else if (id == 45) { // Sweep Attack
|
||||
wrapper.set(Types.INT, 0, 1); // Large Explosion
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
short action;
|
||||
switch (id) {
|
||||
case "minecraft:mob_spawner":
|
||||
action = 1;
|
||||
break;
|
||||
case "minecraft:command_block":
|
||||
action = 2;
|
||||
break;
|
||||
case "minecraft:beacon":
|
||||
action = 3;
|
||||
break;
|
||||
case "minecraft:skull":
|
||||
action = 4;
|
||||
break;
|
||||
case "minecraft:flower_pot":
|
||||
action = 5;
|
||||
break;
|
||||
case "minecraft:banner":
|
||||
action = 6;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.MAP_ITEM_DATA, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.VAR_INT); // Item damage
|
||||
map(Types.BYTE); // Scale
|
||||
read(Types.BOOLEAN); // Tracking position
|
||||
}
|
||||
});
|
||||
final PacketWrapper blockEntityData = PacketWrapper.create(ClientboundPackets1_9.BLOCK_ENTITY_DATA, wrapper.user());
|
||||
blockEntityData.write(Types.BLOCK_POSITION1_8, position);
|
||||
blockEntityData.write(Types.UNSIGNED_BYTE, action);
|
||||
blockEntityData.write(Types.NAMED_COMPOUND_TAG, nbt);
|
||||
blockEntityData.scheduleSend(Protocol1_9To1_8.class, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.SOUND, ClientboundPackets1_8.CUSTOM_SOUND, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
handler(wrapper -> {
|
||||
final int soundId = wrapper.read(Types.VAR_INT);
|
||||
final String soundName = protocol.getMappingData().soundName(soundId);
|
||||
if (soundName == null) {
|
||||
wrapper.cancel();
|
||||
} else {
|
||||
wrapper.write(Types.STRING, protocol.getMappingData().getMappedNamedSound(soundName));
|
||||
}
|
||||
});
|
||||
read(Types.VAR_INT); // Sound category
|
||||
map(Types.INT); // Effect position x
|
||||
map(Types.INT); // Effect position y
|
||||
map(Types.INT); // Effect position z
|
||||
map(Types.FLOAT); // Volume
|
||||
map(Types.UNSIGNED_BYTE); // Pitch
|
||||
}
|
||||
});
|
||||
}
|
||||
protocol.registerClientbound(ClientboundPackets1_9.LEVEL_EVENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Effect id
|
||||
map(Types.BLOCK_POSITION1_8); // Position
|
||||
map(Types.INT); // data
|
||||
map(Types.BOOLEAN); // disable relative volume
|
||||
handler(wrapper -> {
|
||||
int id = wrapper.get(Types.INT, 0);
|
||||
id = EffectIdMappings1_8.getOldId(id);
|
||||
if (id == -1) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
wrapper.set(Types.INT, 0, id);
|
||||
if (id == 2001) {
|
||||
int replacedBlock = protocol.getItemRewriter().handleBlockId(wrapper.get(Types.INT, 1));
|
||||
wrapper.set(Types.INT, 1, replacedBlock);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.LEVEL_PARTICLES, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Particle id
|
||||
handler(wrapper -> {
|
||||
int id = wrapper.get(Types.INT, 0);
|
||||
if (id > 41 && !ViaRewind.getConfig().isReplaceParticles()) {
|
||||
wrapper.cancel();
|
||||
return;
|
||||
}
|
||||
if (id == 42) { // Dragon Breath
|
||||
wrapper.set(Types.INT, 0, 24); // Portal
|
||||
} else if (id == 43) { // End Rod
|
||||
wrapper.set(Types.INT, 0, 3); // Firework Spark
|
||||
} else if (id == 44) { // Damage Indicator
|
||||
wrapper.set(Types.INT, 0, 34); // Heart
|
||||
} else if (id == 45) { // Sweep Attack
|
||||
wrapper.set(Types.INT, 0, 1); // Large Explosion
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.MAP_ITEM_DATA, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.VAR_INT); // Item damage
|
||||
map(Types.BYTE); // Scale
|
||||
read(Types.BOOLEAN); // Tracking position
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9.SOUND, ClientboundPackets1_8.CUSTOM_SOUND, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
handler(wrapper -> {
|
||||
final int soundId = wrapper.read(Types.VAR_INT);
|
||||
final int mappedSoundId = protocol.getMappingData().getFullSoundMappings().getNewId(soundId);
|
||||
if (mappedSoundId == -1) {
|
||||
wrapper.cancel();
|
||||
} else {
|
||||
wrapper.write(Types.STRING, protocol.getMappingData().getFullSoundMappings().mappedIdentifier(mappedSoundId));
|
||||
}
|
||||
});
|
||||
read(Types.VAR_INT); // Sound category
|
||||
map(Types.INT); // Effect position x
|
||||
map(Types.INT); // Effect position y
|
||||
map(Types.INT); // Effect position z
|
||||
map(Types.FLOAT); // Volume
|
||||
map(Types.UNSIGNED_BYTE); // Pitch
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static int blockStateAt(final Chunk chunk, final BlockPosition position) {
|
||||
final int sectionY = position.y() >> 4;
|
||||
if (sectionY < 0 || sectionY >= chunk.getSections().length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final ChunkSection section = chunk.getSections()[sectionY];
|
||||
if (section == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return section.palette(PaletteType.BLOCKS).idAt(position.x() & 0xF, position.y() & 0xF, position.z() & 0xF);
|
||||
}
|
||||
}
|
||||
+17
-17
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,24 +20,24 @@ package com.viaversion.viarewind.protocol.v1_9to1_8.storage;
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
|
||||
public class BlockPlaceDestroyTracker implements StorableObject {
|
||||
private long lastMining;
|
||||
private long lastMining;
|
||||
|
||||
public boolean isMining() {
|
||||
long time = System.currentTimeMillis() - lastMining;
|
||||
return time < 75;
|
||||
}
|
||||
public boolean isMining() {
|
||||
long time = System.currentTimeMillis() - lastMining;
|
||||
return time < 75;
|
||||
}
|
||||
|
||||
public void setMining() {
|
||||
lastMining = System.currentTimeMillis();
|
||||
}
|
||||
public void setMining() {
|
||||
lastMining = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void updateMining() {
|
||||
if (this.isMining()) {
|
||||
lastMining = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
public void updateMining() {
|
||||
if (this.isMining()) {
|
||||
lastMining = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
public void setLastMining(long lastMining) {
|
||||
this.lastMining = lastMining;
|
||||
}
|
||||
public void setLastMining(long lastMining) {
|
||||
this.lastMining = lastMining;
|
||||
}
|
||||
}
|
||||
+47
-48
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,65 +20,64 @@ package com.viaversion.viarewind.protocol.v1_9to1_8.storage;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.data.WitherBossBar;
|
||||
import com.viaversion.viaversion.api.connection.StoredObject;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BossBarStorage extends StoredObject {
|
||||
|
||||
private final Map<UUID, WitherBossBar> bossBars = new HashMap<>();
|
||||
private final Map<UUID, WitherBossBar> bossBars = new HashMap<>();
|
||||
|
||||
public BossBarStorage(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
public BossBarStorage(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
updateLocation();
|
||||
changeWorld();
|
||||
}
|
||||
public void reset() {
|
||||
updateLocation();
|
||||
changeWorld();
|
||||
}
|
||||
|
||||
public void add(UUID uuid, String title, float health) {
|
||||
WitherBossBar bossBar = new WitherBossBar(this.getUser(), uuid, title, health);
|
||||
PlayerPositionTracker playerPositionTracker = this.getUser().get(PlayerPositionTracker.class);
|
||||
bossBar.setPlayerLocation(playerPositionTracker.getPosX(), playerPositionTracker.getPosY(), playerPositionTracker.getPosZ(), playerPositionTracker.getYaw(), playerPositionTracker.getPitch());
|
||||
bossBar.show();
|
||||
bossBars.put(uuid, bossBar);
|
||||
}
|
||||
public void add(UUID uuid, String title, float health) {
|
||||
WitherBossBar bossBar = new WitherBossBar(this.getUser(), uuid, title, health);
|
||||
PlayerPositionTracker playerPositionTracker = this.getUser().get(PlayerPositionTracker.class);
|
||||
bossBar.setPlayerLocation(playerPositionTracker.getPosX(), playerPositionTracker.getPosY(), playerPositionTracker.getPosZ(), playerPositionTracker.getYaw(), playerPositionTracker.getPitch());
|
||||
bossBar.show();
|
||||
bossBars.put(uuid, bossBar);
|
||||
}
|
||||
|
||||
public void remove(UUID uuid) {
|
||||
WitherBossBar bossBar = bossBars.remove(uuid);
|
||||
if (bossBar == null) return;
|
||||
bossBar.hide();
|
||||
}
|
||||
public void remove(UUID uuid) {
|
||||
WitherBossBar bossBar = bossBars.remove(uuid);
|
||||
if (bossBar == null) return;
|
||||
bossBar.hide();
|
||||
}
|
||||
|
||||
public void updateLocation() {
|
||||
PlayerPositionTracker playerPositionTracker = this.getUser().get(PlayerPositionTracker.class);
|
||||
bossBars.values().forEach(bossBar -> {
|
||||
try {
|
||||
bossBar.setPlayerLocation(playerPositionTracker.getPosX(), playerPositionTracker.getPosY(), playerPositionTracker.getPosZ(), playerPositionTracker.getYaw(), playerPositionTracker.getPitch());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
public void updateLocation() {
|
||||
PlayerPositionTracker playerPositionTracker = this.getUser().get(PlayerPositionTracker.class);
|
||||
bossBars.values().forEach(bossBar -> {
|
||||
try {
|
||||
bossBar.setPlayerLocation(playerPositionTracker.getPosX(), playerPositionTracker.getPosY(), playerPositionTracker.getPosZ(), playerPositionTracker.getYaw(), playerPositionTracker.getPitch());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void changeWorld() {
|
||||
bossBars.values().forEach(bossBar -> {
|
||||
bossBar.hide();
|
||||
bossBar.show();
|
||||
});
|
||||
}
|
||||
public void changeWorld() {
|
||||
bossBars.values().forEach(bossBar -> {
|
||||
bossBar.hide();
|
||||
bossBar.show();
|
||||
});
|
||||
}
|
||||
|
||||
public void updateHealth(UUID uuid, float health) {
|
||||
WitherBossBar bossBar = bossBars.get(uuid);
|
||||
if (bossBar == null) return;
|
||||
bossBar.setHealth(health);
|
||||
}
|
||||
public void updateHealth(UUID uuid, float health) {
|
||||
WitherBossBar bossBar = bossBars.get(uuid);
|
||||
if (bossBar == null) return;
|
||||
bossBar.setHealth(health);
|
||||
}
|
||||
|
||||
public void updateTitle(UUID uuid, String title) {
|
||||
WitherBossBar bossBar = bossBars.get(uuid);
|
||||
if (bossBar == null) return;
|
||||
bossBar.setTitle(title);
|
||||
}
|
||||
public void updateTitle(UUID uuid, String title) {
|
||||
WitherBossBar bossBar = bossBars.get(uuid);
|
||||
if (bossBar == null) return;
|
||||
bossBar.setTitle(title);
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.storage;
|
||||
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.data.CommandBlockState;
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public final class CommandBlockStateStorage implements StorableObject {
|
||||
|
||||
private final Map<BlockPosition, Integer> commandBlockStates = new HashMap<>();
|
||||
|
||||
public void storeOrRemove(final BlockPosition position, final int blockState) {
|
||||
if (CommandBlockState.isCommandBlock(blockState)) {
|
||||
commandBlockStates.put(position, blockState);
|
||||
} else {
|
||||
commandBlockStates.remove(position);
|
||||
}
|
||||
}
|
||||
|
||||
public int state(final BlockPosition position) {
|
||||
return commandBlockStates.getOrDefault(position, -1);
|
||||
}
|
||||
|
||||
public void unloadChunk(final int chunkX, final int chunkZ) {
|
||||
final Iterator<BlockPosition> iterator = commandBlockStates.keySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final BlockPosition position = iterator.next();
|
||||
if (position.x() >> 4 == chunkX && position.z() >> 4 == chunkZ) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+81
-82
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,101 +22,100 @@ import com.viaversion.viarewind.protocol.v1_9to1_8.cooldown.CooldownVisualizatio
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class CooldownStorage implements StorableObject {
|
||||
|
||||
private CooldownVisualization.Factory visualizationFactory = CooldownVisualization.Factory.fromConfiguration();
|
||||
private CooldownVisualization current;
|
||||
private CooldownVisualization.Factory visualizationFactory = CooldownVisualization.Factory.fromConfiguration();
|
||||
private CooldownVisualization current;
|
||||
|
||||
private double attackSpeed = 4.0;
|
||||
private long lastHit = 0;
|
||||
private double attackSpeed = 4.0;
|
||||
private long lastHit = 0;
|
||||
|
||||
public void tick(final UserConnection connection) {
|
||||
if (!hasCooldown()) {
|
||||
endCurrentVisualization();
|
||||
return;
|
||||
}
|
||||
BlockPlaceDestroyTracker tracker = connection.get(BlockPlaceDestroyTracker.class);
|
||||
if (tracker.isMining()) {
|
||||
lastHit = 0;
|
||||
endCurrentVisualization();
|
||||
return;
|
||||
}
|
||||
if (current == null) {
|
||||
current = visualizationFactory.create(connection);
|
||||
}
|
||||
try {
|
||||
current.show(getCooldown());
|
||||
} catch (Exception exception) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Unable to show cooldown visualization", exception);
|
||||
}
|
||||
}
|
||||
public void tick(final UserConnection connection) {
|
||||
if (!hasCooldown()) {
|
||||
endCurrentVisualization();
|
||||
return;
|
||||
}
|
||||
BlockPlaceDestroyTracker tracker = connection.get(BlockPlaceDestroyTracker.class);
|
||||
if (tracker.isMining()) {
|
||||
lastHit = 0;
|
||||
endCurrentVisualization();
|
||||
return;
|
||||
}
|
||||
if (current == null) {
|
||||
current = visualizationFactory.create(connection);
|
||||
}
|
||||
try {
|
||||
current.show(getCooldown());
|
||||
} catch (Exception exception) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Unable to show cooldown visualization", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private void endCurrentVisualization() {
|
||||
if (current != null) {
|
||||
try {
|
||||
current.hide();
|
||||
} catch (Exception exception) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Unable to hide cooldown visualization", exception);
|
||||
}
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
private void endCurrentVisualization() {
|
||||
if (current != null) {
|
||||
try {
|
||||
current.hide();
|
||||
} catch (Exception exception) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Unable to hide cooldown visualization", exception);
|
||||
}
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasCooldown() {
|
||||
long time = System.currentTimeMillis() - lastHit;
|
||||
double cooldown = restrain(((double) time) * attackSpeed / 1000d, 1.5);
|
||||
return cooldown > 0.1 && cooldown < 1.1;
|
||||
}
|
||||
public boolean hasCooldown() {
|
||||
long time = System.currentTimeMillis() - lastHit;
|
||||
double cooldown = restrain(((double) time) * attackSpeed / 1000d, 1.5);
|
||||
return cooldown > 0.1 && cooldown < 1.1;
|
||||
}
|
||||
|
||||
public double getCooldown() {
|
||||
long time = System.currentTimeMillis() - lastHit;
|
||||
return restrain(((double) time) * attackSpeed / 1000d, 1);
|
||||
}
|
||||
public double getCooldown() {
|
||||
long time = System.currentTimeMillis() - lastHit;
|
||||
return restrain(((double) time) * attackSpeed / 1000d, 1);
|
||||
}
|
||||
|
||||
private double restrain(double x, double b) {
|
||||
if (x < 0) return 0;
|
||||
return Math.min(x, b);
|
||||
}
|
||||
private double restrain(double x, double b) {
|
||||
if (x < 0) return 0;
|
||||
return Math.min(x, b);
|
||||
}
|
||||
|
||||
public void setAttackSpeed(double base, List<Pair<Byte, Double>> modifiers) {
|
||||
attackSpeed = base;
|
||||
for (int j = 0; j < modifiers.size(); j++) {
|
||||
if (modifiers.get(j).key() == 0) {
|
||||
attackSpeed += modifiers.get(j).value();
|
||||
modifiers.remove(j--);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < modifiers.size(); j++) {
|
||||
if (modifiers.get(j).key() == 1) {
|
||||
attackSpeed += base * modifiers.get(j).value();
|
||||
modifiers.remove(j--);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < modifiers.size(); j++) {
|
||||
if (modifiers.get(j).key() == 2) {
|
||||
attackSpeed *= (1.0 + modifiers.get(j).value());
|
||||
modifiers.remove(j--);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setAttackSpeed(double base, List<Pair<Byte, Double>> modifiers) {
|
||||
attackSpeed = base;
|
||||
for (int j = 0; j < modifiers.size(); j++) {
|
||||
if (modifiers.get(j).key() == 0) {
|
||||
attackSpeed += modifiers.get(j).value();
|
||||
modifiers.remove(j--);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < modifiers.size(); j++) {
|
||||
if (modifiers.get(j).key() == 1) {
|
||||
attackSpeed += base * modifiers.get(j).value();
|
||||
modifiers.remove(j--);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < modifiers.size(); j++) {
|
||||
if (modifiers.get(j).key() == 2) {
|
||||
attackSpeed *= (1.0 + modifiers.get(j).value());
|
||||
modifiers.remove(j--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void hit() {
|
||||
lastHit = System.currentTimeMillis();
|
||||
}
|
||||
public void hit() {
|
||||
lastHit = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void setLastHit(long lastHit) {
|
||||
this.lastHit = lastHit;
|
||||
}
|
||||
public void setLastHit(long lastHit) {
|
||||
this.lastHit = lastHit;
|
||||
}
|
||||
|
||||
public CooldownVisualization.Factory getVisualizationFactory() {
|
||||
return visualizationFactory;
|
||||
}
|
||||
public CooldownVisualization.Factory getVisualizationFactory() {
|
||||
return visualizationFactory;
|
||||
}
|
||||
|
||||
public void setVisualizationFactory(CooldownVisualization.Factory visualizationFactory) {
|
||||
this.visualizationFactory = visualizationFactory;
|
||||
}
|
||||
public void setVisualizationFactory(CooldownVisualization.Factory visualizationFactory) {
|
||||
this.visualizationFactory = visualizationFactory;
|
||||
}
|
||||
}
|
||||
+88
-48
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,70 +18,110 @@
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.storage;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
|
||||
import com.viaversion.viaversion.api.minecraft.Vector;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_9;
|
||||
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
|
||||
import com.viaversion.viaversion.libs.fastutil.ints.*;
|
||||
|
||||
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntMap;
|
||||
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntOpenHashMap;
|
||||
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
|
||||
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import com.viaversion.viaversion.libs.fastutil.ints.IntArrayList;
|
||||
import com.viaversion.viaversion.libs.fastutil.ints.IntList;
|
||||
import com.viaversion.viaversion.libs.fastutil.ints.IntOpenHashSet;
|
||||
import com.viaversion.viaversion.libs.fastutil.ints.IntSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class EntityTracker1_9 extends EntityTrackerBase {
|
||||
|
||||
private final Int2ObjectMap<IntList> vehicles = new Int2ObjectOpenHashMap<>();
|
||||
private final Int2ObjectMap<Vector> offsets = new Int2ObjectOpenHashMap<>();
|
||||
private final Int2IntMap status = new Int2IntOpenHashMap();
|
||||
private final Int2ObjectMap<IntList> vehicles = new Int2ObjectOpenHashMap<>();
|
||||
private final Int2ObjectMap<Vector> offsets = new Int2ObjectOpenHashMap<>();
|
||||
private final Int2IntMap status = new Int2IntOpenHashMap();
|
||||
private final IntSet handActive = new IntOpenHashSet();
|
||||
private final Int2ObjectMap<PendingPotionEntity> pendingPotions = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
public EntityTracker1_9(UserConnection connection) {
|
||||
super(connection, EntityTypes1_9.EntityType.PLAYER);
|
||||
}
|
||||
public EntityTracker1_9(UserConnection connection) {
|
||||
super(connection, EntityTypes1_9.EntityType.PLAYER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEntity(int id) {
|
||||
vehicles.remove(id);
|
||||
offsets.remove(id);
|
||||
status.remove(id);
|
||||
@Override
|
||||
public TrackedEntity removeEntity(int id) {
|
||||
vehicles.remove(id);
|
||||
offsets.remove(id);
|
||||
status.remove(id);
|
||||
handActive.remove(id);
|
||||
pendingPotions.remove(id);
|
||||
|
||||
vehicles.forEach((vehicle, passengers) -> passengers.rem(id));
|
||||
vehicles.int2ObjectEntrySet().removeIf(entry -> entry.getValue().isEmpty());
|
||||
super.removeEntity(id);
|
||||
}
|
||||
vehicles.forEach((vehicle, passengers) -> passengers.rem(id));
|
||||
vehicles.int2ObjectEntrySet().removeIf(entry -> entry.getValue().isEmpty());
|
||||
return super.removeEntity(id);
|
||||
}
|
||||
|
||||
public void resetEntityOffset(final int id) {
|
||||
offsets.remove(id);
|
||||
}
|
||||
public void resetEntityOffset(final int id) {
|
||||
offsets.remove(id);
|
||||
}
|
||||
|
||||
public Vector getEntityOffset(final int id) {
|
||||
return offsets.get(id);
|
||||
}
|
||||
public Vector getEntityOffset(final int id) {
|
||||
return offsets.get(id);
|
||||
}
|
||||
|
||||
public void setEntityOffset(final int id, Vector offset) {
|
||||
offsets.put(id, offset);
|
||||
}
|
||||
public void setEntityOffset(final int id, Vector offset) {
|
||||
offsets.put(id, offset);
|
||||
}
|
||||
|
||||
public IntList getPassengers(final int id) {
|
||||
return vehicles.getOrDefault(id, new IntArrayList());
|
||||
}
|
||||
public IntList getPassengers(final int id) {
|
||||
return vehicles.getOrDefault(id, new IntArrayList());
|
||||
}
|
||||
|
||||
public void setPassengers(final int id, final IntList passengers) {
|
||||
vehicles.put(id, passengers);
|
||||
}
|
||||
public void setPassengers(final int id, final IntList passengers) {
|
||||
vehicles.put(id, passengers);
|
||||
}
|
||||
|
||||
public boolean isInsideVehicle(final int id) {
|
||||
for (List<Integer> vehicle : vehicles.values()) {
|
||||
if (vehicle.contains(id)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean isInsideVehicle(final int id) {
|
||||
for (List<Integer> vehicle : vehicles.values()) {
|
||||
if (vehicle.contains(id)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Integer getVehicle(final int passenger) {
|
||||
for (Map.Entry<Integer, IntList> vehicle : vehicles.int2ObjectEntrySet()) {
|
||||
if (vehicle.getValue().contains(passenger)) return vehicle.getKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public Integer getVehicle(final int passenger) {
|
||||
for (Map.Entry<Integer, IntList> vehicle : vehicles.int2ObjectEntrySet()) {
|
||||
if (vehicle.getValue().contains(passenger)) return vehicle.getKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Int2IntMap getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public boolean isHandActive(final int id) {
|
||||
return handActive.contains(id);
|
||||
}
|
||||
|
||||
public void setHandActive(final int id, final boolean active) {
|
||||
if (active) {
|
||||
handActive.add(id);
|
||||
} else {
|
||||
handActive.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
public Int2ObjectMap<PendingPotionEntity> getPendingPotions() {
|
||||
return pendingPotions;
|
||||
}
|
||||
|
||||
public record PendingPotionEntity(int x, int y, int z, byte pitch, byte yaw, short velocityX, short velocityY, short velocityZ) {
|
||||
|
||||
public PendingPotionEntity withPosition(final int x, final int y, final int z, final byte pitch, final byte yaw) {
|
||||
return new PendingPotionEntity(x, y, z, pitch, yaw, velocityX, velocityY, velocityZ);
|
||||
}
|
||||
|
||||
public PendingPotionEntity withVelocity(final short velocityX, final short velocityY, final short velocityZ) {
|
||||
return new PendingPotionEntity(x, y, z, pitch, yaw, velocityX, velocityY, velocityZ);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Int2IntMap getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viarewind.protocol.v1_9to1_8.storage;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
import com.viaversion.viaversion.libs.gson.JsonElement;
|
||||
|
||||
public final class LastTitle implements StorableObject {
|
||||
|
||||
private JsonElement title;
|
||||
private JsonElement subtitle;
|
||||
|
||||
private long visibleSince;
|
||||
private long visibleUntil;
|
||||
|
||||
private int fadeIn;
|
||||
private int stay;
|
||||
private int fadeOut;
|
||||
|
||||
public LastTitle() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
public void setTitle(final JsonElement title) {
|
||||
this.title = title;
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
this.visibleSince = now;
|
||||
this.visibleUntil = now + titleLength();
|
||||
}
|
||||
|
||||
public void setSubtitle(final JsonElement subtitle) {
|
||||
this.subtitle = subtitle;
|
||||
}
|
||||
|
||||
public void setTimes(final int fadeIn, final int stay, final int fadeOut) {
|
||||
this.fadeIn = fadeIn;
|
||||
this.stay = stay;
|
||||
this.fadeOut = fadeOut;
|
||||
|
||||
if (this.visibleUntil > System.currentTimeMillis()) {
|
||||
final long now = System.currentTimeMillis();
|
||||
this.visibleSince = now;
|
||||
this.visibleUntil = now + titleLength();
|
||||
}
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
this.visibleSince = 0;
|
||||
this.visibleUntil = 0;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this.hide();
|
||||
|
||||
this.fadeIn = 10;
|
||||
this.stay = 70;
|
||||
this.fadeOut = 20;
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return this.title != null && this.visibleUntil > System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public JsonElement title() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public JsonElement subtitle() {
|
||||
return this.subtitle;
|
||||
}
|
||||
|
||||
public int[] remainingTimes() {
|
||||
final int fullLength = Math.max(0, this.fadeIn + this.stay + this.fadeOut);
|
||||
final int elapsed = (int) Math.min(fullLength, Math.max(0, (System.currentTimeMillis() - this.visibleSince) / 50L));
|
||||
if (elapsed < this.fadeIn) {
|
||||
return new int[]{this.fadeIn - elapsed, this.stay, this.fadeOut};
|
||||
}
|
||||
|
||||
final int titleEnd = this.fadeIn + this.stay;
|
||||
if (elapsed < titleEnd) {
|
||||
return new int[]{0, titleEnd - elapsed, this.fadeOut};
|
||||
}
|
||||
|
||||
return new int[]{0, 0, fullLength - elapsed};
|
||||
}
|
||||
|
||||
private long titleLength() {
|
||||
return Math.max(0, this.fadeIn + this.stay + this.fadeOut) * 50L;
|
||||
}
|
||||
|
||||
}
|
||||
+15
-15
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,22 +21,22 @@ import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
|
||||
public class LevitationStorage implements StorableObject {
|
||||
|
||||
private boolean active;
|
||||
private int amplifier;
|
||||
private boolean active;
|
||||
private int amplifier;
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public int getAmplifier() {
|
||||
return amplifier;
|
||||
}
|
||||
public int getAmplifier() {
|
||||
return amplifier;
|
||||
}
|
||||
|
||||
public void setAmplifier(int amplifier) {
|
||||
this.amplifier = amplifier;
|
||||
}
|
||||
public void setAmplifier(int amplifier) {
|
||||
this.amplifier = amplifier;
|
||||
}
|
||||
}
|
||||
+64
-54
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,77 +20,87 @@ package com.viaversion.viarewind.protocol.v1_9to1_8.storage;
|
||||
import com.viaversion.viarewind.protocol.v1_9to1_8.Protocol1_9To1_8;
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class PlayerPositionTracker implements StorableObject {
|
||||
|
||||
private final Queue<PacketWrapper> animations = new ConcurrentLinkedQueue<>();
|
||||
private double posX, posY, posZ;
|
||||
private float yaw, pitch;
|
||||
private boolean onGround;
|
||||
private int confirmId = -1;
|
||||
private final Queue<PacketWrapper> animations = new ConcurrentLinkedQueue<>();
|
||||
private final Queue<PendingTeleport> pendingTeleports = new ConcurrentLinkedQueue<>();
|
||||
private double posX, posY, posZ;
|
||||
private float yaw, pitch;
|
||||
private boolean onGround;
|
||||
|
||||
public void setPos(double x, double y, double z) {
|
||||
this.posX = x;
|
||||
this.posY = y;
|
||||
this.posZ = z;
|
||||
}
|
||||
public void setPos(double x, double y, double z) {
|
||||
this.posX = x;
|
||||
this.posY = y;
|
||||
this.posZ = z;
|
||||
}
|
||||
|
||||
public void sendAnimations() {
|
||||
PacketWrapper wrapper;
|
||||
while ((wrapper = animations.poll()) != null) {
|
||||
wrapper.sendToServer(Protocol1_9To1_8.class);
|
||||
}
|
||||
}
|
||||
public void sendAnimations() {
|
||||
PacketWrapper wrapper;
|
||||
while ((wrapper = animations.poll()) != null) {
|
||||
wrapper.sendToServer(Protocol1_9To1_8.class);
|
||||
}
|
||||
}
|
||||
|
||||
public void queueAnimation(final PacketWrapper wrapper) {
|
||||
animations.add(wrapper);
|
||||
}
|
||||
public void queueAnimation(final PacketWrapper wrapper) {
|
||||
animations.add(wrapper);
|
||||
}
|
||||
|
||||
public void setYaw(float yaw) {
|
||||
this.yaw = yaw % 360f;
|
||||
}
|
||||
public double getPosX() {
|
||||
return this.posX;
|
||||
}
|
||||
|
||||
public void setPitch(float pitch) {
|
||||
this.pitch = pitch % 360f;
|
||||
}
|
||||
public double getPosY() {
|
||||
return this.posY;
|
||||
}
|
||||
|
||||
public double getPosX() {
|
||||
return this.posX;
|
||||
}
|
||||
public double getPosZ() {
|
||||
return this.posZ;
|
||||
}
|
||||
|
||||
public double getPosY() {
|
||||
return this.posY;
|
||||
}
|
||||
public float getYaw() {
|
||||
return this.yaw;
|
||||
}
|
||||
|
||||
public double getPosZ() {
|
||||
return this.posZ;
|
||||
}
|
||||
public void setYaw(float yaw) {
|
||||
this.yaw = yaw % 360f;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return this.yaw;
|
||||
}
|
||||
public float getPitch() {
|
||||
return this.pitch;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return this.pitch;
|
||||
}
|
||||
public void setPitch(float pitch) {
|
||||
this.pitch = pitch % 360f;
|
||||
}
|
||||
|
||||
public boolean isOnGround() {
|
||||
return this.onGround;
|
||||
}
|
||||
public boolean isOnGround() {
|
||||
return this.onGround;
|
||||
}
|
||||
|
||||
public int getConfirmId() {
|
||||
return this.confirmId;
|
||||
}
|
||||
public void setOnGround(boolean onGround) {
|
||||
this.onGround = onGround;
|
||||
}
|
||||
|
||||
public void setOnGround(boolean onGround) {
|
||||
this.onGround = onGround;
|
||||
}
|
||||
public boolean hasPendingTeleports() {
|
||||
return !this.pendingTeleports.isEmpty();
|
||||
}
|
||||
|
||||
public void setConfirmId(int confirmId) {
|
||||
this.confirmId = confirmId;
|
||||
}
|
||||
public void queueTeleport(final int id, final double x, final double y, final double z, final float yaw, final float pitch, final boolean viewRelative) {
|
||||
this.pendingTeleports.add(new PendingTeleport(id, x, y, z, yaw, pitch, viewRelative));
|
||||
}
|
||||
|
||||
public PendingTeleport peekTeleport() {
|
||||
return this.pendingTeleports.peek();
|
||||
}
|
||||
|
||||
public void confirmTeleport() {
|
||||
this.pendingTeleports.poll();
|
||||
}
|
||||
|
||||
public record PendingTeleport(int id, double x, double y, double z, float yaw, float pitch, boolean viewRelative) {
|
||||
}
|
||||
|
||||
}
|
||||
+95
-63
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,83 +30,115 @@ 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;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class WindowTracker extends StoredObject {
|
||||
private final HashMap<Short, String> types = new HashMap<>();
|
||||
private final HashMap<Short, Item[]> brewingItems = new HashMap<>();
|
||||
private final Map<Short, Short> enchantmentProperties = new HashMap<>();
|
||||
private final HashMap<Short, String> types = new HashMap<>();
|
||||
private final HashMap<Short, Item[]> brewingItems = new HashMap<>();
|
||||
private final Map<Short, Short> enchantmentProperties = new HashMap<>();
|
||||
|
||||
public WindowTracker(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
private short openWindowId = 0;
|
||||
private int openWindowSize = 0; // Translated client container slots, excluding the player inventory
|
||||
|
||||
public String get(short windowId) {
|
||||
return types.get(windowId);
|
||||
}
|
||||
public WindowTracker(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
public void put(short windowId, String type) {
|
||||
types.put(windowId, type);
|
||||
}
|
||||
public static void updateBrewingStand(UserConnection user, Item blazePowder, short windowId) {
|
||||
if (blazePowder != null && blazePowder.identifier() != 377) {
|
||||
return;
|
||||
}
|
||||
int amount = blazePowder == null ? 0 : blazePowder.amount();
|
||||
|
||||
public void remove(short windowId) {
|
||||
types.remove(windowId);
|
||||
brewingItems.remove(windowId);
|
||||
}
|
||||
PacketWrapper openWindow = PacketWrapper.create(ClientboundPackets1_8.OPEN_SCREEN, user);
|
||||
openWindow.write(Types.UNSIGNED_BYTE, windowId);
|
||||
openWindow.write(Types.STRING, "minecraft:brewing_stand");
|
||||
|
||||
public Item[] getBrewingItems(short windowId) {
|
||||
return brewingItems.computeIfAbsent(windowId, key -> new Item[]{
|
||||
new DataItem(),
|
||||
new DataItem(),
|
||||
new DataItem(),
|
||||
new DataItem()
|
||||
});
|
||||
}
|
||||
TextComponent title = new StringComponent()
|
||||
.append(new TranslationComponent("container.brewing"))
|
||||
.append(new StringComponent(": ").formatted(TextFormatting.DARK_GRAY))
|
||||
.append(new StringComponent(amount + " ").formatted(TextFormatting.DARK_RED))
|
||||
.append(new TranslationComponent("item.blazePowder.name").formatted(TextFormatting.DARK_RED));
|
||||
|
||||
public short getEnchantmentValue(final short key) {
|
||||
if (!enchantmentProperties.containsKey(key)) {
|
||||
return 0;
|
||||
}
|
||||
return enchantmentProperties.remove(key);
|
||||
}
|
||||
openWindow.write(Types.COMPONENT, TextComponentSerializer.V1_8.serializeJson(title));
|
||||
openWindow.write(Types.UNSIGNED_BYTE, (short) 420);
|
||||
openWindow.scheduleSend(Protocol1_9To1_8.class);
|
||||
|
||||
public void putEnchantmentProperty(short key, short value) {
|
||||
enchantmentProperties.put(key, value);
|
||||
}
|
||||
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.BYTE, (byte) windowId);
|
||||
setSlot.write(Types.SHORT, (short) i);
|
||||
setSlot.write(Types.ITEM1_8, items[i]);
|
||||
setSlot.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearEnchantmentProperties() {
|
||||
enchantmentProperties.clear();
|
||||
}
|
||||
public String get(short windowId) {
|
||||
return types.get(windowId);
|
||||
}
|
||||
|
||||
public static void updateBrewingStand(UserConnection user, Item blazePowder, short windowId) {
|
||||
if (blazePowder != null && blazePowder.identifier() != 377) {
|
||||
return;
|
||||
}
|
||||
int amount = blazePowder == null ? 0 : blazePowder.amount();
|
||||
public void put(short windowId, String type) {
|
||||
types.put(windowId, type);
|
||||
}
|
||||
|
||||
PacketWrapper openWindow = PacketWrapper.create(ClientboundPackets1_8.OPEN_SCREEN, user);
|
||||
openWindow.write(Types.UNSIGNED_BYTE, windowId);
|
||||
openWindow.write(Types.STRING, "minecraft:brewing_stand");
|
||||
public void remove(short windowId) {
|
||||
types.remove(windowId);
|
||||
brewingItems.remove(windowId);
|
||||
if (windowId == openWindowId) {
|
||||
openWindowId = 0;
|
||||
openWindowSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TextComponent title = new StringComponent().
|
||||
append(new TranslationComponent("container.brewing")).
|
||||
append(new StringComponent(": " + TextFormatting.DARK_GRAY)).
|
||||
append(new StringComponent(amount + " " + TextFormatting.DARK_RED)).
|
||||
append(new TranslationComponent("item.blazePowder.name", TextFormatting.DARK_RED));
|
||||
public void openWindow(final short windowId, final String windowType, final int slotCount) {
|
||||
openWindowId = windowId;
|
||||
|
||||
openWindow.write(Types.COMPONENT, TextComponentSerializer.V1_8.serializeJson(title));
|
||||
openWindow.write(Types.UNSIGNED_BYTE, (short) 420);
|
||||
openWindow.scheduleSend(Protocol1_9To1_8.class);
|
||||
// The client only uses the packet's slot count when constructing dynamic inventories.
|
||||
// Fixed menus construct their own slots; use the translated 1.8 layout for those.
|
||||
openWindowSize = switch (windowType) {
|
||||
case "minecraft:furnace", "minecraft:villager", "minecraft:anvil" -> 3;
|
||||
case "minecraft:brewing_stand" -> 4;
|
||||
case "minecraft:beacon" -> 1;
|
||||
case "minecraft:dispenser", "minecraft:dropper" -> 9;
|
||||
case "minecraft:enchanting_table" -> 2;
|
||||
case "minecraft:crafting_table" -> 10;
|
||||
case "minecraft:hopper" -> slotCount;
|
||||
case "EntityHorse" -> slotCount > 2 ? 17 : 2;
|
||||
default -> slotCount / 9 * 9;
|
||||
};
|
||||
}
|
||||
|
||||
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.BYTE, (byte) windowId);
|
||||
setSlot.write(Types.SHORT, (short) i);
|
||||
setSlot.write(Types.ITEM1_8, items[i]);
|
||||
setSlot.scheduleSend(Protocol1_9To1_8.class);
|
||||
}
|
||||
}
|
||||
public short openWindowId() {
|
||||
return openWindowId;
|
||||
}
|
||||
|
||||
public int openWindowSize() {
|
||||
return openWindowSize;
|
||||
}
|
||||
|
||||
public Item[] getBrewingItems(short windowId) {
|
||||
return brewingItems.computeIfAbsent(windowId, key -> new Item[]{
|
||||
new DataItem(),
|
||||
new DataItem(),
|
||||
new DataItem(),
|
||||
new DataItem()
|
||||
});
|
||||
}
|
||||
|
||||
public short getEnchantmentValue(final short key) {
|
||||
if (!enchantmentProperties.containsKey(key)) {
|
||||
return 0;
|
||||
}
|
||||
return enchantmentProperties.remove(key);
|
||||
}
|
||||
|
||||
public void putEnchantmentProperty(short key, short value) {
|
||||
enchantmentProperties.put(key, value);
|
||||
}
|
||||
|
||||
public void clearEnchantmentProperties() {
|
||||
enchantmentProperties.clear();
|
||||
}
|
||||
}
|
||||
+11
-7
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,14 @@ import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
|
||||
public class CooldownIndicatorTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
|
||||
connection.get(CooldownStorage.class).tick(connection);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
|
||||
final CooldownStorage cooldown = connection.get(CooldownStorage.class);
|
||||
if (cooldown == null) {
|
||||
continue;
|
||||
}
|
||||
cooldown.tick(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-24
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This 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,32 +25,34 @@ import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
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()) {
|
||||
continue;
|
||||
}
|
||||
@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 == null) {
|
||||
continue;
|
||||
}
|
||||
if (!levitation.isActive()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final PacketWrapper velocityPacket = PacketWrapper.create(ClientboundPackets1_8.SET_ENTITY_MOTION, connection);
|
||||
velocityPacket.write(Types.VAR_INT, connection.getEntityTracker(Protocol1_9To1_8.class).clientEntityId());
|
||||
velocityPacket.write(Types.SHORT, (short) 0);
|
||||
velocityPacket.write(Types.SHORT, (short) ((levitation.getAmplifier() + 1) * 360));
|
||||
velocityPacket.write(Types.SHORT, (short) 0);
|
||||
try {
|
||||
velocityPacket.scheduleSend(Protocol1_9To1_8.class);
|
||||
} catch (Exception e) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send levitation packet", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
final PacketWrapper velocityPacket = PacketWrapper.create(ClientboundPackets1_8.SET_ENTITY_MOTION, connection);
|
||||
velocityPacket.write(Types.VAR_INT, connection.storables(Protocol1_9To1_8.class).entityTracker().clientEntityId());
|
||||
velocityPacket.write(Types.SHORT, (short) 0);
|
||||
velocityPacket.write(Types.SHORT, (short) ((levitation.getAmplifier() + 1) * 360));
|
||||
velocityPacket.write(Types.SHORT, (short) 0);
|
||||
try {
|
||||
velocityPacket.scheduleSend(Protocol1_9To1_8.class);
|
||||
} catch (Exception e) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send levitation packet", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
|
||||
* Copyright (C) 2018-2025 ViaVersion and contributors
|
||||
* Copyright (C) 2018-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -26,72 +26,74 @@ 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.text.JsonNBTComponentRewriter;
|
||||
import com.viaversion.viaversion.util.ComponentUtil;
|
||||
|
||||
import java.util.logging.Level;
|
||||
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 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);
|
||||
if (text != null) {
|
||||
object.addProperty("translate", text);
|
||||
}
|
||||
}
|
||||
};
|
||||
private static final Pattern UNUSED_COLOR_PATTERN = Pattern.compile("(?>(?>§[0-fk-or])*(§r|\\Z))|(?>(?>§[0-f])*(§[0-f]))");
|
||||
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);
|
||||
if (text != null) {
|
||||
object.addProperty("translate", text);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static String jsonToLegacy(String json) {
|
||||
if (json == null || json.equals("null") || json.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
return jsonToLegacy(JsonParser.parseString(json));
|
||||
} catch (Exception 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(String json) {
|
||||
if (json == null || json.equals("null") || json.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
return jsonToLegacy(JsonParser.parseString(json));
|
||||
} catch (Exception e) {
|
||||
if (Via.getConfig().logTextComponentConversionErrors()) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Could not convert component to legacy text: " + json, e);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
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(null, component);
|
||||
String legacy = ComponentUtil.jsonToLegacy(component);
|
||||
while (legacy.startsWith("§f")) legacy = legacy.substring(2);
|
||||
return legacy;
|
||||
} catch (Exception ex) {
|
||||
if (!Via.getConfig().isSuppressConversionWarnings()) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Could not convert component to legacy text: " + component, ex);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
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(null, component);
|
||||
String legacy = ComponentUtil.jsonToLegacy(component);
|
||||
int attempts = 0;
|
||||
while (legacy.startsWith("§f") && attempts++ < 10) {
|
||||
legacy = legacy.substring(2);
|
||||
}
|
||||
return legacy;
|
||||
} catch (Exception ex) {
|
||||
if (Via.getConfig().logTextComponentConversionErrors()) {
|
||||
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Could not convert component to legacy text: " + component, ex);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static String removeUnusedColor(String legacy, char last) {
|
||||
if (legacy == null) return null;
|
||||
legacy = UNUSED_COLOR_PATTERN.matcher(legacy).replaceAll("$1$2");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < legacy.length(); i++) {
|
||||
char current = legacy.charAt(i);
|
||||
if (current != '§' || i == legacy.length() - 1) {
|
||||
builder.append(current);
|
||||
continue;
|
||||
}
|
||||
current = legacy.charAt(++i);
|
||||
if (current == last) continue;
|
||||
builder.append('§').append(current);
|
||||
last = current;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
public static String removeUnusedColor(String legacy, char last) {
|
||||
if (legacy == null) return null;
|
||||
legacy = UNUSED_COLOR_PATTERN.matcher(legacy).replaceAll("$1$2");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < legacy.length(); i++) {
|
||||
char current = legacy.charAt(i);
|
||||
if (current != '§' || i == legacy.length() - 1) {
|
||||
builder.append(current);
|
||||
continue;
|
||||
}
|
||||
current = legacy.charAt(++i);
|
||||
if (current == last) continue;
|
||||
builder.append('§').append(current);
|
||||
last = current;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -126,6 +126,7 @@
|
||||
},
|
||||
"180": {
|
||||
"id": "128",
|
||||
"data": "-1",
|
||||
"name": "1.8 Red Sandstone Stairs"
|
||||
},
|
||||
"181": {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Loaded 100 of 114 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user