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

* Fix formatting issue to be consistent with spaces
2024-04-05 20:38:35 +02:00
FlorianMichael 819a4d8bb3 More work 2024-03-29 18:13:05 +01:00
FlorianMichael aa5696e586 Overall improvements to README.md 2024-03-29 13:00:02 +01:00
FlorianMichael 3c9232949a Rename classes to match VB 2024-03-29 12:47:38 +01:00
FlorianMichael a43ad2b737 Prepare entity rewriter migration 2024-03-29 12:41:17 +01:00
FlorianMichael 7e5e8fd2c1 Fix enchantments in 1.7->1.8 2024-03-28 18:08:24 +01:00
FlorianMichael 7fc2530693 Compile from repository server 2024-03-28 11:46:11 +01:00
FlorianMichael e104df51b0 Drop format reset 2024-03-28 10:44:32 +01:00
FlorianMichael 6d237cc337 Deprecate and move classes 2024-03-27 20:34:23 +01:00
FlorianMichael a982ac8c38 Move particle class 2024-03-27 20:26:28 +01:00
FlorianMichael 8494976e4f Port 1.8 -> 1.9 item rewriter as well 2024-03-27 20:02:50 +01:00
FlorianMichael 7b2ad249da Use EnchantmentRewriter base (probably) 2024-03-27 18:22:31 +01:00
FlorianMichael 5f73bee3c5 Start with using ViaBackwards API 2024-03-27 18:04:04 +01:00
FlorianMichael 709f918272 Generate item mappings 2024-03-27 13:55:39 +01:00
FlorianMichael dca9854486 Removed support status from README 2024-03-27 13:54:44 +01:00
FlorianMichael d93dce88d8 So it begins... 2024-03-27 11:12:37 +01:00
FlorianMichael 5ae0f29f42 Fixed version range 2024-03-25 17:35:55 +01:00
FlorianMichael eae4a3ac09 Renamed universal artifact to viarewind, fixed platform name in Via dumps 2024-03-25 17:34:07 +01:00
FlorianMichael 5e1ae7ac0f Back to VV dev 2024-03-24 13:06:13 +01:00
FlorianMichael 2422588db5 Remove viafabricplus from dependency list 2024-03-24 13:01:43 +01:00
FlorianMichael 0a1707f1d0 Fix up again 2024-03-23 13:18:47 +01:00
FlorianMichael c6d6128c5e Update publishing plugin usage 2024-03-23 13:11:40 +01:00
FlorianMichael 8f2072d2af [ci skip] Removed unused import 2024-03-23 12:32:59 +01:00
FlorianMichael 42fbcfb26a Gradle 8.7 2024-03-23 12:31:27 +01:00
FlorianMichael a9568d388f Update Hangar publish plugin 2024-03-23 12:29:42 +01:00
FlorianMichael 36ea0fecc6 Fixed compile error 2024-03-09 14:11:41 +01:00
FlorianMichael 6a26bbdf84 Back to VV master 2024-03-09 14:09:30 +01:00
FlorianMichael 45deefdea3 Update ViaNBT API usage 2024-03-09 14:04:37 +01:00
FlorianMichael 476c5f2077 Updated Via API usage 2024-03-09 13:51:19 +01:00
FlorianMichael aaddfb186b Fixed API usage 2024-03-05 21:02:35 +01:00
FlorianMichael 5407bf9922 Bump version to 3.0.7-24w09a-SNAPSHOT 2024-03-05 20:13:44 +01:00
FlorianMichael 8aea3e43aa Bump version to 3.0.7-SNAPSHOT 2024-03-05 20:11:38 +01:00
127 changed files with 4793 additions and 6229 deletions

No files matched your search

+19 -7
View File
@@ -1,22 +1,25 @@
# ViaRewind
[![Latest Release](https://img.shields.io/github/v/release/ViaVersion/ViaRewind)](https://github.com/ViaVersion/ViaRewind/releases)
[![Build Status](https://github.com/ViaVersion/ViaRewind/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaRewind/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**ViaVersion addon to allow 1.8.x and 1.7.x clients on newer server versions.** <br>
**ViaBackwards addon to allow 1.8.x and 1.7.x clients on newer server versions.** <br>
Runs on 1.9-latest servers or 1.8 clients and lower.
**You can override the included version in [ViaFabric](https://modrinth.com/mod/viafabric) or [ViaProxy](https://github.com/ViaVersion/ViaProxy):**
- in **ViaFabric**, put ViaRewind into the `mods` folder
- in **ViaProxy**, put ViaRewind into the `jars` folder
**Depending on the platform and version, this also requires [ViaVersion](https://modrinth.com/mod/viaversion) and [ViaBackwards](https://modrinth.com/mod/viabackwards).**
**Requires [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) and [ViaBackwards](https://hangar.papermc.io/ViaVersion/ViaBackwards) to be installed..**
Support Status
Releases/Dev Builds
-
While ViaRewind will keep getting updates to function with changes to ViaVersion or ViaBackwards, it will likely not receive many bug fixes or additional features anymore.
You can find releases in the following places:
- **Hangar (for our plugins)**: https://hangar.papermc.io/ViaVersion/ViaRewind
- **Modrinth (for our mods)**: https://modrinth.com/mod/viarewind
- **GitHub**: https://github.com/ViaVersion/ViaRewind/releases
Releases / Dev Builds
-
Dev builds for **all** of our projects are on our Jenkins server:
- **Jenkins**: https://ci.viaversion.com/view/ViaRewind/
@@ -27,4 +30,13 @@ Other Links
**Issue tracker:** https://github.com/ViaVersion/ViaRewind/issues
**List of contributors:** https://github.com/ViaVersion/ViaRewind/graphs/contributors
**List of contributors:** https://github.com/ViaVersion/ViaRewind/graphs/contributors
Building
-
After cloning this repository, build the project with Gradle by running `./gradlew build` and take the created jar out
of the `universal/build/libs` directory.
License
-
This project is licensed under the [GNU General Public License Version 3](LICENSE).
@@ -4,7 +4,6 @@ plugins {
}
repositories {
mavenLocal()
maven {
url = uri("https://repo.viaversion.com")
}
@@ -36,6 +35,7 @@ repositories {
dependencies {
compileOnly "com.viaversion:viaversion:${project.viaversion_version}"
compileOnly "com.viaversion:viabackwards:${project.viabackwards_version}"
compileOnly "io.netty:netty-all:${project.netty_version}"
compileOnly "com.google.guava:guava:${project.guava_version}"
}
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
+2 -3
View File
@@ -1,11 +1,10 @@
name: ViaRewind
main: com.viaversion.viarewind.BukkitPlugin
authors: [Gerrygames, FlorianMichael/EnZaXD, creeper123321123]
authors: [FlorianMichael/EnZaXD, Gerrygames, creeper123321123]
version: ${version}
description: ${description}
website: https://viaversion.com/rewind
api-version: 1.13
folia-supported: true
load: STARTUP
depend: [ViaVersion]
softdepend: [ViaBackwards]
depend: [ViaVersion, ViaBackwards]
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
+2 -3
View File
@@ -1,7 +1,6 @@
name: ViaRewind
main: com.viaversion.viarewind.BungeePlugin
authors: [Gerrygames, FlorianMichael/EnZaXD, creeper123321123]
authors: [FlorianMichael/EnZaXD, Gerrygames, creeper123321123]
version: ${version}
depends: [ViaVersion]
softdepends: [ViaBackwards]
depends: [ViaVersion, ViaBackwards]
website: https://viaversion.com/rewind
+1 -1
View File
@@ -13,7 +13,7 @@ sourceSets {
main {
classTokenReplacer {
property("\${version}", rootProject.maven_version)
property("\${impl_version}", "git-${project.name}-${rootProject.maven_version}:${project.latestCommitHash()}")
property("\${impl_version}", "git-ViaRewind-${rootProject.maven_version}:${project.latestCommitHash()}")
}
}
}
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind;
import com.google.common.base.Preconditions;
@@ -15,12 +15,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind;
import com.viaversion.viaversion.util.Config;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.List;
@@ -28,44 +28,88 @@ import java.util.Map;
public class ViaRewindConfig extends Config implements com.viaversion.viarewind.api.ViaRewindConfig {
private CooldownIndicator cooldownIndicator;
private boolean replaceAdventureMode;
private boolean replaceParticles;
private int maxBookPages;
private int maxBookPageSize;
private boolean emulateWorldBorder;
private boolean alwaysShowOriginalMobName;
private String worldBorderParticle;
private boolean enableOffhand;
private String offhandCommand;
public ViaRewindConfig(File configFile) {
super(configFile);
reload();
}
@Override
@Override
public void reload() {
super.reload();
loadFields();
}
private void loadFields() {
cooldownIndicator = CooldownIndicator.valueOf(getString("cooldown-indicator", "TITLE").toUpperCase());
replaceAdventureMode = getBoolean("replace-adventure", false);
replaceParticles = getBoolean("replace-particles", false);
maxBookPages = getInt("max-book-pages", 100);
maxBookPageSize = getInt("max-book-page-length", 5000);
emulateWorldBorder = getBoolean("emulate-world-border", true);
alwaysShowOriginalMobName = getBoolean("always-show-original-mob-name", true);
worldBorderParticle = getString("world-border-particle", "fireworksSpark");
enableOffhand = getBoolean("enable-offhand", true);
offhandCommand = getString("offhand-command", "/offhand");
}
@Override
public CooldownIndicator getCooldownIndicator() {
return CooldownIndicator.valueOf(getString("cooldown-indicator", "TITLE").toUpperCase());
return cooldownIndicator;
}
@Override
public boolean isReplaceAdventureMode() {
return getBoolean("replace-adventure", false);
return replaceAdventureMode;
}
@Override
public boolean isReplaceParticles() {
return getBoolean("replace-particles", false);
return replaceParticles;
}
@Override
public int getMaxBookPages() {
return getInt("max-book-pages", 100);
return maxBookPages;
}
@Override
public int getMaxBookPageSize() {
return getInt("max-book-page-length", 5000);
return maxBookPageSize;
}
@Override
public boolean isEmulateWorldBorder() {
return getBoolean("emulate-world-border", true);
return emulateWorldBorder;
}
@Override
public boolean alwaysShowOriginalMobName() {
return alwaysShowOriginalMobName;
}
@Override
public String getWorldBorderParticle() {
return getString("world-border-particle", "fireworksSpark");
return worldBorderParticle;
}
@Override
public boolean isEnableOffhand() {
return enableOffhand;
}
@Override
public String getOffhandCommand() {
return offhandCommand;
}
@Override
@@ -74,8 +118,12 @@ public class ViaRewindConfig extends Config implements com.viaversion.viarewind.
}
@Override
protected void handleConfig(Map<String, Object> map) {
public InputStream getDefaultConfigInputStream() {
return getClass().getClassLoader().getResourceAsStream("assets/viarewind/config.yml");
}
@Override
protected void handleConfig(Map<String, Object> map) {
}
@Override
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api;
import com.viaversion.viaversion.api.configuration.Config;
@@ -77,10 +76,31 @@ public interface ViaRewindConfig extends Config {
*/
boolean isEmulateWorldBorder();
/**
* Always shows the original mob's name instead of only when hovering over them with the cursor.
*
* @return true if enabled
*/
boolean alwaysShowOriginalMobName();
/**
* The particle to show the world border for the 1.8+ world border for 1.7.x clients
*
* @return the particle name (see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Particle_2">Particle registry for Packet</a>)
*/
String getWorldBorderParticle();
/**
* If enabled, 1.8 players on 1.9+ servers can use /offhand to switch items between their main hand and offhand.
*
* @return true if enabled
*/
boolean isEnableOffhand();
/**
* Allows to define the offhand command
*
* @return the offhand command
*/
String getOffhandCommand();
}
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api;
import com.viaversion.viarewind.ViaRewind;
@@ -50,10 +49,11 @@ public interface ViaRewindPlatform {
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
getLogger().info("Registering protocols...");
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.registerProtocol(new Protocol1_7_2_5To1_7_6_10(), ProtocolVersion.v1_7_1, ProtocolVersion.v1_7_6);
protocolManager.registerProtocol(new Protocol1_7_2_5To1_7_6_10(), ProtocolVersion.v1_7_2, ProtocolVersion.v1_7_6);
protocolManager.registerProtocol(new Protocol1_7_6_10To1_8(), ProtocolVersion.v1_7_6, ProtocolVersion.v1_8);
protocolManager.registerProtocol(new Protocol1_8To1_9(), ProtocolVersion.v1_8, ProtocolVersion.v1_9);
}
@@ -15,13 +15,27 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.data;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
public class FurnaceData {
import java.util.logging.Logger;
public short fuelLeft = 0;
public short maxFuel = 0;
public short progress = 0;
public short maxProgress = 200;
public class RewindMappings extends BackwardsMappings {
public RewindMappings(String unmappedVersion, String mappedVersion) {
super(unmappedVersion, mappedVersion);
}
@Override
protected Logger getLogger() {
return ViaRewind.getPlatform().getLogger();
}
@Override
protected CompoundTag readMappingsFile(String name) {
return VRMappingDataLoader.INSTANCE.loadNBTFromDir(name);
}
}
@@ -15,25 +15,30 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.data;
package com.viaversion.viarewind.utils;
import com.viaversion.viabackwards.api.data.BackwardsMappingDataLoader;
import com.viaversion.viarewind.ViaRewind;
import java.util.HashMap;
import java.util.Map;
import java.io.File;
import java.util.logging.Logger;
public class Enchantments {
public final static Map<Short, String> ENCHANTMENTS = new HashMap<>();
public class VRMappingDataLoader extends BackwardsMappingDataLoader {
static {
ENCHANTMENTS.put((short) 1, "I");
ENCHANTMENTS.put((short) 2, "II");
ENCHANTMENTS.put((short) 3, "III");
ENCHANTMENTS.put((short) 4, "IV");
ENCHANTMENTS.put((short) 5, "V");
ENCHANTMENTS.put((short) 6, "VI");
ENCHANTMENTS.put((short) 7, "VII");
ENCHANTMENTS.put((short) 8, "VIII");
ENCHANTMENTS.put((short) 9, "IX");
ENCHANTMENTS.put((short) 10, "X");
public static final VRMappingDataLoader INSTANCE = new VRMappingDataLoader();
public VRMappingDataLoader() {
super(VRMappingDataLoader.class, "assets/viarewind/data/");
}
@Override
public Logger getLogger() {
return ViaRewind.getPlatform().getLogger();
}
@Override
public File getDataFolder() {
return ViaRewind.getPlatform().getDataFolder();
}
}
@@ -1,102 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
import java.util.List;
/**
* Represents a model that is replacing an entity on the client side (e.g. armor stand)
*/
public abstract class EntityModel<T extends Protocol<?, ?, ?, ?>> {
protected final UserConnection user;
protected final T protocol;
public EntityModel(final UserConnection user, final T protocol) {
this.user = user;
this.protocol = protocol;
}
/**
* @return The entity id of the entity this model is replacing
*/
public abstract int getEntityId();
/**
* Updates the position of the entity this model is replacing
*
* @param x The new x position
* @param y The new y position
* @param z The new z position
*/
public abstract void updateReplacementPosition(final double x, final double y, final double z);
/**
* Handles the original movement packet of the entity this model is replacing
*
* @param x The x position
* @param y The y position
* @param z The z position
*/
public abstract void handleOriginalMovementPacket(final double x, final double y, final double z);
/**
* Sets the yaw and pitch of the entity this model is replacing
*
* @param yaw The new yaw
* @param pitch The new pitch
*/
public abstract void setYawPitch(final float yaw, final float pitch);
/**
* Sets the head yaw of the entity this model is replacing
*
* @param yaw The new head yaw
*/
public abstract void setHeadYaw(final float yaw);
/**
* Spawns the entity this model is replacing
*/
public abstract void sendSpawnPacket();
/**
* Destroys the entity this model is replacing
*/
public abstract void deleteEntity();
/**
* Updates the metadata of the entity this model is replacing
*
* @param metadataList The new metadata
*/
public abstract void updateMetadata(final List<Metadata> metadataList);
public UserConnection getUser() {
return user;
}
public T getProtocol() {
return protocol;
}
}
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.netty;
import io.netty.channel.ChannelHandler;
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.netty;
import io.netty.buffer.ByteBuf;
@@ -1,106 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.util.ChatColorUtil;
public class Replacement {
private final int id;
private final int data;
private final String name;
private String resetName;
private String bracketName;
public Replacement(final int id) {
this(id, -1);
}
public Replacement(final int id, final int data) {
this(id, data, null);
}
public Replacement(final int id, final String name) {
this(id, -1, name);
}
public Replacement(final int id, final int data, final String name) {
this.id = id;
this.data = data;
this.name = name;
}
public void buildNames(final String protocolVersion) {
if (this.name != null) {
this.resetName = ChatColorUtil.translateAlternateColorCodes("&r" + protocolVersion + " " + this.name);
this.bracketName = ChatColorUtil.translateAlternateColorCodes(" &r&7(" + protocolVersion + " " + this.name + "&r&7)");
}
}
public int getId() {
return id;
}
public int getData() {
return data;
}
public String getName() {
return name;
}
/**
* @param item The item to replace
* @return The replacement for the item or the item if not found
*/
public Item replace(final Item item) {
item.setIdentifier(id); // Set the new id
if (data != -1) {
item.setData((short) data); // Set the new data
}
if (name != null) { // Set the new name
CompoundTag rootTag = item.tag() == null ? new CompoundTag() : item.tag(); // Get root tag or create new one if not exists
if (!rootTag.contains("display")) rootTag.put("display", new CompoundTag()); // Create display tag if not exists
final CompoundTag display = rootTag.get("display");
if (display.contains("Name")) {
final StringTag name = display.get("Name");
if (!name.getValue().equals(resetName) && !name.getValue().endsWith(bracketName)) {
name.setValue(name.getValue() + bracketName); // Append the new name tag
}
} else {
display.put("Name", new StringTag(resetName)); // Set the new name tag
}
item.setTag(rootTag);
}
return item;
}
/**
* @param data The data of the item/block
* @return The replacement data for the item/block
*/
public int replaceData(int data) {
return this.data == -1 ? data : this.data;
}
}
@@ -1,116 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.ClientEntityIdChangeListener;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class ReplacementEntityTracker extends StoredObject implements ClientEntityIdChangeListener {
private final Map<EntityType, Pair<EntityType, String>> ENTITY_REPLACEMENTS = new HashMap<>();
private final Map<Integer, EntityType> entityMap = new HashMap<>();
private final Map<Integer, EntityType> entityReplacementMap = new HashMap<>();
private int playerId = -1;
private final ProtocolVersion version;
private final int displayNameVisibilityIndex;
private final MetaType displayNameVisibilityType;
private final int displayNameIndex;
private final MetaType displayNameType;
public ReplacementEntityTracker(UserConnection user, ProtocolVersion version, MetaType displayNameVisibilityType, MetaType displayNameType) {
this(user, version, 3, displayNameVisibilityType, 2, displayNameType);
}
public ReplacementEntityTracker(UserConnection user, ProtocolVersion version, int displayNameVisibilityIndex, MetaType displayNameVisibilityType, int displayNameIndex, MetaType displayNameType) {
super(user);
this.version = version;
this.displayNameVisibilityIndex = displayNameVisibilityIndex;
this.displayNameVisibilityType = displayNameVisibilityType;
this.displayNameIndex = displayNameIndex;
this.displayNameType = displayNameType;
}
public void registerEntity(final EntityType oldType, final EntityType newType, final String name) {
ENTITY_REPLACEMENTS.put(oldType, new Pair<>(newType, this.version.getName() + " " + name));
}
public void addEntity(final int entityId, final EntityTypes1_10.EntityType type) {
entityMap.put(entityId, type);
}
public int replaceEntity(final int entityId, final EntityTypes1_10.EntityType type) {
entityReplacementMap.put(entityId, type);
return ENTITY_REPLACEMENTS.get(type).key().getId();
}
public void removeEntity(final int entityId) {
entityMap.remove(entityId);
entityReplacementMap.remove(entityId);
}
public void clear() {
entityMap.clear();
entityReplacementMap.clear();
}
public boolean isReplaced(final EntityTypes1_10.EntityType type) {
return ENTITY_REPLACEMENTS.containsKey(type);
}
public void updateMetadata(final int entityId, final List<Metadata> metadata) throws Exception {
final String name = ENTITY_REPLACEMENTS.get(entityMap.get(entityId)).value();
metadata.add(new Metadata(this.displayNameVisibilityIndex, this.displayNameVisibilityType, (byte) 1));
metadata.add(new Metadata(this.displayNameIndex, this.displayNameType, name));
}
@Override
public void setClientEntityId(int entityId) {
removeEntity(this.playerId);
addEntity(entityId, EntityTypes1_10.EntityType.ENTITY_HUMAN);
this.playerId = entityId;
}
public Map<Integer, EntityType> getEntityMap() {
return entityMap;
}
public Map<Integer, EntityType> getEntityReplacementMap() {
return entityReplacementMap;
}
public int getPlayerId() {
return playerId;
}
}
@@ -1,115 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viarewind.api.minecraft.IdDataCombine;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
public abstract class ReplacementItemRewriter<T extends AbstractProtocol<?, ?, ?, ?>> implements ItemRewriter<T> {
private final Int2ObjectMap<Replacement> ITEM_REPLACEMENTS = new Int2ObjectOpenHashMap<>();
private final Int2ObjectMap<Replacement> BLOCK_REPLACEMENTS = new Int2ObjectOpenHashMap<>();
private final T protocol;
private final ProtocolVersion protocolVersion;
public ReplacementItemRewriter(final T protocol, final ProtocolVersion protocolVersion) {
this.protocol = protocol;
this.protocolVersion = protocolVersion;
}
public void registerItem(int id, Replacement replacement) {
registerItem(id, -1, replacement);
}
public void registerBlock(int id, Replacement replacement) {
registerBlock(id, -1, replacement);
}
public void registerItemBlock(int id, Replacement replacement) {
registerItemBlock(id, -1, replacement);
}
public void registerItem(int id, int data, Replacement replacement) {
ITEM_REPLACEMENTS.put(generateTrackingId(id, data), replacement);
replacement.buildNames(protocolVersion.getName());
}
public void registerBlock(int id, int data, Replacement replacement) {
BLOCK_REPLACEMENTS.put(generateTrackingId(id, data), replacement);
replacement.buildNames(protocolVersion.getName());
}
public void registerItemBlock(int id, int data, Replacement replacement) {
registerItem(id, data, replacement);
registerBlock(id, data, replacement);
}
/**
* @param item The item to replace
* @return The replacement for the item or the item if not found
*/
public Item replace(Item item) {
Replacement replacement = ITEM_REPLACEMENTS.get(generateTrackingId(item.identifier(), item.data()));
if (replacement == null) replacement = ITEM_REPLACEMENTS.get(generateTrackingId(item.identifier(), -1));
return replacement == null ? item : replacement.replace(item);
}
/**
* @param id The id of the item/block
* @param data The data of the item/block
* @return The replacement for the item/block or null if not found
*/
public Replacement replace(int id, int data) {
Replacement replacement = BLOCK_REPLACEMENTS.get(generateTrackingId(id, data));
if (replacement == null) replacement = BLOCK_REPLACEMENTS.get(generateTrackingId(id, -1));
return replacement;
}
/**
* @param combined The combined id and data
* @return The generated tracking id for the item/block
*/
public int replace(int combined) {
final int data = IdDataCombine.dataFromCombined(combined);
final Replacement replace = replace(IdDataCombine.idFromCombined(combined), data);
return replace != null ? IdDataCombine.toCombined(replace.getId(), replace.replaceData(data)) : combined;
}
/**
* @param id The id of the item/block
* @param data The data of the item/block
* @return The generated tracking id for the item/block
*/
private int generateTrackingId(int id, int data) {
return (id << 16) | (data & 0xFFFF);
}
@Override
public T protocol() {
return this.protocol;
}
}
@@ -0,0 +1,42 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.LegacyBlockItemRewriter;
import com.viaversion.viarewind.api.data.VRMappingDataLoader;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.libs.gson.JsonObject;
public class VRBlockItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType, T extends BackwardsProtocol<C, ?, ?, S>> extends LegacyBlockItemRewriter<C, S, T> {
protected VRBlockItemRewriter(T protocol, String name) {
super(protocol, name);
}
@Override
protected JsonObject readMappingsFile(String name) {
return VRMappingDataLoader.INSTANCE.loadFromDataDir(name);
}
@Override
public String nbtTagName() {
return "VR|" + protocol.getClass().getSimpleName();
}
}
@@ -0,0 +1,71 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
public abstract class VREntityRewriter<C extends ClientboundPacketType, T extends BackwardsProtocol<C, ?, ?, ?>> extends LegacyEntityRewriter<C, T> {
public VREntityRewriter(T protocol) {
super(protocol, MetaType1_8.String, MetaType1_8.Byte);
}
public VREntityRewriter(T protocol, MetaType displayType, MetaType displayVisibilityType) {
super(protocol, displayType, displayVisibilityType);
}
protected void registerJoinGame1_8(final C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
protected void register() {
map(Type.INT); // Entity id
map(Type.UNSIGNED_BYTE); // Game mode
map(Type.BYTE); // Dimension
handler(playerTrackerHandler());
handler(wrapper -> wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Type.BYTE, 0)));
}
});
}
protected void untrackEntities(final UserConnection connection, final int[] entities) {
final EntityTrackerBase tracker = tracker(connection);
for (int entityId : entities) {
tracker.removeEntity(entityId);
}
}
@Override
protected Object getDisplayVisibilityMetaValue() {
return (byte) 1;
}
@Override
protected boolean alwaysShowOriginalMobName() {
return ViaRewind.getConfig().alwaysShowOriginalMobName();
}
}
@@ -15,16 +15,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.NBTType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.ItemArrayType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.ItemType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetadataListType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetadataType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive.ByteIntArrayType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive.PositionUYType;
import com.viaversion.viarewind.api.type.item.NBTType;
import com.viaversion.viarewind.api.type.item.ItemArrayType;
import com.viaversion.viarewind.api.type.item.ItemType;
import com.viaversion.viarewind.api.type.metadata.MetadataListType;
import com.viaversion.viarewind.api.type.metadata.MetadataType;
import com.viaversion.viarewind.api.type.primitive.ByteIntArrayType;
import com.viaversion.viarewind.api.type.primitive.PositionUYType;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
@@ -36,21 +35,21 @@ import java.util.List;
public class Types1_7_6_10 {
// Primitives
public final static Type<int[]> BYTE_INT_ARRAY = new ByteIntArrayType(); // Integer array with byte as length indicator
public static final Type<int[]> BYTE_INT_ARRAY = new ByteIntArrayType(); // Integer array with byte as length indicator
// Positions /shrug
public final static Type<Position> SHORT_POSITION = new PositionUYType<>(Type.SHORT, value -> (short) value);
public final static Type<Position> INT_POSITION = new PositionUYType<>(Type.INT, value -> value);
public final static Type<Position> BYTE_POSITION = new PositionUYType<>(Type.BYTE, value -> (byte) value);
public final static Type<Position> U_BYTE_POSITION = new PositionUYType<>(Type.UNSIGNED_BYTE, value -> (short) value);
public static final Type<Position> SHORT_POSITION = new PositionUYType<>(Type.SHORT, value -> (short) value);
public static final Type<Position> INT_POSITION = new PositionUYType<>(Type.INT, value -> value);
public static final Type<Position> BYTE_POSITION = new PositionUYType<>(Type.BYTE, value -> (byte) value);
public static final Type<Position> U_BYTE_POSITION = new PositionUYType<>(Type.UNSIGNED_BYTE, value -> (short) value);
// Items
public final static Type<CompoundTag> COMPRESSED_NBT = new NBTType();
public final static Type<Item> COMPRESSED_NBT_ITEM = new ItemType();
public final static Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType();
public static final Type<CompoundTag> COMPRESSED_NBT = new NBTType();
public static final Type<Item> COMPRESSED_NBT_ITEM = new ItemType();
public static final Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType();
// Metadata
public final static Type<Metadata> METADATA = new MetadataType();
public final static Type<List<Metadata>> METADATA_LIST = new MetadataListType();
public static final Type<Metadata> METADATA = new MetadataType();
public static final Type<List<Metadata>> METADATA_LIST = new MetadataListType();
}
@@ -1,4 +1,21 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk;
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
@@ -11,7 +28,7 @@ import java.util.zip.Deflater;
public class BulkChunkType1_7_6 extends Type<Chunk[]> {
public final static BulkChunkType1_7_6 TYPE = new BulkChunkType1_7_6();
public static final BulkChunkType1_7_6 TYPE = new BulkChunkType1_7_6();
public BulkChunkType1_7_6() {
super(Chunk[].class);
@@ -15,10 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.chunk;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk;
import com.viaversion.viarewind.api.minecraft.ExtendedBlockStorage;
import com.viaversion.viarewind.utils.ExtendedBlockStorage;
import com.viaversion.viaversion.api.minecraft.chunks.*;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Pair;
@@ -30,7 +29,7 @@ import java.util.zip.Deflater;
public class ChunkType1_7_6 extends Type<Chunk> {
public final static ChunkType1_7_6 TYPE = new ChunkType1_7_6();
public static final ChunkType1_7_6 TYPE = new ChunkType1_7_6();
public ChunkType1_7_6() {
super(Chunk.class);
@@ -15,10 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.item;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
@@ -15,10 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.item;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
package com.viaversion.viarewind.api.type.item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
@@ -15,13 +15,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.metadata;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.VoidType;
public enum MetaType1_7_6_10 implements MetaType {
Byte(0, Type.BYTE),
@@ -30,8 +28,7 @@ public enum MetaType1_7_6_10 implements MetaType {
Float(3, Type.FLOAT),
String(4, Type.STRING),
Slot(5, Types1_7_6_10.COMPRESSED_NBT_ITEM),
Position(6, Type.VECTOR),
NonExistent(-1, new VoidType());
Position(6, Type.VECTOR);
private final int typeID;
private final Type<?> type;
@@ -15,10 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.metadata;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.types.metadata.MetaListTypeTemplate;
import io.netty.buffer.ByteBuf;
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
package com.viaversion.viarewind.api.type.metadata;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.types.metadata.MetaTypeTemplate;
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive;
package com.viaversion.viarewind.api.type.primitive;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
@@ -1,4 +1,21 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive;
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.type.primitive;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.type.Type;
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
@@ -15,10 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
@@ -32,9 +31,10 @@ import java.util.List;
import java.util.stream.Collectors;
public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPackets1_7_2_5, ClientboundPackets1_7_2_5, ServerboundPackets1_7_2_5, ServerboundPackets1_7_2_5> {
public final static ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<String, String>(Type.STRING) {
public static final ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<String, String>(Type.STRING) {
@Override
public String transform(PacketWrapper packetWrapper, String s) {
public String transform(PacketWrapper wrapper, String s) {
return s.replace("-", "");
}
};
@@ -59,12 +59,12 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
map(Type.VAR_INT); // entity id
map(Type.STRING, REMOVE_DASHES); // uuid
map(Type.STRING); // name
handler(packetWrapper -> { // delete data introduced in 1.7.6
final int size = packetWrapper.read(Type.VAR_INT); // data count
handler(wrapper -> { // delete data introduced in 1.7.6
final int size = wrapper.read(Type.VAR_INT); // data count
for (int i = 0; i < size; i++) {
packetWrapper.read(Type.STRING); // data name
packetWrapper.read(Type.STRING); // data value
packetWrapper.read(Type.STRING); // data signature
wrapper.read(Type.STRING); // data name
wrapper.read(Type.STRING); // data value
wrapper.read(Type.STRING); // data signature
}
});
map(Type.INT); // x
@@ -72,7 +72,7 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // item in hand
map(Type.SHORT); // item in hand
map(Types1_7_6_10.METADATA_LIST); // metadata
}
});
@@ -82,29 +82,29 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
public void register() {
map(Type.STRING); // team name
map(Type.BYTE); // mode
handler(packetWrapper -> {
byte mode = packetWrapper.get(Type.BYTE, 0);
handler(wrapper -> {
final byte mode = wrapper.get(Type.BYTE, 0);
if (mode == 0 || mode == 2) { // team is created or information is updated
packetWrapper.passthrough(Type.STRING); // team display name
packetWrapper.passthrough(Type.STRING); // team prefix
packetWrapper.passthrough(Type.STRING); // team suffix
packetWrapper.passthrough(Type.BYTE); // friendly fire
wrapper.passthrough(Type.STRING); // team display name
wrapper.passthrough(Type.STRING); // team prefix
wrapper.passthrough(Type.STRING); // team suffix
wrapper.passthrough(Type.BYTE); // friendly fire
}
if (mode == 0 || mode == 3 || mode == 4) { // team is created, player is added or player is removed
List<String> entryList = new ArrayList<>();
final int size = packetWrapper.read(Type.SHORT);
final int size = wrapper.read(Type.SHORT);
for (int i = 0; i < size; i++) {
entryList.add(packetWrapper.read(Type.STRING));
entryList.add(wrapper.read(Type.STRING));
}
entryList = entryList.stream()
.map(it -> it.length() > 16 ? it.substring(0, 16) : it) // trim to 16 characters
.distinct() // remove duplicates
.collect(Collectors.toList());
.map(it -> it.length() > 16 ? it.substring(0, 16) : it) // trim to 16 characters
.distinct() // remove duplicates
.collect(Collectors.toList());
packetWrapper.write(Type.SHORT, (short) entryList.size());
wrapper.write(Type.SHORT, (short) entryList.size());
for (String entry : entryList) {
packetWrapper.write(Type.STRING, entry);
wrapper.write(Type.STRING, entry);
}
}
});
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
@@ -15,25 +15,23 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.ReplacementItemRewriter;
import com.viaversion.viarewind.api.data.RewindMappings;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.CompressionHandlerProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression.TrackingCompressionHandlerProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.ReplacementItemRewriter1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.task.WorldBorderUpdateTask;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
@@ -46,10 +44,12 @@ import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import java.util.concurrent.TimeUnit;
public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_8, ClientboundPackets1_7_2_5, ServerboundPackets1_8, ServerboundPackets1_7_2_5> {
public class Protocol1_7_6_10To1_8 extends BackwardsProtocol<ClientboundPackets1_8, ClientboundPackets1_7_2_5, ServerboundPackets1_8, ServerboundPackets1_7_2_5> {
private final ReplacementItemRewriter<Protocol1_7_6_10To1_8> itemRewriter = new ReplacementItemRewriter1_7_6_10(this);
private final MetadataRewriter metadataRewriter = new MetadataRewriter(this);
public static final RewindMappings MAPPINGS = new RewindMappings("1.8", "1.7.10");
private final BlockItemPackets1_8 itemRewriter = new BlockItemPackets1_8(this);
private final MetadataRewriter1_7_6_10To1_8 metadataRewriter = new MetadataRewriter1_7_6_10To1_8(this);
public Protocol1_7_6_10To1_8() {
super(ClientboundPackets1_8.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_8.class, ServerboundPackets1_7_2_5.class);
@@ -58,13 +58,12 @@ public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_
@Override
protected void registerPackets() {
itemRewriter.register();
metadataRewriter.register();
EntityPackets.register(this);
InventoryPackets.register(this);
PlayerPackets.register(this);
ScoreboardPackets.register(this);
SpawnPackets.register(this);
WorldPackets.register(this);
EntityPackets1_8.register(this);
PlayerPackets1_8.register(this);
ScoreboardPackets1_8.register(this);
WorldPackets1_8.register(this);
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketHandlers() {
@Override
@@ -117,17 +116,18 @@ public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_
}
@Override
public void init(UserConnection userConnection) {
userConnection.put(new InventoryTracker(userConnection));
userConnection.put(new EntityTracker1_7_6_10(userConnection, metadataRewriter));
userConnection.put(new PlayerSessionStorage(userConnection));
userConnection.put(new GameProfileStorage(userConnection));
userConnection.put(new Scoreboard(userConnection));
userConnection.put(new CompressionStatusTracker(userConnection));
userConnection.put(new WorldBorderEmulator(userConnection));
public void init(UserConnection connection) {
connection.addEntityTracker(this.getClass(), new EntityTracker1_8(connection));
if (!userConnection.has(ClientWorld.class)) {
userConnection.put(new ClientWorld());
connection.put(new InventoryTracker(connection));
connection.put(new PlayerSessionStorage(connection));
connection.put(new GameProfileStorage(connection));
connection.put(new Scoreboard(connection));
connection.put(new CompressionStatusTracker(connection));
connection.put(new WorldBorderEmulator(connection));
if (!connection.has(ClientWorld.class)) {
connection.put(new ClientWorld());
}
}
@@ -141,11 +141,22 @@ public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_
}
@Override
public ReplacementItemRewriter<Protocol1_7_6_10To1_8> getItemRewriter() {
public RewindMappings getMappingData() {
return MAPPINGS;
}
@Override
public BlockItemPackets1_8 getItemRewriter() {
return itemRewriter;
}
public MetadataRewriter getMetadataRewriter() {
@Override
public MetadataRewriter1_7_6_10To1_8 getEntityRewriter() {
return metadataRewriter;
}
@Override
public boolean hasMappingDataToLoad() {
return true;
}
}
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.data;
import java.util.HashMap;
@@ -66,7 +65,7 @@ public enum ParticleIndex1_7_6_10 {
public final String name;
public final int extra;
private final static HashMap<String, ParticleIndex1_7_6_10> particleMap = new HashMap<>();
private static final HashMap<String, ParticleIndex1_7_6_10> particleMap = new HashMap<>();
ParticleIndex1_7_6_10(String name) {
this(name, 0);
@@ -15,16 +15,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.emulation;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetaIndex1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetaIndex;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.api.type.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter1_7_6_10To1_8;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Vector3d;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -33,17 +31,18 @@ import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.TrackedEntityImpl;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEventImpl;
import java.util.ArrayList;
import java.util.List;
// Close this class file while you still can, because it's about to get ugly
public class VirtualHologramEntity {
private final List<Metadata> metadataTracker = new ArrayList<>();
private double locX, locY, locZ;
private final UserConnection user;
private final MetadataRewriter metadataRewriter;
private final int entityId;
private int[] entityIds = null;
@@ -54,64 +53,53 @@ public class VirtualHologramEntity {
private boolean small = false;
private boolean marker = false;
public VirtualHologramEntity(final UserConnection user, final MetadataRewriter metadataRewriter, final int entityId) {
public VirtualHologramEntity(final UserConnection user, final int entityId) {
this.user = user;
this.metadataRewriter = metadataRewriter;
this.entityId = entityId;
}
public void updateReplacementPosition(double x, double y, double z) {
if (x == this.locX && y == this.locY && z == this.locZ) {
return;
}
public void setPosition(final double x, final double y, final double z) throws Exception {
if (x == this.locX && y == this.locY && z == this.locZ) return;
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation(false);
}
public void handleOriginalMovementPacket(double x, double y, double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) {
return;
}
public void setRelativePosition(final double x, final double y, final double z) throws Exception {
if (x == 0.0 && y == 0.0 && z == 0.0) return;
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation(false);
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw == yaw || this.headYaw == yaw || this.pitch == pitch) {
return;
}
public void setRotation(final float yaw, final float pitch) throws Exception {
if (this.yaw == yaw || this.headYaw == yaw || this.pitch == pitch) return;
this.yaw = yaw;
this.headYaw = yaw;
this.pitch = pitch;
updateLocation(false);
}
public void setHeadYaw(float yaw) {
if (this.headYaw == yaw) {
return;
}
public void setHeadYaw(float yaw) throws Exception {
if (this.headYaw == yaw) return;
this.headYaw = yaw;
updateLocation(false);
}
public void updateMetadata(final List<Metadata> metadataList) {
public void syncState(final MetadataRewriter1_7_6_10To1_8 entityRewriter, final List<Metadata> metadataList) throws Exception {
// Merge metadata updates into current tracker
for (Metadata metadata : metadataList) {
metadataTracker.removeIf(m -> m.id() == metadata.id());
metadataTracker.add(metadata);
}
updateState();
}
public void updateState() {
// Filter armor stand data to calculate emulation
byte flags = 0;
byte armorStandFlags = 0;
for (Metadata metadata : metadataTracker) {
@@ -137,16 +125,17 @@ public class VirtualHologramEntity {
if (currentState != prevState) {
deleteEntity();
sendSpawnPacket();
sendSpawnPacket(entityRewriter);
} else {
updateMetadata();
sendMetadataUpdate(entityRewriter);
updateLocation(false);
}
}
public void updateLocation(boolean remount) {
if (entityIds == null) return;
private void updateLocation(final boolean remount) throws Exception {
if (entityIds == null) {
return;
}
if (currentState == State.ZOMBIE) {
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
@@ -155,14 +144,14 @@ public class VirtualHologramEntity {
entityHeadLook.write(Type.INT, entityId);
entityHeadLook.write(Type.BYTE, (byte) ((headYaw / 360f) * 256));
PacketUtil.sendPacket(entityHeadLook, Protocol1_7_6_10To1_8.class, true, true);
entityHeadLook.send(Protocol1_7_6_10To1_8.class);
} else if (currentState == State.HOLOGRAM) {
if (remount) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, null, user);
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, user);
detach.write(Type.INT, entityIds[1]);
detach.write(Type.INT, -1);
detach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(detach, Protocol1_7_6_10To1_8.class, true, true);
detach.send(Protocol1_7_6_10To1_8.class);
}
// Don't ask me where this offset is coming from
@@ -175,12 +164,12 @@ public class VirtualHologramEntity {
attach.write(Type.INT, entityIds[1]);
attach.write(Type.INT, entityIds[0]);
attach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(attach, Protocol1_7_6_10To1_8.class, true, true);
attach.send(Protocol1_7_6_10To1_8.class);
}
}
}
protected void teleportEntity(final int entityId, final double x, final double y, final double z, final float yaw, final float pitch) {
protected void teleportEntity(final int entityId, final double x, final double y, final double z, final float yaw, final float pitch) throws Exception {
final PacketWrapper entityTeleport = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_TELEPORT, user);
entityTeleport.write(Type.INT, entityId); // entity id
@@ -190,10 +179,10 @@ public class VirtualHologramEntity {
entityTeleport.write(Type.BYTE, (byte) ((yaw / 360f) * 256)); // yaw
entityTeleport.write(Type.BYTE, (byte) ((pitch / 360f) * 256)); // pitch
PacketUtil.sendPacket(entityTeleport, Protocol1_7_6_10To1_8.class, true, true);
entityTeleport.send(Protocol1_7_6_10To1_8.class);
}
protected void spawnEntity(final int entityId, final int type, final double locX, final double locY, final double locZ) {
protected void spawnEntity(final int entityId, final int type, final double locX, final double locY, final double locZ) throws Exception {
final PacketWrapper spawnMob = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_MOB, null, user);
spawnMob.write(Type.VAR_INT, entityId); // entity id
@@ -209,61 +198,82 @@ public class VirtualHologramEntity {
spawnMob.write(Type.SHORT, (short) 0); // velocity z
spawnMob.write(Types1_7_6_10.METADATA_LIST, new ArrayList<>()); // metadata
PacketUtil.sendPacket(spawnMob, Protocol1_7_6_10To1_8.class, true, true);
spawnMob.send(Protocol1_7_6_10To1_8.class);
}
public void updateMetadata() {
if (entityIds == null) return;
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_METADATA, null, user);
public void sendMetadataUpdate(final MetadataRewriter1_7_6_10To1_8 entityRewriter) throws Exception {
if (entityIds == null) {
return;
}
final PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_METADATA, user);
if (currentState == State.ZOMBIE) {
writeZombieMeta(metadataPacket);
writeZombieMeta(entityRewriter, metadataPacket);
} else if (currentState == State.HOLOGRAM) {
writeHologramMeta(metadataPacket);
} else {
return;
}
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class, true, true);
metadataPacket.send(Protocol1_7_6_10To1_8.class);
}
private void writeZombieMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[0]);
private void writeZombieMeta(final MetadataRewriter1_7_6_10To1_8 entityRewriter, PacketWrapper wrapper) {
wrapper.write(Type.INT, entityIds[0]);
List<Metadata> metadataList = new ArrayList<>();
// Filter metadata sent by the server and convert them together with our custom metadata
final List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : metadataTracker) {
if (metadata.id() < 0 || metadata.id() > 9) continue;
// Remove non existent metadata
if (metadata.id() < 0 || metadata.id() > 9) {
continue;
}
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
if (small) metadataList.add(new Metadata(12, MetaType1_8.Byte, (byte) 1));
metadataRewriter.transform(EntityTypes1_10.EntityType.ZOMBIE, metadataList);
if (small) {
metadataList.add(new Metadata(12, MetaType1_8.Byte, (byte) 1));
}
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
// Push metadata from the server through metadata conversion 1.7->1.8
for (Metadata metadata : metadataList.toArray(new Metadata[0])) {
final MetaHandlerEvent event = new MetaHandlerEventImpl(wrapper.user(), new TrackedEntityImpl(EntityTypes1_10.EntityType.ZOMBIE), -1, metadata, metadataList);
try {
entityRewriter.handleMetadata(event, metadata);
} catch (Exception e) {
metadataList.remove(metadata);
break;
}
if (event.cancelled()) {
metadataList.remove(metadata);
break;
}
}
wrapper.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
private void writeHologramMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[1]);
private void writeHologramMeta(PacketWrapper wrapper) {
wrapper.write(Type.INT, entityIds[1]);
List<Metadata> metadataList = new ArrayList<>();
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_AGEABLE_AGE.getIndex(), MetaType1_7_6_10.Int, -1700000));
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG.getIndex(), MetaType1_7_6_10.String, name));
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG_VISIBILITY.getIndex(), MetaType1_7_6_10.Byte, (byte) 1));
// Directly write 1.7 metadata here since we are making them up
final List<Metadata> metadataList = new ArrayList<>();
metadataList.add(new Metadata(MetaIndex.ENTITY_AGEABLE_AGE.getIndex(), MetaType1_7_6_10.Int, -1700000));
metadataList.add(new Metadata(MetaIndex.ENTITY_LIVING_NAME_TAG.getIndex(), MetaType1_7_6_10.String, name));
metadataList.add(new Metadata(MetaIndex.ENTITY_LIVING_NAME_TAG_VISIBILITY.getIndex(), MetaType1_7_6_10.Byte, (byte) 1));
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
wrapper.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
public void sendSpawnPacket() {
if (entityIds != null) deleteEntity();
public void sendSpawnPacket(final MetadataRewriter1_7_6_10To1_8 entityRewriter) throws Exception {
if (entityIds != null) {
deleteEntity();
}
if (currentState == State.ZOMBIE) {
spawnEntity(entityId, 54, locX, locY, locZ);
entityIds = new int[]{entityId};
} else if (currentState == State.HOLOGRAM) {
int[] entityIds = {entityId, additionalEntityId()};
final int[] entityIds = { entityId, additionalEntityId() };
PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_ENTITY, null, user);
final PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_ENTITY, user);
spawnSkull.write(Type.VAR_INT, entityIds[0]);
spawnSkull.write(Type.BYTE, (byte) 66);
spawnSkull.write(Type.INT, (int) (locX * 32.0));
@@ -272,14 +282,14 @@ public class VirtualHologramEntity {
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.INT, 0);
PacketUtil.sendPacket(spawnSkull, Protocol1_7_6_10To1_8.class, true, true);
spawnSkull.send(Protocol1_7_6_10To1_8.class);
spawnEntity(entityIds[1], 100, locX, locY, locZ); // Horse
this.entityIds = entityIds;
}
updateMetadata();
sendMetadataUpdate(entityRewriter);
updateLocation(true);
}
@@ -297,16 +307,17 @@ public class VirtualHologramEntity {
return Integer.MAX_VALUE - 16000 - entityId;
}
public void deleteEntity() {
if (entityIds == null) return;
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.DESTROY_ENTITIES, null, user);
public void deleteEntity() throws Exception {
if (entityIds == null) {
return;
}
final PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.DESTROY_ENTITIES, user);
despawn.write(Type.BYTE, (byte) entityIds.length);
for (int id : entityIds) {
despawn.write(Type.INT, id);
}
entityIds = null;
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
despawn.send(Protocol1_7_6_10To1_8.class);
}
private enum State {
@@ -15,10 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.api.type.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
@@ -27,93 +26,124 @@ import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.Optional;
public enum MetaIndex1_7_6_10To1_8 {
public enum MetaIndex {
ENTITY_FLAGS(EntityTypes1_10.EntityType.ENTITY, 0, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_AIR(EntityTypes1_10.EntityType.ENTITY, 1, MetaType1_7_6_10.Short, MetaType1_8.Short),
ENTITY_NAME_TAG(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 2, MetaType1_8.String),
ENTITY_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 3, MetaType1_8.Byte),
ENTITY_SILENT(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 4, MetaType1_8.Byte),
ENTITY_NAME_TAG(EntityTypes1_10.EntityType.ENTITY, -1, null, 2, MetaType1_8.String),
ENTITY_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY, -1, null, 3, MetaType1_8.Byte),
ENTITY_SILENT(EntityTypes1_10.EntityType.ENTITY, -1, null, 4, MetaType1_8.Byte),
ENTITY_LIVING_HEALTH(EntityTypes1_10.EntityType.ENTITY_LIVING, 6, MetaType1_7_6_10.Float, MetaType1_8.Float),
ENTITY_LIVING_POTION_EFFECT_COLOR(EntityTypes1_10.EntityType.ENTITY_LIVING, 7, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENTITY_LIVING_IS_POTION_EFFECT_AMBIENT(EntityTypes1_10.EntityType.ENTITY_LIVING, 8, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_ARROWS(EntityTypes1_10.EntityType.ENTITY_LIVING, 9, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_NAME_TAG(EntityTypes1_10.EntityType.ENTITY_LIVING, 10, MetaType1_7_6_10.String, 2, MetaType1_8.String),
ENTITY_LIVING_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY_LIVING, 11, MetaType1_7_6_10.Byte, 3, MetaType1_8.Byte),
ENTITY_LIVING_AI(EntityTypes1_10.EntityType.ENTITY_LIVING, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Byte),
ENTITY_LIVING_AI(EntityTypes1_10.EntityType.ENTITY_LIVING, -1, null, 15, MetaType1_8.Byte),
ENTITY_AGEABLE_AGE(EntityTypes1_10.EntityType.ENTITY_AGEABLE, 12, MetaType1_7_6_10.Int, MetaType1_8.Byte),
ARMOR_STAND_FLAGS(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 10, MetaType1_8.Byte),
ARMOR_STAND_HEAD_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 11, MetaType1_8.Rotation),
ARMOR_STAND_BODY_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 12, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 13, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 14, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Rotation),
ARMOR_STAND_FLAGS(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 10, MetaType1_8.Byte),
ARMOR_STAND_HEAD_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 11, MetaType1_8.Rotation),
ARMOR_STAND_BODY_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 12, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 13, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 14, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 15, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, null, 16, MetaType1_8.Rotation),
HUMAN_SKIN_FLAGS(EntityTypes1_10.EntityType.ENTITY_HUMAN, 16, MetaType1_7_6_10.Byte, 10, MetaType1_8.Byte),
HUMAN_UNUSED(EntityTypes1_10.EntityType.ENTITY_HUMAN, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Byte),
HUMAN_UNUSED(EntityTypes1_10.EntityType.ENTITY_HUMAN, -1, null, 16, MetaType1_8.Byte),
HUMAN_ABSORPTION_HEATS(EntityTypes1_10.EntityType.ENTITY_HUMAN, 17, MetaType1_7_6_10.Float, MetaType1_8.Float),
HUMAN_SCORE(EntityTypes1_10.EntityType.ENTITY_HUMAN, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_FLAGS(EntityTypes1_10.EntityType.HORSE, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_TYPE(EntityTypes1_10.EntityType.HORSE, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
HORSE_COLOR(EntityTypes1_10.EntityType.HORSE, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_OWNER(EntityTypes1_10.EntityType.HORSE, 21, MetaType1_7_6_10.String, MetaType1_8.String),
HORSE_ARMOR(EntityTypes1_10.EntityType.HORSE, 22, MetaType1_7_6_10.Int, MetaType1_8.Int),
BAT_HANGING(EntityTypes1_10.EntityType.BAT, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_FLAGS(EntityTypes1_10.EntityType.ENTITY_TAMEABLE_ANIMAL, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_OWNER(EntityTypes1_10.EntityType.ENTITY_TAMEABLE_ANIMAL, 17, MetaType1_7_6_10.String, MetaType1_8.String),
OCELOT_TYPE(EntityTypes1_10.EntityType.OCELOT, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_FLAGS(EntityTypes1_10.EntityType.WOLF, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_HEALTH(EntityTypes1_10.EntityType.WOLF, 18, MetaType1_7_6_10.Float, MetaType1_8.Float),
WOLF_BEGGING(EntityTypes1_10.EntityType.WOLF, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_COLLAR_COLOR(EntityTypes1_10.EntityType.WOLF, 20, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
PIG_SADDLE(EntityTypes1_10.EntityType.PIG, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SHEEP_COLOR_OR_SHEARED(EntityTypes1_10.EntityType.SHEEP, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
VILLAGER_TYPE(EntityTypes1_10.EntityType.VILLAGER, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENDERMAN_CARRIED_BLOCK(EntityTypes1_10.EntityType.ENDERMAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Short),
ENDERMAN_CARRIED_BLOCK_DATA(EntityTypes1_10.EntityType.ENDERMAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
ENDERMAN_CARRIED_BLOCK(EntityTypes1_10.EntityType.ENDERMAN, 16, null, MetaType1_8.Short),
ENDERMAN_CARRIED_BLOCK_DATA(EntityTypes1_10.EntityType.ENDERMAN, 17, null, MetaType1_8.Byte),
ENDERMAN_IS_SCREAMING(EntityTypes1_10.EntityType.ENDERMAN, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CHILD(EntityTypes1_10.EntityType.ZOMBIE, 12, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_VILLAGER(EntityTypes1_10.EntityType.ZOMBIE, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CONVERTING(EntityTypes1_10.EntityType.ZOMBIE, 14, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
BLAZE_ON_FIRE(EntityTypes1_10.EntityType.BLAZE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SPIDER_CLIMBING(EntityTypes1_10.EntityType.SPIDER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_STATE(EntityTypes1_10.EntityType.CREEPER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_POWERED(EntityTypes1_10.EntityType.CREEPER, 17, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_IGNITED(EntityTypes1_10.EntityType.CREEPER, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_STATE(EntityTypes1_10.EntityType.GHAST, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_IS_POWERED(EntityTypes1_10.EntityType.GHAST, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
GHAST_IS_POWERED(EntityTypes1_10.EntityType.GHAST, 17, null, MetaType1_8.Byte),
SLIME_SIZE(EntityTypes1_10.EntityType.SLIME, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SKELETON_TYPE(EntityTypes1_10.EntityType.SKELETON, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITCH_AGGRESSIVE(EntityTypes1_10.EntityType.WITCH, 21, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
IRON_GOLEM_IS_PLAYER_CREATED(EntityTypes1_10.EntityType.IRON_GOLEM, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITHER_WATCHED_TARGET_1(EntityTypes1_10.EntityType.WITHER, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TARGET_2(EntityTypes1_10.EntityType.WITHER, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TARGET_3(EntityTypes1_10.EntityType.WITHER, 19, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_INVULNERABLE_TIME(EntityTypes1_10.EntityType.WITHER, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
GUARDIAN_FLAGS(EntityTypes1_10.EntityType.GUARDIAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
GUARDIAN_TARGET(EntityTypes1_10.EntityType.GUARDIAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Int),
GUARDIAN_FLAGS(EntityTypes1_10.EntityType.GUARDIAN, 16, null, MetaType1_8.Byte),
GUARDIAN_TARGET(EntityTypes1_10.EntityType.GUARDIAN, 17, null, MetaType1_8.Int),
BOAT_TIME_SINCE_HIT(EntityTypes1_10.EntityType.BOAT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_FORWARD_DIRECTION(EntityTypes1_10.EntityType.BOAT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_DAMAGE_TAKEN(EntityTypes1_10.EntityType.BOAT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_SHAKING_POWER(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHAKING_DIRECTION(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_DAMAGE_TAKEN(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_BLOCK_INSIDE(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_BLOCK_Y(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 21, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHOW_BLOCK(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 22, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FURNACE_MINECART_IS_POWERED(EntityTypes1_10.EntityType.MINECART_FURNACE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ITEM_ITEM(EntityTypes1_10.EntityType.DROPPED_ITEM, 10, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ARROW_IS_CRITICAL(EntityTypes1_10.EntityType.ARROW, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FIREWORK_INFO(EntityTypes1_10.EntityType.FIREWORK, 8, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ITEM_FRAME_ITEM(EntityTypes1_10.EntityType.ITEM_FRAME, 2, MetaType1_7_6_10.Slot, 8, MetaType1_8.Slot),
ITEM_FRAME_ROTATION(EntityTypes1_10.EntityType.ITEM_FRAME, 3, MetaType1_7_6_10.Byte, 9, MetaType1_8.Byte),
ENDER_CRYSTAL_HEALTH(EntityTypes1_10.EntityType.ENDER_CRYSTAL, 8, MetaType1_7_6_10.Int, 9, MetaType1_8.Int),
;
private final static HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex1_7_6_10To1_8> metadataRewrites = new HashMap<>();
ENDER_CRYSTAL_HEALTH(EntityTypes1_10.EntityType.ENDER_CRYSTAL, 8, MetaType1_7_6_10.Int, 9, MetaType1_8.Int);
private static final HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
static {
for (MetaIndex1_7_6_10To1_8 index : MetaIndex1_7_6_10To1_8.values()) {
for (MetaIndex index : MetaIndex.values()) {
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
}
@@ -124,7 +154,7 @@ public enum MetaIndex1_7_6_10To1_8 {
private final MetaType1_7_6_10 oldType;
private final int index;
MetaIndex1_7_6_10To1_8(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, MetaType1_8 newType) {
MetaIndex(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.newIndex = index;
@@ -132,7 +162,7 @@ public enum MetaIndex1_7_6_10To1_8 {
this.newType = newType;
}
MetaIndex1_7_6_10To1_8(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, int newIndex, MetaType1_8 newType) {
MetaIndex(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, int newIndex, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.oldType = oldType;
@@ -140,7 +170,7 @@ public enum MetaIndex1_7_6_10To1_8 {
this.newType = newType;
}
private static Optional<MetaIndex1_7_6_10To1_8> getIndex(EntityType type, int index) {
private static Optional<MetaIndex> getIndex(EntityType type, int index) {
Pair<EntityType, Integer> pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
@@ -169,10 +199,10 @@ public enum MetaIndex1_7_6_10To1_8 {
return index;
}
public static MetaIndex1_7_6_10To1_8 searchIndex(EntityType type, int index) {
public static MetaIndex searchIndex(EntityType type, int index) {
EntityType currentType = type;
do {
Optional<MetaIndex1_7_6_10To1_8> optMeta = getIndex(currentType, index);
Optional<MetaIndex> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
@@ -1,114 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
@SuppressWarnings({"deprecation"})
public class MetadataRewriter {
private final Protocol1_7_6_10To1_8 protocol;
public MetadataRewriter(Protocol1_7_6_10To1_8 protocol) {
this.protocol = protocol;
}
public void transform(EntityType type, List<Metadata> list) {
for (Metadata entry : new ArrayList<>(list)) {
final MetaIndex1_7_6_10To1_8 metaIndex = MetaIndex1_7_6_10To1_8.searchIndex(type, entry.id());
try {
if (metaIndex == null) {
ViaRewind.getPlatform().getLogger().warning("Could not find 1.8 metadata for " + type + " with index " + entry.id());
list.remove(entry);
continue;
}
if (metaIndex.getOldType() == MetaType1_7_6_10.NonExistent) {
list.remove(entry);
continue;
}
final Object value = entry.getValue();
entry.setTypeAndValue(metaIndex.getNewType(), value);
entry.setMetaTypeUnsafe(metaIndex.getOldType());
entry.setId(metaIndex.getIndex());
switch (metaIndex.getOldType()) {
case Int:
if (metaIndex.getNewType() == MetaType1_8.Byte) {
entry.setValue(((Byte) value).intValue());
if (metaIndex == MetaIndex1_7_6_10To1_8.ENTITY_AGEABLE_AGE) {
if ((Integer) entry.getValue() < 0) {
entry.setValue(-25000);
}
}
}
if (metaIndex.getNewType() == MetaType1_8.Short) {
entry.setValue(((Short) value).intValue());
}
if (metaIndex.getNewType() == MetaType1_8.Int) {
entry.setValue(value);
}
break;
case Byte:
if (metaIndex.getNewType() == MetaType1_8.Int) {
entry.setValue(((Integer) value).byteValue());
}
if (metaIndex.getNewType() == MetaType1_8.Byte) {
if (metaIndex == MetaIndex1_7_6_10To1_8.ITEM_FRAME_ROTATION) {
entry.setValue(Integer.valueOf((Byte) value % 4).byteValue());
} else {
entry.setValue(value);
}
}
if (metaIndex == MetaIndex1_7_6_10To1_8.HUMAN_SKIN_FLAGS) {
byte flags = (byte) value;
boolean cape = (flags & 0x01) != 0;
flags = (byte) (cape ? 0x00 : 0x02);
entry.setValue(flags);
}
break;
case Slot:
entry.setValue(protocol.getItemRewriter().handleItemToClient((Item) value));
break;
case Float:
case String:
case Short:
case Position:
break;
default:
ViaRewind.getPlatform().getLogger().warning("Could not transform metadata for " + type + " with index " + entry.id() + " and type " + metaIndex.getOldType());
list.remove(entry);
break;
}
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Unable to transform metadata", e);
list.remove(entry);
}
}
}
}
@@ -0,0 +1,422 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.VREntityRewriter;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.api.type.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.emulation.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.Scoreboard;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent;
import com.viaversion.viaversion.util.IdAndData;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
public class MetadataRewriter1_7_6_10To1_8 extends VREntityRewriter<ClientboundPackets1_8, Protocol1_7_6_10To1_8> {
public MetadataRewriter1_7_6_10To1_8(Protocol1_7_6_10To1_8 protocol) {
super(protocol, MetaType1_7_6_10.String, MetaType1_7_6_10.Byte);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_8.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // Entity id
map(Type.UNSIGNED_BYTE); // Game mode
map(Type.BYTE); // Dimension
map(Type.UNSIGNED_BYTE); // Difficulty
map(Type.UNSIGNED_BYTE); // Max players
map(Type.STRING); // Level type
read(Type.BOOLEAN); // Reduced debug info
handler(playerTrackerHandler());
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 2) { // adventure
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) 0); // survival
}
}
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
tracker.addPlayer(entityId, wrapper.user().getProtocolInfo().getUuid());
tracker.setClientEntityGameMode(wrapper.get(Type.UNSIGNED_BYTE, 0));
wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Type.BYTE, 0));
// Reset on Velocity server change
wrapper.user().put(new Scoreboard(wrapper.user()));
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.DESTROY_ENTITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT_ARRAY_PRIMITIVE, Types1_7_6_10.BYTE_INT_ARRAY); // Entity ids
handler(wrapper -> {
final int[] entities = wrapper.get(Types1_7_6_10.BYTE_INT_ARRAY, 0);
untrackEntities(wrapper.user(), entities);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_METADATA, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // Entity id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // Metadata
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
final List<Metadata> metadata = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
handleMetadata(entityId, metadata, wrapper.user());
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.BYTE); // Type id
map(Type.INT); // X
map(Type.INT); // Y
map(Type.INT); // Z
map(Type.BYTE); // Pitch
map(Type.BYTE); // Yaw
map(Type.INT); // Data
// Track entity
handler(getObjectTrackerHandler());
handler(getObjectRewriter(id -> EntityTypes1_10.ObjectType.findById(id).orElse(null)));
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(wrapper.get(Type.BYTE, 0), true);
int x = wrapper.get(Type.INT, 0);
int y = wrapper.get(Type.INT, 1);
int z = wrapper.get(Type.INT, 2);
byte pitch = wrapper.get(Type.BYTE, 1);
byte yaw = wrapper.get(Type.BYTE, 2);
int data = wrapper.get(Type.INT, 3);
if (type == EntityTypes1_10.ObjectType.ITEM_FRAME.getType()) {
switch (yaw) {
case -128:
z += 32;
yaw = 0;
break;
case -64:
x -= 32;
yaw = -64;
break;
case 0:
z -= 32;
yaw = -128;
break;
case 64:
x += 32;
yaw = 64;
break;
}
} else if (type == EntityTypes1_10.ObjectType.ARMOR_STAND.getType()) {
wrapper.cancel();
final EntityTracker1_8 tracker = tracker(wrapper.user());
final VirtualHologramEntity hologram = tracker.getHolograms().get(entityId);
hologram.setPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(yaw * 360f / 256);
} else if (type != null && type.isOrHasParent(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
final IdAndData replace = protocol.getItemRewriter().handleBlock(blockId, blockData);
if (replace != null) {
blockId = replace.getId();
blockData = replace.getData();
}
wrapper.set(Type.INT, 3, data = (blockId | blockData << 16));
}
wrapper.set(Type.INT, 0, x);
wrapper.set(Type.INT, 1, y);
wrapper.set(Type.INT, 2, z);
wrapper.set(Type.BYTE, 2, yaw);
if (data > 0) {
wrapper.passthrough(Type.SHORT); // Velocity x
wrapper.passthrough(Type.SHORT); // Velocity y
wrapper.passthrough(Type.SHORT); // Velocity z
}
});
}
});
registerTracker(ClientboundPackets1_8.SPAWN_EXPERIENCE_ORB, EntityType.EXPERIENCE_ORB);
registerTracker(ClientboundPackets1_8.SPAWN_GLOBAL_ENTITY, EntityType.LIGHTNING);
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.STRING); // Title
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // Position
map(Type.UNSIGNED_BYTE, Type.INT); // Rotation
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final Position position = wrapper.get(Types1_7_6_10.INT_POSITION, 0);
final int rotation = wrapper.get(Type.INT, 0);
int modX = 0;
int modZ = 0;
switch (rotation) {
case 0:
modZ = -1;
break;
case 1:
modX = 1;
break;
case 2:
modZ = 1;
break;
case 3:
modX = -1;
break;
}
wrapper.set(Types1_7_6_10.INT_POSITION, 0, new Position(position.x() + modX, position.y(), position.z() + modZ));
addTrackedEntity(wrapper, entityId, EntityTypes1_10.EntityType.PAINTING);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.UNSIGNED_BYTE); // Entity type
map(Type.INT); // X
map(Type.INT); // Y
map(Type.INT); // Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
map(Type.BYTE); // Head yaw
map(Type.SHORT); // Velocity x
map(Type.SHORT); // Velocity y
map(Type.SHORT); // Velocity z
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // Metadata
handler(getTrackerHandler(Type.UNSIGNED_BYTE, 0));
handler(getMobSpawnRewriter(Types1_7_6_10.METADATA_LIST));
// Handle holograms
handler(wrapper -> {
final short typeId = wrapper.get(Type.UNSIGNED_BYTE, 0);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(typeId, false);
if (type == EntityTypes1_10.EntityType.ARMOR_STAND) {
wrapper.cancel();
final int entityId = wrapper.get(Type.VAR_INT, 0);
final int x = wrapper.get(Type.INT, 0);
final int y = wrapper.get(Type.INT, 1);
final int z = wrapper.get(Type.INT, 2);
final byte pitch = wrapper.get(Type.BYTE, 1);
final byte yaw = wrapper.get(Type.BYTE, 0);
final byte headYaw = wrapper.get(Type.BYTE, 2);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getHolograms().get(entityId);
hologram.setPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(headYaw * 360f / 256);
hologram.syncState(protocol().getEntityRewriter(), wrapper.get(Types1_7_6_10.METADATA_LIST, 0));
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
handler(wrapper -> {
final UUID uuid = wrapper.read(Type.UUID);
wrapper.write(Type.STRING, uuid.toString()); // map to string
final GameProfileStorage gameProfileStorage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) {
wrapper.write(Type.STRING, ""); // name
wrapper.write(Type.VAR_INT, 0); // properties count
} else {
wrapper.write(Type.STRING, gameProfile.name.length() > 16 ? gameProfile.name.substring(0, 16) : gameProfile.name); // name
wrapper.write(Type.VAR_INT, gameProfile.properties.size()); // properties count
for (GameProfileStorage.Property property : gameProfile.properties) {
wrapper.write(Type.STRING, property.name); // property name
wrapper.write(Type.STRING, property.value); // property value
wrapper.write(Type.STRING, property.signature == null ? "" : property.signature); // property signature
}
}
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (gameProfile != null && gameProfile.gamemode == 3) { // Spectator mode
for (short i = 0; i < 5; i++) {
final PacketWrapper entityEquipment = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, wrapper.user());
entityEquipment.write(Type.INT, entityId);
entityEquipment.write(Type.SHORT, i);
entityEquipment.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, i == 4 ? gameProfile.getSkull() : null);
entityEquipment.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
tracker.addPlayer(entityId, uuid);
});
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // Current item
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(getTrackerAndMetaHandler(Types1_7_6_10.METADATA_LIST, EntityTypes1_10.EntityType.PLAYER));
}
});
}
@Override
protected void registerRewrites() {
// Handle new entities
mapEntityTypeWithData(EntityType.GUARDIAN, EntityType.SQUID).plainName();
mapEntityTypeWithData(EntityType.ENDERMITE, EntityType.SQUID).plainName();
mapEntityTypeWithData(EntityType.RABBIT, EntityType.CHICKEN).plainName();
// Metadata rewrite
filter().handler((event, meta) -> {
try {
handleMetadata(event, meta);
} catch (Exception e) {
if (Via.getManager().isDebug()) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "An error occurred with entity metadata: " + meta, e);
}
event.cancel();
}
});
}
public void handleMetadata(MetaHandlerEvent event, Metadata metadata) throws Exception {
if (event.entityType() == EntityType.ARMOR_STAND) {
final EntityTracker1_8 tracker = tracker(event.user());
tracker.getHolograms().get(event.entityId()).syncState(this, event.metadataList());
event.cancel(); // We are rewriting metadata manually
return;
}
final MetaIndex metaIndex = MetaIndex.searchIndex(event.entityType(), metadata.id());
if (metaIndex == null) {
// Almost certainly bad data, remove it
event.cancel();
return;
}
if (metaIndex.getOldType() == null) {
event.cancel();
return;
}
final Object value = metadata.getValue();
metadata.setTypeAndValue(metaIndex.getNewType(), value);
metadata.setMetaTypeUnsafe(metaIndex.getOldType());
metadata.setId(metaIndex.getIndex());
switch (metaIndex.getOldType()) {
case Int:
if (metaIndex.getNewType() == MetaType1_8.Byte) {
metadata.setValue(((Byte) value).intValue());
if (metaIndex == MetaIndex.ENTITY_AGEABLE_AGE) {
if ((Integer) metadata.getValue() < 0) {
metadata.setValue(-25000);
}
}
}
if (metaIndex.getNewType() == MetaType1_8.Short) {
metadata.setValue(((Short) value).intValue());
}
if (metaIndex.getNewType() == MetaType1_8.Int) {
metadata.setValue(value);
}
break;
case Byte:
if (metaIndex.getNewType() == MetaType1_8.Int) {
metadata.setValue(((Integer) value).byteValue());
}
if (metaIndex.getNewType() == MetaType1_8.Byte) {
if (metaIndex == MetaIndex.ITEM_FRAME_ROTATION) {
metadata.setValue(Integer.valueOf((Byte) value % 4).byteValue());
} else {
metadata.setValue(value);
}
}
if (metaIndex == MetaIndex.HUMAN_SKIN_FLAGS) {
byte flags = (byte) value;
boolean cape = (flags & 0x01) != 0;
flags = (byte) (cape ? 0x00 : 0x02);
metadata.setValue(flags);
}
break;
case Slot:
metadata.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), (Item) value));
break;
default:
event.cancel();
break;
}
}
@Override
public EntityTypes1_10.EntityType typeFromId(int type) {
return EntityTypes1_10.getTypeFromId(type, false);
}
@Override
public EntityTypes1_10.EntityType objectTypeFromId(int type) {
return EntityTypes1_10.getTypeFromId(type, true);
}
}
@@ -15,28 +15,38 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
import com.viaversion.viarewind.api.rewriter.VRBlockItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.FurnaceData;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.InventoryTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.UUID;
public class InventoryPackets {
public class BlockItemPackets1_8 extends VRBlockItemRewriter<ClientboundPackets1_8, ServerboundPackets1_7_2_5, Protocol1_7_6_10To1_8> {
public static void register(Protocol1_7_6_10To1_8 protocol) {
private LegacyEnchantmentRewriter enchantmentRewriter;
public BlockItemPackets1_8(Protocol1_7_6_10To1_8 protocol) {
super(protocol, "1.8");
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_8.OPEN_WINDOW, wrapper -> {
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
@@ -47,7 +57,7 @@ public class InventoryPackets {
wrapper.write(Type.UNSIGNED_BYTE, windowTypeId); // window type id
final JsonElement titleComponent = wrapper.read(Type.COMPONENT); // Title
String title = ChatUtil.jsonToLegacy(titleComponent);
String title = ChatUtil.jsonToLegacy(wrapper.user(), titleComponent);
title = ChatUtil.removeUnusedColor(title, '8');
if (title.length() > 32) {
title = title.substring(0, 32);
@@ -91,7 +101,7 @@ public class InventoryPackets {
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
handleItemToClient(wrapper.user(), item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
@@ -105,9 +115,10 @@ public class InventoryPackets {
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
playerSession.setPlayerEquipment(wrapper.user().getProtocolInfo().getUuid(), item, 8 - slot);
if (playerSession.isSpectator()) { // Spectator mode didn't exist in 1.7.10
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.isSpectator()) { // Spectator mode didn't exist in 1.7.10
wrapper.cancel();
}
});
@@ -131,7 +142,7 @@ public class InventoryPackets {
System.arraycopy(old, 2, items, 1, old.length - 3);
}
for (int i = 0; i < items.length; i++) {
items[i] = protocol.getItemRewriter().handleItemToClient(items[i]);
items[i] = handleItemToClient(wrapper.user(), items[i]);
}
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, items); // items
});
@@ -140,17 +151,17 @@ public class InventoryPackets {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final UUID userId = wrapper.user().getProtocolInfo().getUuid();
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final Item[] items = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, 0);
for (int i = 5; i < 9; i++) {
playerSession.setPlayerEquipment(userId, items[i], 8 - i);
if (playerSession.isSpectator()) {
wrapper.user().get(PlayerSessionStorage.class).setPlayerEquipment(userId, items[i], 8 - i);
if (tracker.isSpectator()) {
items[i] = null;
}
}
if (playerSession.isSpectator()) {
if (tracker.isSpectator()) {
final GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(userId);
if (profile != null) {
items[5] = profile.getSkull();
@@ -177,7 +188,8 @@ public class InventoryPackets {
short progress = wrapper.get(Type.SHORT, 1);
if (windowType == 2) { // Furnace
final FurnaceData furnace = windowTracker.getFurnaceData().computeIfAbsent(windowId, x -> new FurnaceData());
// TODO | Proper methods (getOrCreate)=
final InventoryTracker.FurnaceData furnace = windowTracker.getFurnaceData().computeIfAbsent(windowId, x -> new InventoryTracker.FurnaceData());
if (progressBarId == 0 || progressBarId == 1) {
if (progressBarId == 0) {
furnace.fuelLeft = progress;
@@ -245,7 +257,7 @@ public class InventoryPackets {
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Type.ITEM1_8, 0);
protocol.getItemRewriter().handleItemToServer(item);
handleItemToServer(wrapper.user(), item);
wrapper.set(Type.ITEM1_8, 0, item);
});
}
@@ -257,13 +269,62 @@ public class InventoryPackets {
map(Type.SHORT); // slot
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM1_8); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Type.ITEM1_8, 0);
protocol.getItemRewriter().handleItemToServer(item);
wrapper.set(Type.ITEM1_8, 0, item);
});
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Type.ITEM1_8, 0)));
}
});
}
@Override
protected void registerRewrites() {
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName(), false);
enchantmentRewriter.registerEnchantment(8, "§7Depth Strider");
}
@Override
public Item handleItemToClient(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToClient(connection, item);
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
enchantmentRewriter.handleToClient(item);
if (item.identifier() == 387) {
final ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
if (pages == null) return item;
final ListTag<StringTag> oldPages = new ListTag<>(StringTag.class);
tag.put(nbtTagName() + "|pages", oldPages);
for (StringTag page : pages) {
final String value = page.getValue();
oldPages.add(new StringTag(value));
page.setValue(ChatUtil.jsonToLegacy(connection, value));
}
}
return item;
}
@Override
public Item handleItemToServer(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
final CompoundTag tag = item.tag();
if (tag == null) return item;
enchantmentRewriter.handleToServer(item);
if (item.identifier() == 387) {
final ListTag<StringTag> oldPages = tag.get(nbtTagName() + "|pages");
if (oldPages != null) {
tag.remove("pages");
tag.put("pages", oldPages);
}
}
return item;
}
}
@@ -15,28 +15,23 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.emulation.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.List;
import java.util.UUID;
public class EntityPackets {
public class EntityPackets1_8 {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EQUIPMENT, new PacketHandlers() {
@@ -49,13 +44,14 @@ public class EntityPackets {
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
protocol.getItemRewriter().handleItemToClient(wrapper.user(), item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
handler(wrapper -> {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final short slot = wrapper.get(Type.SHORT, 0);
final UUID uuid = wrapper.user().get(EntityTracker1_7_6_10.class).getPlayerUUID(wrapper.get(Type.INT, 0));
final UUID uuid = tracker.getPlayerUUID(wrapper.get(Type.INT, 0));
if (uuid == null) return;
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
@@ -84,7 +80,7 @@ public class EntityPackets {
map(Type.VAR_INT, Type.INT); // collected entity id
map(Type.VAR_INT, Type.INT); // collector entity id
handler(wrapper -> wrapper.user().get(EntityTracker1_7_6_10.class).removeEntity(wrapper.get(Type.INT, 0)));
handler(wrapper -> wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class).removeEntity(wrapper.get(Type.INT, 0)));
}
});
@@ -92,25 +88,6 @@ public class EntityPackets {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Type.SHORT); // velocity x
map(Type.SHORT); // velocity y
map(Type.SHORT); // velocity z
}
});
protocol.registerClientbound(ClientboundPackets1_8.DESTROY_ENTITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT_ARRAY_PRIMITIVE, Types1_7_6_10.BYTE_INT_ARRAY); // entity ids
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
for (int entityId : wrapper.get(Types1_7_6_10.BYTE_INT_ARRAY, 0)) {
tracker.removeEntity(entityId);
}
});
}
});
@@ -131,16 +108,16 @@ public class EntityPackets {
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
final VirtualHologramEntity hologram = tracker.getHolograms().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.BYTE, 0);
final int y = wrapper.get(Type.BYTE, 1);
final int z = wrapper.get(Type.BYTE, 2);
hologram.handleOriginalMovementPacket(x / 32.0, y / 32.0, z / 32.0);
hologram.setRelativePosition(x / 32.0, y / 32.0, z / 32.0);
}
});
}
@@ -155,15 +132,15 @@ public class EntityPackets {
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
final VirtualHologramEntity hologram = tracker.getHolograms().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int yaw = wrapper.get(Type.BYTE, 0);
final int pitch = wrapper.get(Type.BYTE, 1);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
@@ -181,9 +158,9 @@ public class EntityPackets {
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
final VirtualHologramEntity hologram = tracker.getHolograms().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.BYTE, 0);
@@ -193,8 +170,8 @@ public class EntityPackets {
final int yaw = wrapper.get(Type.BYTE, 3);
final int pitch = wrapper.get(Type.BYTE, 4);
hologram.handleOriginalMovementPacket(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setRelativePosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
@@ -211,18 +188,16 @@ public class EntityPackets {
map(Type.BYTE); // pitch
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final int entityId = wrapper.get(Type.INT, 0);
final EntityType type = tracker.getEntityMap().get(entityId);
if (type == EntityTypes1_10.EntityType.MINECART_ABSTRACT) { // TODO | Realign all entities?
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.entityType(entityId) == EntityTypes1_10.EntityType.MINECART_ABSTRACT) { // TODO | Realign all entities?
int y = wrapper.get(Type.INT, 2);
y += 12;
wrapper.set(Type.INT, 2, y);
}
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(entityId);
final VirtualHologramEntity hologram = tracker.getHolograms().get(entityId);
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.INT, 1);
@@ -232,8 +207,8 @@ public class EntityPackets {
final int yaw = wrapper.get(Type.BYTE, 0);
final int pitch = wrapper.get(Type.BYTE, 1);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setRotation(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
@@ -246,9 +221,9 @@ public class EntityPackets {
map(Type.BYTE); // head yaw
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
final VirtualHologramEntity hologram = tracker.getHolograms().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int yaw = wrapper.get(Type.BYTE, 0);
@@ -265,13 +240,13 @@ public class EntityPackets {
map(Type.INT); // riding entity id
map(Type.INT); // vehicle entity id
map(Type.BOOLEAN); // leash state
handler(packetWrapper -> {
final boolean leash = packetWrapper.get(Type.BOOLEAN, 0);
handler(wrapper -> {
final boolean leash = wrapper.get(Type.BOOLEAN, 0);
if (!leash) {
final EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final int passenger = packetWrapper.get(Type.INT, 0);
final int vehicle = packetWrapper.get(Type.INT, 1);
final int passenger = wrapper.get(Type.INT, 0);
final int vehicle = wrapper.get(Type.INT, 1);
tracker.setPassenger(vehicle, passenger);
}
@@ -279,33 +254,6 @@ public class EntityPackets {
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_METADATA, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
final List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.getEntityReplacementMap().containsKey(entityId)) {
tracker.updateMetadata(entityId, metadataList);
wrapper.cancel();
return;
}
if (tracker.getEntityMap().containsKey(entityId)) {
protocol.getMetadataRewriter().transform(tracker.getEntityMap().get(entityId), metadataList);
if (metadataList.isEmpty()) {
wrapper.cancel();
}
} else {
wrapper.cancel();
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
@@ -330,12 +278,6 @@ public class EntityPackets {
public void register() {
map(Type.VAR_INT, Type.INT); // entity id
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
if (wrapper.user().get(EntityTracker1_7_6_10.class).getEntityReplacementMap().containsKey(entityId)) {
wrapper.cancel();
return;
}
final int amount = wrapper.passthrough(Type.INT);
for (int i = 0; i < amount; i++) {
wrapper.passthrough(Type.STRING); // id
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.ViaRewind;
@@ -24,9 +23,8 @@ import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10T
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.TitleRenderProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Ray3d;
import com.viaversion.viarewind.utils.math.RayTracing;
@@ -54,40 +52,9 @@ import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;
public class PlayerPackets {
public class PlayerPackets1_8 {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // entity id
map(Type.UNSIGNED_BYTE);// game mode
map(Type.BYTE); // dimension
map(Type.UNSIGNED_BYTE); // difficulty
map(Type.UNSIGNED_BYTE); // max players
map(Type.STRING); // level type
read(Type.BOOLEAN); // reduced debug info
handler(wrapper -> {
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 2) { // adventure
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) 0); // survival
}
}
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.setClientEntityId(wrapper.get(Type.INT, 0));
tracker.addPlayer(wrapper.get(Type.INT, 0), wrapper.user().getProtocolInfo().getUuid());
wrapper.user().get(PlayerSessionStorage.class).gameMode = wrapper.get(Type.UNSIGNED_BYTE, 0);
wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Type.BYTE, 0));
// Reset on Velocity server change
wrapper.user().put(new Scoreboard(wrapper.user()));
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
@@ -123,7 +90,6 @@ public class PlayerPackets {
map(Type.INT); // dimension
map(Type.UNSIGNED_BYTE); // difficulty
map(Type.UNSIGNED_BYTE); // game mode
map(Type.STRING); // level type
handler(wrapper -> {
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 1) == 2) {
@@ -131,18 +97,17 @@ public class PlayerPackets {
}
}
wrapper.user().get(PlayerSessionStorage.class).gameMode = wrapper.get(Type.UNSIGNED_BYTE, 1);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
tracker.setClientEntityGameMode(wrapper.get(Type.UNSIGNED_BYTE, 1));
final ClientWorld world = wrapper.user().get(ClientWorld.class);
final Environment dimension = Environment.getEnvironmentById(wrapper.get(Type.INT, 0));
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final ClientWorld world = wrapper.user().get(ClientWorld.class);
if (world.getEnvironment() != dimension) {
// Clear entities on dimension change and re-track player
world.setEnvironment(dimension.id());
// Reset on dimension change
tracker.clear();
tracker.getEntityMap().put(tracker.getPlayerId(), EntityTypes1_10.EntityType.ENTITY_HUMAN);
tracker.clearEntities();
tracker.addEntity(tracker.clientEntityId(), EntityTypes1_10.EntityType.PLAYER);
}
});
}
@@ -182,8 +147,8 @@ public class PlayerPackets {
wrapper.write(Type.BOOLEAN, playerSession.onGround);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.spectatingPlayerId != tracker.getPlayerId()) {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.spectatingClientEntityId != tracker.clientEntityId()) {
wrapper.cancel();
}
});
@@ -208,8 +173,8 @@ public class PlayerPackets {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) != 3) return; // Change game mode
int gameMode = wrapper.get(Type.FLOAT, 0).intValue();
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
if (gameMode == 3 || playerSession.gameMode == 3) {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (gameMode == 3 || tracker.isSpectator()) {
UUID myId = wrapper.user().getProtocolInfo().getUuid();
Item[] equipment = new Item[4];
if (gameMode == 3) {
@@ -217,7 +182,7 @@ public class PlayerPackets {
equipment[3] = profile == null ? null : profile.getSkull();
} else {
for (int i = 0; i < equipment.length; i++) {
equipment[i] = playerSession.getPlayerEquipment(myId, i);
equipment[i] = wrapper.user().get(PlayerSessionStorage.class).getPlayerEquipment(myId, i);
}
}
@@ -226,7 +191,7 @@ public class PlayerPackets {
setSlot.write(Type.BYTE, (byte) 0);
setSlot.write(Type.SHORT, (short) (8 - i));
setSlot.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, equipment[i]);
PacketUtil.sendPacket(setSlot, Protocol1_7_6_10To1_8.class);
setSlot.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
@@ -234,7 +199,7 @@ public class PlayerPackets {
gameMode = 0;
wrapper.set(Type.FLOAT, 0, 0.0f);
}
wrapper.user().get(PlayerSessionStorage.class).gameMode = gameMode;
tracker.setClientEntityGameMode(gameMode);
});
}
});
@@ -249,51 +214,51 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.PLAYER_INFO, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
int action = packetWrapper.read(Type.VAR_INT);
int count = packetWrapper.read(Type.VAR_INT);
GameProfileStorage gameProfileStorage = packetWrapper.user().get(GameProfileStorage.class);
handler(wrapper -> {
wrapper.cancel();
int action = wrapper.read(Type.VAR_INT);
int count = wrapper.read(Type.VAR_INT);
GameProfileStorage gameProfileStorage = wrapper.user().get(GameProfileStorage.class);
for (int i = 0; i < count; i++) {
UUID uuid = packetWrapper.read(Type.UUID);
UUID uuid = wrapper.read(Type.UUID);
if (action == 0) {
String name = packetWrapper.read(Type.STRING);
String name = wrapper.read(Type.STRING);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) gameProfile = gameProfileStorage.put(uuid, name);
int propertyCount = packetWrapper.read(Type.VAR_INT);
int propertyCount = wrapper.read(Type.VAR_INT);
while (propertyCount-- > 0) {
String propertyName = packetWrapper.read(Type.STRING);
String propertyValue = packetWrapper.read(Type.STRING);
String propertySignature = packetWrapper.read(Type.OPTIONAL_STRING);
String propertyName = wrapper.read(Type.STRING);
String propertyValue = wrapper.read(Type.STRING);
String propertySignature = wrapper.read(Type.OPTIONAL_STRING);
gameProfile.properties.add(new GameProfileStorage.Property(propertyName, propertyValue, propertySignature));
}
int gamemode = packetWrapper.read(Type.VAR_INT);
int ping = packetWrapper.read(Type.VAR_INT);
int gamemode = wrapper.read(Type.VAR_INT);
int ping = wrapper.read(Type.VAR_INT);
gameProfile.ping = ping;
gameProfile.gamemode = gamemode;
JsonElement displayName = packetWrapper.read(Type.OPTIONAL_COMPONENT);
JsonElement displayName = wrapper.read(Type.OPTIONAL_COMPONENT);
if (displayName != null) {
gameProfile.setDisplayName(ChatUtil.jsonToLegacy(displayName));
gameProfile.setDisplayName(ChatUtil.jsonToLegacy(wrapper.user(), displayName));
}
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
} else if (action == 1) {
int gamemode = packetWrapper.read(Type.VAR_INT);
int gamemode = wrapper.read(Type.VAR_INT);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null || gameProfile.gamemode == gamemode) continue;
if (gamemode == 3 || gameProfile.gamemode == 3) {
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
int entityId = tracker.getPlayerEntityId(uuid);
boolean isOwnPlayer = entityId == tracker.getPlayerId();
boolean isOwnPlayer = entityId == tracker.clientEntityId();
if (entityId != -1) {
// Weirdly, PlayerEntity has only 4 slots instead of 5
Item[] equipment = new Item[isOwnPlayer ? 4 : 5];
@@ -301,71 +266,71 @@ public class PlayerPackets {
equipment[isOwnPlayer ? 3 : 4] = gameProfile.getSkull();
} else {
for (int j = 0; j < equipment.length; j++) {
equipment[j] = packetWrapper.user().get(PlayerSessionStorage.class).getPlayerEquipment(uuid, j);
equipment[j] = wrapper.user().get(PlayerSessionStorage.class).getPlayerEquipment(uuid, j);
}
}
for (short slot = 0; slot < equipment.length; slot++) {
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, packetWrapper.user());
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, wrapper.user());
equipmentPacket.write(Type.INT, entityId);
equipmentPacket.write(Type.SHORT, slot);
equipmentPacket.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, equipment[slot]);
PacketUtil.sendPacket(equipmentPacket, Protocol1_7_6_10To1_8.class);
equipmentPacket.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
}
gameProfile.gamemode = gamemode;
} else if (action == 2) {
int ping = packetWrapper.read(Type.VAR_INT);
int ping = wrapper.read(Type.VAR_INT);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
gameProfile.ping = ping;
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
} else if (action == 3) {
JsonElement displayNameComponent = packetWrapper.read(Type.OPTIONAL_COMPONENT);
String displayName = displayNameComponent != null ? ChatUtil.jsonToLegacy(displayNameComponent) : null;
JsonElement displayNameComponent = wrapper.read(Type.OPTIONAL_COMPONENT);
String displayName = displayNameComponent != null ? ChatUtil.jsonToLegacy(wrapper.user(), displayNameComponent) : null;
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null || gameProfile.displayName == null && displayName == null) continue;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
if (gameProfile.displayName == null && displayName != null || gameProfile.displayName != null && displayName == null || !gameProfile.displayName.equals(displayName)) {
gameProfile.setDisplayName(displayName);
}
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
} else if (action == 4) {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.remove(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, wrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
packet.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
});
@@ -378,11 +343,11 @@ public class PlayerPackets {
map(Type.BYTE);
map(Type.FLOAT);
map(Type.FLOAT);
handler(packetWrapper -> {
byte flags = packetWrapper.get(Type.BYTE, 0);
float flySpeed = packetWrapper.get(Type.FLOAT, 0);
float walkSpeed = packetWrapper.get(Type.FLOAT, 1);
PlayerSessionStorage abilities = packetWrapper.user().get(PlayerSessionStorage.class);
handler(wrapper -> {
byte flags = wrapper.get(Type.BYTE, 0);
float flySpeed = wrapper.get(Type.FLOAT, 0);
float walkSpeed = wrapper.get(Type.FLOAT, 1);
PlayerSessionStorage abilities = wrapper.user().get(PlayerSessionStorage.class);
abilities.invincible = (flags & 8) == 8;
abilities.allowFly = (flags & 4) == 4;
abilities.flying = (flags & 2) == 2;
@@ -391,7 +356,7 @@ public class PlayerPackets {
abilities.walkSpeed = walkSpeed;
if (abilities.sprinting && abilities.flying) {
packetWrapper.set(Type.FLOAT, 0, abilities.flySpeed * 2.0f);
wrapper.set(Type.FLOAT, 0, abilities.flySpeed * 2.0f);
}
});
}
@@ -401,44 +366,44 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
handler(wrapper -> {
String channel = wrapper.get(Type.STRING, 0);
if (channel.equals("MC|TrList")) {
packetWrapper.passthrough(Type.INT); //Window Id
wrapper.passthrough(Type.INT); //Window Id
int size;
if (packetWrapper.isReadable(Type.BYTE, 0)) {
size = packetWrapper.passthrough(Type.BYTE);
if (wrapper.isReadable(Type.BYTE, 0)) {
size = wrapper.passthrough(Type.BYTE);
} else {
size = packetWrapper.passthrough(Type.UNSIGNED_BYTE);
size = wrapper.passthrough(Type.UNSIGNED_BYTE);
}
for (int i = 0; i < size; i++) {
Item item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 1
Item item = protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8));
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 1
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 3
item = protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8));
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 3
boolean has3Items = packetWrapper.passthrough(Type.BOOLEAN);
boolean has3Items = wrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 2
item = protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8));
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 2
}
packetWrapper.passthrough(Type.BOOLEAN); //Unavailable
packetWrapper.read(Type.INT); //Uses
packetWrapper.read(Type.INT); //Max Uses
wrapper.passthrough(Type.BOOLEAN); //Unavailable
wrapper.read(Type.INT); //Uses
wrapper.read(Type.INT); //Max Uses
}
} else if (channel.equals("MC|Brand")) {
packetWrapper.write(Type.REMAINING_BYTES, packetWrapper.read(Type.STRING).getBytes(StandardCharsets.UTF_8));
wrapper.write(Type.REMAINING_BYTES, wrapper.read(Type.STRING).getBytes(StandardCharsets.UTF_8));
}
packetWrapper.cancel();
packetWrapper.setPacketType(null);
wrapper.cancel();
wrapper.setPacketType(null);
ByteBuf newPacketBuf = Unpooled.buffer();
packetWrapper.writeToBuffer(newPacketBuf);
PacketWrapper newWrapper = PacketWrapper.create(ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, newPacketBuf, packetWrapper.user());
wrapper.writeToBuffer(newPacketBuf);
PacketWrapper newWrapper = PacketWrapper.create(ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, newPacketBuf, wrapper.user());
newWrapper.passthrough(Type.STRING);
if (newPacketBuf.readableBytes() <= Short.MAX_VALUE) {
newWrapper.write(Type.SHORT, (short) newPacketBuf.readableBytes());
@@ -448,19 +413,15 @@ public class PlayerPackets {
}
});
//Camera
protocol.registerClientbound(ClientboundPackets1_8.CAMERA, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
handler(wrapper -> {
wrapper.cancel();
final int entityId = wrapper.read(Type.VAR_INT);
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
int entityId = packetWrapper.read(Type.VAR_INT);
int spectating = tracker.spectatingPlayerId;
if (spectating != entityId) {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.spectatingClientEntityId != entityId) {
tracker.setSpectating(entityId);
}
});
@@ -471,21 +432,21 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.TITLE, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
handler(wrapper -> {
wrapper.cancel();
TitleRenderProvider titleRenderProvider = Via.getManager().getProviders().get(TitleRenderProvider.class);
if (titleRenderProvider == null) return;
int action = packetWrapper.read(Type.VAR_INT);
UUID uuid = packetWrapper.user().getProtocolInfo().getUuid();
int action = wrapper.read(Type.VAR_INT);
UUID uuid = wrapper.user().getProtocolInfo().getUuid();
switch (action) {
case 0:
titleRenderProvider.setTitle(uuid, packetWrapper.read(Type.STRING));
titleRenderProvider.setTitle(uuid, wrapper.read(Type.STRING));
break;
case 1:
titleRenderProvider.setSubTitle(uuid, packetWrapper.read(Type.STRING));
titleRenderProvider.setSubTitle(uuid, wrapper.read(Type.STRING));
break;
case 2:
titleRenderProvider.setTimings(uuid, packetWrapper.read(Type.INT), packetWrapper.read(Type.INT), packetWrapper.read(Type.INT));
titleRenderProvider.setTimings(uuid, wrapper.read(Type.INT), wrapper.read(Type.INT), wrapper.read(Type.INT));
break;
case 3:
titleRenderProvider.clear(uuid);
@@ -506,13 +467,13 @@ public class PlayerPackets {
@Override
public void register() {
create(Type.STRING, "MC|RPack");
handler(packetWrapper -> {
handler(wrapper -> {
ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
try {
// Url
Type.STRING.write(buf, packetWrapper.read(Type.STRING));
Type.STRING.write(buf, wrapper.read(Type.STRING));
packetWrapper.write(Type.SHORT_BYTE_ARRAY, Type.REMAINING_BYTES.read(buf));
wrapper.write(Type.SHORT_BYTE_ARRAY, Type.REMAINING_BYTES.read(buf));
} finally {
buf.release();
}
@@ -521,26 +482,24 @@ public class PlayerPackets {
}
});
/* INCOMING */
protocol.registerServerbound(ServerboundPackets1_7_2_5.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
int gamemode = packetWrapper.user().get(PlayerSessionStorage.class).gameMode;
if (gamemode == 3 && msg.toLowerCase().startsWith("/stp ")) {
handler(wrapper -> {
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
String msg = wrapper.get(Type.STRING, 0);
if (tracker.isSpectator() && msg.toLowerCase().startsWith("/stp ")) { // TODO add setting
String username = msg.split(" ")[1];
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
GameProfileStorage storage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile profile = storage.get(username, true);
if (profile != null && profile.uuid != null) {
packetWrapper.cancel();
wrapper.cancel();
PacketWrapper teleportPacket = PacketWrapper.create(0x18, null, packetWrapper.user());
PacketWrapper teleportPacket = PacketWrapper.create(0x18, null, wrapper.user());
teleportPacket.write(Type.UUID, profile.uuid);
PacketUtil.sendToServer(teleportPacket, Protocol1_7_6_10To1_8.class, true, true);
teleportPacket.send(Protocol1_7_6_10To1_8.class);
}
}
});
@@ -558,11 +517,11 @@ public class PlayerPackets {
return;
}
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
final PlayerSessionStorage position = wrapper.user().get(PlayerSessionStorage.class);
if (tracker.getVirtualHologramMap().containsKey(entityId)) {
final AABB boundingBox = tracker.getVirtualHologramMap().get(entityId).getBoundingBox();
if (tracker.getHolograms().containsKey(entityId)) {
final AABB boundingBox = tracker.getHolograms().get(entityId).getBoundingBox();
Vector3d pos = new Vector3d(position.getPosX(), position.getPosY() + 1.8, position.getPosZ());
double yaw = Math.toRadians(position.yaw);
@@ -591,9 +550,9 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
handler(wrapper -> {
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = wrapper.get(Type.BOOLEAN, 0);
});
}
});
@@ -606,14 +565,14 @@ public class PlayerPackets {
read(Type.DOUBLE);
map(Type.DOUBLE); //Z
map(Type.BOOLEAN); //OnGround
handler(packetWrapper -> {
double x = packetWrapper.get(Type.DOUBLE, 0);
double feetY = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
handler(wrapper -> {
double x = wrapper.get(Type.DOUBLE, 0);
double feetY = wrapper.get(Type.DOUBLE, 1);
double z = wrapper.get(Type.DOUBLE, 2);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.onGround = wrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
});
}
@@ -625,11 +584,11 @@ public class PlayerPackets {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.yaw = packetWrapper.get(Type.FLOAT, 0);
playerSession.pitch = packetWrapper.get(Type.FLOAT, 1);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
handler(wrapper -> {
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.yaw = wrapper.get(Type.FLOAT, 0);
playerSession.pitch = wrapper.get(Type.FLOAT, 1);
playerSession.onGround = wrapper.get(Type.BOOLEAN, 0);
});
}
});
@@ -644,17 +603,17 @@ public class PlayerPackets {
map(Type.FLOAT); //Yaw
map(Type.FLOAT); //Pitch
map(Type.BOOLEAN); //OnGround
handler(packetWrapper -> {
double x = packetWrapper.get(Type.DOUBLE, 0);
double feetY = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
handler(wrapper -> {
double x = wrapper.get(Type.DOUBLE, 0);
double feetY = wrapper.get(Type.DOUBLE, 1);
double z = wrapper.get(Type.DOUBLE, 2);
float yaw = packetWrapper.get(Type.FLOAT, 0);
float pitch = packetWrapper.get(Type.FLOAT, 1);
float yaw = wrapper.get(Type.FLOAT, 0);
float pitch = wrapper.get(Type.FLOAT, 1);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.onGround = wrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
playerSession.yaw = yaw;
playerSession.pitch = pitch;
@@ -666,11 +625,11 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.VAR_INT); //Status
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.UNSIGNED_BYTE);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
handler(wrapper -> {
int x = wrapper.read(Type.INT);
int y = wrapper.read(Type.UNSIGNED_BYTE);
int z = wrapper.read(Type.INT);
wrapper.write(Type.POSITION1_8, new Position(x, y, z));
});
}
});
@@ -678,19 +637,19 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.UNSIGNED_BYTE);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
handler(wrapper -> {
int x = wrapper.read(Type.INT);
int y = wrapper.read(Type.UNSIGNED_BYTE);
int z = wrapper.read(Type.INT);
wrapper.write(Type.POSITION1_8, new Position(x, y, z));
packetWrapper.passthrough(Type.BYTE); //Direction
Item item = packetWrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
item = protocol.getItemRewriter().handleItemToServer(item);
packetWrapper.write(Type.ITEM1_8, item);
wrapper.passthrough(Type.BYTE); //Direction
Item item = wrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
item = protocol.getItemRewriter().handleItemToServer(wrapper.user(), item);
wrapper.write(Type.ITEM1_8, item);
for (int i = 0; i < 3; i++) {
packetWrapper.passthrough(Type.BYTE);
wrapper.passthrough(Type.BYTE);
}
});
}
@@ -699,11 +658,11 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_7_2_5.ANIMATION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int entityId = packetWrapper.read(Type.INT);
int animation = packetWrapper.read(Type.BYTE); //Animation
handler(wrapper -> {
int entityId = wrapper.read(Type.INT);
int animation = wrapper.read(Type.BYTE); //Animation
if (animation == 1) return;
packetWrapper.cancel();
wrapper.cancel();
//1.7 vanilla client is not sending this packet with animation!=1
switch (animation) {
case 104:
@@ -718,11 +677,11 @@ public class PlayerPackets {
default:
return;
}
PacketWrapper entityAction = PacketWrapper.create(0x0B, null, packetWrapper.user());
PacketWrapper entityAction = PacketWrapper.create(0x0B, null, wrapper.user());
entityAction.write(Type.VAR_INT, entityId);
entityAction.write(Type.VAR_INT, animation);
entityAction.write(Type.VAR_INT, 0);
PacketUtil.sendPacket(entityAction, Protocol1_7_6_10To1_8.class, true, true);
entityAction.send(Protocol1_7_6_10To1_8.class);
});
}
});
@@ -731,18 +690,18 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.INT, Type.VAR_INT); //Entity Id
handler(packetWrapper -> packetWrapper.write(Type.VAR_INT, packetWrapper.read(Type.BYTE) - 1)); //Action Id
handler(wrapper -> wrapper.write(Type.VAR_INT, wrapper.read(Type.BYTE) - 1)); //Action Id
map(Type.INT, Type.VAR_INT); //Action Parameter
handler(packetWrapper -> {
int action = packetWrapper.get(Type.VAR_INT, 1);
handler(wrapper -> {
int action = wrapper.get(Type.VAR_INT, 1);
if (action == 3 || action == 4) {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
playerSession.sprinting = action == 3;
PacketWrapper abilitiesPacket = PacketWrapper.create(0x39, null, packetWrapper.user());
PacketWrapper abilitiesPacket = PacketWrapper.create(0x39, null, wrapper.user());
abilitiesPacket.write(Type.BYTE, playerSession.combineAbilities());
abilitiesPacket.write(Type.FLOAT, playerSession.sprinting ? playerSession.flySpeed * 2.0f : playerSession.flySpeed);
abilitiesPacket.write(Type.FLOAT, playerSession.walkSpeed);
PacketUtil.sendPacket(abilitiesPacket, Protocol1_7_6_10To1_8.class);
abilitiesPacket.send(Protocol1_7_6_10To1_8.class);
}
});
}
@@ -753,28 +712,28 @@ public class PlayerPackets {
public void register() {
map(Type.FLOAT); //Sideways
map(Type.FLOAT); //Forwards
handler(packetWrapper -> {
boolean jump = packetWrapper.read(Type.BOOLEAN);
boolean unmount = packetWrapper.read(Type.BOOLEAN);
handler(wrapper -> {
boolean jump = wrapper.read(Type.BOOLEAN);
boolean unmount = wrapper.read(Type.BOOLEAN);
short flags = 0;
if (jump) flags += 0x01;
if (unmount) flags += 0x02;
packetWrapper.write(Type.UNSIGNED_BYTE, flags);
wrapper.write(Type.UNSIGNED_BYTE, flags);
if (unmount) {
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.spectatingPlayerId != tracker.getPlayerId()) {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, packetWrapper.user());
sneakPacket.write(Type.VAR_INT, tracker.getPlayerId());
EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_7_6_10To1_8.class);
if (tracker.spectatingClientEntityId != tracker.clientEntityId()) {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, wrapper.user());
sneakPacket.write(Type.VAR_INT, tracker.clientEntityId());
sneakPacket.write(Type.VAR_INT, 0); //Start sneaking
sneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketWrapper unsneakPacket = PacketWrapper.create(0x0B, null, packetWrapper.user());
unsneakPacket.write(Type.VAR_INT, tracker.getPlayerId());
PacketWrapper unsneakPacket = PacketWrapper.create(0x0B, null, wrapper.user());
unsneakPacket.write(Type.VAR_INT, tracker.clientEntityId());
unsneakPacket.write(Type.VAR_INT, 1); //Stop sneaking
unsneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketUtil.sendToServer(sneakPacket, Protocol1_7_6_10To1_8.class);
sneakPacket.scheduleSendToServer(Protocol1_7_6_10To1_8.class);
}
}
});
@@ -784,15 +743,15 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_7_2_5.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.SHORT);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
handler(wrapper -> {
int x = wrapper.read(Type.INT);
int y = wrapper.read(Type.SHORT);
int z = wrapper.read(Type.INT);
wrapper.write(Type.POSITION1_8, new Position(x, y, z));
for (int i = 0; i < 4; i++) {
final String line = packetWrapper.read(Type.STRING);
final String line = wrapper.read(Type.STRING);
packetWrapper.write(Type.COMPONENT, ComponentUtil.legacyToJson(line));
wrapper.write(Type.COMPONENT, ComponentUtil.legacyToJson(line));
}
});
}
@@ -804,13 +763,13 @@ public class PlayerPackets {
map(Type.BYTE);
map(Type.FLOAT);
map(Type.FLOAT);
handler(packetWrapper -> {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
handler(wrapper -> {
PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
if (playerSession.allowFly) {
byte flags = packetWrapper.get(Type.BYTE, 0);
byte flags = wrapper.get(Type.BYTE, 0);
playerSession.flying = (flags & 2) == 2;
}
packetWrapper.set(Type.FLOAT, 0, playerSession.flySpeed);
wrapper.set(Type.FLOAT, 0, playerSession.flySpeed);
});
}
});
@@ -820,23 +779,23 @@ public class PlayerPackets {
public void register() {
map(Type.STRING);
create(Type.OPTIONAL_POSITION1_8, null);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
handler(wrapper -> {
String msg = wrapper.get(Type.STRING, 0);
if (msg.toLowerCase().startsWith("/stp ")) {
packetWrapper.cancel();
wrapper.cancel();
String[] args = msg.split(" ");
if (args.length <= 2) {
String prefix = args.length == 1 ? "" : args[1];
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
GameProfileStorage storage = wrapper.user().get(GameProfileStorage.class);
List<GameProfileStorage.GameProfile> profiles = storage.getAllWithPrefix(prefix, true);
PacketWrapper tabComplete = PacketWrapper.create(0x3A, null, packetWrapper.user());
PacketWrapper tabComplete = PacketWrapper.create(0x3A, null, wrapper.user());
tabComplete.write(Type.VAR_INT, profiles.size());
for (GameProfileStorage.GameProfile profile : profiles) {
tabComplete.write(Type.STRING, profile.name);
}
PacketUtil.sendPacket(tabComplete, Protocol1_7_6_10To1_8.class);
tabComplete.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
});
@@ -852,9 +811,9 @@ public class PlayerPackets {
map(Type.BYTE);
map(Type.BOOLEAN);
read(Type.BYTE);
handler(packetWrapper -> {
boolean cape = packetWrapper.read(Type.BOOLEAN);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) (cape ? 127 : 126));
handler(wrapper -> {
boolean cape = wrapper.read(Type.BOOLEAN);
wrapper.write(Type.UNSIGNED_BYTE, (short) (cape ? 127 : 126));
});
}
});
@@ -864,36 +823,36 @@ public class PlayerPackets {
public void register() {
map(Type.STRING);
read(Type.SHORT); // Length
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
handler(wrapper -> {
String channel = wrapper.get(Type.STRING, 0);
switch (channel) {
case "MC|TrSel": {
packetWrapper.passthrough(Type.INT);
packetWrapper.read(Type.REMAINING_BYTES); // unused data ???
wrapper.passthrough(Type.INT);
wrapper.read(Type.REMAINING_BYTES); // unused data ???
break;
}
case "MC|ItemName": {
byte[] data = packetWrapper.read(Type.REMAINING_BYTES);
byte[] data = wrapper.read(Type.REMAINING_BYTES);
String name = new String(data, StandardCharsets.UTF_8);
packetWrapper.write(Type.STRING, name);
wrapper.write(Type.STRING, name);
InventoryTracker windowTracker = packetWrapper.user().get(InventoryTracker.class);
PacketWrapper updateCost = PacketWrapper.create(0x31, null, packetWrapper.user());
InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
PacketWrapper updateCost = PacketWrapper.create(0x31, null, wrapper.user());
updateCost.write(Type.UNSIGNED_BYTE, windowTracker.anvilId);
updateCost.write(Type.SHORT, (short) 0);
updateCost.write(Type.SHORT, windowTracker.levelCost);
PacketUtil.sendPacket(updateCost, Protocol1_7_6_10To1_8.class, true, true);
updateCost.send(Protocol1_7_6_10To1_8.class);
break;
}
case "MC|BEdit":
case "MC|BSign": {
Item book = packetWrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
Item book = wrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
CompoundTag tag = book.tag();
if (tag != null && tag.contains("pages")) {
ListTag pages = tag.get("pages");
ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
@@ -901,11 +860,11 @@ public class PlayerPackets {
page.setValue(value);
}
}
packetWrapper.write(Type.ITEM1_8, book);
wrapper.write(Type.ITEM1_8, book);
break;
}
case "MC|Brand": {
packetWrapper.write(Type.STRING, new String(packetWrapper.read(Type.REMAINING_BYTES), StandardCharsets.UTF_8));
wrapper.write(Type.STRING, new String(wrapper.read(Type.REMAINING_BYTES), StandardCharsets.UTF_8));
break;
}
}
@@ -15,12 +15,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.Scoreboard;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
@@ -31,62 +29,62 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class ScoreboardPackets {
public class ScoreboardPackets1_8 {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.SCOREBOARD_OBJECTIVE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
String name = packetWrapper.passthrough(Type.STRING);
handler(wrapper -> {
String name = wrapper.passthrough(Type.STRING);
if (name.length() > 16) {
packetWrapper.set(Type.STRING, 0, name = name.substring(0, 16));
wrapper.set(Type.STRING, 0, name = name.substring(0, 16));
}
byte mode = packetWrapper.read(Type.BYTE);
byte mode = wrapper.read(Type.BYTE);
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
Scoreboard scoreboard = wrapper.user().get(Scoreboard.class);
if (mode == 0) {
if (scoreboard.objectiveExists(name)) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
scoreboard.addObjective(name);
} else if (mode == 1) {
if (!scoreboard.objectiveExists(name)) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
if (scoreboard.getColorIndependentSidebar() != null) {
String username = packetWrapper.user().getProtocolInfo().getUsername();
String username = wrapper.user().getProtocolInfo().getUsername();
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
if (color.isPresent()) {
String sidebar = scoreboard.getColorDependentSidebar().get(color.get());
if (name.equals(sidebar)) {
PacketWrapper sidebarPacket = PacketWrapper.create(0x3D, null, packetWrapper.user());
PacketWrapper sidebarPacket = PacketWrapper.create(0x3D, null, wrapper.user());
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, scoreboard.getColorIndependentSidebar());
PacketUtil.sendPacket(sidebarPacket, Protocol1_7_6_10To1_8.class);
sidebarPacket.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
}
scoreboard.removeObjective(name);
} else if (mode == 2) {
if (!scoreboard.objectiveExists(name)) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
}
if (mode == 0 || mode == 2) {
String displayName = packetWrapper.passthrough(Type.STRING);
String displayName = wrapper.passthrough(Type.STRING);
if (displayName.length() > 32) {
packetWrapper.set(Type.STRING, 1, displayName.substring(0, 32));
wrapper.set(Type.STRING, 1, displayName.substring(0, 32));
}
packetWrapper.read(Type.STRING);
wrapper.read(Type.STRING);
} else {
packetWrapper.write(Type.STRING, "");
wrapper.write(Type.STRING, "");
}
packetWrapper.write(Type.BYTE, mode);
wrapper.write(Type.BYTE, mode);
});
}
});
@@ -96,10 +94,10 @@ public class ScoreboardPackets {
public void register() {
map(Type.STRING); // Name
map(Type.VAR_INT, Type.BYTE); // Mode
handler(packetWrapper -> {
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
String name = packetWrapper.get(Type.STRING, 0);
byte mode = packetWrapper.get(Type.BYTE, 0);
handler(wrapper -> {
Scoreboard scoreboard = wrapper.user().get(Scoreboard.class);
String name = wrapper.get(Type.STRING, 0);
byte mode = wrapper.get(Type.BYTE, 0);
if (mode == 1) {
name = scoreboard.removeTeamForScore(name);
@@ -113,17 +111,17 @@ public class ScoreboardPackets {
name = name.substring(0, 16);
}
}
packetWrapper.set(Type.STRING, 0, name);
wrapper.set(Type.STRING, 0, name);
String objective = packetWrapper.read(Type.STRING);
String objective = wrapper.read(Type.STRING);
if (objective.length() > 16) {
objective = objective.substring(0, 16);
}
if (mode != 1) {
int score = packetWrapper.read(Type.VAR_INT);
packetWrapper.write(Type.STRING, objective);
packetWrapper.write(Type.INT, score);
int score = wrapper.read(Type.VAR_INT);
wrapper.write(Type.STRING, objective);
wrapper.write(Type.INT, score);
}
});
}
@@ -134,15 +132,15 @@ public class ScoreboardPackets {
public void register() {
map(Type.BYTE); // Position
map(Type.STRING); // Score name
handler(packetWrapper -> {
byte position = packetWrapper.get(Type.BYTE, 0);
String name = packetWrapper.get(Type.STRING, 0);
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
handler(wrapper -> {
byte position = wrapper.get(Type.BYTE, 0);
String name = wrapper.get(Type.STRING, 0);
Scoreboard scoreboard = wrapper.user().get(Scoreboard.class);
if (position > 2) { // team specific sidebar
byte receiverTeamColor = (byte) (position - 3);
scoreboard.getColorDependentSidebar().put(receiverTeamColor, name);
String username = packetWrapper.user().getProtocolInfo().getUsername();
String username = wrapper.user().getProtocolInfo().getUsername();
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
if (color.isPresent() && color.get() == receiverTeamColor) {
position = 1;
@@ -151,17 +149,17 @@ public class ScoreboardPackets {
}
} else if (position == 1) { // team independent sidebar
scoreboard.setColorIndependentSidebar(name);
String username = packetWrapper.user().getProtocolInfo().getUsername();
String username = wrapper.user().getProtocolInfo().getUsername();
Optional<Byte> color = scoreboard.getPlayerTeamColor(username);
if (color.isPresent() && scoreboard.getColorDependentSidebar().containsKey(color.get())) {
position = -1;
}
}
if (position == -1) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
packetWrapper.set(Type.BYTE, 0, position);
wrapper.set(Type.BYTE, 0, position);
});
}
});
@@ -170,26 +168,26 @@ public class ScoreboardPackets {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String team = packetWrapper.get(Type.STRING, 0);
handler(wrapper -> {
String team = wrapper.get(Type.STRING, 0);
if (team == null) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
byte mode = packetWrapper.passthrough(Type.BYTE);
byte mode = wrapper.passthrough(Type.BYTE);
Scoreboard scoreboard = packetWrapper.user().get(Scoreboard.class);
Scoreboard scoreboard = wrapper.user().get(Scoreboard.class);
if (mode != 0 && !scoreboard.teamExists(team)) {
packetWrapper.cancel();
wrapper.cancel();
return;
} else if (mode == 0 && scoreboard.teamExists(team)) {
scoreboard.removeTeam(team);
PacketWrapper remove = PacketWrapper.create(0x3E, null, packetWrapper.user());
PacketWrapper remove = PacketWrapper.create(0x3E, null, wrapper.user());
remove.write(Type.STRING, team);
remove.write(Type.BYTE, (byte) 1);
PacketUtil.sendPacket(remove, Protocol1_7_6_10To1_8.class, true, true);
remove.send(Protocol1_7_6_10To1_8.class);
}
if (mode == 0) {
@@ -199,54 +197,54 @@ public class ScoreboardPackets {
}
if (mode == 0 || mode == 2) {
packetWrapper.passthrough(Type.STRING); // Display name
packetWrapper.passthrough(Type.STRING); // prefix
packetWrapper.passthrough(Type.STRING); // suffix
packetWrapper.passthrough(Type.BYTE); // friendly fire
packetWrapper.read(Type.STRING); // name tag visibility
byte color = packetWrapper.read(Type.BYTE);
wrapper.passthrough(Type.STRING); // Display name
wrapper.passthrough(Type.STRING); // prefix
wrapper.passthrough(Type.STRING); // suffix
wrapper.passthrough(Type.BYTE); // friendly fire
wrapper.read(Type.STRING); // name tag visibility
byte color = wrapper.read(Type.BYTE);
if (mode == 2 && scoreboard.getTeamColor(team).get() != color) {
String username = packetWrapper.user().getProtocolInfo().getUsername();
String username = wrapper.user().getProtocolInfo().getUsername();
String sidebar = scoreboard.getColorDependentSidebar().get(color);
PacketWrapper sidebarPacket = packetWrapper.create(0x3D);
PacketWrapper sidebarPacket = wrapper.create(0x3D);
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, sidebar == null ? "" : sidebar);
PacketUtil.sendPacket(sidebarPacket, Protocol1_7_6_10To1_8.class);
sidebarPacket.scheduleSend(Protocol1_7_6_10To1_8.class);
}
scoreboard.setTeamColor(team, color);
}
if (mode == 0 || mode == 3 || mode == 4) {
byte color = scoreboard.getTeamColor(team).get();
String[] entries = packetWrapper.read(Type.STRING_ARRAY);
String[] entries = wrapper.read(Type.STRING_ARRAY);
List<String> entryList = new ArrayList<>();
for (String entry : entries) {
String username = packetWrapper.user().getProtocolInfo().getUsername();
String username = wrapper.user().getProtocolInfo().getUsername();
if (mode == 4) {
if (!scoreboard.isPlayerInTeam(entry, team)) continue;
scoreboard.removePlayerFromTeam(entry, team);
if (entry.equals(username)) {
PacketWrapper sidebarPacket = packetWrapper.create(0x3D);
PacketWrapper sidebarPacket = wrapper.create(0x3D);
sidebarPacket.write(Type.BYTE, (byte) 1);
sidebarPacket.write(Type.STRING, scoreboard.getColorIndependentSidebar() == null ? "" : scoreboard.getColorIndependentSidebar());
PacketUtil.sendPacket(sidebarPacket, Protocol1_7_6_10To1_8.class);
sidebarPacket.scheduleSend(Protocol1_7_6_10To1_8.class);
}
} else {
scoreboard.addPlayerToTeam(entry, team);
if (entry.equals(username) && scoreboard.getColorDependentSidebar().containsKey(color)) {
PacketWrapper displayObjective = packetWrapper.create(0x3D);
PacketWrapper displayObjective = wrapper.create(0x3D);
displayObjective.write(Type.BYTE, (byte) 1);
displayObjective.write(Type.STRING, scoreboard.getColorDependentSidebar().get(color));
PacketUtil.sendPacket(displayObjective, Protocol1_7_6_10To1_8.class);
displayObjective.scheduleSend(Protocol1_7_6_10To1_8.class);
}
}
entryList.add(entry);
}
packetWrapper.write(Type.SHORT, (short) entryList.size());
wrapper.write(Type.SHORT, (short) entryList.size());
for (String entry : entryList) {
packetWrapper.write(Type.STRING, entry);
wrapper.write(Type.STRING, entry);
}
}
});
@@ -1,314 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.rewriter.Replacement;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.List;
import java.util.UUID;
public class SpawnPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
handler(wrapper -> {
final UUID uuid = wrapper.read(Type.UUID);
wrapper.write(Type.STRING, uuid.toString()); // map to string
final GameProfileStorage gameProfileStorage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) {
wrapper.write(Type.STRING, ""); // name
wrapper.write(Type.VAR_INT, 0); // properties count
} else {
wrapper.write(Type.STRING, gameProfile.name.length() > 16 ? gameProfile.name.substring(0, 16) : gameProfile.name); // name
wrapper.write(Type.VAR_INT, gameProfile.properties.size()); // properties count
for (GameProfileStorage.Property property : gameProfile.properties) {
wrapper.write(Type.STRING, property.name); // property name
wrapper.write(Type.STRING, property.value); // property value
wrapper.write(Type.STRING, property.signature == null ? "" : property.signature); // property signature
}
}
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (gameProfile != null && gameProfile.gamemode == 3) { // Spectator mode
for (short i = 0; i < 5; i++) {
final PacketWrapper entityEquipment = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, wrapper.user());
entityEquipment.write(Type.INT, entityId);
entityEquipment.write(Type.SHORT, i);
entityEquipment.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, i == 4 ? gameProfile.getSkull() : null);
entityEquipment.scheduleSend(Protocol1_7_6_10To1_8.class, true);
}
}
tracker.addPlayer(entityId, uuid);
});
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // item in hand id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final List<Metadata> metadata = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
protocol.getMetadataRewriter().transform(EntityTypes1_10.EntityType.PLAYER, metadata);
wrapper.set(Types1_7_6_10.METADATA_LIST, 0, metadata);
});
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.PLAYER);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // pitch
map(Type.BYTE); // yaw
map(Type.INT); // data
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(wrapper.get(Type.BYTE, 0), true);
final int entityId = wrapper.get(Type.VAR_INT, 0);
int x = wrapper.get(Type.INT, 0);
int y = wrapper.get(Type.INT, 1);
int z = wrapper.get(Type.INT, 2);
byte pitch = wrapper.get(Type.BYTE, 1);
byte yaw = wrapper.get(Type.BYTE, 2);
int data = wrapper.get(Type.INT, 3);
if (type == EntityTypes1_10.ObjectType.ITEM_FRAME.getType()) {
switch (yaw) {
case -128:
z += 32;
yaw = 0;
break;
case -64:
x -= 32;
yaw = -64;
break;
case 0:
z -= 32;
yaw = -128;
break;
case 64:
x += 32;
yaw = 64;
break;
}
} else if (type == EntityTypes1_10.ObjectType.ARMOR_STAND.getType()) {
wrapper.cancel();
final VirtualHologramEntity hologram = new VirtualHologramEntity(wrapper.user(), protocol.getMetadataRewriter(), entityId);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(yaw * 360f / 256);
tracker.trackHologram(entityId, hologram);
}
// TODO | Realign all entities
wrapper.set(Type.INT, 0, x);
wrapper.set(Type.INT, 1, y);
wrapper.set(Type.INT, 2, z);
wrapper.set(Type.BYTE, 2, yaw);
tracker.addEntity(entityId, type);
if (type != null && type.isOrHasParent(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
final Replacement replace = protocol.getItemRewriter().replace(blockId, blockData);
if (replace != null) {
blockId = replace.getId();
blockData = replace.replaceData(blockData);
}
wrapper.set(Type.INT, 3, data = (blockId | blockData << 16));
}
if (data > 0) {
wrapper.passthrough(Type.SHORT); // velocity x
wrapper.passthrough(Type.SHORT); // velocity y
wrapper.passthrough(Type.SHORT); // velocity z
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.UNSIGNED_BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.BYTE); // head yaw
map(Type.SHORT); // velocity x
map(Type.SHORT); // velocity y
map(Type.SHORT); // velocity z
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final short typeId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (typeId == 255 || typeId == -1) {
wrapper.cancel();
}
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(typeId, false);
final int entityId = wrapper.get(Type.VAR_INT, 0);
final int x = wrapper.get(Type.INT, 0);
final int y = wrapper.get(Type.INT, 1);
final int z = wrapper.get(Type.INT, 2);
final byte pitch = wrapper.get(Type.BYTE, 1);
final byte yaw = wrapper.get(Type.BYTE, 0);
final byte headYaw = wrapper.get(Type.BYTE, 2);
final List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
if (type == EntityTypes1_10.EntityType.ARMOR_STAND) {
final VirtualHologramEntity hologram = new VirtualHologramEntity(wrapper.user(), protocol.getMetadataRewriter(), entityId);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(headYaw * 360f / 256);
tracker.trackHologram(entityId, hologram);
tracker.updateMetadata(entityId, metadataList); // Track and remap hologram <-> zombie metadata
wrapper.cancel();
} else {
protocol.getMetadataRewriter().transform(type, metadataList);
tracker.addEntity(entityId, type);
if (tracker.isReplaced(type)) {
final int newTypeId = tracker.replaceEntity(entityId, type);
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) newTypeId);
tracker.updateMetadata(entityId, metadataList);
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.STRING); // title
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // position
map(Type.UNSIGNED_BYTE, Type.INT); // rotation
handler(wrapper -> {
final Position position = wrapper.get(Types1_7_6_10.INT_POSITION, 0);
final int rotation = wrapper.get(Type.INT, 0);
int modX = 0;
int modZ = 0;
switch (rotation) {
case 0:
modZ = -1;
break;
case 1:
modX = 1;
break;
case 2:
modZ = 1;
break;
case 3:
modX = -1;
break;
}
wrapper.set(Types1_7_6_10.INT_POSITION, 0, new Position(position.x() + modX, position.y(), position.z() + modZ));
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.PAINTING);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_EXPERIENCE_ORB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.SHORT); // count
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.EXPERIENCE_ORB);
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_GLOBAL_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // entity id
map(Type.BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.LIGHTNING);
});
}
});
}
}
@@ -15,21 +15,17 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.WorldBorderEmulator;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk.ChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk.BulkChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.ParticleIndex1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.type.chunk.ChunkType1_7_6;
import com.viaversion.viarewind.api.type.chunk.BulkChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.data.ParticleIndex1_7_6_10;
import com.viaversion.viarewind.api.type.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
@@ -39,29 +35,33 @@ import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.util.ChatColorUtil;
import com.viaversion.viaversion.util.IdAndData;
public class WorldPackets {
private static void rewriteBlockIds(final Protocol1_7_6_10To1_8 protocol, final Chunk chunk) {
for (ChunkSection section : chunk.getSections()) {
if (section == null) continue;
final DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < palette.size(); i++) {
palette.setIdByIndex(i, protocol.getItemRewriter().replace(palette.idByIndex(i)));
}
}
}
public class WorldPackets1_8 {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.CHUNK_DATA, wrapper -> {
final ClientWorld world = wrapper.user().get(ClientWorld.class);
final Chunk chunk = wrapper.read(ChunkType1_8.forEnvironment(world.getEnvironment()));
rewriteBlockIds(protocol, chunk);
protocol.getItemRewriter().handleChunk(chunk);
wrapper.write(ChunkType1_7_6.TYPE, chunk);
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_CHANGE, new PacketHandlers() {
@Override
protected void register() {
map(Type.POSITION1_8, Types1_7_6_10.U_BYTE_POSITION); // position
handler(wrapper -> {
int data = wrapper.read(Type.VAR_INT); // block data
data = protocol.getItemRewriter().handleBlockId(data);
wrapper.write(Type.VAR_INT, IdAndData.getId(data)); // block id
wrapper.write(Type.UNSIGNED_BYTE, (short) IdAndData.getData(data)); // block data
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.MULTI_BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
@@ -76,26 +76,12 @@ public class WorldPackets {
for (BlockChangeRecord record : records) {
wrapper.write(Type.SHORT, (short) (record.getSectionX() << 12 | record.getSectionZ() << 8 | record.getY())); // position
wrapper.write(Type.SHORT, (short) protocol.getItemRewriter().replace(record.getBlockId())); // block id
wrapper.write(Type.SHORT, (short) protocol.getItemRewriter().handleBlockId(record.getBlockId())); // block id
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_CHANGE, new PacketHandlers() {
@Override
protected void register() {
map(Type.POSITION1_8, Types1_7_6_10.U_BYTE_POSITION); // position
handler(wrapper -> {
int data = wrapper.read(Type.VAR_INT); // block data
data = protocol.getItemRewriter().replace(data);
wrapper.write(Type.VAR_INT, data >> 4); // block id
wrapper.write(Type.UNSIGNED_BYTE, (short) (data & 0xF)); // block data
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ACTION, new PacketHandlers() {
@Override
public void register() {
@@ -118,7 +104,7 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.MAP_BULK_CHUNK, wrapper -> {
final Chunk[] chunks = wrapper.read(BulkChunkType1_8.TYPE);
for (Chunk chunk : chunks) {
rewriteBlockIds(protocol, chunk);
protocol.getItemRewriter().handleChunk(chunk);
}
wrapper.write(BulkChunkType1_7_6.TYPE, chunks);
@@ -185,7 +171,7 @@ public class WorldPackets {
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
String line = wrapper.read(Type.STRING);
line = ChatUtil.jsonToLegacy(line);
line = ChatUtil.jsonToLegacy(wrapper.user(), line);
line = ChatUtil.removeUnusedColor(line, '0');
if (line.length() > 15) {
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.CompressionStatusTracker;
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider;
import com.viaversion.viaversion.api.platform.providers.Provider;
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viaversion.api.type.Type;
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viaversion.api.type.Type;
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viarewind.api.netty.EmptyChannelHandler;
@@ -27,8 +26,8 @@ import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
public class TrackingCompressionHandlerProvider extends CompressionHandlerProvider {
public final static String COMPRESS_HANDLER_NAME = "compress";
public final static String DECOMPRESS_HANDLER_NAME = "decompress";
public static final String COMPRESS_HANDLER_NAME = "compress";
public static final String DECOMPRESS_HANDLER_NAME = "decompress";
@Override
public void onHandleLoginCompressionPacket(UserConnection user, int threshold) {
@@ -1,230 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter;
import com.viaversion.viarewind.api.rewriter.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.api.rewriter.Replacement;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import java.util.ArrayList;
import java.util.List;
public class ReplacementItemRewriter1_7_6_10 extends ReplacementItemRewriter<Protocol1_7_6_10To1_8> {
private final static String VIA_REWIND_TAG_KEY = "ViaRewind1_7_6_10to1_8";
public ReplacementItemRewriter1_7_6_10(Protocol1_7_6_10To1_8 protocol) {
super(protocol, ProtocolVersion.v1_8);
}
@Override
public void register() {
registerBlock(176, new Replacement(63));
registerBlock(177, new Replacement(68));
registerBlock(193, new Replacement(64));
registerBlock(194, new Replacement(64));
registerBlock(195, new Replacement(64));
registerBlock(196, new Replacement(64));
registerBlock(197, new Replacement(64));
registerBlock(77, 5, new Replacement(69, 6));
registerBlock(77, 13, new Replacement(69, 14));
registerBlock(77, 0, new Replacement(69, 0));
registerBlock(77, 8, new Replacement(69, 8));
registerBlock(143, 5, new Replacement(69, 6));
registerBlock(143, 13, new Replacement(69, 14));
registerBlock(143, 0, new Replacement(69, 0));
registerBlock(143, 8, new Replacement(69, 8));
registerBlock(178, new Replacement(151));
registerBlock(182, 0, new Replacement(44, 1));
registerBlock(182, 8, new Replacement(44, 9));
registerItem(425, new Replacement(323, "Banner"));
registerItem(409, new Replacement(406, "Prismarine Shard"));
registerItem(410, new Replacement(406, "Prismarine Crystal"));
registerItem(416, new Replacement(280, "Armor Stand"));
registerItem(423, new Replacement(363, "Raw Mutton"));
registerItem(424, new Replacement(364, "Cooked Mutton"));
registerItem(411, new Replacement(365, "Raw Rabbit"));
registerItem(412, new Replacement(366, "Cooked Rabbit"));
registerItem(413, new Replacement(282, "Rabbit Stew"));
registerItem(414, new Replacement(375, "Rabbit's Foot"));
registerItem(415, new Replacement(334, "Rabbit Hide"));
registerItem(373, 8203, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 8235, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 8267, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 16395, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(373, 16427, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(373, 16459, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(383, 30, new Replacement(383, "Spawn ArmorStand"));
registerItem(383, 67, new Replacement(383, "Spawn Endermite"));
registerItem(383, 68, new Replacement(383, "Spawn Guardian"));
registerItem(383, 101, new Replacement(383, "Spawn Rabbit"));
registerItem(19, 1, new Replacement(19, 0, "Wet Sponge"));
registerItem(182, new Replacement(44, 1, "Red Sandstone Slab"));
registerItemBlock(166, new Replacement(20, "Barrier"));
registerItemBlock(167, new Replacement(96, "Iron Trapdoor"));
registerItemBlock(1, 1, new Replacement(1, 0, "Granite"));
registerItemBlock(1, 2, new Replacement(1, 0, "Polished Granite"));
registerItemBlock(1, 3, new Replacement(1, 0, "Diorite"));
registerItemBlock(1, 4, new Replacement(1, 0, "Polished Diorite"));
registerItemBlock(1, 5, new Replacement(1, 0, "Andesite"));
registerItemBlock(1, 6, new Replacement(1, 0, "Polished Andesite"));
registerItemBlock(168, 0, new Replacement(1, 0, "Prismarine"));
registerItemBlock(168, 1, new Replacement(98, 0, "Prismarine Bricks"));
registerItemBlock(168, 2, new Replacement(98, 1, "Dark Prismarine"));
registerItemBlock(169, new Replacement(89, "Sea Lantern"));
registerItemBlock(165, new Replacement(95, 5, "Slime Block"));
registerItemBlock(179, 0, new Replacement(24, "Red Sandstone"));
registerItemBlock(179, 1, new Replacement(24, "Chiseled Red Sandstone"));
registerItemBlock(179, 2, new Replacement(24, "Smooth Sandstone"));
registerItemBlock(181, new Replacement(43, 1, "Double Red Sandstone Slab"));
registerItemBlock(180, new Replacement(128, "Red Sandstone Stairs"));
registerItemBlock(188, new Replacement(85, "Spruce Fence"));
registerItemBlock(189, new Replacement(85, "Birch Fence"));
registerItemBlock(190, new Replacement(85, "Jungle Fence"));
registerItemBlock(191, new Replacement(85, "Dark Oak Fence"));
registerItemBlock(192, new Replacement(85, "Acacia Fence"));
registerItemBlock(183, new Replacement(107, "Spruce Fence Gate"));
registerItemBlock(184, new Replacement(107, "Birch Fence Gate"));
registerItemBlock(185, new Replacement(107, "Jungle Fence Gate"));
registerItemBlock(186, new Replacement(107, "Dark Oak Fence Gate"));
registerItemBlock(187, new Replacement(107, "Acacia Fence Gate"));
registerItemBlock(427, new Replacement(324, "Spruce Door"));
registerItemBlock(428, new Replacement(324, "Birch Door"));
registerItemBlock(429, new Replacement(324, "Jungle Door"));
registerItemBlock(430, new Replacement(324, "Dark Oak Door"));
registerItemBlock(431, new Replacement(324, "Acacia Door"));
registerItemBlock(157, new Replacement(28, "Activator Rail"));
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
CompoundTag viaRewindTag = new CompoundTag();
tag.put(VIA_REWIND_TAG_KEY, viaRewindTag);
viaRewindTag.put("id", new ShortTag((short) item.identifier()));
viaRewindTag.put("data", new ShortTag(item.data()));
CompoundTag display = tag.get("display");
if (display != null && display.contains("Name")) {
viaRewindTag.put("displayName", new StringTag((String) display.get("Name").getValue()));
}
if (display != null && display.contains("Lore")) {
viaRewindTag.put("lore", new ListTag(((ListTag) display.get("Lore")).getValue()));
}
if (tag.contains("ench") || tag.contains("StoredEnchantments")) {
ListTag enchTag = tag.contains("ench") ? tag.get("ench") : tag.get("StoredEnchantments");
List<Tag> lore = new ArrayList<>();
for (Tag ench : new ArrayList<>(enchTag.getValue())) {
short id = ((NumberTag) ((CompoundTag) ench).get("id")).asShort();
short lvl = ((NumberTag) ((CompoundTag) ench).get("lvl")).asShort();
String s;
if (id == 8) {
s = "§r§7Depth Strider ";
} else {
continue;
}
enchTag.remove(ench);
s += Enchantments.ENCHANTMENTS.getOrDefault(lvl, "enchantment.level." + lvl);
lore.add(new StringTag(s));
}
if (!lore.isEmpty()) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaRewindTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
lore.addAll(loreTag.getValue());
loreTag.setValue(lore);
}
}
if (item.identifier() == 387 && tag.contains("pages")) {
ListTag pages = tag.get("pages");
ListTag oldPages = new ListTag(StringTag.class);
viaRewindTag.put("pages", oldPages);
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
oldPages.add(new StringTag(value));
value = ChatUtil.jsonToLegacy(value);
page.setValue(value);
}
}
replace(item);
if (viaRewindTag.size() == 2 && (short) viaRewindTag.get("id").getValue() == item.identifier() && (short) viaRewindTag.get("data").getValue() == item.data()) {
item.tag().remove(VIA_REWIND_TAG_KEY);
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null || !item.tag().contains(VIA_REWIND_TAG_KEY)) return item;
CompoundTag viaVersionTag = tag.remove(VIA_REWIND_TAG_KEY);
item.setIdentifier((short) viaVersionTag.get("id").getValue());
item.setData((Short) viaVersionTag.get("data").getValue());
if (viaVersionTag.contains("noDisplay")) tag.remove("display");
if (viaVersionTag.contains("displayName")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
StringTag name = display.get("Name");
if (name == null) display.put("Name", new StringTag((String) viaVersionTag.get("displayName").getValue()));
else name.setValue((String) viaVersionTag.get("displayName").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Name");
}
if (item.identifier() == 387) {
ListTag oldPages = viaVersionTag.get("pages");
tag.remove("pages");
tag.put("pages", oldPages);
}
return item;
}
}
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
@@ -1,193 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.ReplacementEntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
public class EntityTracker1_7_6_10 extends ReplacementEntityTracker {
protected final MetadataRewriter metadataRewriter;
private final Map<Integer, Integer> vehicleMap = new ConcurrentHashMap<>();
private final Map<Integer, VirtualHologramEntity> virtualHologramMap = new HashMap<>();
private final Map<Integer, UUID> playersByEntityId = new HashMap<>();
private final Map<UUID, Integer> playersByUniqueId = new HashMap<>();
public int spectatingPlayerId = -1;
public EntityTracker1_7_6_10(UserConnection user, final MetadataRewriter metadataRewriter) {
super(user, ProtocolVersion.v1_8, MetaType1_7_6_10.Byte, MetaType1_7_6_10.String);
this.metadataRewriter = metadataRewriter;
registerEntity(EntityTypes1_10.EntityType.GUARDIAN, EntityTypes1_10.EntityType.SQUID, "Guardian");
registerEntity(EntityTypes1_10.EntityType.ENDERMITE, EntityTypes1_10.EntityType.SQUID, "Endermite");
registerEntity(EntityTypes1_10.EntityType.RABBIT, EntityTypes1_10.EntityType.CHICKEN, "Rabbit");
}
public void trackHologram(final int entityId, final VirtualHologramEntity hologram) {
addEntity(entityId, EntityTypes1_10.EntityType.ARMOR_STAND);
getEntityReplacementMap().put(entityId, EntityTypes1_10.EntityType.ARMOR_STAND);
virtualHologramMap.put(entityId, hologram);
}
@Override
public void updateMetadata(int entityId, List<Metadata> metadata) throws Exception {
if (virtualHologramMap.containsKey(entityId)) {
virtualHologramMap.get(entityId).updateMetadata(metadata);
return;
}
super.updateMetadata(entityId, metadata);
}
@Override
public void removeEntity(int entityId) {
super.removeEntity(entityId);
if (playersByEntityId.containsKey(entityId)) {
final UUID playerId = playersByEntityId.remove(entityId);
playersByUniqueId.remove(playerId);
getUser().get(PlayerSessionStorage.class).getPlayerEquipment().remove(playerId);
}
}
@Override
public void clear() {
super.clear();
vehicleMap.clear();
}
@Override
public void setClientEntityId(int entityId) {
if (this.spectatingPlayerId == this.getPlayerId()) {
this.spectatingPlayerId = entityId;
}
super.setClientEntityId(entityId);
}
public void addPlayer(final Integer entityId, final UUID uuid) {
playersByUniqueId.put(uuid, entityId);
playersByEntityId.put(entityId, uuid);
}
public UUID getPlayerUUID(final int entityId) {
return playersByEntityId.get(entityId);
}
public int getPlayerEntityId(final UUID uuid) {
return playersByUniqueId.getOrDefault(uuid, -1);
}
public int getVehicle(final int passengerId) {
for (Map.Entry<Integer, Integer> vehicle : vehicleMap.entrySet()) {
if (vehicle.getValue() == passengerId) {
return vehicle.getValue();
}
}
return -1;
}
public int getPassenger(int vehicleId) {
return vehicleMap.getOrDefault(vehicleId, -1);
}
protected void startSneaking() {
try {
final PacketWrapper entityAction = PacketWrapper.create(ServerboundPackets1_7_2_5.ENTITY_ACTION, getUser());
entityAction.write(Type.VAR_INT, this.getPlayerId()); // entity id
entityAction.write(Type.VAR_INT, 0); // action id, start sneaking
entityAction.write(Type.VAR_INT, 0); // jump boost
entityAction.sendToServer(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send sneak packet", e);
}
}
public void setPassenger(int vehicleId, int passengerId) {
if (vehicleId == this.spectatingPlayerId && this.spectatingPlayerId != this.getPlayerId()) {
startSneaking();
setSpectating(this.getPlayerId());
}
if (vehicleId == -1) {
vehicleMap.remove(getVehicle(passengerId));
} else if (passengerId == -1) {
vehicleMap.remove(vehicleId);
} else {
vehicleMap.put(vehicleId, passengerId);
}
}
protected void attachEntity(final int target) {
try {
final PacketWrapper attachEntity = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, getUser());
attachEntity.write(Type.INT, this.getPlayerId()); // vehicle id
attachEntity.write(Type.INT, target); // passenger id
attachEntity.write(Type.BOOLEAN, false); // leash
attachEntity.scheduleSend(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send attach packet", e);
}
}
public void setSpectating(int spectating) {
if (spectating != this.getPlayerId() && getPassenger(spectating) != -1) {
startSneaking();
setSpectating(this.getPlayerId());
return;
}
if (this.spectatingPlayerId != spectating && this.spectatingPlayerId != this.getPlayerId()) {
attachEntity(-1);
}
this.spectatingPlayerId = spectating;
if (spectating != this.getPlayerId()) {
attachEntity(this.spectatingPlayerId);
}
}
public Map<Integer, VirtualHologramEntity> getVirtualHologramMap() {
return virtualHologramMap;
}
}
@@ -0,0 +1,183 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.emulation.VirtualHologramEntity;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntArrayMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectArrayMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntOpenHashMap;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
public class EntityTracker1_8 extends EntityTrackerBase {
private final Int2ObjectMap<VirtualHologramEntity> holograms = new Int2ObjectArrayMap<>();
private final Int2IntMap vehicles = new Int2IntArrayMap();
private final Int2ObjectMap<UUID> entityIdToUUID = new Int2ObjectArrayMap<>();
private final Object2IntMap<UUID> entityUUIDToId = new Object2IntOpenHashMap<>();
public int spectatingClientEntityId = -1;
private int clientEntityGameMode;
public EntityTracker1_8(UserConnection connection) {
super(connection, EntityTypes1_10.EntityType.ENTITY_HUMAN);
}
@Override
public void addEntity(int id, EntityType type) {
super.addEntity(id, type);
if (type == EntityTypes1_10.EntityType.ARMOR_STAND) {
holograms.put(id, new VirtualHologramEntity(user(), id));
}
}
@Override
public void removeEntity(int entityId) {
super.removeEntity(entityId);
if (entityIdToUUID.containsKey(entityId)) {
final UUID playerId = entityIdToUUID.remove(entityId);
entityUUIDToId.removeInt(playerId);
user().get(PlayerSessionStorage.class).getPlayerEquipment().remove(playerId);
}
}
@Override
public void clearEntities() {
super.clearEntities();
vehicles.clear();
}
@Override
public void setClientEntityId(int entityId) {
if (this.spectatingClientEntityId == this.clientEntityId()) {
this.spectatingClientEntityId = entityId;
}
super.setClientEntityId(entityId);
}
public void addPlayer(final int entityId, final UUID uuid) {
entityUUIDToId.put(uuid, entityId);
entityIdToUUID.put(entityId, uuid);
}
public UUID getPlayerUUID(final int entityId) {
return entityIdToUUID.get(entityId);
}
public int getPlayerEntityId(final UUID uuid) {
return entityUUIDToId.getOrDefault(uuid, -1);
}
public int getVehicle(final int passengerId) {
for (Map.Entry<Integer, Integer> vehicle : vehicles.entrySet()) {
if (vehicle.getValue() == passengerId) {
return vehicle.getValue();
}
}
return -1;
}
public int getPassenger(int vehicleId) {
return vehicles.getOrDefault(vehicleId, -1);
}
protected void startSneaking() {
try {
final PacketWrapper entityAction = PacketWrapper.create(ServerboundPackets1_7_2_5.ENTITY_ACTION, user());
entityAction.write(Type.VAR_INT, this.clientEntityId()); // Entity id
entityAction.write(Type.VAR_INT, 0); // Action id
entityAction.write(Type.VAR_INT, 0); // Jump boost
entityAction.sendToServer(Protocol1_7_6_10To1_8.class);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send sneak packet", e);
}
}
public void setPassenger(final int vehicleId, final int passengerId) {
if (vehicleId == this.spectatingClientEntityId && this.spectatingClientEntityId != this.clientEntityId()) {
startSneaking();
setSpectating(this.clientEntityId());
}
if (vehicleId == -1) {
vehicles.remove(getVehicle(passengerId));
} else if (passengerId == -1) {
vehicles.remove(vehicleId);
} else {
vehicles.put(vehicleId, passengerId);
}
}
protected void attachEntity(final int target) {
try {
final PacketWrapper attachEntity = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, user());
attachEntity.write(Type.INT, this.clientEntityId()); // vehicle id
attachEntity.write(Type.INT, target); // passenger id
attachEntity.write(Type.BOOLEAN, false); // leash
attachEntity.scheduleSend(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send attach packet", e);
}
}
public void setSpectating(int spectating) {
if (spectating != this.clientEntityId() && getPassenger(spectating) != -1) {
startSneaking();
setSpectating(this.clientEntityId());
return;
}
if (this.spectatingClientEntityId != spectating && this.spectatingClientEntityId != this.clientEntityId()) {
attachEntity(-1);
}
this.spectatingClientEntityId = spectating;
if (spectating != this.clientEntityId()) {
attachEntity(this.spectatingClientEntityId);
}
}
public Int2ObjectMap<VirtualHologramEntity> getHolograms() {
return holograms;
}
public boolean isSpectator() {
return clientEntityGameMode == 3;
}
public void setClientEntityGameMode(int clientEntityGameMode) {
this.clientEntityGameMode = clientEntityGameMode;
}
}
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.utils.ChatUtil;
@@ -15,20 +15,16 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.FurnaceData;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class InventoryTracker extends StoredObject {
public final static Map<String, Integer> WINDOW_TYPE_REGISTRY = new HashMap<>();
public static final Map<String, Integer> WINDOW_TYPE_REGISTRY = new HashMap<>();
static {
WINDOW_TYPE_REGISTRY.put("minecraft:container", 0);
@@ -76,4 +72,13 @@ public class InventoryTracker extends StoredObject {
public HashMap<Short, FurnaceData> getFurnaceData() {
return furnaceData;
}
public static class FurnaceData {
public short fuelLeft = 0;
public short maxFuel = 0;
public short progress = 0;
public short maxProgress = 200;
}
}
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
@@ -28,9 +27,6 @@ import java.util.UUID;
public class PlayerSessionStorage extends StoredObject {
// Player info
public int gameMode;
// Player abilities
public boolean sprinting, allowFly, flying, invincible, creative;
public float flySpeed, walkSpeed;
@@ -95,10 +91,6 @@ public class PlayerSessionStorage extends StoredObject {
items[slot] = equipment;
}
public boolean isSpectator() {
return gameMode == 3;
}
public Map<UUID, Item[]> getPlayerEquipment() {
return playerEquipment;
}
@@ -15,12 +15,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -112,7 +110,7 @@ public class Scoreboard extends StoredObject {
return objectives.contains(name);
}
public String sendTeamForScore(String score) {
public String sendTeamForScore(String score) throws Exception {
if (score.length() <= 16) return score;
if (scoreTeams.containsKey(score)) return scoreTeams.get(score).name;
int l = 16;
@@ -143,12 +141,12 @@ public class Scoreboard extends StoredObject {
teamPacket.write(Type.BYTE, (byte) 0);
teamPacket.write(Type.SHORT, (short) 1);
teamPacket.write(Type.STRING, name);
PacketUtil.sendPacket(teamPacket, Protocol1_7_6_10To1_8.class, true, true);
teamPacket.send(Protocol1_7_6_10To1_8.class);
return name;
}
public String removeTeamForScore(String score) {
public String removeTeamForScore(String score) throws Exception {
ScoreTeam scoreTeam = scoreTeams.remove(score);
if (scoreTeam == null) return score;
scoreTeamNames.remove(scoreTeam.name);
@@ -156,7 +154,7 @@ public class Scoreboard extends StoredObject {
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.TEAMS, getUser());
teamPacket.write(Type.STRING, scoreTeam.name);
teamPacket.write(Type.BYTE, (byte) 1);
PacketUtil.sendPacket(teamPacket, Protocol1_7_6_10To1_8.class, true, true);
teamPacket.send(Protocol1_7_6_10To1_8.class);
return scoreTeam.name;
}
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.task;
import com.viaversion.viarewind.ViaRewind;
@@ -31,7 +30,7 @@ import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.logging.Level;
public class WorldBorderUpdateTask implements Runnable {
public final static int VIEW_DISTANCE = 16;
public static final int VIEW_DISTANCE = 16;
@Override
public void run() {
@@ -15,17 +15,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9;
import com.viaversion.viarewind.api.rewriter.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.rewriter.ReplacementItemRewriter1_8;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.data.RewindMappings;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata.MetadataRewriter1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.packets.*;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.utils.Ticker;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.task.CooldownIndicatorTask;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.task.LevitationUpdateTask;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.type.Type;
@@ -35,40 +36,27 @@ import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, ClientboundPackets1_8, ServerboundPackets1_9, ServerboundPackets1_8> {
private final ReplacementItemRewriter<Protocol1_8To1_9> itemRewriter = new ReplacementItemRewriter1_8(this);
private final MetadataRewriter metadataRewriter = new MetadataRewriter(this);
public class Protocol1_8To1_9 extends BackwardsProtocol<ClientboundPackets1_9, ClientboundPackets1_8, ServerboundPackets1_9, ServerboundPackets1_8> {
public Queue<PacketWrapper> animationsToSend = new ConcurrentLinkedQueue<>();
public final static Set<String> VALID_ATTRIBUTES = new HashSet<>();
public final static ValueTransformer<Double, Integer> TO_OLD_INT = new ValueTransformer<Double, Integer>(Type.INT) {
public static final ValueTransformer<Double, Integer> DOUBLE_TO_INT_TIMES_32 = new ValueTransformer<Double, Integer>(Type.INT) {
@Override
public Integer transform(PacketWrapper wrapper, Double inputValue) {
return (int) (inputValue * 32.0D);
}
};
public final static ValueTransformer<Float, Byte> DEGREES_TO_ANGLE = new ValueTransformer<Float, Byte>(Type.BYTE) {
public static final ValueTransformer<Float, Byte> DEGREES_TO_ANGLE = new ValueTransformer<Float, Byte>(Type.BYTE) {
@Override
public Byte transform(PacketWrapper packetWrapper, Float degrees) throws Exception {
public Byte transform(PacketWrapper packetWrapper, Float degrees) {
return (byte) ((degrees / 360F) * 256);
}
};
static {
VALID_ATTRIBUTES.add("generic.maxHealth");
VALID_ATTRIBUTES.add("generic.followRange");
VALID_ATTRIBUTES.add("generic.knockbackResistance");
VALID_ATTRIBUTES.add("generic.movementSpeed");
VALID_ATTRIBUTES.add("generic.attackDamage");
VALID_ATTRIBUTES.add("horse.jumpStrength");
VALID_ATTRIBUTES.add("zombie.spawnReinforcements");
}
public static final RewindMappings MAPPINGS = new RewindMappings();
private final BlockItemPackets1_9 itemRewriter = new BlockItemPackets1_9(this);
private final MetadataRewriter1_8To1_9 metadataRewriter = new MetadataRewriter1_8To1_9(this);
public Protocol1_8To1_9() {
super(ClientboundPackets1_9.class, ClientboundPackets1_8.class, ServerboundPackets1_9.class, ServerboundPackets1_8.class);
@@ -76,38 +64,53 @@ public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, Cl
@Override
protected void registerPackets() {
metadataRewriter.register();
itemRewriter.register();
EntityPackets.register(this);
InventoryPackets.register(this);
PlayerPackets.register(this);
ScoreboardPackets.register(this);
SpawnPackets.register(this);
WorldPackets.register(this);
EntityPackets1_9.register(this);
PlayerPackets1_9.register(this);
WorldPackets1_9.register(this);
}
@Override
public void init(UserConnection userConnection) {
Ticker.init();
public void init(UserConnection connection) {
connection.addEntityTracker(this.getClass(), new EntityTracker1_9(connection));
userConnection.put(new Windows(userConnection));
userConnection.put(new EntityTracker(userConnection, this));
userConnection.put(new Levitation(userConnection));
userConnection.put(new PlayerPosition(userConnection));
userConnection.put(new Cooldown(userConnection));
userConnection.put(new BlockPlaceDestroyTracker(userConnection));
userConnection.put(new BossBarStorage(userConnection));
if (!userConnection.has(ClientWorld.class)) {
userConnection.put(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));
if (!connection.has(ClientWorld.class)) {
connection.put(new ClientWorld());
}
}
@Override
public ReplacementItemRewriter<Protocol1_8To1_9> getItemRewriter() {
public void register(ViaProviders providers) {
Via.getManager().getScheduler().scheduleRepeating(new LevitationUpdateTask(), 0L, 50L, TimeUnit.MILLISECONDS);
Via.getManager().getScheduler().scheduleRepeating(new CooldownIndicatorTask(), 0L, 50L, TimeUnit.MILLISECONDS);
}
@Override
public RewindMappings getMappingData() {
return MAPPINGS;
}
@Override
public BlockItemPackets1_9 getItemRewriter() {
return itemRewriter;
}
public MetadataRewriter getMetadataRewriter() {
@Override
public MetadataRewriter1_8To1_9 getEntityRewriter() {
return metadataRewriter;
}
@Override
public boolean hasMappingDataToLoad() {
return true;
}
}
@@ -15,17 +15,13 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.sound;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.data;
import java.util.HashMap;
public class Effect {
private final static HashMap<Integer, Integer> effects = new HashMap<>();
public class EffectMappings {
public static int getOldId(int id) {
return effects.getOrDefault(id, id);
}
private static final HashMap<Integer, Integer> effects = new HashMap<>();
static {
effects.put(1003, 1002);
@@ -66,4 +62,8 @@ public class Effect {
effects.put(3000, -1);
effects.put(3001, -1);
}
public static int getOldId(int id) {
return effects.getOrDefault(id, id);
}
}
@@ -15,17 +15,17 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.rewriter;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.data;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
import java.util.HashMap;
import java.util.Map;
// TODO | Check if this is correct???
public class PotionMappings {
public final static Map<String, String> POTION_NAME_INDEX = new HashMap<>();
public final static Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
public static final Map<String, String> POTION_NAME_INDEX = new HashMap<>();
public static final Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
static {
POTION_NAME_TO_ID.putAll(ItemRewriter.POTION_NAME_TO_ID);
@@ -0,0 +1,48 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.data;
import com.viaversion.viarewind.api.data.VRMappingDataLoader;
import com.viaversion.viaversion.libs.fastutil.objects.ObjectArrayList;
import com.viaversion.viaversion.libs.fastutil.objects.ObjectList;
import com.viaversion.viaversion.libs.gson.JsonArray;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
public final class RewindMappings extends com.viaversion.viarewind.api.data.RewindMappings {
private final ObjectList<String> sounds = new ObjectArrayList<>();
public RewindMappings() {
super("1.9.4", "1.8");
}
@Override
protected void loadExtras(CompoundTag data) {
super.loadExtras(data);
final JsonArray sounds = VRMappingDataLoader.INSTANCE.loadData("sounds-1.9.4.json").getAsJsonArray("sounds");
for (final JsonElement sound : sounds) {
this.sounds.add(sound.getAsString());
}
}
public String soundName(final int soundId) {
return sounds.get(soundId);
}
}
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.ViaRewindConfig.CooldownIndicator;
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
public class DisabledCooldownVisualization implements CooldownVisualization {
@Override
@@ -15,8 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -15,9 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation;
package com.viaversion.viarewind.protocol.protocol1_8to1_9.bossbar;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.legacy.bossbar.BossBar;
@@ -29,9 +29,9 @@ import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viarewind.utils.PacketUtil;
import java.util.*;
import java.util.logging.Level;
public class WitherBossBar implements BossBar {
private static int highestId = Integer.MAX_VALUE - 10000;
@@ -61,7 +61,13 @@ public class WitherBossBar implements BossBar {
@Override
public BossBar setTitle(String title) {
this.title = title;
if (this.visible) updateMetadata();
if (this.visible) {
try {
updateMetadata();
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to update wither boss bar title", e);
}
}
return this;
}
@@ -73,8 +79,16 @@ public class WitherBossBar implements BossBar {
@Override
public BossBar setHealth(float health) {
this.health = health;
if (this.health <= 0) this.health = 0.0001f;
if (this.visible) updateMetadata();
if (this.health <= 0) {
this.health = 0.0001f;
}
if (this.visible) {
try {
updateMetadata();
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to update wither boss bar health", e);
}
}
return this;
}
@@ -147,7 +161,11 @@ public class WitherBossBar implements BossBar {
public BossBar show() {
if (!this.visible) {
this.visible = true;
spawnWither();
try {
spawnWither();
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to spawn wither boss bar", e);
}
}
return this;
}
@@ -156,7 +174,11 @@ public class WitherBossBar implements BossBar {
public BossBar hide() {
if (this.visible) {
this.visible = false;
despawnWither();
try {
despawnWither();
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to despawn wither boss bar", e);
}
}
return this;
}
@@ -171,26 +193,26 @@ public class WitherBossBar implements BossBar {
return this.uuid;
}
public void setLocation(double x, double y, double z) {
public void setLocation(double x, double y, double z) throws Exception {
locX = x;
locY = y;
locZ = z;
updateLocation();
}
private void spawnWither() {
PacketWrapper packetWrapper = PacketWrapper.create(0x0F, null, this.connection);
packetWrapper.write(Type.VAR_INT, entityId);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) 64);
packetWrapper.write(Type.INT, (int) (locX * 32d));
packetWrapper.write(Type.INT, (int) (locY * 32d));
packetWrapper.write(Type.INT, (int) (locZ * 32d));
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.SHORT, (short) 0);
packetWrapper.write(Type.SHORT, (short) 0);
packetWrapper.write(Type.SHORT, (short) 0);
private void spawnWither() throws Exception {
PacketWrapper wrapper = PacketWrapper.create(0x0F, null, this.connection);
wrapper.write(Type.VAR_INT, entityId);
wrapper.write(Type.UNSIGNED_BYTE, (short) 64);
wrapper.write(Type.INT, (int) (locX * 32d));
wrapper.write(Type.INT, (int) (locY * 32d));
wrapper.write(Type.INT, (int) (locZ * 32d));
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.SHORT, (short) 0);
wrapper.write(Type.SHORT, (short) 0);
wrapper.write(Type.SHORT, (short) 0);
List<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(0, MetaType1_8.Byte, (byte) 0x20));
@@ -198,45 +220,45 @@ public class WitherBossBar implements BossBar {
metadata.add(new Metadata(3, MetaType1_8.Byte, (byte) 1));
metadata.add(new Metadata(6, MetaType1_8.Float, health * 300f));
packetWrapper.write(Types1_8.METADATA_LIST, metadata);
wrapper.write(Types1_8.METADATA_LIST, metadata);
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
wrapper.scheduleSend(Protocol1_8To1_9.class);
}
private void updateLocation() {
PacketWrapper packetWrapper = PacketWrapper.create(0x18, null, this.connection);
packetWrapper.write(Type.VAR_INT, entityId);
packetWrapper.write(Type.INT, (int) (locX * 32d));
packetWrapper.write(Type.INT, (int) (locY * 32d));
packetWrapper.write(Type.INT, (int) (locZ * 32d));
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BOOLEAN, false);
private void updateLocation() throws Exception {
PacketWrapper wrapper = PacketWrapper.create(0x18, null, this.connection);
wrapper.write(Type.VAR_INT, entityId);
wrapper.write(Type.INT, (int) (locX * 32d));
wrapper.write(Type.INT, (int) (locY * 32d));
wrapper.write(Type.INT, (int) (locZ * 32d));
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.BYTE, (byte) 0);
wrapper.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
wrapper.scheduleSend(Protocol1_8To1_9.class);
}
private void updateMetadata() {
PacketWrapper packetWrapper = PacketWrapper.create(0x1C, null, this.connection);
packetWrapper.write(Type.VAR_INT, entityId);
private void updateMetadata() throws Exception {
PacketWrapper wrapper = PacketWrapper.create(0x1C, null, this.connection);
wrapper.write(Type.VAR_INT, entityId);
List<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(2, MetaType1_8.String, title));
metadata.add(new Metadata(6, MetaType1_8.Float, health * 300f));
packetWrapper.write(Types1_8.METADATA_LIST, metadata);
wrapper.write(Types1_8.METADATA_LIST, metadata);
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
wrapper.scheduleSend(Protocol1_8To1_9.class);
}
private void despawnWither() {
PacketWrapper packetWrapper = PacketWrapper.create(0x13, null, this.connection);
packetWrapper.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
private void despawnWither() throws Exception {
PacketWrapper wrapper = PacketWrapper.create(0x13, null, this.connection);
wrapper.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
wrapper.scheduleSend(Protocol1_8To1_9.class);
}
public void setPlayerLocation(double posX, double posY, double posZ, float yaw, float pitch) {
public void setPlayerLocation(double posX, double posY, double posZ, float yaw, float pitch) throws Exception {
double yawR = Math.toRadians(yaw);
double pitchR = Math.toRadians(pitch);
@@ -1,98 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public abstract class EntityModel1_8To1_9 extends EntityModel<Protocol1_8To1_9> {
public EntityModel1_8To1_9(UserConnection user, Protocol1_8To1_9 protocol) {
super(user, protocol);
}
protected void sendTeleportWithHead(int entityId, double locX, double locY, double locZ, float yaw, float pitch, float headYaw) {
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
sendHeadYaw(entityId, headYaw);
}
protected void teleportEntity(int entityId, double locX, double locY, double locZ, float yaw, float pitch) {
PacketWrapper teleport = PacketWrapper.create(ClientboundPackets1_8.ENTITY_TELEPORT, null, user);
teleport.write(Type.VAR_INT, entityId);
teleport.write(Type.INT, (int) (locX * 32.0));
teleport.write(Type.INT, (int) (locY * 32.0));
teleport.write(Type.INT, (int) (locZ * 32.0));
teleport.write(Type.BYTE, (byte) ((yaw / 360f) * 256));
teleport.write(Type.BYTE, (byte) ((pitch / 360f) * 256));
teleport.write(Type.BOOLEAN, true);
PacketUtil.sendPacket(teleport, Protocol1_8To1_9.class, true, true);
}
protected void sendHeadYaw(int entityId, float headYaw) {
PacketWrapper head = PacketWrapper.create(ClientboundPackets1_8.ENTITY_HEAD_LOOK, null, user);
head.write(Type.VAR_INT, entityId);
head.write(Type.BYTE, (byte) ((headYaw / 360f) * 256));
PacketUtil.sendPacket(head, Protocol1_8To1_9.class, true, true);
}
protected void sendSpawn(int entityId, int type) {
PacketWrapper spawn = PacketWrapper.create(ClientboundPackets1_8.SPAWN_MOB, null, user);
spawn.write(Type.VAR_INT, entityId);
spawn.write(Type.UNSIGNED_BYTE, (short) type);
spawn.write(Type.INT, 0);
spawn.write(Type.INT, 0);
spawn.write(Type.INT, 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.SHORT, (short) 0);
spawn.write(Type.SHORT, (short) 0);
spawn.write(Type.SHORT, (short) 0);
List<Metadata> list = new ArrayList<>();
spawn.write(Types1_8.METADATA_LIST, list);
PacketUtil.sendPacket(spawn, Protocol1_8To1_9.class, true, true);
}
protected void sendSpawnEntity(int entityId, int type) {
PacketWrapper spawn = PacketWrapper.create(ClientboundPackets1_8.SPAWN_ENTITY, null, user);
spawn.write(Type.VAR_INT, entityId);
spawn.write(Type.BYTE, (byte) type);
spawn.write(Type.INT, 0);
spawn.write(Type.INT, 0);
spawn.write(Type.INT, 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.INT, 0);
PacketUtil.sendPacket(spawn, Protocol1_8To1_9.class, true, true);
}
}
@@ -1,103 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public class ShulkerBulletModel extends EntityModel1_8To1_9 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
private float yaw, pitch;
private float headYaw;
public ShulkerBulletModel(UserConnection user, Protocol1_8To1_9 protocol, int entityId) {
super(user, protocol);
this.entityId = entityId;
sendSpawnPacket();
}
@Override
public void updateReplacementPosition(double x, double y, double z) {
if (x != this.locX || y != this.locY || z != this.locZ) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
}
@Override
public void handleOriginalMovementPacket(double x, double y, double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) return;
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
@Override
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw && this.pitch != pitch) {
this.yaw = yaw;
this.pitch = pitch;
updateLocation();
}
}
@Override
public void setHeadYaw(float yaw) {
this.headYaw = yaw;
}
@Override
public void updateMetadata(List<Metadata> metadataList) {
}
public void updateLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
@Override
public void sendSpawnPacket() {
sendSpawnEntity(entityId, 66);
}
@Override
public void deleteEntity() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_8.DESTROY_ENTITIES, null, user);
despawn.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_8To1_9.class, true, true);
}
@Override
public int getEntityId() {
return this.entityId;
}
}
@@ -1,121 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_9;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public class ShulkerModel extends EntityModel1_8To1_9 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
public ShulkerModel(UserConnection user, Protocol1_8To1_9 protocol, int entityId) {
super(user, protocol);
this.entityId = entityId;
sendSpawnPacket();
}
@Override
public void updateReplacementPosition(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
@Override
public void handleOriginalMovementPacket(double x, double y, double z) {
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
@Override
public void setYawPitch(float yaw, float pitch) {
}
@Override
public void setHeadYaw(float yaw) {
}
@Override
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateMetadata();
}
public void updateLocation() {
teleportEntity(entityId, locX, locY, locZ, 0, 0);
}
public void updateMetadata() {
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_METADATA, null, user);
metadataPacket.write(Type.VAR_INT, entityId);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
if (metadata.id() == 11 || metadata.id() == 12 || metadata.id() == 13) continue;
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
metadataList.add(new Metadata(11, MetaType1_9.VarInt, 2));
getProtocol().getMetadataRewriter().transform(user.get(EntityTracker.class), entityId, metadataList, EntityTypes1_10.EntityType.MAGMA_CUBE);
metadataPacket.write(Types1_8.METADATA_LIST, metadataList);
PacketUtil.sendPacket(metadataPacket, Protocol1_8To1_9.class);
}
@Override
public void sendSpawnPacket() {
sendSpawn(entityId, 62);
// Old clients don't like empty metadata
}
@Override
public void deleteEntity() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.DESTROY_ENTITIES, null, user);
despawn.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_8To1_9.class, true, true);
}
@Override
public int getEntityId() {
return this.entityId;
}
}
@@ -15,9 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetaIndex;
import com.viaversion.viaversion.util.Pair;
@@ -27,34 +27,32 @@ import java.util.Optional;
public class MetaIndex1_8to1_9 {
private final static HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
private static final HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
static {
for (MetaIndex index : MetaIndex.values())
for (MetaIndex index : MetaIndex.values()) {
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
}
private static Optional<MetaIndex> getIndex(EntityTypes1_10.EntityType type, int index) {
Pair<EntityTypes1_10.EntityType, Integer> pair = new Pair<>(type, index);
private static Optional<MetaIndex> getIndex(final EntityType type, final int index) {
final Pair<EntityType, Integer> pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
} else {
return Optional.empty();
}
return Optional.empty();
}
public static MetaIndex searchIndex(EntityTypes1_10.EntityType type, int index) {
EntityTypes1_10.EntityType currentType = type;
public static MetaIndex searchIndex(final EntityType type, final int index) {
EntityType currentType = type;
do {
Optional<MetaIndex> optMeta = getIndex(currentType, index);
final Optional<MetaIndex> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
}
currentType = currentType.getParent();
} while (currentType != null);
return null;
}
}
@@ -1,152 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker;
import com.viaversion.viaversion.api.minecraft.EulerAngle;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetaIndex;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MetadataRewriter {
private final Protocol1_8To1_9 protocol;
public MetadataRewriter(Protocol1_8To1_9 protocol) {
this.protocol = protocol;
}
public void transform(EntityTracker tracker, int entityId, List<Metadata> list) {
transform(tracker, entityId, list, tracker.getClientEntityTypes().get(entityId));
}
private static final byte HAND_ACTIVE_BIT = 0;
private static final byte STATUS_USE_BIT = 4;
public void transform(EntityTracker tracker, int entityId, List<Metadata> list, EntityType entityType) {
for (Metadata metadata : list) {
if (metadata.id() == MetaIndex.ENTITY_STATUS.getIndex()) {
tracker.getStatusInformation().put(entityId, (Byte) metadata.getValue());
}
}
for (Metadata entry : new ArrayList<>(list)) {
MetaIndex metaIndex = MetaIndex1_8to1_9.searchIndex(entityType, entry.id());
try {
if (metaIndex != null) {
if (metaIndex.getOldType() == MetaType1_8.NonExistent || metaIndex.getNewType() == null) {
list.remove(entry);
if (metaIndex == MetaIndex.PLAYER_HAND) {
byte status = tracker.getStatusInformation().getOrDefault(entityId, (byte) 0);
if ((((byte) entry.value()) & 1 << HAND_ACTIVE_BIT) != 0) {
status = (byte) (status | 1 << STATUS_USE_BIT);
} else {
status = (byte) (status & ~(1 << STATUS_USE_BIT));
}
list.add(new Metadata(MetaIndex.ENTITY_STATUS.getIndex(), MetaType1_8.Byte, status));
}
continue;
}
Object value = entry.getValue();
entry.setMetaTypeUnsafe(metaIndex.getOldType());
entry.setId(metaIndex.getIndex());
switch (metaIndex.getNewType()) {
case Byte:
if (metaIndex.getOldType() == MetaType1_8.Byte) {
entry.setValue(value);
}
if (metaIndex.getOldType() == MetaType1_8.Int) {
entry.setValue(((Byte) value).intValue());
}
break;
case OptUUID:
if (metaIndex.getOldType() != MetaType1_8.String) {
list.remove(entry);
break;
}
UUID owner = (UUID) value;
if (owner == null) entry.setValue("");
else entry.setValue(owner.toString());
break;
case BlockID:
list.remove(entry);
list.add(new Metadata(metaIndex.getIndex(), MetaType1_8.Short, ((Integer) value).shortValue()));
break;
case VarInt:
if (metaIndex.getOldType() == MetaType1_8.Byte) {
entry.setValue(((Integer) value).byteValue());
}
if (metaIndex.getOldType() == MetaType1_8.Short) {
entry.setValue(((Integer) value).shortValue());
}
if (metaIndex.getOldType() == MetaType1_8.Int) {
entry.setValue(value);
}
break;
case Float:
entry.setValue(value);
break;
case String:
entry.setValue(value);
break;
case Boolean:
if (metaIndex == MetaIndex.AGEABLE_AGE) entry.setValue((byte) ((Boolean) value ? -1 : 0));
else entry.setValue((byte) ((Boolean) value ? 1 : 0));
break;
case Slot:
entry.setValue(protocol.getItemRewriter().handleItemToClient((Item) value));
break;
case Position:
Vector vector = (Vector) value;
entry.setValue(vector);
break;
case Vector3F:
EulerAngle angle = (EulerAngle) value;
entry.setValue(angle);
break;
case Chat:
entry.setValue(value);
break;
default:
ViaRewind.getPlatform().getLogger().warning("[Out] Unhandled MetaDataType: " + metaIndex.getNewType());
list.remove(entry);
break;
}
if (!metaIndex.getOldType().type().getOutputClass().isAssignableFrom(entry.getValue().getClass())) {
list.remove(entry);
}
} else {
throw new Exception("Could not find valid metadata");
}
} catch (Exception e) {
list.remove(entry);
}
}
}
}
@@ -0,0 +1,338 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.VREntityRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker1_9;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.EulerAngle;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetaIndex;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent;
import com.viaversion.viaversion.util.IdAndData;
import java.util.UUID;
import java.util.logging.Level;
public class MetadataRewriter1_8To1_9 extends VREntityRewriter<ClientboundPackets1_9, Protocol1_8To1_9> {
private static final byte HAND_ACTIVE_BIT = 0;
private static final byte STATUS_USE_BIT = 4;
public MetadataRewriter1_8To1_9(Protocol1_8To1_9 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
registerJoinGame1_8(ClientboundPackets1_9.JOIN_GAME);
registerRemoveEntities(ClientboundPackets1_9.DESTROY_ENTITIES);
registerMetadataRewriter(ClientboundPackets1_9.ENTITY_METADATA, Types1_9.METADATA_LIST, Types1_8.METADATA_LIST);
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
read(Type.UUID); // Entity UUID
map(Type.BYTE); // Entity type
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.BYTE); // Pitch
map(Type.BYTE); // Yaw
map(Type.INT); // Data
// Track entity
handler(getObjectTrackerHandler());
handler(getObjectRewriter(id -> EntityTypes1_10.ObjectType.findById(id).orElse(null)));
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final int entityType = wrapper.get(Type.BYTE, 0);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(entityType, true);
// Cancel new entities which can't be handled properly
if (type == EntityTypes1_10.EntityType.AREA_EFFECT_CLOUD || type == EntityTypes1_10.EntityType.SPECTRAL_ARROW || type == EntityTypes1_10.EntityType.DRAGON_FIREBALL) {
wrapper.cancel();
return;
}
if (type.is(EntityTypes1_10.EntityType.BOAT)) {
byte yaw = wrapper.get(Type.BYTE, 1);
yaw -= 64;
wrapper.set(Type.BYTE, 1, yaw);
int y = wrapper.get(Type.INT, 1);
y += 10;
wrapper.set(Type.INT, 1, y);
}
int data = wrapper.get(Type.INT, 3);
if (type.isOrHasParent(EntityTypes1_10.EntityType.ARROW) && data != 0) {
wrapper.set(Type.INT, 3, --data);
}
if (type.is(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
IdAndData replace = protocol.getItemRewriter().handleBlock(blockId, blockData);
if (replace != null) {
wrapper.set(Type.INT, 3, replace.getId() | replace.getData() << 12);
}
}
if (data > 0) {
wrapper.passthrough(Type.SHORT); // Velocity x
wrapper.passthrough(Type.SHORT); // Velocity y
wrapper.passthrough(Type.SHORT); // Velocity z
} else {
final short velocityX = wrapper.read(Type.SHORT);
final short velocityY = wrapper.read(Type.SHORT);
final short velocityZ = wrapper.read(Type.SHORT);
final PacketWrapper velocityPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_VELOCITY, wrapper.user());
velocityPacket.write(Type.VAR_INT, entityId);
velocityPacket.write(Type.SHORT, velocityX);
velocityPacket.write(Type.SHORT, velocityY);
velocityPacket.write(Type.SHORT, velocityZ);
velocityPacket.scheduleSend(Protocol1_8To1_9.class);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_EXPERIENCE_ORB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.SHORT); // Count
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
wrapper.user().getEntityTracker(Protocol1_8To1_9.class).addEntity(entityId, EntityTypes1_10.EntityType.EXPERIENCE_ORB);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_GLOBAL_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.BYTE); // Type
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
wrapper.user().getEntityTracker(Protocol1_8To1_9.class).addEntity(entityId, EntityTypes1_10.EntityType.LIGHTNING);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
read(Type.UUID); // Entity UUID
map(Type.UNSIGNED_BYTE); // Entity type
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
map(Type.BYTE); // Head pitch
map(Type.SHORT); // Velocity x
map(Type.SHORT); // Velocity y
map(Type.SHORT); // Velocity z
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST); // Metadata
handler(getTrackerHandler(Type.UNSIGNED_BYTE, 0));
handler(getMobSpawnRewriter(Types1_8.METADATA_LIST));
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
read(Type.UUID); // Entity UUID
map(Type.STRING); // Title
map(Type.POSITION1_8); // Position
map(Type.BYTE, Type.UNSIGNED_BYTE); // Direction
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
wrapper.user().getEntityTracker(Protocol1_8To1_9.class).addEntity(entityId, EntityTypes1_10.EntityType.PAINTING);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.UUID); // Player UUID
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
create(Type.SHORT, (short) 0); // Current item
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST); // Metadata
handler(getTrackerAndMetaHandler(Types1_8.METADATA_LIST, EntityTypes1_10.EntityType.PLAYER));
}
});
}
@Override
protected void registerRewrites() {
// Handle new entities
mapEntityTypeWithData(EntityType.SHULKER, EntityType.MAGMA_CUBE).plainName();
mapEntityTypeWithData(EntityType.SHULKER_BULLET, EntityType.WITCH).plainName();
// Metadata rewrite
filter().handler((event, meta) -> {
try {
handleMetadata(event, meta);
} catch (Exception e) {
if (Via.getManager().isDebug()) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "An error occurred with entity metadata: " + meta, e);
}
event.cancel();
}
});
}
private void handleMetadata(MetaHandlerEvent event, Metadata metadata) {
final EntityTracker1_9 tracker = tracker(event.user());
if (metadata.id() == MetaIndex.ENTITY_STATUS.getIndex()) {
tracker.getStatus().put(event.entityId(), (Byte) metadata.value());
}
final MetaIndex metaIndex = MetaIndex1_8to1_9.searchIndex(event.entityType(), metadata.id());
if (metaIndex == null) {
// Almost certainly bad data, remove it
event.cancel();
return;
}
if (metaIndex.getOldType() == null || metaIndex.getNewType() == null) {
if (metaIndex == MetaIndex.PLAYER_HAND) { // Player eating/aiming/drinking
int status = tracker.getStatus().getOrDefault(event.entityId(), 0);
if ((((byte) metadata.value()) & 1 << HAND_ACTIVE_BIT) != 0) {
status = (byte) (status | 1 << STATUS_USE_BIT);
} else {
status = (byte) (status & ~(1 << STATUS_USE_BIT));
}
event.createExtraMeta(new Metadata(MetaIndex.ENTITY_STATUS.getIndex(), MetaType1_8.Byte, status));
return;
}
event.cancel();
return;
}
metadata.setId(metaIndex.getIndex());
metadata.setMetaTypeUnsafe(metaIndex.getOldType());
final Object value = metadata.getValue();
switch (metaIndex.getNewType()) {
case Byte:
if (metaIndex.getOldType() == MetaType1_8.Byte) {
metadata.setValue(value);
}
if (metaIndex.getOldType() == MetaType1_8.Int) {
metadata.setValue(((Byte) value).intValue());
}
break;
case OptUUID:
if (metaIndex.getOldType() != MetaType1_8.String) {
event.cancel();
break;
}
final UUID owner = (UUID) value;
metadata.setValue(owner != null ? owner.toString() : "");
break;
case BlockID:
event.cancel();
event.createExtraMeta(new Metadata(metaIndex.getIndex(), MetaType1_8.Short, ((Integer) value).shortValue()));
break;
case VarInt:
if (metaIndex.getOldType() == MetaType1_8.Byte) {
metadata.setValue(((Integer) value).byteValue());
}
if (metaIndex.getOldType() == MetaType1_8.Short) {
metadata.setValue(((Integer) value).shortValue());
}
if (metaIndex.getOldType() == MetaType1_8.Int) {
metadata.setValue(value);
}
break;
case Float:
case String:
case Chat:
metadata.setValue(value);
break;
case Boolean:
final boolean bool = (Boolean) value;
if (metaIndex == MetaIndex.AGEABLE_CREATURE_AGE) {
metadata.setValue((byte) (bool ? -1 : 0));
} else {
metadata.setValue((byte) (bool ? 1 : 0));
}
break;
case Slot:
metadata.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), (Item) value));
break;
case Position:
final Vector vector = (Vector) value;
metadata.setValue(vector);
break;
case Vector3F:
final EulerAngle angle = (EulerAngle) value;
metadata.setValue(angle);
break;
default:
event.cancel();
break;
}
}
@Override
public EntityType typeFromId(int type) {
return EntityTypes1_10.getTypeFromId(type, false);
}
@Override
public EntityType objectTypeFromId(int type) {
return EntityTypes1_10.getTypeFromId(type, true);
}
}
@@ -0,0 +1,316 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
import com.viaversion.viarewind.api.rewriter.VRBlockItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.data.PotionMappings;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.WindowTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
import com.viaversion.viaversion.util.Key;
import java.util.HashSet;
import java.util.Set;
import static com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter.potionNameFromDamage;
public class BlockItemPackets1_9 extends VRBlockItemRewriter<ClientboundPackets1_9, ServerboundPackets1_8, Protocol1_8To1_9> {
public final Set<String> VALID_ATTRIBUTES = new HashSet<>();
private LegacyEnchantmentRewriter enchantmentRewriter;
public BlockItemPackets1_9(Protocol1_8To1_9 protocol) {
super(protocol, "1.9");
VALID_ATTRIBUTES.add("generic.maxHealth");
VALID_ATTRIBUTES.add("generic.followRange");
VALID_ATTRIBUTES.add("generic.knockbackResistance");
VALID_ATTRIBUTES.add("generic.movementSpeed");
VALID_ATTRIBUTES.add("generic.attackDamage");
VALID_ATTRIBUTES.add("horse.jumpStrength");
VALID_ATTRIBUTES.add("zombie.spawnReinforcements");
}
@Override
protected void registerPackets() {
registerBlockChange(ClientboundPackets1_9.BLOCK_CHANGE);
registerMultiBlockChange(ClientboundPackets1_9.MULTI_BLOCK_CHANGE);
registerCreativeInvAction(ServerboundPackets1_8.CREATIVE_INVENTORY_ACTION);
protocol.registerClientbound(ClientboundPackets1_9.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
wrapper.user().get(WindowTracker.class).remove(windowId);
});
protocol.registerClientbound(ClientboundPackets1_9.OPEN_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
final String windowType = wrapper.passthrough(Type.STRING);
final JsonElement windowTitle = wrapper.passthrough(Type.COMPONENT);
wrapper.user().get(WindowTracker.class).put(windowId, windowType);
// TODO check
if (windowType.equalsIgnoreCase("minecraft:shulker_box")) {
wrapper.set(Type.STRING, 0, "minecraft:container");
}
if (windowTitle.toString().equalsIgnoreCase("{\"translate\":\"container.shulkerBox\"}")) {
wrapper.set(Type.COMPONENT, 0, JsonParser.parseString("{\"text\":\"Shulker Box\"}"));
}
});
protocol.registerClientbound(ClientboundPackets1_9.WINDOW_ITEMS, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
Item[] items = wrapper.passthrough(Type.ITEM1_8_SHORT_ARRAY);
for (int i = 0; i < items.length; i++) {
items[i] = handleItemToClient(wrapper.user(), items[i]);
}
if (windowId == 0 && items.length == 46) {
Item[] old = items;
items = new Item[45];
System.arraycopy(old, 0, items, 0, 45);
} else {
final String type = wrapper.user().get(WindowTracker.class).get(windowId);
if (type != null && type.equalsIgnoreCase("minecraft:brewing_stand")) {
System.arraycopy(items, 0, wrapper.user().get(WindowTracker.class).getBrewingItems(windowId), 0, 4);
WindowTracker.updateBrewingStand(wrapper.user(), items[4], windowId);
Item[] old = items;
items = new Item[old.length - 1];
System.arraycopy(old, 0, items, 0, 4);
System.arraycopy(old, 5, items, 4, old.length - 5);
}
}
});
protocol.registerClientbound(ClientboundPackets1_9.SET_SLOT, wrapper -> {
final byte windowId = wrapper.passthrough(Type.UNSIGNED_BYTE).byteValue();
final short slot = wrapper.passthrough(Type.SHORT);
final Item item = wrapper.passthrough(Type.ITEM1_8);
handleItemToClient(wrapper.user(), item);
if (windowId == 0 && slot == 45) {
wrapper.cancel();
return;
}
final WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
final String windowType = windowTracker.get(windowId);
if (windowType != null && windowType.equalsIgnoreCase("minecraft:brewing_stand")) {
if (slot > 4) {
wrapper.set(Type.SHORT, 0, (short) (slot - 1));
} else if (slot == 4) {
wrapper.cancel();
WindowTracker.updateBrewingStand(wrapper.user(), wrapper.get(Type.ITEM1_8, 0), windowId);
} else {
windowTracker.getBrewingItems(windowId)[slot] = wrapper.get(Type.ITEM1_8, 0);
}
}
});
protocol.registerServerbound(ServerboundPackets1_8.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
wrapper.user().get(WindowTracker.class).remove(windowId);
});
protocol.registerServerbound(ServerboundPackets1_8.CLICK_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE); // Window id
map(Type.SHORT); // Slot
map(Type.BYTE); // Button
map(Type.SHORT); // Action number
map(Type.BYTE, Type.VAR_INT); // Mode
map(Type.ITEM1_8); // Clicked item
handler(wrapper -> handleItemToServer(wrapper.user(), wrapper.get(Type.ITEM1_8, 0)));
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
final String windowType = wrapper.user().get(WindowTracker.class).get(windowId);
if (windowType != null && windowType.equalsIgnoreCase("minecraft:brewing_stand")) {
final short slot = wrapper.get(Type.SHORT, 0);
if (slot > 3) {
wrapper.set(Type.SHORT, 0, (short) (slot + 1));
}
}
});
}
});
}
@Override
protected void registerRewrites() {
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName());
enchantmentRewriter.registerEnchantment(9, "§7Frost Walker");
enchantmentRewriter.registerEnchantment(70, "§7Mending");
}
@Override
public Item handleItemToClient(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToClient(connection, item);
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
enchantmentRewriter.handleToClient(item);
CompoundTag displayTag = tag.get("display");
if (item.data() != 0 && tag.contains("Unbreakable")) {
final ByteTag unbreakableTag = tag.get("Unbreakable");
if (unbreakableTag != null && unbreakableTag.asByte() != 0) {
tag.put(nbtTagName() + "|Unbreakable", new ByteTag(unbreakableTag.asByte()));
tag.remove("Unbreakable");
if (displayTag == null) { // Remove the display tag again if it was only added to emulate unbreakable
tag.put("display", displayTag = new CompoundTag());
tag.put(nbtTagName() + "|noDisplay", new ByteTag());
}
ListTag<StringTag> loreTag = displayTag.getListTag("Lore", StringTag.class);
if (loreTag == null) {
displayTag.put("Lore", loreTag = new ListTag<>(StringTag.class));
}
loreTag.add(new StringTag("§9Unbreakable"));
}
}
if (item.identifier() == 383 && item.data() == 0) { // Spawn eggs
int data = 0;
final CompoundTag entityTag = tag.getCompoundTag("EntityTag");
if (entityTag != null) {
final StringTag idTag = entityTag.getStringTag("id");
if (idTag != null) {
final String id = idTag.getValue();
if (ItemRewriter.ENTITY_NAME_TO_ID.containsKey(id)) {
data = ItemRewriter.ENTITY_NAME_TO_ID.get(id);
} else if (displayTag == null) {
tag.put("display", displayTag = new CompoundTag());
tag.put(nbtTagName() + "|noDisplay", new ByteTag());
displayTag.put("Name", new StringTag("§rSpawn " + id));
}
}
}
item.setData((short) data);
}
// Potion, splash potion, lingering potion
final boolean potion = item.identifier() == 373;
final boolean splashPotion = item.identifier() == 438;
final boolean lingeringPotion = item.identifier() == 441;
if (potion || splashPotion || lingeringPotion) {
int data = 0;
final StringTag potionTag = tag.getStringTag("Potion");
if (potionTag != null) {
String potionName = Key.stripMinecraftNamespace(potionTag.getValue());
if (PotionMappings.POTION_NAME_TO_ID.containsKey(potionName)) {
data = PotionMappings.POTION_NAME_TO_ID.get(potionName);
}
if (splashPotion) {
potionName += "_splash";
} else if (lingeringPotion) {
potionName += "_lingering";
}
// Don't override custom name
if ((displayTag == null || !displayTag.contains("Name")) && PotionMappings.POTION_NAME_INDEX.containsKey(potionName)) {
tag.put("display", displayTag = new CompoundTag());
tag.put(nbtTagName() + "|noDisplay", new ByteTag());
displayTag.put("Name", new StringTag(PotionMappings.POTION_NAME_INDEX.get(potionName)));
}
}
if (splashPotion || lingeringPotion) { // Convert splash and lingering potions to normal potions
item.setIdentifier(373);
data += 8192;
}
item.setData((short) data);
}
final ListTag<CompoundTag> attributeModifiers = tag.getListTag("AttributeModifiers", CompoundTag.class);
if (attributeModifiers != null) {
tag.put(nbtTagName() + "|AttributeModifiers", attributeModifiers.copy());
attributeModifiers.getValue().removeIf(entries -> {
final StringTag nameTag = entries.getStringTag("AttributeName");
return nameTag != null && !VALID_ATTRIBUTES.contains(nameTag.getValue());
});
}
return item;
}
@Override
public Item handleItemToServer(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
enchantmentRewriter.handleToServer(item);
if (item.identifier() == 383 && item.data() != 0) { // Spawn eggs
if (!tag.contains("EntityTag") && ItemRewriter.ENTITY_ID_TO_NAME.containsKey((int) item.data())) {
final CompoundTag entityTag = new CompoundTag();
entityTag.put("id", new StringTag(ItemRewriter.ENTITY_ID_TO_NAME.get((int) item.data())));
tag.put("EntityTag", entityTag);
}
item.setData((short) 0);
}
if (item.identifier() == 373 && !tag.contains("Potion")) { // Potions
if (item.data() >= 16384) {
item.setIdentifier(438);
item.setData((short) (item.data() - 8192));
}
final String name = item.data() == 8192 ? "water" : potionNameFromDamage(item.data());
tag.put("Potion", new StringTag("minecraft:" + name));
item.setData((short) 0);
}
final Tag noDisplayTag = tag.remove(nbtTagName() + "|noDisplay");
if (noDisplayTag != null) {
tag.remove("display");
}
final Tag unbreakableTag = tag.remove(nbtTagName() + "|Unbreakable");
if (unbreakableTag != null) {
tag.put("Unbreakable", unbreakableTag);
}
final Tag attributeModifiersTag = tag.remove(nbtTagName() + "|AttributeModifiers");
if (attributeModifiersTag != null) {
tag.put("AttributeModifiers", attributeModifiersTag);
}
return item;
}
}
@@ -1,482 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.Cooldown;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.Levitation;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.PlayerPosition;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.util.RelativeMoveUtil;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class EntityPackets {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_STATUS, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
handler(packetWrapper -> {
byte status = packetWrapper.read(Type.BYTE);
if (status > 23) {
packetWrapper.cancel();
return;
}
packetWrapper.write(Type.BYTE, status);
});
}
});
//Entity Relative Move
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int relX = packetWrapper.read(Type.SHORT);
int relY = packetWrapper.read(Type.SHORT);
int relZ = packetWrapper.read(Type.SHORT);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
replacement.handleOriginalMovementPacket(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
return;
}
Vector[] moves = RelativeMoveUtil.calculateRelativeMoves(packetWrapper.user(), entityId, relX, relY, relZ);
packetWrapper.write(Type.BYTE, (byte) moves[0].blockX());
packetWrapper.write(Type.BYTE, (byte) moves[0].blockY());
packetWrapper.write(Type.BYTE, (byte) moves[0].blockZ());
boolean onGround = packetWrapper.passthrough(Type.BOOLEAN);
if (moves.length > 1) {
PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION, null, packetWrapper.user());
secondPacket.write(Type.VAR_INT, packetWrapper.get(Type.VAR_INT, 0));
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
secondPacket.write(Type.BYTE, (byte) moves[1].blockZ());
secondPacket.write(Type.BOOLEAN, onGround);
PacketUtil.sendPacket(secondPacket, Protocol1_8To1_9.class);
}
});
}
});
//Entity Relative Move And Look
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int relX = packetWrapper.read(Type.SHORT);
int relY = packetWrapper.read(Type.SHORT);
int relZ = packetWrapper.read(Type.SHORT);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
replacement.handleOriginalMovementPacket(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
replacement.setYawPitch(packetWrapper.read(Type.BYTE) * 360f / 256, packetWrapper.read(Type.BYTE) * 360f / 256);
return;
}
Vector[] moves = RelativeMoveUtil.calculateRelativeMoves(packetWrapper.user(), entityId, relX, relY, relZ);
packetWrapper.write(Type.BYTE, (byte) moves[0].blockX());
packetWrapper.write(Type.BYTE, (byte) moves[0].blockY());
packetWrapper.write(Type.BYTE, (byte) moves[0].blockZ());
byte yaw = packetWrapper.passthrough(Type.BYTE);
byte pitch = packetWrapper.passthrough(Type.BYTE);
boolean onGround = packetWrapper.passthrough(Type.BOOLEAN);
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
yaw -= 64;
packetWrapper.set(Type.BYTE, 3, yaw);
}
if (moves.length > 1) {
PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION_AND_ROTATION, null, packetWrapper.user());
secondPacket.write(Type.VAR_INT, packetWrapper.get(Type.VAR_INT, 0));
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
secondPacket.write(Type.BYTE, (byte) moves[1].blockZ());
secondPacket.write(Type.BYTE, yaw);
secondPacket.write(Type.BYTE, pitch);
secondPacket.write(Type.BOOLEAN, onGround);
PacketUtil.sendPacket(secondPacket, Protocol1_8To1_9.class);
}
});
}
});
//Entity Look
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BOOLEAN);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
int pitch = packetWrapper.get(Type.BYTE, 1);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = packetWrapper.get(Type.BYTE, 0);
yaw -= 64;
packetWrapper.set(Type.BYTE, 0, yaw);
}
});
}
});
//Entity
//Vehicle Move -> Entity Teleport
protocol.registerClientbound(ClientboundPackets1_9.VEHICLE_MOVE, ClientboundPackets1_8.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int vehicle = tracker.getVehicle(tracker.getPlayerId());
if (vehicle == -1) packetWrapper.cancel();
packetWrapper.write(Type.VAR_INT, vehicle);
});
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.FLOAT, Protocol1_8To1_9.DEGREES_TO_ANGLE);
map(Type.FLOAT, Protocol1_8To1_9.DEGREES_TO_ANGLE);
handler(packetWrapper -> {
if (packetWrapper.isCancelled()) return;
PlayerPosition position = packetWrapper.user().get(PlayerPosition.class);
double x = packetWrapper.get(Type.INT, 0) / 32d;
double y = packetWrapper.get(Type.INT, 1) / 32d;
double z = packetWrapper.get(Type.INT, 2) / 32d;
position.setPos(x, y, z);
});
create(Type.BOOLEAN, true);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = packetWrapper.get(Type.BYTE, 1);
yaw -= 64;
packetWrapper.set(Type.BYTE, 0, yaw);
int y = packetWrapper.get(Type.INT, 1);
y += 10;
packetWrapper.set(Type.INT, 1, y);
}
});
}
});
//Use Bed
//Destroy Entities
protocol.registerClientbound(ClientboundPackets1_9.DESTROY_ENTITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT_ARRAY_PRIMITIVE);
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
for (int entityId : packetWrapper.get(Type.VAR_INT_ARRAY_PRIMITIVE, 0))
tracker.removeEntity(entityId);
});
}
});
//Remove Entity Effect
protocol.registerClientbound(ClientboundPackets1_9.REMOVE_ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
handler(packetWrapper -> {
int id = packetWrapper.get(Type.BYTE, 0);
if (id > 23) packetWrapper.cancel();
if (id == 25) {
if (packetWrapper.get(Type.VAR_INT, 0) != packetWrapper.user().get(EntityTracker.class).getPlayerId())
return;
Levitation levitation = packetWrapper.user().get(Levitation.class);
levitation.setActive(false);
}
});
}
});
//Entity Head Look
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_HEAD_LOOK, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
replacement.setHeadYaw(yaw * 360f / 256);
}
});
}
});
//Entity Metadata
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_METADATA, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST);
handler(wrapper -> {
List<Metadata> metadataList = wrapper.get(Types1_8.METADATA_LIST, 0);
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (tracker.getClientEntityTypes().containsKey(entityId)) {
protocol.getMetadataRewriter().transform(tracker, entityId, metadataList);
if (metadataList.isEmpty()) wrapper.cancel();
} else {
tracker.addMetadataToBuffer(entityId, metadataList);
wrapper.cancel();
}
});
}
});
//Attach Entity
protocol.registerClientbound(ClientboundPackets1_9.ATTACH_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.INT);
create(Type.BOOLEAN, true);
}
});
//Entity Velocity
//Entity Equipment
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_EQUIPMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
handler(packetWrapper -> {
// todo check if this is correct for the own player
int slot = packetWrapper.read(Type.VAR_INT);
if (slot == 1) {
packetWrapper.cancel();
} else if (slot > 1) {
slot -= 1;
}
packetWrapper.write(Type.SHORT, (short) slot);
});
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToClient(packetWrapper.get(Type.ITEM1_8, 0))));
}
});
//Set Passengers
protocol.registerClientbound(ClientboundPackets1_9.SET_PASSENGERS, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
EntityTracker entityTracker = packetWrapper.user().get(EntityTracker.class);
int vehicle = packetWrapper.read(Type.VAR_INT);
int count = packetWrapper.read(Type.VAR_INT);
ArrayList<Integer> passengers = new ArrayList<>();
for (int i = 0; i < count; i++) passengers.add(packetWrapper.read(Type.VAR_INT));
List<Integer> oldPassengers = entityTracker.getPassengers(vehicle);
entityTracker.setPassengers(vehicle, passengers);
if (!oldPassengers.isEmpty()) {
for (Integer passenger : oldPassengers) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, null, packetWrapper.user());
detach.write(Type.INT, passenger);
detach.write(Type.INT, -1);
detach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(detach, Protocol1_8To1_9.class);
}
}
for (int i = 0; i < count; i++) {
int v = i == 0 ? vehicle : passengers.get(i - 1);
int p = passengers.get(i);
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, null, packetWrapper.user());
attach.write(Type.INT, p);
attach.write(Type.INT, v);
attach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(attach, Protocol1_8To1_9.class);
}
});
}
});
//Collect Item
//Entity Teleport
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BOOLEAN);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = packetWrapper.get(Type.BYTE, 1);
yaw -= 64;
packetWrapper.set(Type.BYTE, 0, yaw);
int y = packetWrapper.get(Type.INT, 1);
y += 10;
packetWrapper.set(Type.INT, 1, y);
}
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
packetWrapper.user().get(EntityTracker.class).resetEntityOffset(entityId);
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.INT, 0);
int y = packetWrapper.get(Type.INT, 1);
int z = packetWrapper.get(Type.INT, 2);
int yaw = packetWrapper.get(Type.BYTE, 0);
int pitch = packetWrapper.get(Type.BYTE, 1);
replacement.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
});
//Entity Properties
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_PROPERTIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.INT);
handler(packetWrapper -> {
boolean player = packetWrapper.get(Type.VAR_INT, 0) == packetWrapper.user().get(EntityTracker.class).getPlayerId();
int size = packetWrapper.get(Type.INT, 0);
int removed = 0;
for (int i = 0; i < size; i++) {
String key = packetWrapper.read(Type.STRING);
boolean skip = !Protocol1_8To1_9.VALID_ATTRIBUTES.contains(key);
double value = packetWrapper.read(Type.DOUBLE);
int modifierSize = packetWrapper.read(Type.VAR_INT);
if (!skip) {
packetWrapper.write(Type.STRING, key);
packetWrapper.write(Type.DOUBLE, value);
packetWrapper.write(Type.VAR_INT, modifierSize);
} else {
removed++;
}
ArrayList<Pair<Byte, Double>> modifiers = new ArrayList<>();
for (int j = 0; j < modifierSize; j++) {
UUID uuid = packetWrapper.read(Type.UUID);
double amount = packetWrapper.read(Type.DOUBLE);
byte operation = packetWrapper.read(Type.BYTE);
modifiers.add(new Pair<>(operation, amount));
if (skip) continue;
packetWrapper.write(Type.UUID, uuid);
packetWrapper.write(Type.DOUBLE, amount);
packetWrapper.write(Type.BYTE, operation);
}
if (player && key.equals("generic.attackSpeed")) {
packetWrapper.user().get(Cooldown.class).setAttackSpeed(value, modifiers);
}
}
packetWrapper.set(Type.INT, 0, size - removed);
});
}
});
//Entity Effect
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.VAR_INT);
map(Type.BYTE);
handler(packetWrapper -> {
int id = packetWrapper.get(Type.BYTE, 0);
if (id > 23) packetWrapper.cancel();
if (id == 25) {
if (packetWrapper.get(Type.VAR_INT, 0) != packetWrapper.user().get(EntityTracker.class).getPlayerId())
return;
Levitation levitation = packetWrapper.user().get(Levitation.class);
levitation.setActive(true);
levitation.setAmplifier(packetWrapper.get(Type.BYTE, 1));
}
});
}
});
}
}
@@ -0,0 +1,333 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.CooldownStorage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.LevitationStorage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.PlayerPositionTracker;
import com.viaversion.viarewind.utils.math.RelativeMoveUtil;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.fastutil.ints.IntArrayList;
import com.viaversion.viaversion.libs.fastutil.ints.IntList;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class EntityPackets1_9 {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_STATUS, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // Entity id
handler(wrapper -> {
final byte status = wrapper.read(Type.BYTE);
if (status > 23) { // Remove op permission level 0-4 (24-28)
wrapper.cancel();
return;
}
wrapper.write(Type.BYTE, status);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_POSITION, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final int deltaX = wrapper.read(Type.SHORT);
final int deltaY = wrapper.read(Type.SHORT);
final int deltaZ = wrapper.read(Type.SHORT);
final Vector[] moves = RelativeMoveUtil.calculateRelativeMoves(wrapper.user(), entityId, deltaX, deltaY, deltaZ);
wrapper.write(Type.BYTE, (byte) moves[0].blockX());
wrapper.write(Type.BYTE, (byte) moves[0].blockY());
wrapper.write(Type.BYTE, (byte) moves[0].blockZ());
final boolean onGround = wrapper.passthrough(Type.BOOLEAN);
if (moves.length > 1) {
final PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION, wrapper.user());
secondPacket.write(Type.VAR_INT, entityId);
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
secondPacket.write(Type.BYTE, (byte) moves[1].blockZ());
secondPacket.write(Type.BOOLEAN, onGround);
secondPacket.scheduleSend(Protocol1_8To1_9.class);
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_POSITION_AND_ROTATION, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final int deltaX = wrapper.read(Type.SHORT);
final int deltaY = wrapper.read(Type.SHORT);
final int deltaZ = wrapper.read(Type.SHORT);
final Vector[] moves = RelativeMoveUtil.calculateRelativeMoves(wrapper.user(), entityId, deltaX, deltaY, deltaZ);
wrapper.write(Type.BYTE, (byte) moves[0].blockX());
wrapper.write(Type.BYTE, (byte) moves[0].blockY());
wrapper.write(Type.BYTE, (byte) moves[0].blockZ());
byte yaw = wrapper.passthrough(Type.BYTE);
final byte pitch = wrapper.passthrough(Type.BYTE);
final boolean onGround = wrapper.passthrough(Type.BOOLEAN);
EntityType type = wrapper.user().getEntityTracker(Protocol1_8To1_9.class).entityType(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
yaw -= 64;
wrapper.set(Type.BYTE, 3, yaw);
}
if (moves.length > 1) {
final PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION_AND_ROTATION, wrapper.user());
secondPacket.write(Type.VAR_INT, entityId);
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
secondPacket.write(Type.BYTE, (byte) moves[1].blockZ());
secondPacket.write(Type.BYTE, yaw);
secondPacket.write(Type.BYTE, pitch);
secondPacket.write(Type.BOOLEAN, onGround);
secondPacket.scheduleSend(Protocol1_8To1_9.class);
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_ROTATION, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final EntityType type = wrapper.user().getEntityTracker(Protocol1_8To1_9.class).entityType(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = wrapper.read(Type.BYTE);
yaw -= 64;
wrapper.write(Type.BYTE, yaw);
}
});
protocol.registerClientbound(ClientboundPackets1_9.VEHICLE_MOVE, ClientboundPackets1_8.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
final int vehicle = tracker.getVehicle(tracker.clientEntityId());
if (vehicle == -1) {
wrapper.cancel();
}
wrapper.write(Type.VAR_INT, vehicle);
});
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.FLOAT, Protocol1_8To1_9.DEGREES_TO_ANGLE); // Yaw
map(Type.FLOAT, Protocol1_8To1_9.DEGREES_TO_ANGLE); // Pitch
handler(wrapper -> {
if (wrapper.isCancelled()) return;
final PlayerPositionTracker position = wrapper.user().get(PlayerPositionTracker.class);
double x = wrapper.get(Type.INT, 0) / 32d;
double y = wrapper.get(Type.INT, 1) / 32d;
double z = wrapper.get(Type.INT, 2) / 32d;
position.setPos(x, y, z);
});
create(Type.BOOLEAN, true);
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityType type = wrapper.user().getEntityTracker(Protocol1_8To1_9.class).entityType(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = wrapper.get(Type.BYTE, 1);
yaw -= 64;
wrapper.set(Type.BYTE, 0, yaw);
int y = wrapper.get(Type.INT, 1);
y += 10;
wrapper.set(Type.INT, 1, y);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.REMOVE_ENTITY_EFFECT, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final int effectId = wrapper.passthrough(Type.BYTE);
if (effectId > 23) { // Throw away new effects
wrapper.cancel();
}
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
if (effectId == 25 && entityId == tracker.clientEntityId()) {
wrapper.user().get(LevitationStorage.class).setActive(false);
}
});
protocol.registerClientbound(ClientboundPackets1_9.ATTACH_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // Attached entity id
map(Type.INT); // Holding entity id
create(Type.BOOLEAN, true); // Leash
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_EQUIPMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
handler(wrapper -> {
// todo check if this is correct for the own player
int slot = wrapper.read(Type.VAR_INT);
if (slot == 1) {
wrapper.cancel();
} else if (slot > 1) {
slot -= 1;
}
wrapper.write(Type.SHORT, (short) slot);
});
map(Type.ITEM1_8); // Item
handler(wrapper -> protocol.getItemRewriter().handleItemToClient(wrapper.user(), wrapper.get(Type.ITEM1_8, 0)));
}
});
protocol.registerClientbound(ClientboundPackets1_9.SET_PASSENGERS, null, wrapper -> {
wrapper.cancel();
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
final int vehicle = wrapper.read(Type.VAR_INT);
final IntList oldPassengers = tracker.getPassengers(vehicle);
final int count = wrapper.read(Type.VAR_INT);
final IntList passengers = new IntArrayList();
for (int i = 0; i < count; i++) {
passengers.add(wrapper.read(Type.VAR_INT));
}
tracker.setPassengers(vehicle, passengers);
if (!oldPassengers.isEmpty()) {
for (Integer passenger : oldPassengers) {
final PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, wrapper.user());
detach.write(Type.INT, passenger); // Attached entity id
detach.write(Type.INT, -1); // Holding entity id
detach.write(Type.BOOLEAN, false); // Leash
detach.scheduleSend(Protocol1_8To1_9.class);
}
}
for (int i = 0; i < count; i++) {
final int attachedEntityId = passengers.getInt(i);
final int holdingEntityId = i == 0 ? vehicle : passengers.getInt(i - 1);
final PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, wrapper.user());
attach.write(Type.INT, attachedEntityId);
attach.write(Type.INT, holdingEntityId);
attach.write(Type.BOOLEAN, false); // Leash
attach.scheduleSend(Protocol1_8To1_9.class);
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Entity id
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // X
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Y
map(Type.DOUBLE, Protocol1_8To1_9.DOUBLE_TO_INT_TIMES_32); // Z
map(Type.BYTE); // Yaw
map(Type.BYTE); // Pitch
map(Type.BOOLEAN); // On ground
handler(wrapper -> {
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
if (tracker.entityType(entityId) == EntityTypes1_10.EntityType.BOAT) {
byte yaw = wrapper.get(Type.BYTE, 1);
yaw -= 64;
wrapper.set(Type.BYTE, 0, yaw);
int y = wrapper.get(Type.INT, 1);
y += 10;
wrapper.set(Type.INT, 1, y);
}
tracker.resetEntityOffset(entityId);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_PROPERTIES, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
final boolean player = entityId == tracker.clientEntityId();
// Throw away new attributes and track attack speed
int removed = 0;
final int size = wrapper.passthrough(Type.INT);
for (int i = 0; i < size; i++) {
final String key = wrapper.read(Type.STRING);
final double value = wrapper.read(Type.DOUBLE);
final int modifierSize = wrapper.read(Type.VAR_INT);
final boolean valid = protocol.getItemRewriter().VALID_ATTRIBUTES.contains(key);
if (valid) {
wrapper.write(Type.STRING, key);
wrapper.write(Type.DOUBLE, value);
wrapper.write(Type.VAR_INT, modifierSize);
}
final List<Pair<Byte, Double>> modifiers = new ArrayList<>();
for (int j = 0; j < modifierSize; j++) {
final UUID modifierId = wrapper.read(Type.UUID); // UUID
final double amount = wrapper.read(Type.DOUBLE); // Amount
final byte operation = wrapper.read(Type.BYTE); // Operation
if (valid) {
wrapper.write(Type.UUID, modifierId);
wrapper.write(Type.DOUBLE, amount);
wrapper.write(Type.BYTE, operation);
}
modifiers.add(new Pair<>(operation, amount));
}
if (!valid) {
if (player && key.equals("generic.attackSpeed")) {
wrapper.user().get(CooldownStorage.class).setAttackSpeed(value, modifiers);
}
removed++;
}
}
wrapper.set(Type.INT, 0, size - removed);
});
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_EFFECT, wrapper -> {
final int entityId = wrapper.passthrough(Type.VAR_INT);
final int effectId = wrapper.passthrough(Type.BYTE);
final byte amplifier = wrapper.passthrough(Type.BYTE);
if (effectId > 23) { // Throw away new effects
wrapper.cancel();
}
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
if (effectId == 25 && entityId == tracker.clientEntityId()) {
final LevitationStorage levitation = wrapper.user().get(LevitationStorage.class);
levitation.setActive(true);
levitation.setAmplifier(amplifier);
}
});
}
}
@@ -1,187 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.Windows;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
public class InventoryPackets {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.CLOSE_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowsId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
packetWrapper.user().get(Windows.class).remove(windowsId);
});
}
});
//Open Window
protocol.registerClientbound(ClientboundPackets1_9.OPEN_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.STRING);
map(Type.COMPONENT);
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
String type = packetWrapper.get(Type.STRING, 0);
if (type.equals("EntityHorse")) packetWrapper.passthrough(Type.INT);
});
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
String windowType = packetWrapper.get(Type.STRING, 0);
packetWrapper.user().get(Windows.class).put(windowId, windowType);
});
handler(packetWrapper -> {
String type = packetWrapper.get(Type.STRING, 0);
if (type.equalsIgnoreCase("minecraft:shulker_box")) {
packetWrapper.set(Type.STRING, 0, type = "minecraft:container");
}
String name = packetWrapper.get(Type.COMPONENT, 0).toString();
if (name.equalsIgnoreCase("{\"translate\":\"container.shulkerBox\"}")) {
packetWrapper.set(Type.COMPONENT, 0, JsonParser.parseString("{\"text\":\"Shulker Box\"}"));
}
});
}
});
//Window Items
protocol.registerClientbound(ClientboundPackets1_9.WINDOW_ITEMS, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
Item[] items = packetWrapper.read(Type.ITEM1_8_SHORT_ARRAY);
for (int i = 0; i < items.length; i++) {
items[i] = protocol.getItemRewriter().handleItemToClient(items[i]);
}
if (windowId == 0 && items.length == 46) {
Item[] old = items;
items = new Item[45];
System.arraycopy(old, 0, items, 0, 45);
} else {
String type = packetWrapper.user().get(Windows.class).get(windowId);
if (type != null && type.equalsIgnoreCase("minecraft:brewing_stand")) {
System.arraycopy(items, 0, packetWrapper.user().get(Windows.class).getBrewingItems(windowId), 0, 4);
Windows.updateBrewingStand(packetWrapper.user(), items[4], windowId);
Item[] old = items;
items = new Item[old.length - 1];
System.arraycopy(old, 0, items, 0, 4);
System.arraycopy(old, 5, items, 4, old.length - 5);
}
}
packetWrapper.write(Type.ITEM1_8_SHORT_ARRAY, items);
});
}
});
//Window Property
//Set Slot
protocol.registerClientbound(ClientboundPackets1_9.SET_SLOT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.SHORT);
map(Type.ITEM1_8);
handler(packetWrapper -> {
packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToClient(packetWrapper.get(Type.ITEM1_8, 0)));
byte windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0).byteValue();
short slot = packetWrapper.get(Type.SHORT, 0);
if (windowId == 0 && slot == 45) {
packetWrapper.cancel();
return;
}
String type = packetWrapper.user().get(Windows.class).get(windowId);
if (type == null) return;
if (type.equalsIgnoreCase("minecraft:brewing_stand")) {
if (slot > 4) {
packetWrapper.set(Type.SHORT, 0, slot -= 1);
} else if (slot == 4) {
packetWrapper.cancel();
Windows.updateBrewingStand(packetWrapper.user(), packetWrapper.get(Type.ITEM1_8, 0), windowId);
} else {
packetWrapper.user().get(Windows.class).getBrewingItems(windowId)[slot] = packetWrapper.get(Type.ITEM1_8, 0);
}
}
});
}
});
/* INCOMING */
//Close Window
protocol.registerServerbound(ServerboundPackets1_8.CLOSE_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowsId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
packetWrapper.user().get(Windows.class).remove(windowsId);
});
}
});
//Click Window
protocol.registerServerbound(ServerboundPackets1_8.CLICK_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.SHORT);
map(Type.BYTE);
map(Type.SHORT);
map(Type.BYTE, Type.VAR_INT);
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToServer(packetWrapper.get(Type.ITEM1_8, 0))));
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
Windows windows = packetWrapper.user().get(Windows.class);
String type = windows.get(windowId);
if (type == null) return;
if (type.equalsIgnoreCase("minecraft:brewing_stand")) {
short slot = packetWrapper.get(Type.SHORT, 0);
if (slot > 3) {
packetWrapper.set(Type.SHORT, 0, slot += 1);
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT);
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToServer(packetWrapper.get(Type.ITEM1_8, 0))));
}
});
}
}
@@ -1,635 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import java.util.ArrayList;
import java.util.UUID;
public class PlayerPackets {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.BOSSBAR, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
UUID uuid = packetWrapper.read(Type.UUID);
int action = packetWrapper.read(Type.VAR_INT);
BossBarStorage bossBarStorage = packetWrapper.user().get(BossBarStorage.class);
if (action == 0) {
bossBarStorage.add(uuid, ChatUtil.jsonToLegacy(packetWrapper.read(Type.COMPONENT)), packetWrapper.read(Type.FLOAT));
packetWrapper.read(Type.VAR_INT);
packetWrapper.read(Type.VAR_INT);
packetWrapper.read(Type.UNSIGNED_BYTE);
} else if (action == 1) {
bossBarStorage.remove(uuid);
} else if (action == 2) {
bossBarStorage.updateHealth(uuid, packetWrapper.read(Type.FLOAT));
} else if (action == 3) {
String title = ChatUtil.jsonToLegacy(packetWrapper.read(Type.COMPONENT));
bossBarStorage.updateTitle(uuid, title);
}
});
}
});
//Tab-Complete
//Chat Message
//Set Cooldown
protocol.cancelClientbound(ClientboundPackets1_9.COOLDOWN);
//Custom Payload
protocol.registerClientbound(ClientboundPackets1_9.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
if (channel.equals("MC|TrList")) {
packetWrapper.passthrough(Type.INT); //Window Id
int size;
if (packetWrapper.isReadable(Type.BYTE, 0)) {
size = packetWrapper.passthrough(Type.BYTE);
} else {
size = packetWrapper.passthrough(Type.UNSIGNED_BYTE);
}
final ItemRewriter<?> itemRewriter = protocol.getItemRewriter();
for (int i = 0; i < size; i++) {
packetWrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(packetWrapper.read(Type.ITEM1_8))); //Buy Item 1
packetWrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(packetWrapper.read(Type.ITEM1_8))); //Buy Item 3
boolean has3Items = packetWrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
packetWrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(packetWrapper.read(Type.ITEM1_8))); //Buy Item 2
}
packetWrapper.passthrough(Type.BOOLEAN); //Unavailable
packetWrapper.passthrough(Type.INT); //Uses
packetWrapper.passthrough(Type.INT); //Max Uses
}
} else if (channel.equals("MC|BOpen")) {
packetWrapper.read(Type.VAR_INT);
}
});
}
});
//Disconnect
//Change Game State
protocol.registerClientbound(ClientboundPackets1_9.GAME_EVENT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.FLOAT);
handler(packetWrapper -> {
int reason = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
if (reason == 3)
packetWrapper.user().get(EntityTracker.class).setPlayerGamemode(packetWrapper.get(Type.FLOAT, 0).intValue());
});
}
});
//Join Game
protocol.registerClientbound(ClientboundPackets1_9.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.UNSIGNED_BYTE);
map(Type.BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.STRING);
map(Type.BOOLEAN);
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.setPlayerId(packetWrapper.get(Type.INT, 0));
tracker.setPlayerGamemode(packetWrapper.get(Type.UNSIGNED_BYTE, 0));
tracker.getClientEntityTypes().put(tracker.getPlayerId(), EntityTypes1_10.EntityType.ENTITY_HUMAN);
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
world.setEnvironment(packetWrapper.get(Type.BYTE, 0));
});
}
});
//Open Sign Editor
//Player Abilities
//Player List Item
//Player Position And Look
protocol.registerClientbound(ClientboundPackets1_9.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BYTE);
handler(packetWrapper -> {
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
int teleportId = packetWrapper.read(Type.VAR_INT);
pos.setConfirmId(teleportId);
byte flags = packetWrapper.get(Type.BYTE, 0);
double x = packetWrapper.get(Type.DOUBLE, 0);
double y = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
float yaw = packetWrapper.get(Type.FLOAT, 0);
float pitch = packetWrapper.get(Type.FLOAT, 1);
packetWrapper.set(Type.BYTE, 0, (byte) 0);
if (flags != 0) {
if ((flags & 0x01) != 0) {
x += pos.getPosX();
packetWrapper.set(Type.DOUBLE, 0, x);
}
if ((flags & 0x02) != 0) {
y += pos.getPosY();
packetWrapper.set(Type.DOUBLE, 1, y);
}
if ((flags & 0x04) != 0) {
z += pos.getPosZ();
packetWrapper.set(Type.DOUBLE, 2, z);
}
if ((flags & 0x08) != 0) {
yaw += pos.getYaw();
packetWrapper.set(Type.FLOAT, 0, yaw);
}
if ((flags & 0x10) != 0) {
pitch += pos.getPitch();
packetWrapper.set(Type.FLOAT, 1, pitch);
}
}
pos.setPos(x, y, z);
pos.setYaw(yaw);
pos.setPitch(pitch);
});
}
});
//Resource Pack Send
//Respawn
protocol.registerClientbound(ClientboundPackets1_9.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.STRING);
handler(packetWrapper -> packetWrapper.user().get(EntityTracker.class).setPlayerGamemode(packetWrapper.get(Type.UNSIGNED_BYTE, 1)));
handler(packetWrapper -> {
packetWrapper.user().get(BossBarStorage.class).updateLocation();
packetWrapper.user().get(BossBarStorage.class).changeWorld();
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
world.setEnvironment(packetWrapper.get(Type.INT, 0));
});
}
});
//Camera
//Held Item Change
//Set Experience
//Update Health
//Spawn Position
//Title
//Player List Header And Footer
/* INCOMING */
//Chat Message
protocol.registerServerbound(ServerboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
if (msg.toLowerCase().startsWith("/offhand")) {
packetWrapper.cancel();
PacketWrapper swapItems = PacketWrapper.create(0x13, null, packetWrapper.user());
swapItems.write(Type.VAR_INT, 6);
swapItems.write(Type.POSITION1_8, new Position(0, 0, 0));
swapItems.write(Type.BYTE, (byte) 255);
PacketUtil.sendToServer(swapItems, Protocol1_8To1_9.class, true, true);
}
});
}
});
//Confirm Transaction
//Use Entity
protocol.registerServerbound(ServerboundPackets1_8.INTERACT_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.VAR_INT);
handler(packetWrapper -> {
int type = packetWrapper.get(Type.VAR_INT, 1);
if (type == 2) {
packetWrapper.passthrough(Type.FLOAT);
packetWrapper.passthrough(Type.FLOAT);
packetWrapper.passthrough(Type.FLOAT);
}
if (type == 2 || type == 0) {
packetWrapper.write(Type.VAR_INT, 0);
}
});
}
});
//Player
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.BOOLEAN);
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int playerId = tracker.getPlayerId();
if (tracker.isInsideVehicle(playerId)) packetWrapper.cancel();
});
}
});
//Player Position
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.BOOLEAN);
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
if (pos.getConfirmId() != -1) return;
pos.setPos(packetWrapper.get(Type.DOUBLE, 0), packetWrapper.get(Type.DOUBLE, 1),
packetWrapper.get(Type.DOUBLE, 2));
pos.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
});
handler(packetWrapper -> packetWrapper.user().get(BossBarStorage.class).updateLocation());
}
});
//Player Look
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
if (pos.getConfirmId() != -1) return;
pos.setYaw(packetWrapper.get(Type.FLOAT, 0));
pos.setPitch(packetWrapper.get(Type.FLOAT, 1));
pos.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
});
handler(packetWrapper -> packetWrapper.user().get(BossBarStorage.class).updateLocation());
}
});
//Player Position And Look
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
double x = packetWrapper.get(Type.DOUBLE, 0);
double y = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
float yaw = packetWrapper.get(Type.FLOAT, 0);
float pitch = packetWrapper.get(Type.FLOAT, 1);
boolean onGround = packetWrapper.get(Type.BOOLEAN, 0);
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
if (pos.getConfirmId() != -1) {
if (pos.getPosX() == x && pos.getPosY() == y && pos.getPosZ() == z
&& pos.getYaw() == yaw && pos.getPitch() == pitch) {
PacketWrapper confirmTeleport = packetWrapper.create(0x00);
confirmTeleport.write(Type.VAR_INT, pos.getConfirmId());
PacketUtil.sendToServer(confirmTeleport,
Protocol1_8To1_9.class, true, true);
pos.setConfirmId(-1);
}
} else {
pos.setPos(x, y, z);
pos.setYaw(yaw);
pos.setPitch(pitch);
pos.setOnGround(onGround);
packetWrapper.user().get(BossBarStorage.class).updateLocation();
}
});
}
});
//Player Digging
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_DIGGING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.POSITION1_8);
handler(packetWrapper -> {
int state = packetWrapper.get(Type.VAR_INT, 0);
if (state == 0) {
packetWrapper.user().get(BlockPlaceDestroyTracker.class).setMining(true);
} else if (state == 2) {
BlockPlaceDestroyTracker tracker = packetWrapper.user().get(BlockPlaceDestroyTracker.class);
tracker.setMining(false);
tracker.setLastMining(System.currentTimeMillis() + 100);
packetWrapper.user().get(Cooldown.class).setLastHit(0);
} else if (state == 1) {
BlockPlaceDestroyTracker tracker = packetWrapper.user().get(BlockPlaceDestroyTracker.class);
tracker.setMining(false);
tracker.setLastMining(0);
packetWrapper.user().get(Cooldown.class).hit();
}
});
}
});
//Player Block Placement
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
map(Type.BYTE, Type.VAR_INT);
read(Type.ITEM1_8);
create(Type.VAR_INT, 0); //Main Hand
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
if (packetWrapper.get(Type.VAR_INT, 0) == -1) {
packetWrapper.cancel();
PacketWrapper useItem = PacketWrapper.create(0x1D, null, packetWrapper.user());
useItem.write(Type.VAR_INT, 0);
PacketUtil.sendToServer(useItem, Protocol1_8To1_9.class, true, true);
}
});
handler(packetWrapper -> {
if (packetWrapper.get(Type.VAR_INT, 0) != -1) {
packetWrapper.user().get(BlockPlaceDestroyTracker.class).place();
}
});
}
});
//Held Item Change
protocol.registerServerbound(ServerboundPackets1_8.HELD_ITEM_CHANGE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> packetWrapper.user().get(Cooldown.class).hit());
}
});
//Animation
protocol.registerServerbound(ServerboundPackets1_8.ANIMATION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
/* We have to add ArmAnimation to a queue to be sent on PacketPlayInFlying. In 1.9,
* PacketPlayInArmAnimation is sent after PacketPlayInUseEntity, not before like it used to be.
* However, all packets are sent before PacketPlayInFlying. We'd just do a normal delay, but
* it would cause the packet to be sent after PacketPlayInFlying, potentially false flagging
* anticheats that check for this behavior from clients. Since all packets are sent before
* PacketPlayInFlying, if we queue it to be sent right before PacketPlayInFlying is processed,
* we can be certain it will be sent after PacketPlayInUseEntity */
packetWrapper.cancel();
final PacketWrapper delayedPacket = PacketWrapper.create(0x1A,
null, packetWrapper.user());
delayedPacket.write(Type.VAR_INT, 0); //Main Hand
((Protocol1_8To1_9) protocol).animationsToSend.add(delayedPacket);
});
handler(packetWrapper -> {
packetWrapper.user().get(BlockPlaceDestroyTracker.class).updateMining();
packetWrapper.user().get(Cooldown.class).hit();
});
}
});
//Entity Action
protocol.registerServerbound(ServerboundPackets1_8.ENTITY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.VAR_INT);
map(Type.VAR_INT);
handler(packetWrapper -> {
int action = packetWrapper.get(Type.VAR_INT, 1);
if (action == 6) {
packetWrapper.set(Type.VAR_INT, 1, 7);
} else if (action == 0) {
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
if (!pos.isOnGround()) {
PacketWrapper elytra = PacketWrapper.create(0x14, null, packetWrapper.user());
elytra.write(Type.VAR_INT, packetWrapper.get(Type.VAR_INT, 0));
elytra.write(Type.VAR_INT, 8);
elytra.write(Type.VAR_INT, 0);
PacketUtil.sendToServer(elytra, Protocol1_8To1_9.class, true, false);
}
}
});
}
});
//Steer Vehicle
protocol.registerServerbound(ServerboundPackets1_8.STEER_VEHICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int playerId = tracker.getPlayerId();
int vehicle = tracker.getVehicle(playerId);
if (vehicle != -1 && tracker.getClientEntityTypes().get(vehicle) == EntityTypes1_10.EntityType.BOAT) {
PacketWrapper steerBoat = PacketWrapper.create(0x11, null, packetWrapper.user());
float left = packetWrapper.get(Type.FLOAT, 0);
float forward = packetWrapper.get(Type.FLOAT, 1);
steerBoat.write(Type.BOOLEAN, forward != 0.0f || left < 0.0f);
steerBoat.write(Type.BOOLEAN, forward != 0.0f || left > 0.0f);
PacketUtil.sendToServer(steerBoat, Protocol1_8To1_9.class);
}
});
}
});
//Update Sign
protocol.registerServerbound(ServerboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
handler(packetWrapper -> {
for (int i = 0; i < 4; i++) {
packetWrapper.write(Type.STRING, ChatUtil.jsonToLegacy(packetWrapper.read(Type.COMPONENT)));
}
});
}
});
//Player Abilities
//Tab Complete
protocol.registerServerbound(ServerboundPackets1_8.TAB_COMPLETE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> packetWrapper.write(Type.BOOLEAN, false));
map(Type.OPTIONAL_POSITION1_8);
}
});
//Client Settings
protocol.registerServerbound(ServerboundPackets1_8.CLIENT_SETTINGS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
map(Type.BYTE, Type.VAR_INT);
map(Type.BOOLEAN);
map(Type.UNSIGNED_BYTE);
create(Type.VAR_INT, 1);
handler(packetWrapper -> {
short flags = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
PacketWrapper updateSkin = PacketWrapper.create(0x1C, null, packetWrapper.user());
updateSkin.write(Type.VAR_INT, packetWrapper.user().get(EntityTracker.class).getPlayerId());
ArrayList<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(10, MetaType1_8.Byte, (byte) flags));
updateSkin.write(Types1_8.METADATA_LIST, metadata);
PacketUtil.sendPacket(updateSkin, Protocol1_8To1_9.class);
});
}
});
//Client Status
//Custom Payload
protocol.registerServerbound(ServerboundPackets1_8.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
if (channel.equals("MC|BEdit") || channel.equals("MC|BSign")) {
Item book = packetWrapper.passthrough(Type.ITEM);
book.setIdentifier(386);
CompoundTag tag = book.tag();
if (tag.contains("pages")) {
ListTag pages = tag.get("pages");
if (pages.size() > ViaRewind.getConfig().getMaxBookPages()) {
packetWrapper.user().disconnect("Too many book pages");
return;
}
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
if (value.length() > ViaRewind.getConfig().getMaxBookPageSize()) {
packetWrapper.user().disconnect("Book page too large");
return;
}
value = ChatUtil.jsonToLegacy(value);
page.setValue(value);
}
}
} else if (channel.equals("MC|AdvCdm")) {
packetWrapper.set(Type.STRING, 0, channel = "MC|AdvCmd");
}
});
}
});
//Spectate
//Resource Pack Status
}
}
@@ -0,0 +1,537 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import java.util.ArrayList;
import java.util.UUID;
public class PlayerPackets1_9 {
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.BOSSBAR, null, wrapper -> {
wrapper.cancel();
final BossBarStorage bossbar = wrapper.user().get(BossBarStorage.class);
final UUID uuid = wrapper.read(Type.UUID);
final int action = wrapper.read(Type.VAR_INT);
if (action == 0 /* add */) {
final JsonElement title = wrapper.read(Type.COMPONENT);
final float health = wrapper.read(Type.FLOAT);
wrapper.read(Type.VAR_INT); // Color
wrapper.read(Type.VAR_INT); // Division
wrapper.read(Type.UNSIGNED_BYTE); // Flags
bossbar.add(uuid, ChatUtil.jsonToLegacy(wrapper.user(), title), health);
} else if (action == 1 /* remove */) {
bossbar.remove(uuid);
} else if (action == 2 /* update health */) {
final float health = wrapper.read(Type.FLOAT);
bossbar.updateHealth(uuid, health);
} else if (action == 3 /* update title */) {
final JsonElement title = wrapper.read(Type.COMPONENT);
bossbar.updateTitle(uuid, ChatUtil.jsonToLegacy(wrapper.user(), title));
}
});
protocol.registerClientbound(ClientboundPackets1_9.TEAMS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // Team name
map(Type.BYTE); // Mode
handler(wrapper -> {
final byte mode = wrapper.get(Type.BYTE, 0);
if (mode == 0 /* create team */ || mode == 2 /* update team info */) {
wrapper.passthrough(Type.STRING); // Display name
wrapper.passthrough(Type.STRING); // Prefix
wrapper.passthrough(Type.STRING); // Suffix
wrapper.passthrough(Type.BYTE); // Friendly fire
wrapper.passthrough(Type.STRING); // Name tag visibility
wrapper.read(Type.STRING); // Collision rule
}
});
}
});
protocol.cancelClientbound(ClientboundPackets1_9.COOLDOWN);
protocol.registerClientbound(ClientboundPackets1_9.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // Channel
handlerSoftFail(wrapper -> {
final String channel = wrapper.get(Type.STRING, 0);
if (channel.equals("MC|TrList")) {
wrapper.passthrough(Type.INT); // Window id
int size;
if (wrapper.isReadable(Type.BYTE, 0)) {
size = wrapper.passthrough(Type.BYTE);
} else {
size = wrapper.passthrough(Type.UNSIGNED_BYTE);
}
final ItemRewriter<?> itemRewriter = protocol.getItemRewriter();
for (int i = 0; i < size; i++) {
wrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8))); // Buy item 1
wrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8))); // Buy item 3
boolean has3Items = wrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
wrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(wrapper.user(), wrapper.read(Type.ITEM1_8))); // Buy item 2
}
wrapper.passthrough(Type.BOOLEAN); //Unavailable
wrapper.passthrough(Type.INT); //Uses
wrapper.passthrough(Type.INT); //Max Uses
}
} else if (channel.equals("MC|BOpen")) {
wrapper.read(Type.VAR_INT);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); // X
map(Type.DOUBLE); // Feet y
map(Type.DOUBLE); // Z
map(Type.FLOAT); // Yaw
map(Type.FLOAT); // Pitch
map(Type.BYTE); // Relative arguments
handler(wrapper -> {
final PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
pos.setConfirmId(wrapper.read(Type.VAR_INT));
byte flags = wrapper.get(Type.BYTE, 0);
double x = wrapper.get(Type.DOUBLE, 0);
double y = wrapper.get(Type.DOUBLE, 1);
double z = wrapper.get(Type.DOUBLE, 2);
float yaw = wrapper.get(Type.FLOAT, 0);
float pitch = wrapper.get(Type.FLOAT, 1);
wrapper.set(Type.BYTE, 0, (byte) 0);
if (flags != 0) {
if ((flags & 0x01) != 0) {
x += pos.getPosX();
wrapper.set(Type.DOUBLE, 0, x);
}
if ((flags & 0x02) != 0) {
y += pos.getPosY();
wrapper.set(Type.DOUBLE, 1, y);
}
if ((flags & 0x04) != 0) {
z += pos.getPosZ();
wrapper.set(Type.DOUBLE, 2, z);
}
if ((flags & 0x08) != 0) {
yaw += pos.getYaw();
wrapper.set(Type.FLOAT, 0, yaw);
}
if ((flags & 0x10) != 0) {
pitch += pos.getPitch();
wrapper.set(Type.FLOAT, 1, pitch);
}
}
pos.setPos(x, y, z);
pos.setYaw(yaw);
pos.setPitch(pitch);
});
}
});
protocol.registerClientbound(ClientboundPackets1_9.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); // Dimension
handler(wrapper -> wrapper.user().get(BossBarStorage.class).reset());
handler(wrapper -> {
final ClientWorld world = wrapper.user().get(ClientWorld.class);
world.setEnvironment(wrapper.get(Type.INT, 0));
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); // Message
handler(wrapper -> {
if (!ViaRewind.getConfig().isEnableOffhand()) {
return;
}
final String msg = wrapper.get(Type.STRING, 0);
if (msg.toLowerCase().trim().startsWith(ViaRewind.getConfig().getOffhandCommand())) {
wrapper.cancel();
final PacketWrapper swapItems = PacketWrapper.create(ServerboundPackets1_9.PLAYER_DIGGING, wrapper.user());
swapItems.write(Type.VAR_INT, 6);
swapItems.write(Type.POSITION1_8, new Position(0, 0, 0));
swapItems.write(Type.BYTE, (byte) 255);
swapItems.sendToServer(Protocol1_8To1_9.class);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.INTERACT_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); // Target
map(Type.VAR_INT); // Type
handler(wrapper -> {
final int type = wrapper.get(Type.VAR_INT, 1);
if (type == 2 /* attack */) {
wrapper.passthrough(Type.FLOAT); // Target x
wrapper.passthrough(Type.FLOAT); // Target y
wrapper.passthrough(Type.FLOAT); // Target z
}
if (type == 2 /* attack */ || type == 0 /* interact */) {
wrapper.write(Type.VAR_INT, 0); // Hand
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.BOOLEAN); // On ground
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
if (tracker.isInsideVehicle(tracker.clientEntityId())) {
wrapper.cancel();
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); // X
map(Type.DOUBLE); // Feet y
map(Type.DOUBLE); // Z
map(Type.BOOLEAN); // On ground
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
final PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (pos.getConfirmId() != -1) {
return;
}
pos.setPos(wrapper.get(Type.DOUBLE, 0), wrapper.get(Type.DOUBLE, 1), wrapper.get(Type.DOUBLE, 2));
pos.setOnGround(wrapper.get(Type.BOOLEAN, 0));
});
handler(wrapper -> wrapper.user().get(BossBarStorage.class).updateLocation());
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (pos.getConfirmId() != -1) return;
pos.setYaw(wrapper.get(Type.FLOAT, 0));
pos.setPitch(wrapper.get(Type.FLOAT, 1));
pos.setOnGround(wrapper.get(Type.BOOLEAN, 0));
});
handler(wrapper -> wrapper.user().get(BossBarStorage.class).updateLocation());
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(wrapper -> {
wrapper.user().get(PlayerPositionTracker.class).sendAnimations();
double x = wrapper.get(Type.DOUBLE, 0);
double y = wrapper.get(Type.DOUBLE, 1);
double z = wrapper.get(Type.DOUBLE, 2);
float yaw = wrapper.get(Type.FLOAT, 0);
float pitch = wrapper.get(Type.FLOAT, 1);
boolean onGround = wrapper.get(Type.BOOLEAN, 0);
PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (pos.getConfirmId() != -1) {
if (pos.getPosX() == x && pos.getPosY() == y && pos.getPosZ() == z
&& pos.getYaw() == yaw && pos.getPitch() == pitch) {
PacketWrapper confirmTeleport = wrapper.create(0x00);
confirmTeleport.write(Type.VAR_INT, pos.getConfirmId());
confirmTeleport.sendToServer(Protocol1_8To1_9.class);
pos.setConfirmId(-1);
}
} else {
pos.setPos(x, y, z);
pos.setYaw(yaw);
pos.setPitch(pitch);
pos.setOnGround(onGround);
wrapper.user().get(BossBarStorage.class).updateLocation();
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_DIGGING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.POSITION1_8);
handler(wrapper -> {
int state = wrapper.get(Type.VAR_INT, 0);
if (state == 0) {
wrapper.user().get(BlockPlaceDestroyTracker.class).setMining();
} else if (state == 2) {
BlockPlaceDestroyTracker tracker = wrapper.user().get(BlockPlaceDestroyTracker.class);
tracker.setMining();
tracker.setLastMining(System.currentTimeMillis() + 100);
wrapper.user().get(CooldownStorage.class).setLastHit(0);
} else if (state == 1) {
BlockPlaceDestroyTracker tracker = wrapper.user().get(BlockPlaceDestroyTracker.class);
tracker.setMining();
tracker.setLastMining(0);
wrapper.user().get(CooldownStorage.class).hit();
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
map(Type.BYTE, Type.VAR_INT);
read(Type.ITEM1_8);
create(Type.VAR_INT, 0); //Main Hand
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
handler(wrapper -> {
if (wrapper.get(Type.VAR_INT, 0) == -1) {
wrapper.cancel();
PacketWrapper useItem = PacketWrapper.create(0x1D, null, wrapper.user());
useItem.write(Type.VAR_INT, 0);
useItem.sendToServer(Protocol1_8To1_9.class);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.HELD_ITEM_CHANGE, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> wrapper.user().get(CooldownStorage.class).hit());
}
});
protocol.registerServerbound(ServerboundPackets1_8.ANIMATION, new PacketHandlers() {
@Override
public void register() {
handler(wrapper -> {
wrapper.cancel();
/* We have to add ArmAnimation to a queue to be sent on PacketPlayInFlying. In 1.9,
* PacketPlayInArmAnimation is sent after PacketPlayInUseEntity, not before like it used to be.
* However, all packets are sent before PacketPlayInFlying. We'd just do a normal delay, but
* it would cause the packet to be sent after PacketPlayInFlying, potentially false flagging
* anticheats that check for this behavior from clients. Since all packets are sent before
* PacketPlayInFlying, if we queue it to be sent right before PacketPlayInFlying is processed,
* we can be certain it will be sent after PacketPlayInUseEntity */
wrapper.cancel();
final PacketWrapper delayedPacket = PacketWrapper.create(0x1A, null, wrapper.user());
delayedPacket.write(Type.VAR_INT, 0); //Main Hand
wrapper.user().get(PlayerPositionTracker.class).queueAnimation(delayedPacket);
});
handler(wrapper -> {
wrapper.user().get(BlockPlaceDestroyTracker.class).updateMining();
wrapper.user().get(CooldownStorage.class).hit();
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.ENTITY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.VAR_INT);
map(Type.VAR_INT);
handler(wrapper -> {
int action = wrapper.get(Type.VAR_INT, 1);
if (action == 6) {
wrapper.set(Type.VAR_INT, 1, 7);
} else if (action == 0) {
PlayerPositionTracker pos = wrapper.user().get(PlayerPositionTracker.class);
if (!pos.isOnGround()) {
PacketWrapper elytra = PacketWrapper.create(0x14, null, wrapper.user());
elytra.write(Type.VAR_INT, wrapper.get(Type.VAR_INT, 0));
elytra.write(Type.VAR_INT, 8);
elytra.write(Type.VAR_INT, 0);
elytra.scheduleSendToServer(Protocol1_8To1_9.class);
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.STEER_VEHICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.UNSIGNED_BYTE);
handler(wrapper -> {
final EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
final int vehicle = tracker.getVehicle(tracker.clientEntityId());
if (vehicle != -1 && tracker.entityType(vehicle) == EntityTypes1_10.EntityType.BOAT) {
PacketWrapper steerBoat = PacketWrapper.create(0x11, null, wrapper.user());
float left = wrapper.get(Type.FLOAT, 0);
float forward = wrapper.get(Type.FLOAT, 1);
steerBoat.write(Type.BOOLEAN, forward != 0.0f || left < 0.0f);
steerBoat.write(Type.BOOLEAN, forward != 0.0f || left > 0.0f);
steerBoat.scheduleSendToServer(Protocol1_8To1_9.class);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
wrapper.write(Type.STRING, ChatUtil.jsonToLegacy(wrapper.user(), wrapper.read(Type.COMPONENT)));
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.TAB_COMPLETE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
create(Type.BOOLEAN, false);
map(Type.OPTIONAL_POSITION1_8);
}
});
protocol.registerServerbound(ServerboundPackets1_8.CLIENT_SETTINGS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
map(Type.BYTE, Type.VAR_INT);
map(Type.BOOLEAN);
map(Type.UNSIGNED_BYTE);
create(Type.VAR_INT, 1);
handler(wrapper -> {
short flags = wrapper.get(Type.UNSIGNED_BYTE, 0);
PacketWrapper updateSkin = PacketWrapper.create(0x1C, null, wrapper.user());
updateSkin.write(Type.VAR_INT, wrapper.user().getEntityTracker(Protocol1_8To1_9.class).clientEntityId());
ArrayList<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(10, MetaType1_8.Byte, (byte) flags));
updateSkin.write(Types1_8.METADATA_LIST, metadata);
updateSkin.scheduleSend(Protocol1_8To1_9.class);
});
}
});
protocol.registerServerbound(ServerboundPackets1_8.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(wrapper -> {
String channel = wrapper.get(Type.STRING, 0);
if (channel.equals("MC|BEdit") || channel.equals("MC|BSign")) {
Item book = wrapper.passthrough(Type.ITEM);
book.setIdentifier(386);
CompoundTag tag = book.tag();
if (tag.contains("pages")) {
ListTag<StringTag> pages = tag.getListTag("pages", StringTag.class);
if (pages.size() > ViaRewind.getConfig().getMaxBookPages()) {
wrapper.user().disconnect("Too many book pages");
return;
}
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
if (value.length() > ViaRewind.getConfig().getMaxBookPageSize()) {
wrapper.user().disconnect("Book page too large");
return;
}
value = ChatUtil.jsonToLegacy(wrapper.user(), value);
page.setValue(value);
}
}
} else if (channel.equals("MC|AdvCdm")) {
wrapper.set(Type.STRING, 0, "MC|AdvCmd");
}
});
}
});
}
}
@@ -1,65 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
public class ScoreboardPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
//Display Scoreboard
//Scoreboard Objective
//Scoreboard Team
protocol.registerClientbound(ClientboundPackets1_9.TEAMS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
handler(packetWrapper -> {
byte mode = packetWrapper.get(Type.BYTE, 0);
if (mode == 0 || mode == 2) {
packetWrapper.passthrough(Type.STRING); //Display Name
packetWrapper.passthrough(Type.STRING); //Prefix
packetWrapper.passthrough(Type.STRING); //Suffix
packetWrapper.passthrough(Type.BYTE); //Friendly Flags
packetWrapper.passthrough(Type.STRING); //Name Tag Visibility
packetWrapper.read(Type.STRING); //Skip Collision Rule
packetWrapper.passthrough(Type.BYTE); //Friendly Flags
}
if (mode == 0 || mode == 3 || mode == 4) {
packetWrapper.passthrough(Type.STRING_ARRAY);
}
});
}
});
//Update Score
}
}
@@ -1,272 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement.ShulkerBulletModel;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement.ShulkerModel;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viarewind.api.rewriter.Replacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import java.util.List;
public class SpawnPackets {
public static void register(Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
read(Type.UUID);
map(Type.BYTE);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.INT);
handler(packetWrapper -> {
final int entityId = packetWrapper.get(Type.VAR_INT, 0);
final int typeId = packetWrapper.get(Type.BYTE, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(typeId, true);
//cancel AREA_EFFECT_CLOUD = 3, SPECTRAL_ARROW = 91, DRAGON_FIREBALL = 93
if (typeId == 3 || typeId == 91 || typeId == 92 || typeId == 93) {
packetWrapper.cancel();
return;
}
if (type == null) {
ViaRewind.getPlatform().getLogger().warning("[ViaRewind] Unhandled Spawn Object Type: " + typeId);
packetWrapper.cancel();
return;
}
int x = packetWrapper.get(Type.INT, 0);
int y = packetWrapper.get(Type.INT, 1);
int z = packetWrapper.get(Type.INT, 2);
if (type.is(EntityTypes1_10.EntityType.BOAT)) {
byte yaw = packetWrapper.get(Type.BYTE, 1);
yaw -= 64;
packetWrapper.set(Type.BYTE, 1, yaw);
y += 10;
packetWrapper.set(Type.INT, 1, y);
} else if (type.is(EntityTypes1_10.EntityType.SHULKER_BULLET)) {
packetWrapper.cancel();
ShulkerBulletModel shulkerBulletReplacement = new ShulkerBulletModel(packetWrapper.user(), protocol, entityId);
shulkerBulletReplacement.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
tracker.addEntityReplacement(shulkerBulletReplacement);
return;
}
int data = packetWrapper.get(Type.INT, 3);
//Rewrite Object Data
if (type.isOrHasParent(EntityTypes1_10.EntityType.ARROW) && data != 0) {
packetWrapper.set(Type.INT, 3, --data);
}
if (type.is(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
Replacement replace = protocol.getItemRewriter().replace(blockId, blockData);
if (replace != null) {
packetWrapper.set(Type.INT, 3, replace.getId() | replace.replaceData(data) << 12);
}
}
if (data > 0) {
packetWrapper.passthrough(Type.SHORT);
packetWrapper.passthrough(Type.SHORT);
packetWrapper.passthrough(Type.SHORT);
} else {
short vX = packetWrapper.read(Type.SHORT);
short vY = packetWrapper.read(Type.SHORT);
short vZ = packetWrapper.read(Type.SHORT);
PacketWrapper velocityPacket = PacketWrapper.create(0x12, null, packetWrapper.user());
velocityPacket.write(Type.VAR_INT, entityId);
velocityPacket.write(Type.SHORT, vX);
velocityPacket.write(Type.SHORT, vY);
velocityPacket.write(Type.SHORT, vZ);
PacketUtil.sendPacket(velocityPacket, Protocol1_8To1_9.class);
}
tracker.getClientEntityTypes().put(entityId, type);
tracker.sendMetadataBuffer(entityId);
});
}
});
//Spawn Experience Orb
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_EXPERIENCE_ORB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.SHORT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.EXPERIENCE_ORB);
tracker.sendMetadataBuffer(entityId);
});
}
});
//Spawn Global Entity
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_GLOBAL_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.LIGHTNING);
tracker.sendMetadataBuffer(entityId);
});
}
});
//Spawn Mob
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
read(Type.UUID);
map(Type.UNSIGNED_BYTE);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BYTE);
map(Type.SHORT);
map(Type.SHORT);
map(Type.SHORT);
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int typeId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
int x = packetWrapper.get(Type.INT, 0);
int y = packetWrapper.get(Type.INT, 1);
int z = packetWrapper.get(Type.INT, 2);
byte pitch = packetWrapper.get(Type.BYTE, 1);
byte yaw = packetWrapper.get(Type.BYTE, 0);
byte headYaw = packetWrapper.get(Type.BYTE, 2);
if (typeId == 69) {
packetWrapper.cancel();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
ShulkerModel shulkerReplacement = new ShulkerModel(packetWrapper.user(), protocol, entityId);
shulkerReplacement.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
shulkerReplacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
shulkerReplacement.setHeadYaw(headYaw * 360f / 256);
tracker.addEntityReplacement(shulkerReplacement);
} else if (typeId == -1 || typeId == 255) {
packetWrapper.cancel();
}
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int typeId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.getTypeFromId(typeId, false));
tracker.sendMetadataBuffer(entityId);
});
handler(wrapper -> {
List<Metadata> metadataList = wrapper.get(Types1_8.METADATA_LIST, 0);
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
EntityModel replacement;
if ((replacement = tracker.getEntityReplacement(entityId)) != null) {
replacement.updateMetadata(metadataList);
} else if (tracker.getClientEntityTypes().containsKey(entityId)) {
protocol.getMetadataRewriter().transform(tracker, entityId, metadataList);
} else {
wrapper.cancel();
}
});
}
});
//Spawn Painting
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
read(Type.UUID);
map(Type.STRING);
map(Type.POSITION1_8);
map(Type.BYTE, Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.PAINTING);
tracker.sendMetadataBuffer(entityId);
});
}
});
//Spawn Player
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.UUID);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.BYTE);
map(Type.BYTE);
handler(packetWrapper -> packetWrapper.write(Type.SHORT, (short) 0));
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST);
this.handler(wrapper -> {
int entityId = wrapper.get(Type.VAR_INT, 0);
List<Metadata> metadataList = wrapper.get(Types1_8.METADATA_LIST, 0);
protocol.getMetadataRewriter().transform(wrapper.user().get(EntityTracker.class), entityId, metadataList, EntityTypes1_10.EntityType.PLAYER);
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.PLAYER);
tracker.sendMetadataBuffer(entityId);
});
}
});
}
}
@@ -15,16 +15,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.sound.Effect;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.sound.SoundRemapper;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.data.EffectMappings;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.chunks.BaseChunk;
@@ -46,7 +42,7 @@ import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_
import java.util.ArrayList;
public class WorldPackets {
public class WorldPackets1_9 {
public static void register(Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_ENTITY_DATA, new PacketHandlers() {
@@ -55,8 +51,8 @@ public class WorldPackets {
map(Type.POSITION1_8);
map(Type.UNSIGNED_BYTE);
map(Type.NAMED_COMPOUND_TAG);
handler(packetWrapper -> {
CompoundTag tag = packetWrapper.get(Type.NAMED_COMPOUND_TAG, 0);
handler(wrapper -> {
CompoundTag tag = wrapper.get(Type.NAMED_COMPOUND_TAG, 0);
if (tag != null && tag.contains("SpawnData")) {
CompoundTag spawnData = tag.get("SpawnData");
if (spawnData.contains("id")) {
@@ -69,7 +65,6 @@ public class WorldPackets {
}
});
//Block Action
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_ACTION, new PacketHandlers() {
@Override
public void register() {
@@ -77,59 +72,26 @@ public class WorldPackets {
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.VAR_INT);
handler(packetWrapper -> {
int block = packetWrapper.get(Type.VAR_INT, 0);
handler(wrapper -> {
int block = wrapper.get(Type.VAR_INT, 0);
if (block >= 219 && block <= 234) {
packetWrapper.set(Type.VAR_INT, 0, block = 130);
wrapper.set(Type.VAR_INT, 0, 130);
}
});
}
});
//Block Change
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION1_8);
map(Type.VAR_INT);
handler(packetWrapper -> {
int combined = packetWrapper.get(Type.VAR_INT, 0);
int replacedCombined = protocol.getItemRewriter().replace(combined);
packetWrapper.set(Type.VAR_INT, 0, replacedCombined);
});
}
});
//Server Difficulty
//Multi Block Change
protocol.registerClientbound(ClientboundPackets1_9.MULTI_BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.INT);
map(Type.BLOCK_CHANGE_RECORD_ARRAY);
handler(packetWrapper -> {
for (BlockChangeRecord record : packetWrapper.get(Type.BLOCK_CHANGE_RECORD_ARRAY, 0)) {
int replacedCombined = protocol.getItemRewriter().replace(record.getBlockId());
record.setBlockId(replacedCombined);
}
});
}
});
//Named Sound Effect
protocol.registerClientbound(ClientboundPackets1_9.NAMED_SOUND, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String name = packetWrapper.get(Type.STRING, 0);
name = SoundRemapper.getOldName(name);
handler(wrapper -> {
String name = wrapper.get(Type.STRING, 0);
name = protocol.getMappingData().getMappedNamedSound(name);
if (name == null) {
packetWrapper.cancel();
wrapper.cancel();
} else {
packetWrapper.set(Type.STRING, 0, name);
wrapper.set(Type.STRING, 0, name);
}
});
read(Type.VAR_INT);
@@ -141,36 +103,34 @@ public class WorldPackets {
}
});
//Unload Chunk
protocol.registerClientbound(ClientboundPackets1_9.UNLOAD_CHUNK, ClientboundPackets1_8.CHUNK_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
final Environment environment = packetWrapper.user().get(ClientWorld.class).getEnvironment();
handler(wrapper -> {
final Environment environment = wrapper.user().get(ClientWorld.class).getEnvironment();
final int chunkX = packetWrapper.read(Type.INT);
final int chunkZ = packetWrapper.read(Type.INT);
final int chunkX = wrapper.read(Type.INT);
final int chunkZ = wrapper.read(Type.INT);
packetWrapper.write(ChunkType1_8.forEnvironment(environment), new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], null, new ArrayList<>()));
wrapper.write(ChunkType1_8.forEnvironment(environment), new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], null, new ArrayList<>()));
});
}
});
//Chunk Data
protocol.registerClientbound(ClientboundPackets1_9.CHUNK_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
final Environment environment = packetWrapper.user().get(ClientWorld.class).getEnvironment();
handler(wrapper -> {
final Environment environment = wrapper.user().get(ClientWorld.class).getEnvironment();
Chunk chunk = packetWrapper.read(ChunkType1_9_1.forEnvironment(environment));
Chunk chunk = wrapper.read(ChunkType1_9_1.forEnvironment(environment));
for (ChunkSection section : chunk.getSections()) {
if (section == null) continue;
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < palette.size(); i++) {
int block = palette.idByIndex(i);
int replacedBlock = protocol.getItemRewriter().replace(block);
int replacedBlock = protocol.getItemRewriter().handleBlockId(block);
palette.setIdByIndex(i, replacedBlock);
}
}
@@ -185,9 +145,9 @@ public class WorldPackets {
chunk = new BaseChunk(chunk.getX(), chunk.getZ(), true, false, 1, sections, chunk.getBiomeData(), chunk.getBlockEntities());
}
packetWrapper.write(ChunkType1_8.forEnvironment(environment), chunk);
wrapper.write(ChunkType1_8.forEnvironment(environment), chunk);
final UserConnection user = packetWrapper.user();
final UserConnection user = wrapper.user();
chunk.getBlockEntities().forEach(nbt -> {
if (!nbt.contains("x") || !nbt.contains("y") || !nbt.contains("z") || !nbt.contains("id"))
return;
@@ -223,13 +183,16 @@ public class WorldPackets {
updateTileEntity.write(Type.UNSIGNED_BYTE, action);
updateTileEntity.write(Type.NBT, nbt);
PacketUtil.sendPacket(updateTileEntity, Protocol1_8To1_9.class, false, false);
try {
updateTileEntity.scheduleSend(Protocol1_8To1_9.class, false);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().warning("Error sending tile entity update packet: " + e.getMessage());
}
});
});
}
});
//Effect
protocol.registerClientbound(ClientboundPackets1_9.EFFECT, new PacketHandlers() {
@Override
public void register() {
@@ -237,47 +200,45 @@ public class WorldPackets {
map(Type.POSITION1_8);
map(Type.INT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
int id = packetWrapper.get(Type.INT, 0);
id = Effect.getOldId(id);
handler(wrapper -> {
int id = wrapper.get(Type.INT, 0);
id = EffectMappings.getOldId(id);
if (id == -1) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
packetWrapper.set(Type.INT, 0, id);
wrapper.set(Type.INT, 0, id);
if (id == 2001) {
int replacedBlock = protocol.getItemRewriter().replace(packetWrapper.get(Type.INT, 1));
packetWrapper.set(Type.INT, 1, replacedBlock);
int replacedBlock = protocol.getItemRewriter().handleBlockId(wrapper.get(Type.INT, 1));
wrapper.set(Type.INT, 1, replacedBlock);
}
});
}
});
//Particle
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_PARTICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
handler(packetWrapper -> {
int type = packetWrapper.get(Type.INT, 0);
handler(wrapper -> {
int type = wrapper.get(Type.INT, 0);
if (type > 41 && !ViaRewind.getConfig().isReplaceParticles()) {
packetWrapper.cancel();
wrapper.cancel();
return;
}
if (type == 42) { // Dragon Breath
packetWrapper.set(Type.INT, 0, 24); // Portal
wrapper.set(Type.INT, 0, 24); // Portal
} else if (type == 43) { // End Rod
packetWrapper.set(Type.INT, 0, 3); // Firework Spark
wrapper.set(Type.INT, 0, 3); // Firework Spark
} else if (type == 44) { // Damage Indicator
packetWrapper.set(Type.INT, 0, 34); // Heart
wrapper.set(Type.INT, 0, 34); // Heart
} else if (type == 45) { // Sweep Attack
packetWrapper.set(Type.INT, 0, 1); // Large Explosion
wrapper.set(Type.INT, 0, 1); // Large Explosion
}
});
}
});
//Map
protocol.registerClientbound(ClientboundPackets1_9.MAP_DATA, new PacketHandlers() {
@Override
public void register() {
@@ -287,25 +248,19 @@ public class WorldPackets {
}
});
//Combat Event
//World Border
//Update Time
//Update Sign
//Sound Effects
protocol.registerClientbound(ClientboundPackets1_9.SOUND, ClientboundPackets1_8.NAMED_SOUND, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int soundId = packetWrapper.read(Type.VAR_INT);
String sound = SoundRemapper.oldNameFromId(soundId);
if (sound == null) {
packetWrapper.cancel();
handler(wrapper -> {
final int soundId = wrapper.read(Type.VAR_INT);
final String soundName = protocol.getMappingData().soundName(soundId);
if (soundName == null) {
wrapper.cancel();
} else {
packetWrapper.write(Type.STRING, sound);
wrapper.write(Type.STRING, protocol.getMappingData().getMappedNamedSound(soundName));
}
});
handler(packetWrapper -> packetWrapper.read(Type.VAR_INT));
read(Type.VAR_INT);
map(Type.INT);
map(Type.INT);
map(Type.INT);
@@ -1,314 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.rewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.api.rewriter.Replacement;
import com.viaversion.viarewind.api.rewriter.ReplacementItemRewriter;
import com.viaversion.viarewind.utils.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
import java.util.ArrayList;
import java.util.List;
import static com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter.potionNameFromDamage;
public class ReplacementItemRewriter1_8 extends ReplacementItemRewriter<Protocol1_8To1_9> {
public final static String VIA_REWIND_TAG_KEY = "ViaRewind1_8to1_9";
public ReplacementItemRewriter1_8(Protocol1_8To1_9 protocol) {
super(protocol, ProtocolVersion.v1_9);
}
@Override
public void register() {
registerItem(198, new Replacement(50, 0, "End Rod"));
registerItem(434, new Replacement(391, "Beetroot"));
registerItem(435, new Replacement(361, "Beetroot Seeds"));
registerItem(436, new Replacement(282, "Beetroot Soup"));
registerItem(432, new Replacement(322, "Chorus Fruit"));
registerItem(433, new Replacement(393, "Popped Chorus Fruit"));
registerItem(437, new Replacement(373, "Dragons Breath"));
registerItem(443, new Replacement(299, "Elytra"));
registerItem(426, new Replacement(410, "End Crystal"));
registerItem(442, new Replacement(425, "Shield"));
registerItem(439, new Replacement(262, "Spectral Arrow"));
registerItem(440, new Replacement(262, "Tipped Arrow"));
registerItem(444, new Replacement(333, "Spruce Boat"));
registerItem(445, new Replacement(333, "Birch Boat"));
registerItem(446, new Replacement(333, "Jungle Boat"));
registerItem(447, new Replacement(333, "Acacia Boat"));
registerItem(448, new Replacement(333, "Dark Oak Boat"));
registerItem(204, new Replacement(43, 7, "Purpur Double Slab"));
registerItem(205, new Replacement(44, 7, "Purpur Slab"));
registerBlock(209, new Replacement(119));
registerBlock(198, 0, new Replacement(50, 5));
registerBlock(198, 1, new Replacement(50, 5));
registerBlock(198, 2, new Replacement(50, 4));
registerBlock(198, 3, new Replacement(50, 3));
registerBlock(198, 4, new Replacement(50, 2));
registerBlock(198, 5, new Replacement(50, 1));
registerBlock(204, new Replacement(43, 7));
registerBlock(205, 0, new Replacement(44, 7));
registerBlock(205, 8, new Replacement(44, 15));
registerBlock(207, new Replacement(141));
registerBlock(137, new Replacement(137, 0));
registerItemBlock(199, new Replacement(35, 10, "Chorus Plant"));
registerItemBlock(200, new Replacement(35, 2, "Chorus Flower"));
registerItemBlock(201, new Replacement(155, 0, "Purpur Block"));
registerItemBlock(202, new Replacement(155, 2, "Purpur Pillar"));
registerItemBlock(203, 0, new Replacement(156, 0, "Purpur Stairs"));
registerItemBlock(203, 1, new Replacement(156, 1, "Purpur Stairs"));
registerItemBlock(203, 2, new Replacement(156, 2, "Purpur Stairs"));
registerItemBlock(203, 3, new Replacement(156, 3, "Purpur Stairs"));
registerItemBlock(203, 4, new Replacement(156, 4, "Purpur Stairs"));
registerItemBlock(203, 5, new Replacement(156, 5, "Purpur Stairs"));
registerItemBlock(203, 6, new Replacement(156, 6, "Purpur Stairs"));
registerItemBlock(203, 7, new Replacement(156, 7, "Purpur Stairs"));
registerItemBlock(203, 8, new Replacement(156, 8, "Purpur Stairs"));
registerItemBlock(206, new Replacement(121, 0, "Endstone Bricks"));
registerItemBlock(207, new Replacement(141, "Beetroot Block"));
registerItemBlock(208, new Replacement(2, 0, "Grass Path"));
registerItemBlock(209, new Replacement(90, "End Gateway"));
registerItemBlock(210, new Replacement(137, 0, "Repeating Command Block"));
registerItemBlock(211, new Replacement(137, 0, "Chain Command Block"));
registerItemBlock(212, new Replacement(79, 0, "Frosted Ice"));
registerItemBlock(214, new Replacement(87, 0, "Nether Wart Block"));
registerItemBlock(215, new Replacement(112, 0, "Red Nether Brick"));
registerItemBlock(217, new Replacement(166, 0, "Structure Void"));
registerItemBlock(255, new Replacement(137, 0, "Structure Block"));
registerItemBlock(397, 5, new Replacement(397, 0, "Dragon Head"));
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null) item.setTag(tag = new CompoundTag());
CompoundTag viaVersionTag = new CompoundTag();
tag.put(VIA_REWIND_TAG_KEY, viaVersionTag);
viaVersionTag.put("id", new ShortTag((short) item.identifier()));
viaVersionTag.put("data", new ShortTag(item.data()));
CompoundTag display = tag.get("display");
if (display != null && display.contains("Name")) {
viaVersionTag.put("displayName", new StringTag((String) display.get("Name").getValue()));
}
if (display != null && display.contains("Lore")) {
viaVersionTag.put("lore", new ListTag(((ListTag) display.get("Lore")).getValue()));
}
if (tag.contains("ench") || tag.contains("StoredEnchantments")) {
ListTag enchTag = tag.contains("ench") ? tag.get("ench") : tag.get("StoredEnchantments");
List<Tag> lore = new ArrayList<>();
for (Tag ench : new ArrayList<>(enchTag.getValue())) {
short id = ((NumberTag) ((CompoundTag) ench).get("id")).asShort();
short lvl = ((NumberTag) ((CompoundTag) ench).get("lvl")).asShort();
String s;
if (id == 70) {
s = "§r§7Mending ";
} else if (id == 9) {
s = "§r§7Frost Walker ";
} else {
continue;
}
enchTag.remove(ench);
s += Enchantments.ENCHANTMENTS.getOrDefault(lvl, "enchantment.level." + lvl);
lore.add(new StringTag(s));
}
if (!lore.isEmpty()) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
lore.addAll(loreTag.getValue());
loreTag.setValue(lore);
}
}
if (item.data() != 0 && tag.contains("Unbreakable")) {
ByteTag unbreakable = tag.get("Unbreakable");
if (unbreakable.asByte() != 0) {
viaVersionTag.put("Unbreakable", new ByteTag(unbreakable.asByte()));
tag.remove("Unbreakable");
if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
loreTag.add(new StringTag("§9Unbreakable"));
}
}
if (tag.contains("AttributeModifiers")) {
viaVersionTag.put("AttributeModifiers", tag.get("AttributeModifiers").copy());
}
if (item.identifier() == 383 && item.data() == 0) {
int data = 0;
if (tag.contains("EntityTag")) {
CompoundTag entityTag = tag.get("EntityTag");
if (entityTag.contains("id")) {
StringTag id = entityTag.get("id");
if (ItemRewriter.ENTITY_NAME_TO_ID.containsKey(id.getValue())) {
data = ItemRewriter.ENTITY_NAME_TO_ID.get(id.getValue());
} else if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
display.put("Name", new StringTag("§rSpawn " + id.getValue()));
}
}
}
item.setData((short) data);
}
replace(item);
if (item.identifier() == 373 || item.identifier() == 438 || item.identifier() == 441) {
int data = 0;
if (tag.contains("Potion")) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (PotionMappings.POTION_NAME_TO_ID.containsKey(potionName)) {
data = PotionMappings.POTION_NAME_TO_ID.get(potionName);
}
if (item.identifier() == 438) potionName += "_splash";
else if (item.identifier() == 441) potionName += "_lingering";
if ((display == null || !display.contains("Name")) && PotionMappings.POTION_NAME_INDEX.containsKey(potionName)) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
display.put("Name", new StringTag(PotionMappings.POTION_NAME_INDEX.get(potionName)));
}
}
if (item.identifier() == 438 || item.identifier() == 441) {
item.setIdentifier(373);
data += 8192;
}
item.setData((short) data);
}
if (tag.contains("AttributeModifiers")) {
ListTag attributes = tag.get("AttributeModifiers");
for (int i = 0; i < attributes.size(); i++) {
CompoundTag attribute = attributes.get(i);
String name = (String) attribute.get("AttributeName").getValue();
if (!Protocol1_8To1_9.VALID_ATTRIBUTES.contains(name)) {
attributes.remove(attribute);
i--;
}
}
}
if (viaVersionTag.size() == 2 && (short) viaVersionTag.get("id").getValue() == item.identifier() && (short) viaVersionTag.get("data").getValue() == item.data()) {
item.tag().remove(VIA_REWIND_TAG_KEY);
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (item.identifier() == 383 && item.data() != 0) {
if (tag == null) item.setTag(tag = new CompoundTag());
if (!tag.contains("EntityTag") && ItemRewriter.ENTITY_ID_TO_NAME.containsKey((int) item.data())) {
CompoundTag entityTag = new CompoundTag();
entityTag.put("id", new StringTag(ItemRewriter.ENTITY_ID_TO_NAME.get((int) item.data())));
tag.put("EntityTag", entityTag);
}
item.setData((short) 0);
}
if (item.identifier() == 373 && (tag == null || !tag.contains("Potion"))) {
if (tag == null) item.setTag(tag = new CompoundTag());
if (item.data() >= 16384) {
item.setIdentifier(438);
item.setData((short) (item.data() - 8192));
}
String name = item.data() == 8192 ? "water" : potionNameFromDamage(item.data());
tag.put("Potion", new StringTag("minecraft:" + name));
item.setData((short) 0);
}
if (tag == null || !item.tag().contains("ViaRewind1_8to1_9")) return item;
CompoundTag viaVersionTag = tag.remove("ViaRewind1_8to1_9");
item.setIdentifier((short) viaVersionTag.get("id").getValue());
item.setData((Short) viaVersionTag.get("data").getValue());
if (viaVersionTag.contains("noDisplay")) tag.remove("display");
if (viaVersionTag.contains("Unbreakable")) {
tag.put("Unbreakable", viaVersionTag.get("Unbreakable").copy());
}
if (viaVersionTag.contains("displayName")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
StringTag name = display.get("Name");
if (name == null) display.put("Name", new StringTag((String) viaVersionTag.get("displayName").getValue()));
else name.setValue((String) viaVersionTag.get("displayName").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Name");
}
if (viaVersionTag.contains("lore")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
ListTag lore = display.get("Lore");
if (lore == null) display.put("Lore", new ListTag((List<Tag>) viaVersionTag.get("lore").getValue()));
else lore.setValue((List<Tag>) viaVersionTag.get("lore").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Lore");
}
tag.remove("AttributeModifiers");
if (viaVersionTag.contains("AttributeModifiers")) {
tag.put("AttributeModifiers", viaVersionTag.get("AttributeModifiers"));
}
return item;
}
}
@@ -1,885 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.sound;
import java.util.HashMap;
public class SoundRemapper {
private final static HashMap<Integer, String> sounds1_9 = new HashMap<>();
private final static HashMap<String, String> sound1_9to1_8 = new HashMap<>();
private static int id;
private static void register1_9Sound(String sound1_9) {
sounds1_9.put(id++, sound1_9);
}
private static void registerSoundRemapping(String sound1_9, String sound1_8) {
sound1_9to1_8.put(sound1_9, sound1_8);
}
public static String oldNameFromId(int id) {
String sound1_9 = sounds1_9.get(id);
if (sound1_9 == null) return null;
return getOldName(sound1_9);
}
public static String getOldName(String sound1_9) {
return sound1_9to1_8.getOrDefault(sound1_9, sound1_9);
}
static {
registerSoundRemapping("entity.zombie_horse.ambient", "mob.horse.zombie.idle");
registerSoundRemapping("block.note.snare", "note.snare");
registerSoundRemapping("block.wood_button.click_off", "random.wood_click");
registerSoundRemapping("block.wood_button.click_on", "random.wood_click");
registerSoundRemapping("block.gravel.break", "dig.gravel");
registerSoundRemapping("block.gravel.place", "dig.gravel");
registerSoundRemapping("entity.arrow.hit", "random.bowhit");
registerSoundRemapping("block.tripwire.detach", "random.bowhit");
registerSoundRemapping("entity.splash_potion.break", "dig.glass");
registerSoundRemapping("block.glass.break", "dig.glass");
registerSoundRemapping("entity.zombie.ambient", "mob.zombie.say");
registerSoundRemapping("entity.zombie_villager.ambient", "mob.zombie.say");
registerSoundRemapping("entity.pig.death", "mob.pig.death");
registerSoundRemapping("entity.mule.hurt", "mob.horse.donkey.hit");
registerSoundRemapping("entity.donkey.hurt", "mob.horse.donkey.hit");
registerSoundRemapping("entity.endermen.ambient", "mob.endermen.idle");
registerSoundRemapping("block.portal.ambient", "portal.portal");
registerSoundRemapping("entity.generic.burn", "random.fizz");
registerSoundRemapping("block.fire.extinguish", "random.fizz");
registerSoundRemapping("block.redstone_torch.burnout", "random.fizz");
registerSoundRemapping("block.lava.extinguish", "random.fizz");
registerSoundRemapping("entity.generic.extinguish_fire", "random.fizz");
registerSoundRemapping("block.note.harp", "note.harp");
registerSoundRemapping("block.snow.hit", "step.snow");
registerSoundRemapping("block.snow.fall", "step.snow");
registerSoundRemapping("block.snow.step", "step.snow");
registerSoundRemapping("entity.arrow.hit_player", "random.successful_hit");
registerSoundRemapping("entity.zombie_pig.hurt", "mob.zombiepig.zpighurt");
registerSoundRemapping("entity.wolf.howl", "mob.wolf.howl");
registerSoundRemapping("entity.firework.launch", "fireworks.launch");
registerSoundRemapping("entity.cow.hurt", "mob.cow.hurt");
registerSoundRemapping("entity.cow.death", "mob.cow.hurt");
registerSoundRemapping("entity.firework.large_blast", "fireworks.largeBlast");
registerSoundRemapping("entity.blaze.hurt", "mob.blaze.hit");
registerSoundRemapping("entity.villager.death", "mob.villager.death");
registerSoundRemapping("entity.blaze.death", "mob.blaze.death");
registerSoundRemapping("entity.zombie_horse.death", "mob.horse.zombie.death");
registerSoundRemapping("entity.silverfish.death", "mob.silverfish.kill");
registerSoundRemapping("entity.endermite.death", "mob.silverfish.kill");
registerSoundRemapping("record.ward", "records.ward");
registerSoundRemapping("entity.wolf.pant", "mob.wolf.panting");
registerSoundRemapping("block.metal.break", "dig.stone");
registerSoundRemapping("block.metal.place", "dig.stone");
registerSoundRemapping("entity.armorstand.place", "dig.stone");
registerSoundRemapping("block.stone.break", "dig.stone");
registerSoundRemapping("block.stone.place", "dig.stone");
registerSoundRemapping("block.anvil.break", "dig.stone");
registerSoundRemapping("block.glass.place", "dig.stone");
registerSoundRemapping("entity.endermen.stare", "mob.endermen.stare");
registerSoundRemapping("entity.small_magmacube.hurt", "mob.slime.small");
registerSoundRemapping("block.slime.fall", "mob.slime.small");
registerSoundRemapping("entity.small_slime.death", "mob.slime.small");
registerSoundRemapping("block.slime.step", "mob.slime.small");
registerSoundRemapping("entity.small_magmacube.death", "mob.slime.small");
registerSoundRemapping("entity.small_slime.hurt", "mob.slime.small");
registerSoundRemapping("block.slime.hit", "mob.slime.small");
registerSoundRemapping("music.nether", "music.game.nether");
registerSoundRemapping("entity.ghast.death", "mob.ghast.death");
registerSoundRemapping("entity.guardian.attack", "mob.guardian.attack");
registerSoundRemapping("block.dispenser.fail", "random.click");
registerSoundRemapping("block.comparator.click", "random.click");
registerSoundRemapping("block.stone_button.click_on", "random.click");
registerSoundRemapping("block.stone_button.click_off", "random.click");
registerSoundRemapping("block.tripwire.click_on", "random.click");
registerSoundRemapping("block.dispenser.dispense", "random.click");
registerSoundRemapping("ui.button.click", "random.click");
registerSoundRemapping("block.lever.click", "random.click");
registerSoundRemapping("block.tripwire.attach", "random.click");
registerSoundRemapping("block.stone_pressureplate.click_on", "random.click");
registerSoundRemapping("block.wood_pressureplate.click_off", "random.click");
registerSoundRemapping("block.stone_pressureplate.click_off", "random.click");
registerSoundRemapping("block.metal_pressureplate.click_off", "random.click");
registerSoundRemapping("block.tripwire.click_off", "random.click");
registerSoundRemapping("block.metal_pressureplate.click_on", "random.click");
registerSoundRemapping("block.wood_pressureplate.click_on", "random.click");
registerSoundRemapping("entity.zombie_pig.ambient", "mob.zombiepig.zpig");
registerSoundRemapping("music.dragon", "music.game.end.dragon");
registerSoundRemapping("entity.firework.twinkle_far", "fireworks.twinkle_far");
registerSoundRemapping("entity.elder_guardian.ambient_land", "mob.guardian.land.idle");
registerSoundRemapping("entity.guardian.ambient_land", "mob.guardian.land.idle");
registerSoundRemapping("block.grass.break", "dig.grass");
registerSoundRemapping("block.grass.place", "dig.grass");
registerSoundRemapping("entity.skeleton.step", "mob.skeleton.step");
registerSoundRemapping("entity.wither.death", "mob.wither.death");
registerSoundRemapping("entity.wolf.hurt", "mob.wolf.hurt");
registerSoundRemapping("entity.pig.saddle", "mob.horse.leather");
registerSoundRemapping("entity.horse.saddle", "mob.horse.leather");
registerSoundRemapping("entity.bat.loop", "mob.bat.loop");
registerSoundRemapping("entity.ghast.hurt", "mob.ghast.scream");
registerSoundRemapping("entity.creeper.death", "mob.creeper.death");
registerSoundRemapping("entity.horse.gallop", "mob.horse.gallop");
registerSoundRemapping("entity.wither.spawn", "mob.wither.spawn");
registerSoundRemapping("entity.endermen.hurt", "mob.endermen.hit");
registerSoundRemapping("entity.creeper.hurt", "mob.creeper.say");
registerSoundRemapping("entity.horse.step_wood", "mob.horse.wood");
registerSoundRemapping("entity.rabbit.death", "mob.rabbit.death");
registerSoundRemapping("entity.zombie_villager.converted", "mob.zombie.unfect");
registerSoundRemapping("block.anvil.use", "random.anvil_use");
registerSoundRemapping("block.enderchest.close", "random.chestclosed");
registerSoundRemapping("entity.mooshroom.shear", "mob.sheep.shear");
registerSoundRemapping("entity.sheep.shear", "mob.sheep.shear");
registerSoundRemapping("entity.item.pickup", "random.pop");
registerSoundRemapping("entity.bat.death", "mob.bat.death");
registerSoundRemapping("block.wood.place", "dig.wood");
registerSoundRemapping("block.wood.break", "dig.wood");
registerSoundRemapping("block.ladder.place", "dig.wood");
registerSoundRemapping("entity.armorstand.fall", "dig.wood");
registerSoundRemapping("block.ladder.break", "dig.wood");
registerSoundRemapping("record.chirp", "records.chirp");
registerSoundRemapping("entity.mule.death", "mob.horse.donkey.death");
registerSoundRemapping("entity.donkey.death", "mob.horse.donkey.death");
registerSoundRemapping("entity.firework.blast", "fireworks.blast");
registerSoundRemapping("entity.zombie_pig.angry", "mob.zombiepig.zpigangry");
registerSoundRemapping("entity.guardian.flop", "mob.guardian.flop");
registerSoundRemapping("entity.villager.yes", "mob.villager.yes");
registerSoundRemapping("entity.ghast.warn", "mob.ghast.charge");
registerSoundRemapping("entity.tnt.primed", "creeper.primed");
registerSoundRemapping("entity.creeper.primed", "creeper.primed");
registerSoundRemapping("block.sand.place", "dig.sand");
registerSoundRemapping("block.sand.break", "dig.sand");
registerSoundRemapping("entity.chicken.ambient", "mob.chicken.say");
registerSoundRemapping("record.13", "records.13");
registerSoundRemapping("record.11", "records.11");
registerSoundRemapping("entity.elder_guardian.death", "mob.guardian.elder.death");
registerSoundRemapping("entity.firework.twinkle", "fireworks.twinkle");
registerSoundRemapping("entity.skeleton_horse.death", "mob.horse.skeleton.death");
registerSoundRemapping("weather.rain", "ambient.weather.rain");
registerSoundRemapping("weather.rain.above", "ambient.weather.rain");
registerSoundRemapping("block.portal.trigger", "portal.trigger");
registerSoundRemapping("block.enderchest.open", "random.chestopen");
registerSoundRemapping("entity.horse.land", "mob.horse.land");
registerSoundRemapping("entity.endermite.step", "mob.silverfish.step");
registerSoundRemapping("entity.silverfish.step", "mob.silverfish.step");
registerSoundRemapping("entity.bat.takeoff", "mob.bat.takeoff");
registerSoundRemapping("entity.villager.no", "mob.villager.no");
registerSoundRemapping("entity.irongolem.step", "mob.irongolem.walk");
registerSoundRemapping("block.note.hat", "note.hat");
registerSoundRemapping("entity.zombie.attack_iron_door", "mob.zombie.metal");
registerSoundRemapping("entity.villager.trading", "mob.villager.haggle");
registerSoundRemapping("item.firecharge.use", "mob.ghast.fireball");
registerSoundRemapping("entity.ghast.shoot", "mob.ghast.fireball");
registerSoundRemapping("entity.enderdragon.shoot", "mob.ghast.fireball");
registerSoundRemapping("entity.blaze.shoot", "mob.ghast.fireball");
registerSoundRemapping("music.credits", "music.game.end.credits");
registerSoundRemapping("entity.irongolem.death", "mob.irongolem.death");
registerSoundRemapping("entity.item.break", "random.break");
registerSoundRemapping("item.shield.break", "random.break");
registerSoundRemapping("record.mellohi", "records.mellohi");
registerSoundRemapping("entity.zombie_villager.cure", "mob.zombie.remedy");
registerSoundRemapping("entity.enderpearl.throw", "random.bow");
registerSoundRemapping("block.dispenser.launch", "random.bow");
registerSoundRemapping("entity.skeleton.shoot", "random.bow");
registerSoundRemapping("entity.endereye.launch", "random.bow");
registerSoundRemapping("entity.firework.shoot", "random.bow");
registerSoundRemapping("entity.experience_bottle.throw", "random.bow");
registerSoundRemapping("entity.snowman.shoot", "random.bow");
registerSoundRemapping("entity.arrow.shoot", "random.bow");
registerSoundRemapping("entity.egg.throw", "random.bow");
registerSoundRemapping("entity.snowball.throw", "random.bow");
registerSoundRemapping("entity.bobber.throw", "random.bow");
registerSoundRemapping("entity.lingeringpotion.throw", "random.bow");
registerSoundRemapping("entity.splash_potion.throw", "random.bow");
registerSoundRemapping("entity.villager.ambient", "mob.villager.idle");
registerSoundRemapping("block.cloth.hit", "step.cloth");
registerSoundRemapping("block.cloth.step", "step.cloth");
registerSoundRemapping("block.cloth.fall", "step.cloth");
registerSoundRemapping("entity.silverfish.hurt", "mob.silverfish.hit");
registerSoundRemapping("entity.endermite.hurt", "mob.silverfish.hit");
registerSoundRemapping("music.game", "music.game");
registerSoundRemapping("block.lava.ambient", "liquid.lava");
registerSoundRemapping("record.mall", "records.mall");
registerSoundRemapping("entity.blaze.burn", "fire.fire");
registerSoundRemapping("block.fire.ambient", "fire.fire");
registerSoundRemapping("entity.zombie.attack_door_wood", "mob.zombie.wood");
registerSoundRemapping("entity.chicken.step", "mob.chicken.step");
registerSoundRemapping("record.stal", "records.stal");
registerSoundRemapping("entity.elder_guardian.hurt_land", "mob.guardian.land.hit");
registerSoundRemapping("entity.guardian.hurt_land", "mob.guardian.land.hit");
registerSoundRemapping("entity.chicken.egg", "mob.chicken.plop");
registerSoundRemapping("entity.donkey.chest", "mob.chicken.plop");
registerSoundRemapping("entity.enderdragon.flap", "mob.enderdragon.wings");
registerSoundRemapping("block.grass.step", "step.grass");
registerSoundRemapping("block.grass.fall", "step.grass");
registerSoundRemapping("block.grass.hit", "step.grass");
registerSoundRemapping("entity.horse.breathe", "mob.horse.breathe");
registerSoundRemapping("entity.mule.ambient", "mob.horse.donkey.idle");
registerSoundRemapping("entity.donkey.ambient", "mob.horse.donkey.idle");
registerSoundRemapping("record.far", "records.far");
registerSoundRemapping("entity.spider.step", "mob.spider.step");
registerSoundRemapping("entity.cow.ambient", "mob.cow.say");
registerSoundRemapping("entity.horse.jump", "mob.horse.jump");
registerSoundRemapping("entity.horse.step", "mob.horse.soft");
registerSoundRemapping("entity.guardian.hurt", "mob.guardian.hit");
registerSoundRemapping("entity.enderdragon.death", "mob.enderdragon.end");
registerSoundRemapping("entity.zombie_villager.step", "mob.zombie.step");
registerSoundRemapping("entity.zombie.step", "mob.zombie.step");
registerSoundRemapping("entity.enderdragon.ambient", "mob.enderdragon.growl");
registerSoundRemapping("entity.enderdragon.growl", "mob.enderdragon.growl");
registerSoundRemapping("entity.wolf.shake", "mob.wolf.shake");
registerSoundRemapping("entity.endermen.death", "mob.endermen.death");
registerSoundRemapping("block.anvil.place", "random.anvil_land");
registerSoundRemapping("block.anvil.land", "random.anvil_land");
registerSoundRemapping("entity.minecart.inside", "minecart.inside");
registerSoundRemapping("entity.slime.squish", "mob.slime.big");
registerSoundRemapping("entity.magmacube.hurt", "mob.slime.big");
registerSoundRemapping("entity.magmacube.death", "mob.slime.big");
registerSoundRemapping("block.slime.break", "mob.slime.big");
registerSoundRemapping("block.slime.place", "mob.slime.big");
registerSoundRemapping("entity.slime.jump", "mob.slime.big");
registerSoundRemapping("entity.slime.hurt", "mob.slime.big");
registerSoundRemapping("entity.slime.death", "mob.slime.big");
registerSoundRemapping("block.water.ambient", "liquid.water");
registerSoundRemapping("entity.pig.hurt", "mob.pig.say");
registerSoundRemapping("entity.pig.ambient", "mob.pig.say");
registerSoundRemapping("entity.wither.shoot", "mob.wither.shoot");
registerSoundRemapping("record.blocks", "records.blocks");
registerSoundRemapping("item.firecharge.use", "item.fireCharge.use");
registerSoundRemapping("entity.ghast.shoot", "item.fireCharge.use");
registerSoundRemapping("entity.enderdragon.shoot", "item.fireCharge.use");
registerSoundRemapping("entity.blaze.shoot", "item.fireCharge.use");
registerSoundRemapping("block.sand.hit", "step.sand");
registerSoundRemapping("block.sand.step", "step.sand");
registerSoundRemapping("block.sand.fall", "step.sand");
registerSoundRemapping("music.creative", "music.game.creative");
registerSoundRemapping("entity.irongolem.hurt", "mob.irongolem.hit");
registerSoundRemapping("entity.horse.death", "mob.horse.death");
registerSoundRemapping("entity.bat.hurt", "mob.bat.hurt");
registerSoundRemapping("entity.ghast.scream", "mob.ghast.affectionate_scream");
registerSoundRemapping("entity.elder_guardian.ambient", "mob.guardian.elder.idle");
registerSoundRemapping("entity.zombie_pig.death", "mob.zombiepig.zpigdeath");
registerSoundRemapping("entity.lightning.thunder", "ambient.weather.thunder");
registerSoundRemapping("entity.minecart.riding", "minecart.base");
registerSoundRemapping("block.ladder.step", "step.ladder");
registerSoundRemapping("block.ladder.fall", "step.ladder");
registerSoundRemapping("block.ladder.hit", "step.ladder");
registerSoundRemapping("entity.donkey.angry", "mob.horse.donkey.angry");
registerSoundRemapping("ambient.cave", "ambient.cave.cave");
registerSoundRemapping("record.wait", "records.wait");
registerSoundRemapping("entity.firework.blast_far", "fireworks.blast_far");
registerSoundRemapping("entity.generic.drink", "random.drink");
registerSoundRemapping("music.menu", "music.menu");
registerSoundRemapping("entity.cat.hiss", "mob.cat.hiss");
registerSoundRemapping("block.note.basedrum", "note.bd");
registerSoundRemapping("entity.spider.ambient", "mob.spider.say");
registerSoundRemapping("entity.spider.hurt", "mob.spider.say");
registerSoundRemapping("block.stone.fall", "step.stone");
registerSoundRemapping("block.anvil.fall", "step.stone");
registerSoundRemapping("block.metal.step", "step.stone");
registerSoundRemapping("block.stone.hit", "step.stone");
registerSoundRemapping("block.glass.fall", "step.stone");
registerSoundRemapping("block.stone.step", "step.stone");
registerSoundRemapping("block.anvil.step", "step.stone");
registerSoundRemapping("block.metal.hit", "step.stone");
registerSoundRemapping("block.glass.step", "step.stone");
registerSoundRemapping("block.metal.fall", "step.stone");
registerSoundRemapping("block.glass.hit", "step.stone");
registerSoundRemapping("block.anvil.hit", "step.stone");
registerSoundRemapping("entity.player.levelup", "random.levelup");
registerSoundRemapping("block.lava.pop", "liquid.lavapop");
registerSoundRemapping("entity.sheep.hurt", "mob.sheep.say");
registerSoundRemapping("entity.sheep.death", "mob.sheep.say");
registerSoundRemapping("entity.sheep.ambient", "mob.sheep.say");
registerSoundRemapping("entity.skeleton.ambient", "mob.skeleton.say");
registerSoundRemapping("entity.blaze.ambient", "mob.blaze.breathe");
registerSoundRemapping("entity.bat.ambient", "mob.bat.idle");
registerSoundRemapping("entity.magmacube.squish", "mob.magmacube.big");
registerSoundRemapping("entity.horse.ambient", "mob.horse.idle");
registerSoundRemapping("entity.zombie_horse.hurt", "mob.horse.zombie.hit");
registerSoundRemapping("entity.irongolem.attack", "mob.irongolem.throw");
registerSoundRemapping("block.cloth.break", "dig.cloth");
registerSoundRemapping("block.cloth.place", "dig.cloth");
registerSoundRemapping("block.gravel.fall", "step.gravel");
registerSoundRemapping("block.gravel.step", "step.gravel");
registerSoundRemapping("block.gravel.hit", "step.gravel");
registerSoundRemapping("entity.endermite.ambient", "mob.silverfish.say");
registerSoundRemapping("entity.silverfish.ambient", "mob.silverfish.say");
registerSoundRemapping("entity.cat.purr", "mob.cat.purr");
registerSoundRemapping("entity.zombie.infect", "mob.zombie.infect");
registerSoundRemapping("entity.generic.eat", "random.eat");
registerSoundRemapping("entity.wolf.ambient", "mob.wolf.bark");
registerSoundRemapping("entity.tnt.primed", "game.tnt.primed");
registerSoundRemapping("entity.creeper.primed", "game.tnt.primed");
registerSoundRemapping("entity.sheep.step", "mob.sheep.step");
registerSoundRemapping("entity.zombie_villager.death", "mob.zombie.death");
registerSoundRemapping("entity.zombie.death", "mob.zombie.death");
registerSoundRemapping("entity.shulker.teleport", "mob.endermen.portal");
registerSoundRemapping("item.chorus_fruit.teleport", "mob.endermen.portal");
registerSoundRemapping("entity.endermen.teleport", "mob.endermen.portal");
registerSoundRemapping("entity.horse.angry", "mob.horse.angry");
registerSoundRemapping("entity.wolf.growl", "mob.wolf.growl");
registerSoundRemapping("block.snow.break", "dig.snow");
registerSoundRemapping("block.snow.place", "dig.snow");
registerSoundRemapping("block.piston.extend", "tile.piston.out");
registerSoundRemapping("entity.player.burp", "random.burp");
registerSoundRemapping("entity.cow.step", "mob.cow.step");
registerSoundRemapping("entity.wither.hurt", "mob.wither.hurt");
registerSoundRemapping("entity.guardian.death_land", "mob.guardian.land.death");
registerSoundRemapping("entity.elder_guardian.death_land", "mob.guardian.land.death");
registerSoundRemapping("music.end", "music.game.end");
registerSoundRemapping("entity.chicken.hurt", "mob.chicken.hurt");
registerSoundRemapping("entity.chicken.death", "mob.chicken.hurt");
registerSoundRemapping("entity.wolf.step", "mob.wolf.step");
registerSoundRemapping("entity.wolf.death", "mob.wolf.death");
registerSoundRemapping("entity.wolf.whine", "mob.wolf.whine");
registerSoundRemapping("block.note.pling", "note.pling");
registerSoundRemapping("entity.rabbit.hurt", "mob.rabbit.hurt");
registerSoundRemapping("entity.cat.purreow", "mob.cat.purreow");
registerSoundRemapping("entity.firework.large_blast_far", "fireworks.largeBlast_far");
registerSoundRemapping("entity.skeleton.hurt", "mob.skeleton.hurt");
registerSoundRemapping("entity.spider.death", "mob.spider.death");
registerSoundRemapping("block.anvil.destroy", "random.anvil_break");
registerSoundRemapping("record.cat", "records.cat");
registerSoundRemapping("entity.wither.ambient", "mob.wither.idle");
registerSoundRemapping("entity.elder_guardian.hurt", "mob.guardian.elder.hit");
registerSoundRemapping("entity.endermen.scream", "mob.endermen.scream");
registerSoundRemapping("entity.cat.death", "mob.cat.hitt");
registerSoundRemapping("entity.cat.hurt", "mob.cat.hitt");
registerSoundRemapping("entity.small_magmacube.squish", "mob.magmacube.small");
registerSoundRemapping("item.flintandsteel.use", "fire.ignite");
registerSoundRemapping("entity.enderdragon.hurt", "mob.enderdragon.hit");
registerSoundRemapping("entity.zombie.hurt", "mob.zombie.hurt");
registerSoundRemapping("entity.zombie_villager.hurt", "mob.zombie.hurt");
registerSoundRemapping("entity.enderdragon_fireball.explode", "random.explode");
registerSoundRemapping("entity.generic.explode", "random.explode");
registerSoundRemapping("entity.lightning.impact", "random.explode");
registerSoundRemapping("block.end_gateway.spawn", "random.explode");
registerSoundRemapping("entity.slime.attack", "mob.slime.attack");
registerSoundRemapping("entity.magmacube.jump", "mob.magmacube.jump");
registerSoundRemapping("entity.bobber.splash", "random.splash");
registerSoundRemapping("entity.skeleton_horse.hurt", "mob.horse.skeleton.hit");
registerSoundRemapping("entity.rabbit.jump", "mob.rabbit.hop");
registerSoundRemapping("entity.ghast.ambient", "mob.ghast.moan");
registerSoundRemapping("entity.elder_guardian.curse", "mob.guardian.curse");
registerSoundRemapping("entity.splash_potion.break", "game.potion.smash");
registerSoundRemapping("block.glass.break", "game.potion.smash");
registerSoundRemapping("block.note.bass", "note.bassattack");
registerSoundRemapping("block.dispenser.fail", "gui.button.press");
registerSoundRemapping("block.comparator.click", "gui.button.press");
registerSoundRemapping("block.stone_button.click_on", "gui.button.press");
registerSoundRemapping("block.stone_button.click_off", "gui.button.press");
registerSoundRemapping("block.tripwire.click_on", "gui.button.press");
registerSoundRemapping("block.dispenser.dispense", "gui.button.press");
registerSoundRemapping("ui.button.click", "gui.button.press");
registerSoundRemapping("block.lever.click", "gui.button.press");
registerSoundRemapping("block.tripwire.attach", "gui.button.press");
registerSoundRemapping("block.stone_pressureplate.click_on", "gui.button.press");
registerSoundRemapping("block.wood_pressureplate.click_off", "gui.button.press");
registerSoundRemapping("block.stone_pressureplate.click_off", "gui.button.press");
registerSoundRemapping("block.metal_pressureplate.click_off", "gui.button.press");
registerSoundRemapping("block.tripwire.click_off", "gui.button.press");
registerSoundRemapping("block.metal_pressureplate.click_on", "gui.button.press");
registerSoundRemapping("block.wood_pressureplate.click_on", "gui.button.press");
registerSoundRemapping("entity.experience_orb.touch", "random.orb");
registerSoundRemapping("entity.experience_orb.pickup", "random.orb");
registerSoundRemapping("entity.wither.break_block", "mob.zombie.woodbreak");
registerSoundRemapping("entity.zombie.break_door_wood", "mob.zombie.woodbreak");
registerSoundRemapping("entity.horse.armor", "mob.horse.armor");
registerSoundRemapping("entity.rabbit.ambient", "mob.rabbit.idle");
registerSoundRemapping("block.piston.contract", "tile.piston.in");
registerSoundRemapping("entity.cat.ambient", "mob.cat.meow");
registerSoundRemapping("entity.pig.step", "mob.pig.step");
registerSoundRemapping("record.strad", "records.strad");
registerSoundRemapping("block.wood.hit", "step.wood");
registerSoundRemapping("block.wood.fall", "step.wood");
registerSoundRemapping("block.wood.step", "step.wood");
registerSoundRemapping("block.portal.travel", "portal.travel");
registerSoundRemapping("entity.guardian.death", "mob.guardian.death");
registerSoundRemapping("entity.skeleton.death", "mob.skeleton.death");
registerSoundRemapping("entity.horse.hurt", "mob.horse.hit");
registerSoundRemapping("entity.villager.hurt", "mob.villager.hit");
registerSoundRemapping("entity.skeleton_horse.ambient", "mob.horse.skeleton.idle");
registerSoundRemapping("block.chest.open", "random.chestopen");
registerSoundRemapping("block.chest.close", "random.chestclosed");
registerSoundRemapping("entity.player.hurt_on_fire", "game.player.hurt");
registerSoundRemapping("entity.player.hurt_drown", "game.player.hurt");
registerSoundRemapping("entity.generic.swim", "game.neutral.swim");
registerSoundRemapping("entity.hostile.swim", "game.hostile.swim");
registerSoundRemapping("entity.player.swim", "game.player.swim");
registerSoundRemapping("entity.player.splash", "game.player.swim.splash");
registerSoundRemapping("entity.hostile.splash", "game.hostile.swim.splash");
registerSoundRemapping("entity.generic.splash", "game.neutral.swim.splash");
registerSoundRemapping("entity.generic.death", "game.neutral.die");
registerSoundRemapping("entity.hostile.hurt", "game.hostile.hurt");
registerSoundRemapping("entity.player.hurt", "game.player.hurt");
registerSoundRemapping("entity.hostile.death", "game.hostile.die");
registerSoundRemapping("entity.generic.hurt", "game.neutral.hurt");
registerSoundRemapping("entity.player.death", "game.player.die");
registerSoundRemapping("entity.player.big_fall", "game.player.hurt.fall.big");
registerSoundRemapping("entity.generic.big_fall", "game.neutral.hurt.fall.big");
registerSoundRemapping("entity.hostile.big_fall", "game.hostile.hurt.fall.big");
registerSoundRemapping("entity.hostile.small_fall", "game.hostile.hurt.fall.small");
registerSoundRemapping("entity.player.small_fall", "game.player.hurt.fall.small");
registerSoundRemapping("entity.generic.small_fall", "game.neutral.hurt.fall.small");
register1_9Sound("ambient.cave");
register1_9Sound("block.anvil.break");
register1_9Sound("block.anvil.destroy");
register1_9Sound("block.anvil.fall");
register1_9Sound("block.anvil.hit");
register1_9Sound("block.anvil.land");
register1_9Sound("block.anvil.place");
register1_9Sound("block.anvil.step");
register1_9Sound("block.anvil.use");
register1_9Sound("block.brewing_stand.brew");
register1_9Sound("block.chest.close");
register1_9Sound("block.chest.locked");
register1_9Sound("block.chest.open");
register1_9Sound("block.chorus_flower.death");
register1_9Sound("block.chorus_flower.grow");
register1_9Sound("block.cloth.break");
register1_9Sound("block.cloth.fall");
register1_9Sound("block.cloth.hit");
register1_9Sound("block.cloth.place");
register1_9Sound("block.cloth.step");
register1_9Sound("block.comparator.click");
register1_9Sound("block.dispenser.dispense");
register1_9Sound("block.dispenser.fail");
register1_9Sound("block.dispenser.launch");
register1_9Sound("block.end_gateway.spawn");
register1_9Sound("block.enderchest.close");
register1_9Sound("block.enderchest.open");
register1_9Sound("block.fence_gate.close");
register1_9Sound("block.fence_gate.open");
register1_9Sound("block.fire.ambient");
register1_9Sound("block.fire.extinguish");
register1_9Sound("block.furnace.fire_crackle");
register1_9Sound("block.glass.break");
register1_9Sound("block.glass.fall");
register1_9Sound("block.glass.hit");
register1_9Sound("block.glass.place");
register1_9Sound("block.glass.step");
register1_9Sound("block.grass.break");
register1_9Sound("block.grass.fall");
register1_9Sound("block.grass.hit");
register1_9Sound("block.grass.place");
register1_9Sound("block.grass.step");
register1_9Sound("block.gravel.break");
register1_9Sound("block.gravel.fall");
register1_9Sound("block.gravel.hit");
register1_9Sound("block.gravel.place");
register1_9Sound("block.gravel.step");
register1_9Sound("block.iron_door.close");
register1_9Sound("block.iron_door.open");
register1_9Sound("block.iron_trapdoor.close");
register1_9Sound("block.iron_trapdoor.open");
register1_9Sound("block.ladder.break");
register1_9Sound("block.ladder.fall");
register1_9Sound("block.ladder.hit");
register1_9Sound("block.ladder.place");
register1_9Sound("block.ladder.step");
register1_9Sound("block.lava.ambient");
register1_9Sound("block.lava.extinguish");
register1_9Sound("block.lava.pop");
register1_9Sound("block.lever.click");
register1_9Sound("block.metal.break");
register1_9Sound("block.metal.fall");
register1_9Sound("block.metal.hit");
register1_9Sound("block.metal.place");
register1_9Sound("block.metal.step");
register1_9Sound("block.metal_pressureplate.click_off");
register1_9Sound("block.metal_pressureplate.click_on");
register1_9Sound("block.note.basedrum");
register1_9Sound("block.note.bass");
register1_9Sound("block.note.harp");
register1_9Sound("block.note.hat");
register1_9Sound("block.note.pling");
register1_9Sound("block.note.snare");
register1_9Sound("block.piston.contract");
register1_9Sound("block.piston.extend");
register1_9Sound("block.portal.ambient");
register1_9Sound("block.portal.travel");
register1_9Sound("block.portal.trigger");
register1_9Sound("block.redstone_torch.burnout");
register1_9Sound("block.sand.break");
register1_9Sound("block.sand.fall");
register1_9Sound("block.sand.hit");
register1_9Sound("block.sand.place");
register1_9Sound("block.sand.step");
register1_9Sound("block.slime.break");
register1_9Sound("block.slime.fall");
register1_9Sound("block.slime.hit");
register1_9Sound("block.slime.place");
register1_9Sound("block.slime.step");
register1_9Sound("block.snow.break");
register1_9Sound("block.snow.fall");
register1_9Sound("block.snow.hit");
register1_9Sound("block.snow.place");
register1_9Sound("block.snow.step");
register1_9Sound("block.stone.break");
register1_9Sound("block.stone.fall");
register1_9Sound("block.stone.hit");
register1_9Sound("block.stone.place");
register1_9Sound("block.stone.step");
register1_9Sound("block.stone_button.click_off");
register1_9Sound("block.stone_button.click_on");
register1_9Sound("block.stone_pressureplate.click_off");
register1_9Sound("block.stone_pressureplate.click_on");
register1_9Sound("block.tripwire.attach");
register1_9Sound("block.tripwire.click_off");
register1_9Sound("block.tripwire.click_on");
register1_9Sound("block.tripwire.detach");
register1_9Sound("block.water.ambient");
register1_9Sound("block.waterlily.place");
register1_9Sound("block.wood.break");
register1_9Sound("block.wood.fall");
register1_9Sound("block.wood.hit");
register1_9Sound("block.wood.place");
register1_9Sound("block.wood.step");
register1_9Sound("block.wood_button.click_off");
register1_9Sound("block.wood_button.click_on");
register1_9Sound("block.wood_pressureplate.click_off");
register1_9Sound("block.wood_pressureplate.click_on");
register1_9Sound("block.wooden_door.close");
register1_9Sound("block.wooden_door.open");
register1_9Sound("block.wooden_trapdoor.close");
register1_9Sound("block.wooden_trapdoor.open");
register1_9Sound("enchant.thorns.hit");
register1_9Sound("entity.armorstand.break");
register1_9Sound("entity.armorstand.fall");
register1_9Sound("entity.armorstand.hit");
register1_9Sound("entity.armorstand.place");
register1_9Sound("entity.arrow.hit");
register1_9Sound("entity.arrow.hit_player");
register1_9Sound("entity.arrow.shoot");
register1_9Sound("entity.bat.ambient");
register1_9Sound("entity.bat.death");
register1_9Sound("entity.bat.hurt");
register1_9Sound("entity.bat.loop");
register1_9Sound("entity.bat.takeoff");
register1_9Sound("entity.blaze.ambient");
register1_9Sound("entity.blaze.burn");
register1_9Sound("entity.blaze.death");
register1_9Sound("entity.blaze.hurt");
register1_9Sound("entity.blaze.shoot");
register1_9Sound("entity.bobber.splash");
register1_9Sound("entity.bobber.throw");
register1_9Sound("entity.cat.ambient");
register1_9Sound("entity.cat.death");
register1_9Sound("entity.cat.hiss");
register1_9Sound("entity.cat.hurt");
register1_9Sound("entity.cat.purr");
register1_9Sound("entity.cat.purreow");
register1_9Sound("entity.chicken.ambient");
register1_9Sound("entity.chicken.death");
register1_9Sound("entity.chicken.egg");
register1_9Sound("entity.chicken.hurt");
register1_9Sound("entity.chicken.step");
register1_9Sound("entity.cow.ambient");
register1_9Sound("entity.cow.death");
register1_9Sound("entity.cow.hurt");
register1_9Sound("entity.cow.milk");
register1_9Sound("entity.cow.step");
register1_9Sound("entity.creeper.death");
register1_9Sound("entity.creeper.hurt");
register1_9Sound("entity.creeper.primed");
register1_9Sound("entity.donkey.ambient");
register1_9Sound("entity.donkey.angry");
register1_9Sound("entity.donkey.chest");
register1_9Sound("entity.donkey.death");
register1_9Sound("entity.donkey.hurt");
register1_9Sound("entity.egg.throw");
register1_9Sound("entity.elder_guardian.ambient");
register1_9Sound("entity.elder_guardian.ambient_land");
register1_9Sound("entity.elder_guardian.curse");
register1_9Sound("entity.elder_guardian.death");
register1_9Sound("entity.elder_guardian.death_land");
register1_9Sound("entity.elder_guardian.hurt");
register1_9Sound("entity.elder_guardian.hurt_land");
register1_9Sound("entity.enderdragon.ambient");
register1_9Sound("entity.enderdragon.death");
register1_9Sound("entity.enderdragon.flap");
register1_9Sound("entity.enderdragon.growl");
register1_9Sound("entity.enderdragon.hurt");
register1_9Sound("entity.enderdragon.shoot");
register1_9Sound("entity.enderdragon_fireball.explode");
register1_9Sound("entity.endereye.launch");
register1_9Sound("entity.endermen.ambient");
register1_9Sound("entity.endermen.death");
register1_9Sound("entity.endermen.hurt");
register1_9Sound("entity.endermen.scream");
register1_9Sound("entity.endermen.stare");
register1_9Sound("entity.endermen.teleport");
register1_9Sound("entity.endermite.ambient");
register1_9Sound("entity.endermite.death");
register1_9Sound("entity.endermite.hurt");
register1_9Sound("entity.endermite.step");
register1_9Sound("entity.enderpearl.throw");
register1_9Sound("entity.experience_bottle.throw");
register1_9Sound("entity.experience_orb.pickup");
register1_9Sound("entity.experience_orb.touch");
register1_9Sound("entity.firework.blast");
register1_9Sound("entity.firework.blast_far");
register1_9Sound("entity.firework.large_blast");
register1_9Sound("entity.firework.large_blast_far");
register1_9Sound("entity.firework.launch");
register1_9Sound("entity.firework.shoot");
register1_9Sound("entity.firework.twinkle");
register1_9Sound("entity.firework.twinkle_far");
register1_9Sound("entity.generic.big_fall");
register1_9Sound("entity.generic.burn");
register1_9Sound("entity.generic.death");
register1_9Sound("entity.generic.drink");
register1_9Sound("entity.generic.eat");
register1_9Sound("entity.generic.explode");
register1_9Sound("entity.generic.extinguish_fire");
register1_9Sound("entity.generic.hurt");
register1_9Sound("entity.generic.small_fall");
register1_9Sound("entity.generic.splash");
register1_9Sound("entity.generic.swim");
register1_9Sound("entity.ghast.ambient");
register1_9Sound("entity.ghast.death");
register1_9Sound("entity.ghast.hurt");
register1_9Sound("entity.ghast.scream");
register1_9Sound("entity.ghast.shoot");
register1_9Sound("entity.ghast.warn");
register1_9Sound("entity.guardian.ambient");
register1_9Sound("entity.guardian.ambient_land");
register1_9Sound("entity.guardian.attack");
register1_9Sound("entity.guardian.death");
register1_9Sound("entity.guardian.death_land");
register1_9Sound("entity.guardian.flop");
register1_9Sound("entity.guardian.hurt");
register1_9Sound("entity.guardian.hurt_land");
register1_9Sound("entity.horse.ambient");
register1_9Sound("entity.horse.angry");
register1_9Sound("entity.horse.armor");
register1_9Sound("entity.horse.breathe");
register1_9Sound("entity.horse.death");
register1_9Sound("entity.horse.eat");
register1_9Sound("entity.horse.gallop");
register1_9Sound("entity.horse.hurt");
register1_9Sound("entity.horse.jump");
register1_9Sound("entity.horse.land");
register1_9Sound("entity.horse.saddle");
register1_9Sound("entity.horse.step");
register1_9Sound("entity.horse.step_wood");
register1_9Sound("entity.hostile.big_fall");
register1_9Sound("entity.hostile.death");
register1_9Sound("entity.hostile.hurt");
register1_9Sound("entity.hostile.small_fall");
register1_9Sound("entity.hostile.splash");
register1_9Sound("entity.hostile.swim");
register1_9Sound("entity.irongolem.attack");
register1_9Sound("entity.irongolem.death");
register1_9Sound("entity.irongolem.hurt");
register1_9Sound("entity.irongolem.step");
register1_9Sound("entity.item.break");
register1_9Sound("entity.item.pickup");
register1_9Sound("entity.itemframe.add_item");
register1_9Sound("entity.itemframe.break");
register1_9Sound("entity.itemframe.place");
register1_9Sound("entity.itemframe.remove_item");
register1_9Sound("entity.itemframe.rotate_item");
register1_9Sound("entity.leashknot.break");
register1_9Sound("entity.leashknot.place");
register1_9Sound("entity.lightning.impact");
register1_9Sound("entity.lightning.thunder");
register1_9Sound("entity.lingeringpotion.throw");
register1_9Sound("entity.magmacube.death");
register1_9Sound("entity.magmacube.hurt");
register1_9Sound("entity.magmacube.jump");
register1_9Sound("entity.magmacube.squish");
register1_9Sound("entity.minecart.inside");
register1_9Sound("entity.minecart.riding");
register1_9Sound("entity.mooshroom.shear");
register1_9Sound("entity.mule.ambient");
register1_9Sound("entity.mule.death");
register1_9Sound("entity.mule.hurt");
register1_9Sound("entity.painting.break");
register1_9Sound("entity.painting.place");
register1_9Sound("entity.pig.ambient");
register1_9Sound("entity.pig.death");
register1_9Sound("entity.pig.hurt");
register1_9Sound("entity.pig.saddle");
register1_9Sound("entity.pig.step");
register1_9Sound("entity.player.attack.crit");
register1_9Sound("entity.player.attack.knockback");
register1_9Sound("entity.player.attack.nodamage");
register1_9Sound("entity.player.attack.strong");
register1_9Sound("entity.player.attack.sweep");
register1_9Sound("entity.player.attack.weak");
register1_9Sound("entity.player.big_fall");
register1_9Sound("entity.player.breath");
register1_9Sound("entity.player.burp");
register1_9Sound("entity.player.death");
register1_9Sound("entity.player.hurt");
register1_9Sound("entity.player.levelup");
register1_9Sound("entity.player.small_fall");
register1_9Sound("entity.player.splash");
register1_9Sound("entity.player.swim");
register1_9Sound("entity.rabbit.ambient");
register1_9Sound("entity.rabbit.attack");
register1_9Sound("entity.rabbit.death");
register1_9Sound("entity.rabbit.hurt");
register1_9Sound("entity.rabbit.jump");
register1_9Sound("entity.sheep.ambient");
register1_9Sound("entity.sheep.death");
register1_9Sound("entity.sheep.hurt");
register1_9Sound("entity.sheep.shear");
register1_9Sound("entity.sheep.step");
register1_9Sound("entity.shulker.ambient");
register1_9Sound("entity.shulker.close");
register1_9Sound("entity.shulker.death");
register1_9Sound("entity.shulker.hurt");
register1_9Sound("entity.shulker.hurt_closed");
register1_9Sound("entity.shulker.open");
register1_9Sound("entity.shulker.shoot");
register1_9Sound("entity.shulker.teleport");
register1_9Sound("entity.shulker_bullet.hit");
register1_9Sound("entity.shulker_bullet.hurt");
register1_9Sound("entity.silverfish.ambient");
register1_9Sound("entity.silverfish.death");
register1_9Sound("entity.silverfish.hurt");
register1_9Sound("entity.silverfish.step");
register1_9Sound("entity.skeleton.ambient");
register1_9Sound("entity.skeleton.death");
register1_9Sound("entity.skeleton.hurt");
register1_9Sound("entity.skeleton.shoot");
register1_9Sound("entity.skeleton.step");
register1_9Sound("entity.skeleton_horse.ambient");
register1_9Sound("entity.skeleton_horse.death");
register1_9Sound("entity.skeleton_horse.hurt");
register1_9Sound("entity.slime.attack");
register1_9Sound("entity.slime.death");
register1_9Sound("entity.slime.hurt");
register1_9Sound("entity.slime.jump");
register1_9Sound("entity.slime.squish");
register1_9Sound("entity.small_magmacube.death");
register1_9Sound("entity.small_magmacube.hurt");
register1_9Sound("entity.small_magmacube.squish");
register1_9Sound("entity.small_slime.death");
register1_9Sound("entity.small_slime.hurt");
register1_9Sound("entity.small_slime.jump");
register1_9Sound("entity.small_slime.squish");
register1_9Sound("entity.snowball.throw");
register1_9Sound("entity.snowman.ambient");
register1_9Sound("entity.snowman.death");
register1_9Sound("entity.snowman.hurt");
register1_9Sound("entity.snowman.shoot");
register1_9Sound("entity.spider.ambient");
register1_9Sound("entity.spider.death");
register1_9Sound("entity.spider.hurt");
register1_9Sound("entity.spider.step");
register1_9Sound("entity.splash_potion.break");
register1_9Sound("entity.splash_potion.throw");
register1_9Sound("entity.squid.ambient");
register1_9Sound("entity.squid.death");
register1_9Sound("entity.squid.hurt");
register1_9Sound("entity.tnt.primed");
register1_9Sound("entity.villager.ambient");
register1_9Sound("entity.villager.death");
register1_9Sound("entity.villager.hurt");
register1_9Sound("entity.villager.no");
register1_9Sound("entity.villager.trading");
register1_9Sound("entity.villager.yes");
register1_9Sound("entity.witch.ambient");
register1_9Sound("entity.witch.death");
register1_9Sound("entity.witch.drink");
register1_9Sound("entity.witch.hurt");
register1_9Sound("entity.witch.throw");
register1_9Sound("entity.wither.ambient");
register1_9Sound("entity.wither.break_block");
register1_9Sound("entity.wither.death");
register1_9Sound("entity.wither.hurt");
register1_9Sound("entity.wither.shoot");
register1_9Sound("entity.wither.spawn");
register1_9Sound("entity.wolf.ambient");
register1_9Sound("entity.wolf.death");
register1_9Sound("entity.wolf.growl");
register1_9Sound("entity.wolf.howl");
register1_9Sound("entity.wolf.hurt");
register1_9Sound("entity.wolf.pant");
register1_9Sound("entity.wolf.shake");
register1_9Sound("entity.wolf.step");
register1_9Sound("entity.wolf.whine");
register1_9Sound("entity.zombie.ambient");
register1_9Sound("entity.zombie.attack_door_wood");
register1_9Sound("entity.zombie.attack_iron_door");
register1_9Sound("entity.zombie.break_door_wood");
register1_9Sound("entity.zombie.death");
register1_9Sound("entity.zombie.hurt");
register1_9Sound("entity.zombie.infect");
register1_9Sound("entity.zombie.step");
register1_9Sound("entity.zombie_horse.ambient");
register1_9Sound("entity.zombie_horse.death");
register1_9Sound("entity.zombie_horse.hurt");
register1_9Sound("entity.zombie_pig.ambient");
register1_9Sound("entity.zombie_pig.angry");
register1_9Sound("entity.zombie_pig.death");
register1_9Sound("entity.zombie_pig.hurt");
register1_9Sound("entity.zombie_villager.ambient");
register1_9Sound("entity.zombie_villager.converted");
register1_9Sound("entity.zombie_villager.cure");
register1_9Sound("entity.zombie_villager.death");
register1_9Sound("entity.zombie_villager.hurt");
register1_9Sound("entity.zombie_villager.step");
register1_9Sound("item.armor.equip_chain");
register1_9Sound("item.armor.equip_diamond");
register1_9Sound("item.armor.equip_generic");
register1_9Sound("item.armor.equip_gold");
register1_9Sound("item.armor.equip_iron");
register1_9Sound("item.armor.equip_leather");
register1_9Sound("item.bottle.fill");
register1_9Sound("item.bottle.fill_dragonbreath");
register1_9Sound("item.bucket.empty");
register1_9Sound("item.bucket.empty_lava");
register1_9Sound("item.bucket.fill");
register1_9Sound("item.bucket.fill_lava");
register1_9Sound("item.chorus_fruit.teleport");
register1_9Sound("item.firecharge.use");
register1_9Sound("item.flintandsteel.use");
register1_9Sound("item.hoe.till");
register1_9Sound("item.shield.block");
register1_9Sound("item.shield.break");
register1_9Sound("item.shovel.flatten");
register1_9Sound("music.creative");
register1_9Sound("music.credits");
register1_9Sound("music.dragon");
register1_9Sound("music.end");
register1_9Sound("music.game");
register1_9Sound("music.menu");
register1_9Sound("music.nether");
register1_9Sound("record.11");
register1_9Sound("record.13");
register1_9Sound("record.blocks");
register1_9Sound("record.cat");
register1_9Sound("record.chirp");
register1_9Sound("record.far");
register1_9Sound("record.mall");
register1_9Sound("record.mellohi");
register1_9Sound("record.stal");
register1_9Sound("record.strad");
register1_9Sound("record.wait");
register1_9Sound("record.ward");
register1_9Sound("ui.button.click");
register1_9Sound("weather.rain");
register1_9Sound("weather.rain.above");
}
}
@@ -15,42 +15,22 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.connection.StorableObject;
public class BlockPlaceDestroyTracker extends StoredObject {
private long blockPlaced, lastMining;
private boolean mining;
public BlockPlaceDestroyTracker(UserConnection user) {
super(user);
}
public long getBlockPlaced() {
return blockPlaced;
}
public void place() {
blockPlaced = System.currentTimeMillis();
}
public class BlockPlaceDestroyTracker implements StorableObject {
private long lastMining;
public boolean isMining() {
long time = System.currentTimeMillis() - lastMining;
return time < 75;
}
public void setMining(boolean mining) {
this.mining = mining && getUser().get(EntityTracker.class).getPlayerGamemode() != 1;
public void setMining() {
lastMining = System.currentTimeMillis();
}
public long getLastMining() {
return lastMining;
}
public void updateMining() {
if (this.isMining()) {
lastMining = System.currentTimeMillis();
@@ -15,10 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.bossbar.WitherBossBar;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation.WitherBossBar;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -27,16 +26,22 @@ import java.util.Map;
import java.util.UUID;
public class BossBarStorage extends StoredObject {
private final Map<UUID, WitherBossBar> bossBars = new HashMap<>();
public BossBarStorage(UserConnection user) {
super(user);
}
public void add(UUID uuid, String title, float health) {
public void reset() {
updateLocation();
changeWorld();
}
public void add(UUID uuid, String title, float health) throws Exception {
WitherBossBar bossBar = new WitherBossBar(this.getUser(), uuid, title, health);
PlayerPosition playerPosition = this.getUser().get(PlayerPosition.class);
bossBar.setPlayerLocation(playerPosition.getPosX(), playerPosition.getPosY(), playerPosition.getPosZ(), playerPosition.getYaw(), playerPosition.getPitch());
PlayerPositionTracker playerPositionTracker = this.getUser().get(PlayerPositionTracker.class);
bossBar.setPlayerLocation(playerPositionTracker.getPosX(), playerPositionTracker.getPosY(), playerPositionTracker.getPosZ(), playerPositionTracker.getYaw(), playerPositionTracker.getPitch());
bossBar.show();
bossBars.put(uuid, bossBar);
}
@@ -48,8 +53,14 @@ public class BossBarStorage extends StoredObject {
}
public void updateLocation() {
PlayerPosition playerPosition = this.getUser().get(PlayerPosition.class);
bossBars.values().forEach(bossBar -> bossBar.setPlayerLocation(playerPosition.getPosX(), playerPosition.getPosY(), playerPosition.getPosZ(), playerPosition.getYaw(), playerPosition.getPitch()));
PlayerPositionTracker playerPositionTracker = this.getUser().get(PlayerPositionTracker.class);
bossBars.values().forEach(bossBar -> {
try {
bossBar.setPlayerLocation(playerPositionTracker.getPosX(), playerPositionTracker.getPosY(), playerPositionTracker.getPosZ(), playerPositionTracker.getYaw(), playerPositionTracker.getPitch());
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
public void changeWorld() {
@@ -15,46 +15,37 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown.CooldownVisualization;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown.CooldownVisualization.Factory;
import com.viaversion.viarewind.utils.Tickable;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.emulation.CooldownVisualization;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.util.Pair;
import java.util.ArrayList;
import java.util.Objects;
import java.util.List;
import java.util.logging.Level;
public class Cooldown extends StoredObject implements Tickable {
public class CooldownStorage implements StorableObject {
private double attackSpeed = 4.0;
private long lastHit = 0;
private CooldownVisualization.Factory visualizationFactory = CooldownVisualization.Factory.fromConfiguration();
private CooldownVisualization current;
public Cooldown(final UserConnection user) {
super(user);
}
@Override
public void tick() {
public void tick(final UserConnection connection) {
if (!hasCooldown()) {
endCurrentVisualization();
return;
}
BlockPlaceDestroyTracker tracker = getUser().get(BlockPlaceDestroyTracker.class);
BlockPlaceDestroyTracker tracker = connection.get(BlockPlaceDestroyTracker.class);
if (tracker.isMining()) {
lastHit = 0;
endCurrentVisualization();
return;
}
if (current == null) {
current = visualizationFactory.create(getUser());
current = visualizationFactory.create(connection);
}
try {
current.show(getCooldown());
@@ -76,29 +67,21 @@ public class Cooldown extends StoredObject implements Tickable {
public boolean hasCooldown() {
long time = System.currentTimeMillis() - lastHit;
double cooldown = restrain(((double) time) * attackSpeed / 1000d, 0, 1.5);
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, 0, 1);
return restrain(((double) time) * attackSpeed / 1000d, 1);
}
private double restrain(double x, double a, double b) {
if (x < a) return a;
private double restrain(double x, double b) {
if (x < 0) return 0;
return Math.min(x, b);
}
public double getAttackSpeed() {
return attackSpeed;
}
public void setAttackSpeed(double attackSpeed) {
this.attackSpeed = attackSpeed;
}
public void setAttackSpeed(double base, ArrayList<Pair<Byte, Double>> modifiers) {
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) {
@@ -127,8 +110,4 @@ public class Cooldown extends StoredObject implements Tickable {
public void setLastHit(long lastHit) {
this.lastHit = lastHit;
}
public void setVisualizationFactory(Factory visualizationFactory) {
this.visualizationFactory = Objects.requireNonNull(visualizationFactory, "visualizationFactory");
}
}
@@ -1,191 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.ClientEntityIdChangeListener;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class EntityTracker extends StoredObject implements ClientEntityIdChangeListener {
protected final Protocol1_8To1_9 protocol;
private final Map<Integer, List<Integer>> vehicleMap = new ConcurrentHashMap<>();
private final Map<Integer, EntityTypes1_10.EntityType> clientEntityTypes = new ConcurrentHashMap<>();
private final Map<Integer, List<Metadata>> metadataBuffer = new ConcurrentHashMap<>();
private final Map<Integer, EntityModel> entityReplacements = new ConcurrentHashMap<>();
private final Map<Integer, Vector> entityOffsets = new ConcurrentHashMap<>();
private final Map<Integer, Byte> statusInformation = new ConcurrentHashMap<>();
private int playerId;
private int playerGamemode = 0;
public EntityTracker(UserConnection user, Protocol1_8To1_9 protocol) {
super(user);
this.protocol = protocol;
}
public void setPlayerId(int entityId) {
playerId = entityId;
}
public int getPlayerId() {
return playerId;
}
public int getPlayerGamemode() {
return playerGamemode;
}
public void setPlayerGamemode(int playerGamemode) {
this.playerGamemode = playerGamemode;
}
public void removeEntity(int entityId) {
vehicleMap.remove(entityId);
vehicleMap.forEach((vehicle, passengers) -> passengers.remove((Integer) entityId));
vehicleMap.entrySet().removeIf(entry -> entry.getValue().isEmpty());
clientEntityTypes.remove(entityId);
entityOffsets.remove(entityId);
if (entityReplacements.containsKey(entityId)) {
entityReplacements.remove(entityId).deleteEntity();
}
}
public void resetEntityOffset(int entityId) {
entityOffsets.remove(entityId);
}
public Vector getEntityOffset(int entityId) {
return entityOffsets.get(entityId);
}
public void addToEntityOffset(int entityId, short relX, short relY, short relZ) {
entityOffsets.compute(entityId, (key, offset) -> {
if (offset == null) {
return new Vector(relX, relY, relZ);
} else {
return new Vector(offset.blockX() + relX, offset.blockY() + relY, offset.blockZ() + relZ);
}
});
}
public void setEntityOffset(int entityId, short relX, short relY, short relZ) {
entityOffsets.compute(entityId, (key, offset) -> new Vector(relX, relY, relZ));
}
public void setEntityOffset(int entityId, Vector offset) {
entityOffsets.put(entityId, offset);
}
public List<Integer> getPassengers(int entityId) {
return vehicleMap.getOrDefault(entityId, new ArrayList<>());
}
public void setPassengers(int entityId, List<Integer> passengers) {
vehicleMap.put(entityId, passengers);
}
public void addEntityReplacement(EntityModel entityModel) {
entityReplacements.put(entityModel.getEntityId(), entityModel);
}
public EntityModel getEntityReplacement(int entityId) {
return entityReplacements.get(entityId);
}
public Map<Integer, EntityTypes1_10.EntityType> getClientEntityTypes() {
return this.clientEntityTypes;
}
public void addMetadataToBuffer(int entityID, List<Metadata> metadataList) {
if (this.metadataBuffer.containsKey(entityID)) {
this.metadataBuffer.get(entityID).addAll(metadataList);
} else if (!metadataList.isEmpty()) {
this.metadataBuffer.put(entityID, metadataList);
}
}
public List<Metadata> getBufferedMetadata(int entityId) {
return metadataBuffer.get(entityId);
}
public boolean isInsideVehicle(int entityId) {
for (List<Integer> vehicle : vehicleMap.values()) {
if (vehicle.contains(entityId)) return true;
}
return false;
}
public int getVehicle(int passenger) {
for (Map.Entry<Integer, List<Integer>> vehicle : vehicleMap.entrySet()) {
if (vehicle.getValue().contains(passenger)) return vehicle.getKey();
}
return -1;
}
public boolean isPassenger(int vehicle, int passenger) {
return vehicleMap.containsKey(vehicle) && vehicleMap.get(vehicle).contains(passenger);
}
public void sendMetadataBuffer(int entityId) {
if (!this.metadataBuffer.containsKey(entityId)) return;
if (entityReplacements.containsKey(entityId)) {
entityReplacements.get(entityId).updateMetadata(this.metadataBuffer.remove(entityId));
} else {
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_8.ENTITY_METADATA, this.getUser());
wrapper.write(Type.VAR_INT, entityId);
wrapper.write(Types1_8.METADATA_LIST, this.metadataBuffer.get(entityId));
protocol.getMetadataRewriter().transform(this, entityId, this.metadataBuffer.get(entityId));
if (!this.metadataBuffer.get(entityId).isEmpty()) {
try {
wrapper.send(Protocol1_8To1_9.class);
} catch (Exception ex) {
ex.printStackTrace();
}
}
this.metadataBuffer.remove(entityId);
}
}
@Override
public void setClientEntityId(int playerEntityId) {
clientEntityTypes.remove(this.playerId);
this.playerId = playerEntityId;
clientEntityTypes.put(this.playerId, EntityTypes1_10.EntityType.ENTITY_HUMAN);
}
public Map<Integer, Byte> getStatusInformation() {
return statusInformation;
}
}
@@ -0,0 +1,87 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.fastutil.ints.*;
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();
public EntityTracker1_9(UserConnection connection) {
super(connection, EntityTypes1_10.EntityType.ENTITY_HUMAN);
}
@Override
public void removeEntity(int id) {
vehicles.remove(id);
offsets.remove(id);
status.remove(id);
vehicles.forEach((vehicle, passengers) -> passengers.removeInt(id));
vehicles.int2ObjectEntrySet().removeIf(entry -> entry.getValue().isEmpty());
super.removeEntity(id);
}
public void resetEntityOffset(final int id) {
offsets.remove(id);
}
public Vector getEntityOffset(final int id) {
return offsets.get(id);
}
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 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 int getVehicle(final int passenger) {
for (Map.Entry<Integer, IntList> vehicle : vehicles.int2ObjectEntrySet()) {
if (vehicle.getValue().contains(passenger)) return vehicle.getKey();
}
return -1;
}
public Int2IntMap getStatus() {
return status;
}
}
@@ -1,60 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.Tickable;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
public class Levitation extends StoredObject implements Tickable {
private int amplifier;
private volatile boolean active = false;
public Levitation(UserConnection user) {
super(user);
}
@Override
public void tick() {
if (!active) {
return;
}
int vY = (amplifier + 1) * 360;
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_8.ENTITY_VELOCITY, null, Levitation.this.getUser());
packet.write(Type.VAR_INT, getUser().get(EntityTracker.class).getPlayerId());
packet.write(Type.SHORT, (short) 0);
packet.write(Type.SHORT, (short) vY);
packet.write(Type.SHORT, (short) 0);
PacketUtil.sendPacket(packet, Protocol1_8To1_9.class);
}
public void setActive(boolean active) {
this.active = active;
}
public void setAmplifier(int amplifier) {
this.amplifier = amplifier;
}
}
@@ -15,20 +15,28 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
package com.viaversion.viarewind.api.minecraft;
import com.viaversion.viaversion.api.connection.StorableObject;
public class IdDataCombine {
public class LevitationStorage implements StorableObject {
public static int idFromCombined(final int combined) {
return combined >> 4;
private boolean active;
private int amplifier;
public boolean isActive() {
return active;
}
public static int dataFromCombined(final int combined) {
return combined & 0xF;
public void setActive(boolean active) {
this.active = active;
}
public static int toCombined(final int id, final int data) {
return (id << 4) | (data & 0xF);
public int getAmplifier() {
return amplifier;
}
public void setAmplifier(int amplifier) {
this.amplifier = amplifier;
}
}
@@ -1,133 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class PlayerPosition extends StoredObject {
private double posX, posY, posZ;
private float yaw, pitch;
private boolean onGround;
private int confirmId = -1;
public PlayerPosition(UserConnection user) {
super(user);
}
public void setPos(double x, double y, double z) {
this.posX = x;
this.posY = y;
this.posZ = z;
}
public void setYaw(float yaw) {
this.yaw = yaw % 360f;
}
public void setPitch(float pitch) {
this.pitch = pitch % 360f;
}
public double getPosX() {
return this.posX;
}
public double getPosY() {
return this.posY;
}
public double getPosZ() {
return this.posZ;
}
public float getYaw() {
return this.yaw;
}
public float getPitch() {
return this.pitch;
}
public boolean isOnGround() {
return this.onGround;
}
public int getConfirmId() {
return this.confirmId;
}
public void setPosX(double posX) {
this.posX = posX;
}
public void setPosY(double posY) {
this.posY = posY;
}
public void setPosZ(double posZ) {
this.posZ = posZ;
}
public void setOnGround(boolean onGround) {
this.onGround = onGround;
}
public void setConfirmId(int confirmId) {
this.confirmId = confirmId;
}
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof PlayerPosition)) return false;
final PlayerPosition other = (PlayerPosition) o;
if (!other.canEqual(this)) return false;
if (Double.compare(this.getPosX(), other.getPosX()) != 0) return false;
if (Double.compare(this.getPosY(), other.getPosY()) != 0) return false;
if (Double.compare(this.getPosZ(), other.getPosZ()) != 0) return false;
if (Float.compare(this.getYaw(), other.getYaw()) != 0) return false;
if (Float.compare(this.getPitch(), other.getPitch()) != 0) return false;
if (this.isOnGround() != other.isOnGround()) return false;
return this.getConfirmId() == other.getConfirmId();
}
protected boolean canEqual(final Object other) {
return other instanceof PlayerPosition;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
final long $posX = Double.doubleToLongBits(this.getPosX());
result = result * PRIME + (int) ($posX >>> 32 ^ $posX);
final long $posY = Double.doubleToLongBits(this.getPosY());
result = result * PRIME + (int) ($posY >>> 32 ^ $posY);
final long $posZ = Double.doubleToLongBits(this.getPosZ());
result = result * PRIME + (int) ($posZ >>> 32 ^ $posZ);
result = result * PRIME + Float.floatToIntBits(this.getYaw());
result = result * PRIME + Float.floatToIntBits(this.getPitch());
result = result * PRIME + (this.isOnGround() ? 79 : 97);
result = result * PRIME + this.getConfirmId();
return result;
}
public String toString() {
return "PlayerPosition(posX=" + this.getPosX() + ", posY=" + this.getPosY() + ", posZ=" + this.getPosZ() + ", yaw=" + this.getYaw() + ", pitch=" + this.getPitch() + ", onGround=" + this.isOnGround() + ", confirmId=" + this.getConfirmId() + ")";
}
}
@@ -0,0 +1,96 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2018-2024 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
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;
public void setPos(double x, double y, double z) {
this.posX = x;
this.posY = y;
this.posZ = z;
}
public void sendAnimations() throws Exception {
PacketWrapper wrapper;
while ((wrapper = animations.poll()) != null) {
wrapper.sendToServer(Protocol1_8To1_9.class);
}
}
public void queueAnimation(final PacketWrapper wrapper) {
animations.add(wrapper);
}
public void setYaw(float yaw) {
this.yaw = yaw % 360f;
}
public void setPitch(float pitch) {
this.pitch = pitch % 360f;
}
public double getPosX() {
return this.posX;
}
public double getPosY() {
return this.posY;
}
public double getPosZ() {
return this.posZ;
}
public float getYaw() {
return this.yaw;
}
public float getPitch() {
return this.pitch;
}
public boolean isOnGround() {
return this.onGround;
}
public int getConfirmId() {
return this.confirmId;
}
public void setOnGround(boolean onGround) {
this.onGround = onGround;
}
public void setConfirmId(int confirmId) {
this.confirmId = confirmId;
}
}
@@ -15,11 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.storage;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
@@ -35,11 +33,11 @@ import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.HashMap;
public class Windows extends StoredObject {
public class WindowTracker extends StoredObject {
private final HashMap<Short, String> types = new HashMap<>();
private final HashMap<Short, Item[]> brewingItems = new HashMap<>();
public Windows(UserConnection user) {
public WindowTracker(UserConnection user) {
super(user);
}
@@ -65,7 +63,7 @@ public class Windows extends StoredObject {
});
}
public static void updateBrewingStand(UserConnection user, Item blazePowder, short windowId) {
public static void updateBrewingStand(UserConnection user, Item blazePowder, short windowId) throws Exception {
if (blazePowder != null && blazePowder.identifier() != 377) {
return;
}
@@ -83,15 +81,15 @@ public class Windows extends StoredObject {
openWindow.write(Type.COMPONENT, TextComponentSerializer.V1_8.serializeJson(title));
openWindow.write(Type.UNSIGNED_BYTE, (short) 420);
PacketUtil.sendPacket(openWindow, Protocol1_8To1_9.class);
openWindow.scheduleSend(Protocol1_8To1_9.class);
Item[] items = user.get(Windows.class).getBrewingItems(windowId);
Item[] items = user.get(WindowTracker.class).getBrewingItems(windowId);
for (int i = 0; i < items.length; i++) {
PacketWrapper setSlot = PacketWrapper.create(ClientboundPackets1_8.SET_SLOT, user);
setSlot.write(Type.UNSIGNED_BYTE, windowId);
setSlot.write(Type.SHORT, (short) i);
setSlot.write(Type.ITEM1_8, items[i]);
PacketUtil.sendPacket(setSlot, Protocol1_8To1_9.class);
setSlot.scheduleSend(Protocol1_8To1_9.class);
}
}
}
@@ -15,26 +15,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.task;
package com.viaversion.viarewind.utils;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.CooldownStorage;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
public class Ticker {
private static boolean init = false;
public class CooldownIndicatorTask implements Runnable {
public static void init() {
if (init) return;
synchronized (Ticker.class) {
if (init) return;
init = true;
@Override
public void run() {
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
connection.get(CooldownStorage.class).tick(connection);
}
Via.getPlatform().runRepeatingSync(() ->
Via.getManager().getConnectionManager().getConnections().forEach(user ->
user.getStoredObjects().values().stream()
.filter(Tickable.class::isInstance)
.map(Tickable.class::cast)
.forEach(Tickable::tick)
), 1L);
}
}
Loaded 100 of 127 files, more files were not shown because too many files have changed in this diff. Show more