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

* Small cleanup

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

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

* Recommend atleast viafabric 0.4.10 or higher.

Having "*" for viafabric included is not a great idea as then all copies are accepted including unsupported ones.
2023-10-09 01:42:30 +02:00
FlorianMichael 1f651a67c7 Bump version to 3.0.3-SNAPSHOT 2023-10-09 01:35:26 +02:00
FlorianMichael 2d3e495f85 Fixed metadata issues, added new config options to emulate world border, cleaned protocol code. 2023-10-09 01:28:58 +02:00
FlorianMichael 7689769e26 Fixed merge conflict. 2023-10-08 22:56:38 +02:00
FlorianMichael 990a5bafe1 Merge remote-tracking branch 'origin/1.7-particle-data-fix' into dev
# Conflicts:
#	core/src/main/java/de/gerrygames/viarewind/protocol/protocol1_7_6_10to1_8/packets/WorldPackets.java
2023-10-08 22:53:24 +02:00
FlorianMichael bdef039008 Fixed loading on Bukkit 2023-10-08 20:49:40 +02:00
FlorianMichael f516528e77 Rewrote entity packet translations 2023-10-08 12:42:21 +02:00
FlorianMichael ad85d1c4fd 1.7 -> 1.8: deleted Ticker system 2023-10-08 12:21:20 +02:00
FlorianMichael 15769e5ee3 Initial rewrite of entity emulation system
Don't buffer Entity Metadata
2023-10-08 12:08:40 +02:00
FlorianMichael a7e865ee6d Allow platform implementation to define config path 2023-10-08 08:59:52 +02:00
FlorianMichael 4a0a4bb40c Fabric is also a thing! 2023-10-08 07:18:10 +02:00
FlorianMichael 16d308610e Updated all platform implementations 2023-10-08 07:15:58 +02:00
FlorianMichael b5825462bf Fixed 1.7 -> 1.8 metadata rewriting not working 2023-10-08 06:22:42 +02:00
FlorianMichael fe123b13b7 Load 1.8 -> 1.9 item replacements 2023-10-08 06:16:56 +02:00
FlorianMichael 3fa305f637 Refactor ItemRewriter and replacement system 2023-10-08 06:15:51 +02:00
FlorianMichael 5a0e57a4a0 Added more exception handling to Metadata rewriter (1.7 -> 1.8) 2023-10-08 03:35:24 +02:00
FlorianMichael 76dcad78ce Start with rewriting Replacement system 2023-10-08 03:13:49 +02:00
FlorianMichael bff3a99f2d Rewrote chunk handling (1.7 -> 1.8) completely. 2023-10-08 02:22:54 +02:00
FlorianMichael f95a2db7f5 Small code cleanup. 2023-10-08 01:38:39 +02:00
FlorianMichael 5a126695c3 Bump version to 3.0.2-SNAPSHOT 2023-10-07 23:02:10 +02:00
FlorianMichael e84a9b619f Cleaned up Compression handling 2023-10-07 21:39:20 +02:00
FlorianMichael 684e6d1377 Cleaned up Protocol 1.7.2 -> 1.7.6 2023-10-07 20:59:53 +02:00
FlorianMichael f1988765ba Don't allow platform to be initialized twice. 2023-10-07 20:33:12 +02:00
FlorianMichael df28363692 Mention ViaProxy instead of ViaFabricPlus in README file. 2023-10-07 20:29:36 +02:00
FlorianMichael eb6e7b17b8 Merge remote-tracking branch 'origin/master' into dev 2023-10-07 20:22:20 +02:00
Nassim Jahnke 85c2816808 Fix branch check on headless ci 2023-09-26 10:51:32 +10:00
Nassim Jahnke f7a2f22bed [ci skip] Fix branch check in publishing 2023-09-26 00:27:47 +10:00
FlorianMichael 1cce662f36 Move util to correct package 2023-09-23 03:29:59 +02:00
FlorianMichael bf359bb81e Improved Hologram detection method in ArmorStandReplacement 2023-09-23 03:20:44 +02:00
FlorianMichael 925484c45e Apply checkstyle, build javadoc and source jar file 2023-09-22 23:09:33 +02:00
FlorianMichael 916cb9bae0 Fixed compile error 2023-09-21 20:24:18 +02:00
Terrence S 3892a02ce3 Make overall formatting more consistent plus a few spelling fixes and minor changes (#455) 2023-09-21 20:18:53 +02:00
FlorianMichael c2bf1a6231 Bump version to 3.0.1-SNAPSHOT 2023-09-21 20:11:42 +02:00
ShinyDialga 2b791879d3 Fix data values for BLOCK_CRACK and BLOCK_DUST particles for 1.7 players 2021-03-22 22:22:25 -05:00
123 changed files with 4377 additions and 4988 deletions

No files matched your search

+2 -2
View File
@@ -5,9 +5,9 @@
**ViaVersion addon to allow 1.8.x and 1.7.x clients on newer server versions.** <br>
Runs on 1.9-latest servers or 1.8 clients and lower.
**On Fabric, use either [ViaFabric](https://modrinth.com/mod/viafabric) or [ViaFabricPlus](https://modrinth.com/mod/viafabricplus). To override the included version**
**You can override the included version in [ViaFabric](https://modrinth.com/mod/viafabric) or [ViaProxy](https://github.com/ViaVersion/ViaProxy):**
- in **ViaFabric**, put ViaRewind into the `mods` folder
- in **ViaFabricPlus**, put ViaRewind into the `ViaFabricPlus/jars` folder
- in **ViaProxy**, put ViaRewind into the `jars` folder
**Depending on the platform and version, this also requires [ViaVersion](https://modrinth.com/mod/viaversion) and [ViaBackwards](https://modrinth.com/mod/viabackwards).**
@@ -19,16 +19,14 @@
package com.viaversion.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
import com.viaversion.viaversion.api.Via;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
public class BukkitPlugin extends JavaPlugin implements ViaRewindPlatform {
@Override
public void onEnable() {
ViaRewindConfig conf = new ViaRewindConfig(new File(getDataFolder(), "config.yml"));
conf.reloadConfig();
this.init(conf);
public BukkitPlugin() {
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
}
}
+1 -1
View File
@@ -5,5 +5,5 @@ plugins {
dependencies {
api project(":viarewind-common")
compileOnly(annotationProcessor("net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT"))
compileOnly(annotationProcessor("net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT"))
}
@@ -19,16 +19,15 @@
package com.viaversion.viarewind;
import com.viaversion.viarewind.api.ViaRewindPlatform;
import com.viaversion.viaversion.api.Via;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
public class BungeePlugin extends Plugin implements ViaRewindPlatform {
@Override
public void onEnable() {
ViaRewindConfig conf = new ViaRewindConfig(new File(getDataFolder(), "config.yml"));
conf.reloadConfig();
this.init(conf);
}
@Override
public void onLoad() {
Via.getManager().addEnableListener(() -> this.init(new File(getDataFolder(), "config.yml")));
}
}
@@ -18,6 +18,7 @@
package com.viaversion.viarewind;
import com.google.common.base.Preconditions;
import com.viaversion.viarewind.api.ViaRewindConfig;
import com.viaversion.viarewind.api.ViaRewindPlatform;
@@ -27,6 +28,8 @@ public class ViaRewind {
private static ViaRewindConfig config;
public static void init(ViaRewindPlatform platform, ViaRewindConfig config) {
Preconditions.checkArgument(ViaRewind.platform == null, "ViaRewind is already initialized");
ViaRewind.platform = platform;
ViaRewind.config = config;
}
@@ -27,9 +27,10 @@ import java.util.List;
import java.util.Map;
public class ViaRewindConfig extends Config implements com.viaversion.viarewind.api.ViaRewindConfig {
public ViaRewindConfig(File configFile) {
super(configFile);
reloadConfig();
reload();
}
@Override
@@ -57,7 +58,17 @@ public class ViaRewindConfig extends Config implements com.viaversion.viarewind.
return getInt("max-book-page-length", 5000);
}
@Override
@Override
public boolean isEmulateWorldBorder() {
return getBoolean("emulate-world-border", true);
}
@Override
public String getWorldBorderParticle() {
return getString("world-border-particle", "fireworksSpark");
}
@Override
public URL getDefaultConfigURL() {
return getClass().getClassLoader().getResource("assets/viarewind/config.yml");
}
@@ -18,10 +18,12 @@
package com.viaversion.viarewind.api;
import com.viaversion.viaversion.api.configuration.Config;
/**
* This class is used to get the platform specific config
*/
public interface ViaRewindConfig {
public interface ViaRewindConfig extends Config {
enum CooldownIndicator {
TITLE, ACTION_BAR, BOSS_BAR, DISABLED
@@ -67,4 +69,18 @@ public interface ViaRewindConfig {
* @return the max amount of characters
*/
int getMaxBookPageSize();
/**
* Whether to emulate the 1.8+ world border for 1.7.x clients
*
* @return true if enabled
*/
boolean isEmulateWorldBorder();
/**
* The particle to show the world border for the 1.8+ world border for 1.7.x clients
*
* @return the particle name (see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Particle_2">Particle registry for Packet</a>)
*/
String getWorldBorderParticle();
}
@@ -18,14 +18,16 @@
package com.viaversion.viarewind.api;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.ViaRewindConfig;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.Protocol1_7_2_5To1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.ProtocolManager;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import java.io.File;
import java.util.logging.Logger;
/**
@@ -39,16 +41,20 @@ public interface ViaRewindPlatform {
/**
* Initialize ViaRewind
*/
default void init(ViaRewindConfig config) {
default void init(final File configFile) {
ViaRewindConfig config = new ViaRewindConfig(configFile);
config.reload();
Via.getManager().getConfigurationProvider().register(config);
ViaRewind.init(this, config);
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.registerProtocol(new Protocol1_8To1_9(), ProtocolVersion.v1_8, ProtocolVersion.v1_9);
protocolManager.registerProtocol(new Protocol1_7_6_10To1_8(), ProtocolVersion.v1_7_6, ProtocolVersion.v1_8);
protocolManager.registerProtocol(new Protocol1_7_2_5To1_7_6_10(), ProtocolVersion.v1_7_1, ProtocolVersion.v1_7_6);
protocolManager.registerProtocol(new Protocol1_7_6_10To1_8(), ProtocolVersion.v1_7_6, ProtocolVersion.v1_8);
protocolManager.registerProtocol(new Protocol1_8To1_9(), ProtocolVersion.v1_8, ProtocolVersion.v1_9);
}
/**
@@ -0,0 +1,102 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
import java.util.List;
/**
* Represents a model that is replacing an entity on the client side (e.g. armor stand)
*/
public abstract class EntityModel<T extends Protocol<?, ?, ?, ?>> {
protected final UserConnection user;
protected final T protocol;
public EntityModel(final UserConnection user, final T protocol) {
this.user = user;
this.protocol = protocol;
}
/**
* @return The entity id of the entity this model is replacing
*/
public abstract int getEntityId();
/**
* Updates the position of the entity this model is replacing
*
* @param x The new x position
* @param y The new y position
* @param z The new z position
*/
public abstract void updateReplacementPosition(final double x, final double y, final double z);
/**
* Handles the original movement packet of the entity this model is replacing
*
* @param x The x position
* @param y The y position
* @param z The z position
*/
public abstract void handleOriginalMovementPacket(final double x, final double y, final double z);
/**
* Sets the yaw and pitch of the entity this model is replacing
*
* @param yaw The new yaw
* @param pitch The new pitch
*/
public abstract void setYawPitch(final float yaw, final float pitch);
/**
* Sets the head yaw of the entity this model is replacing
*
* @param yaw The new head yaw
*/
public abstract void setHeadYaw(final float yaw);
/**
* Spawns the entity this model is replacing
*/
public abstract void sendSpawnPacket();
/**
* Destroys the entity this model is replacing
*/
public abstract void deleteEntity();
/**
* Updates the metadata of the entity this model is replacing
*
* @param metadataList The new metadata
*/
public abstract void updateMetadata(final List<Metadata> metadataList);
public UserConnection getUser() {
return user;
}
public T getProtocol() {
return protocol;
}
}
@@ -0,0 +1,78 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.minecraft;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.NibbleArray;
public class ExtendedBlockStorage {
private final byte[] blockLSBArray = new byte[4096];
private final NibbleArray blockMetadataArray = new NibbleArray(this.blockLSBArray.length);
private final NibbleArray blockLightArray = new NibbleArray(this.blockLSBArray.length);
private NibbleArray blockMSBArray;
private NibbleArray skyLightArray;
public ExtendedBlockStorage(final boolean skylight) {
if (skylight) {
this.skyLightArray = new NibbleArray(this.blockLSBArray.length);
}
}
public void setBlockId(final int x, final int y, final int z, final int value) {
this.blockLSBArray[ChunkSection.index(x, y, z)] = (byte) (value & 255);
if (value > 255) {
this.getOrCreateBlockMSBArray().set(x, y, z, (value & 0xF00) >> 8);
} else if (this.blockMSBArray != null) {
this.blockMSBArray.set(x, y, z, 0);
}
}
public void setBlockMetadata(final int x, final int y, final int z, final int value) {
this.blockMetadataArray.set(x, y, z, value);
}
public boolean hasBlockMSBArray() {
return this.blockMSBArray != null;
}
public byte[] getBlockLSBArray() {
return this.blockLSBArray;
}
public NibbleArray getOrCreateBlockMSBArray() {
if (this.blockMSBArray == null) {
return this.blockMSBArray = new NibbleArray(this.blockLSBArray.length);
}
return this.blockMSBArray;
}
public NibbleArray getBlockMetadataArray() {
return this.blockMetadataArray;
}
public NibbleArray getBlockLightArray() {
return this.blockLightArray;
}
public NibbleArray getSkyLightArray() {
return this.skyLightArray;
}
}
@@ -16,20 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.storage;
package com.viaversion.viarewind.api.minecraft;
public class BlockState {
public class IdDataCombine {
public static int extractId(int raw) {
return raw >> 4;
public static int idFromCombined(final int combined) {
return combined >> 4;
}
public static int extractData(int raw) {
return raw & 0xF;
public static int dataFromCombined(final int combined) {
return combined & 0xF;
}
public static int stateToRaw(int id, int data) {
public static int toCombined(final int id, final int data) {
return (id << 4) | (data & 0xF);
}
}
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.netty;
package com.viaversion.viarewind.api.netty;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.netty;
package com.viaversion.viarewind.api.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
@@ -0,0 +1,86 @@
package com.viaversion.viarewind.api.rewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.MetaIndex1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.ClientEntityIdChangeListener;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ReplacementEntityTracker extends StoredObject implements ClientEntityIdChangeListener {
private final Map<EntityTypes1_10.EntityType, Pair<EntityTypes1_10.EntityType, String>> ENTITY_REPLACEMENTS = new HashMap<>();
private final Map<Integer, EntityTypes1_10.EntityType> entityMap = new HashMap<>();
private final Map<Integer, EntityTypes1_10.EntityType> entityReplacementMap = new HashMap<>();
private int playerId = -1;
private final ProtocolVersion version;
public ReplacementEntityTracker(UserConnection user, final ProtocolVersion version) {
super(user);
this.version = version;
}
public void registerEntity(final EntityTypes1_10.EntityType oldType, final EntityTypes1_10.EntityType newType, final String name) {
ENTITY_REPLACEMENTS.put(oldType, new Pair<>(newType, this.version.getName() + " " + name));
}
public void addEntity(final int entityId, final EntityTypes1_10.EntityType type) {
entityMap.put(entityId, type);
}
public int replaceEntity(final int entityId, final EntityTypes1_10.EntityType type) {
entityReplacementMap.put(entityId, type);
return ENTITY_REPLACEMENTS.get(type).key().getId();
}
public void removeEntity(final int entityId) {
entityMap.remove(entityId);
entityReplacementMap.remove(entityId);
}
public void clear() {
entityMap.clear();
entityReplacementMap.clear();
}
public boolean isReplaced(final EntityTypes1_10.EntityType type) {
return ENTITY_REPLACEMENTS.containsKey(type);
}
public void updateMetadata(final int entityId, final List<Metadata> metadata) throws Exception {
final String name = ENTITY_REPLACEMENTS.get(entityMap.get(entityId)).value();
metadata.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG_VISIBILITY.getNewIndex(), MetaType1_7_6_10.Byte, (byte) 1)); // TODO: Make this definable for 1.8 -> 1.9 ?
metadata.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG.getNewIndex(), MetaType1_7_6_10.String, name));
}
@Override
public void setClientEntityId(int entityId) {
removeEntity(this.playerId);
addEntity(entityId, EntityTypes1_10.EntityType.ENTITY_HUMAN);
this.playerId = entityId;
}
public Map<Integer, EntityTypes1_10.EntityType> getEntityMap() {
return entityMap;
}
public Map<Integer, EntityTypes1_10.EntityType> getEntityReplacementMap() {
return entityReplacementMap;
}
public int getPlayerId() {
return playerId;
}
}
@@ -16,38 +16,43 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.replacement;
package com.viaversion.viarewind.api.rewriter.item;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.util.ChatColorUtil;
public class Replacement {
private final int id;
private final int data;
private final String name;
private String resetName;
private String bracketName;
public Replacement(int id) {
public Replacement(final int id) {
this(id, -1);
}
public Replacement(int id, int data) {
public Replacement(final int id, final int data) {
this(id, data, null);
}
public Replacement(int id, String name) {
public Replacement(final int id, final String name) {
this(id, -1, name);
}
public Replacement(int id, int data, String name) {
public Replacement(final int id, final int data, final String name) {
this.id = id;
this.data = data;
this.name = name;
if (name!=null) {
this.resetName = "§r" + name;
this.bracketName = " §r§7(" + name + "§r§7)";
}
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)");
}
}
@@ -63,25 +68,38 @@ public class Replacement {
return name;
}
public Item replace(Item item) {
item.setIdentifier(id);
if (data!=-1) item.setData((short)data);
if (name!=null) {
CompoundTag compoundTag = item.tag()==null ? new CompoundTag() : item.tag();
if (!compoundTag.contains("display")) compoundTag.put("display", new CompoundTag());
CompoundTag display = compoundTag.get("display");
/**
* @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")) {
StringTag name = display.get("Name");
if (!name.getValue().equals(resetName) && !name.getValue().endsWith(bracketName))
name.setValue(name.getValue() + bracketName);
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));
display.put("Name", new StringTag(resetName)); // Set the new name tag
}
item.setTag(compoundTag);
item.setTag(rootTag);
}
return item;
}
/**
* @param data The data of the item/block
* @return The replacement data for the item/block
*/
public int replaceData(int data) {
return this.data == -1 ? data : this.data;
}
@@ -0,0 +1,115 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.api.rewriter.item;
import com.viaversion.viarewind.api.minecraft.IdDataCombine;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
public abstract class ReplacementItemRewriter<T extends AbstractProtocol<?, ?, ?, ?>> implements ItemRewriter<T> {
private final Int2ObjectMap<Replacement> ITEM_REPLACEMENTS = new Int2ObjectOpenHashMap<>();
private final Int2ObjectMap<Replacement> BLOCK_REPLACEMENTS = new Int2ObjectOpenHashMap<>();
private final T protocol;
private final ProtocolVersion protocolVersion;
public ReplacementItemRewriter(final T protocol, final ProtocolVersion protocolVersion) {
this.protocol = protocol;
this.protocolVersion = protocolVersion;
}
public void registerItem(int id, Replacement replacement) {
registerItem(id, -1, replacement);
}
public void registerBlock(int id, Replacement replacement) {
registerBlock(id, -1, replacement);
}
public void registerItemBlock(int id, Replacement replacement) {
registerItemBlock(id, -1, replacement);
}
public void registerItem(int id, int data, Replacement replacement) {
ITEM_REPLACEMENTS.put(generateTrackingId(id, data), replacement);
replacement.buildNames(protocolVersion.getName());
}
public void registerBlock(int id, int data, Replacement replacement) {
BLOCK_REPLACEMENTS.put(generateTrackingId(id, data), replacement);
replacement.buildNames(protocolVersion.getName());
}
public void registerItemBlock(int id, int data, Replacement replacement) {
registerItem(id, data, replacement);
registerBlock(id, data, replacement);
}
/**
* @param item The item to replace
* @return The replacement for the item or the item if not found
*/
public Item replace(Item item) {
Replacement replacement = ITEM_REPLACEMENTS.get(generateTrackingId(item.identifier(), item.data()));
if (replacement == null) replacement = ITEM_REPLACEMENTS.get(generateTrackingId(item.identifier(), -1));
return replacement == null ? item : replacement.replace(item);
}
/**
* @param id The id of the item/block
* @param data The data of the item/block
* @return The replacement for the item/block or null if not found
*/
public Replacement replace(int id, int data) {
Replacement replacement = BLOCK_REPLACEMENTS.get(generateTrackingId(id, data));
if (replacement == null) replacement = BLOCK_REPLACEMENTS.get(generateTrackingId(id, -1));
return replacement;
}
/**
* @param combined The combined id and data
* @return The generated tracking id for the item/block
*/
public int replace(int combined) {
final int data = IdDataCombine.dataFromCombined(combined);
final Replacement replace = replace(IdDataCombine.idFromCombined(combined), data);
return replace != null ? IdDataCombine.toCombined(replace.getId(), replace.replaceData(data)) : combined;
}
/**
* @param id The id of the item/block
* @param data The data of the item/block
* @return The generated tracking id for the item/block
*/
private int generateTrackingId(int id, int data) {
return (id << 16) | (data & 0xFFFF);
}
@Override
public T protocol() {
return this.protocol;
}
}
@@ -16,11 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8;
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
public enum ClientboundPackets1_7 implements ClientboundPacketType {
public enum ClientboundPackets1_7_2_5 implements ClientboundPacketType {
KEEP_ALIVE, // 0x00
JOIN_GAME, // 0x01
CHAT_MESSAGE, // 0x02
@@ -18,23 +18,21 @@
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ServerboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPackets1_7, ClientboundPackets1_7, ServerboundPackets1_7, ServerboundPackets1_7> {
public static final ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<String, String>(Type.STRING) {
public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPackets1_7_2_5, ClientboundPackets1_7_2_5, ServerboundPackets1_7_2_5, ServerboundPackets1_7_2_5> {
public final static ValueTransformer<String, String> REMOVE_DASHES = new ValueTransformer<String, String>(Type.STRING) {
@Override
public String transform(PacketWrapper packetWrapper, String s) {
return s.replace("-", "");
@@ -42,65 +40,66 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
};
public Protocol1_7_2_5To1_7_6_10() {
super(ClientboundPackets1_7.class, ClientboundPackets1_7.class, ServerboundPackets1_7.class, ServerboundPackets1_7.class);
super(ClientboundPackets1_7_2_5.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class, ServerboundPackets1_7_2_5.class);
}
@Override
protected void registerPackets() {
//Login Success
this.registerClientbound(State.LOGIN, 0x02, 0x02, new PacketHandlers() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.STRING, REMOVE_DASHES);
map(Type.STRING);
map(Type.STRING, REMOVE_DASHES); // uuid
map(Type.STRING); // name
}
});
//Spawn Player
this.registerClientbound(ClientboundPackets1_7.SPAWN_PLAYER, new PacketHandlers() {
this.registerClientbound(ClientboundPackets1_7_2_5.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.STRING, REMOVE_DASHES);
map(Type.STRING);
handler(packetWrapper -> {
int size = packetWrapper.read(Type.VAR_INT);
for (int i = 0; i < size * 3; i++) packetWrapper.read(Type.STRING);
map(Type.VAR_INT); // entity id
map(Type.STRING, REMOVE_DASHES); // uuid
map(Type.STRING); // name
handler(packetWrapper -> { // delete data introduced in 1.7.6
final int size = packetWrapper.read(Type.VAR_INT); // data count
for (int i = 0; i < size; i++) {
packetWrapper.read(Type.STRING); // data name
packetWrapper.read(Type.STRING); // data value
packetWrapper.read(Type.STRING); // data signature
}
});
map(Type.INT);
map(Type.INT);
map(Type.INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.SHORT);
map(Types1_7_6_10.METADATA_LIST);
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // item in hand
map(Types1_7_6_10.METADATA_LIST); // metadata
}
});
//Teams
this.registerClientbound(ClientboundPackets1_7.TEAMS, new PacketHandlers() {
this.registerClientbound(ClientboundPackets1_7_2_5.TEAMS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
map(Type.STRING); // team name
map(Type.BYTE); // mode
handler(packetWrapper -> {
byte mode = packetWrapper.get(Type.BYTE, 0);
if (mode == 0 || mode == 2) {
packetWrapper.passthrough(Type.STRING);
packetWrapper.passthrough(Type.STRING);
packetWrapper.passthrough(Type.STRING);
packetWrapper.passthrough(Type.BYTE);
if (mode == 0 || mode == 2) { // team is created or information is updated
packetWrapper.passthrough(Type.STRING); // team display name
packetWrapper.passthrough(Type.STRING); // team prefix
packetWrapper.passthrough(Type.STRING); // team suffix
packetWrapper.passthrough(Type.BYTE); // friendly fire
}
if (mode == 0 || mode == 3 || mode == 4) {
if (mode == 0 || mode == 3 || mode == 4) { // team is created, player is added or player is removed
List<String> entryList = new ArrayList<>();
int size = packetWrapper.read(Type.SHORT);
final int size = packetWrapper.read(Type.SHORT);
for (int i = 0; i < size; i++) {
entryList.add(packetWrapper.read(Type.STRING));
}
entryList = entryList.stream()
.map(it -> it.length() > 16 ? it.substring(0, 16) : it)
.distinct()
.map(it -> it.length() > 16 ? it.substring(0, 16) : it) // trim to 16 characters
.distinct() // remove duplicates
.collect(Collectors.toList());
packetWrapper.write(Type.SHORT, (short) entryList.size());
@@ -112,9 +111,4 @@ public class Protocol1_7_2_5To1_7_6_10 extends AbstractProtocol<ClientboundPacke
}
});
}
@Override
public void init(UserConnection userConnection) {
}
}
@@ -16,11 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8;
package com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
public enum ServerboundPackets1_7 implements ServerboundPacketType {
public enum ServerboundPackets1_7_2_5 implements ServerboundPacketType {
KEEP_ALIVE, // 0x00
CHAT_MESSAGE, // 0x01
INTERACT_ENTITY, // 0x02
@@ -18,12 +18,20 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets.*;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.CompressionHandlerProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression.TrackingCompressionHandlerProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.ReplacementItemRewriter1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.*;
import com.viaversion.viarewind.utils.Ticker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.task.WorldBorderUpdateTask;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.Direction;
@@ -31,19 +39,26 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_8, ClientboundPackets1_7,
ServerboundPackets1_8, ServerboundPackets1_7> {
import java.util.concurrent.TimeUnit;
public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_8, ClientboundPackets1_7_2_5, ServerboundPackets1_8, ServerboundPackets1_7_2_5> {
private final ReplacementItemRewriter<Protocol1_7_6_10To1_8> itemRewriter = new ReplacementItemRewriter1_7_6_10(this);
private final MetadataRewriter metadataRewriter = new MetadataRewriter(this);
public Protocol1_7_6_10To1_8() {
super(ClientboundPackets1_8.class, ClientboundPackets1_7.class, ServerboundPackets1_8.class, ServerboundPackets1_7.class);
super(ClientboundPackets1_8.class, ClientboundPackets1_7_2_5.class, ServerboundPackets1_8.class, ServerboundPackets1_7_2_5.class);
}
@Override
protected void registerPackets() {
itemRewriter.register();
EntityPackets.register(this);
InventoryPackets.register(this);
PlayerPackets.register(this);
@@ -51,79 +66,98 @@ public class Protocol1_7_6_10To1_8 extends AbstractProtocol<ClientboundPackets1_
SpawnPackets.register(this);
WorldPackets.register(this);
this.registerClientbound(ClientboundPackets1_8.KEEP_ALIVE, new PacketHandlers() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT);
map(Type.STRING); // server hash
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // public key
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // verification token
}
});
this.cancelClientbound(ClientboundPackets1_8.SET_COMPRESSION); // unused
this.registerServerbound(ServerboundPackets1_7.KEEP_ALIVE, new PacketHandlers() {
this.registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_COMPRESSION.getId(), ClientboundLoginPackets.LOGIN_COMPRESSION.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT);
}
});
handler(wrapper -> {
final int threshold = wrapper.read(Type.VAR_INT);
//Encryption Request
this.registerClientbound(State.LOGIN, 0x01, 0x01, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING); //Server ID
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // Public key
map(Type.BYTE_ARRAY_PRIMITIVE, Type.SHORT_BYTE_ARRAY); // Verification token
}
});
//Set Compression
this.registerClientbound(State.LOGIN, 0x03, 0x03, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Via.getManager().getProviders().get(CompressionHandlerProvider.class)
.handleSetCompression(packetWrapper.user(), packetWrapper.read(Type.VAR_INT));
packetWrapper.cancel();
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onHandleLoginCompressionPacket(wrapper.user(), threshold);
wrapper.cancel();
});
}
});
//Encryption Response
this.registerServerbound(State.LOGIN, 0x01, 0x01, new PacketHandlers() {
this.cancelClientbound(ClientboundPackets1_8.SET_COMPRESSION); // unused
this.registerClientbound(ClientboundPackets1_8.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // Shared secret
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // Verification token
map(Type.VAR_INT, Type.INT); // id
}
});
this.registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // shared secret
map(Type.SHORT_BYTE_ARRAY, Type.BYTE_ARRAY_PRIMITIVE); // verification token
}
});
this.registerServerbound(ServerboundPackets1_7_2_5.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT); // id
}
});
}
@Override
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
Via.getManager().getProviders().get(CompressionHandlerProvider.class)
.handleTransform(packetWrapper.user());
Via.getManager().getProviders().get(CompressionHandlerProvider.class).onTransformPacket(packetWrapper.user());
// if (direction == Direction.CLIENTBOUND) {
// System.out.println("Pre: " + direction + " " + state + " " + packetWrapper.getId() + " " + ClientboundPackets1_8.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// } else {
// System.out.println("Pre: " + direction + " " + state + " " + packetWrapper.getId() + " " + ServerboundPackets1_7_2_5.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// }
super.transform(direction, state, packetWrapper);
// if (direction == Direction.CLIENTBOUND) {
// System.out.println("Post: " + direction + " " + state + " " + packetWrapper.getId() + " " + ClientboundPackets1_7_2_5.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// } else {
// System.out.println("Post: " + direction + " " + state + " " + packetWrapper.getId() + " " + ServerboundPackets1_8.values()[packetWrapper.getId()].getName() + ": " + packetWrapper);
// }
}
@Override
public void init(UserConnection userConnection) {
Ticker.init();
userConnection.put(new Windows(userConnection));
userConnection.put(new EntityTracker(userConnection));
userConnection.put(new PlayerPosition(userConnection));
userConnection.put(new InventoryTracker(userConnection));
userConnection.put(new EntityTracker1_7_6_10(userConnection, metadataRewriter));
userConnection.put(new PlayerSessionStorage(userConnection));
userConnection.put(new GameProfileStorage(userConnection));
userConnection.put(new Scoreboard(userConnection));
userConnection.put(new CompressionSendStorage(userConnection));
userConnection.put(new WorldBorder(userConnection));
userConnection.put(new PlayerAbilities(userConnection));
userConnection.put(new ClientWorld(userConnection));
userConnection.put(new CompressionStatusTracker(userConnection));
userConnection.put(new WorldBorderEmulator(userConnection));
if (!userConnection.has(ClientWorld.class)) {
userConnection.put(new ClientWorld());
}
}
@Override
public void register(ViaProviders providers) {
providers.register(CompressionHandlerProvider.class, new CompressionHandlerProvider());
providers.register(CompressionHandlerProvider.class, new TrackingCompressionHandlerProvider());
if (ViaRewind.getConfig().isEmulateWorldBorder()) {
Via.getManager().getScheduler().scheduleRepeating(new WorldBorderUpdateTask(), 0L, 50L, TimeUnit.MILLISECONDS);
}
}
@Override
public ReplacementItemRewriter<Protocol1_7_6_10To1_8> getItemRewriter() {
return itemRewriter;
}
public MetadataRewriter getMetadataRewriter() {
return metadataRewriter;
}
}
@@ -1,155 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.chunks;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ReplacementRegistry1_7_6_10to1_8;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.CustomByteType;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import java.io.ByteArrayOutputStream;
import java.util.zip.DeflaterOutputStream;
public class ChunkPacketTransformer {
private static byte[] transformChunkData(byte[] data, int primaryBitMask, boolean skyLight, boolean groundUp) throws Exception {
ByteBuf inputData = Unpooled.wrappedBuffer(data);
ByteBuf finalBuf = ByteBufAllocator.DEFAULT.buffer();
try {
ChunkSection[] sections = new ChunkSection[16];
for (int i = 0; i < 16; i++) {
if ((primaryBitMask & 1 << i) == 0) continue;
sections[i] = Types1_8.CHUNK_SECTION.read(inputData);
}
for (int i = 0; i < 16; i++) {
if ((primaryBitMask & 1 << i) == 0) continue;
ChunkSection section = sections[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int k = 0; k < palette.size(); k++) {
int blockData = palette.idByIndex(k);
blockData = ReplacementRegistry1_7_6_10to1_8.replace(blockData);
palette.setIdByIndex(k, blockData);
}
}
for (int i = 0; i < 16; i++) {
if ((primaryBitMask & 1 << i) == 0) continue;
ChunkSection section = sections[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < 4096; j++) {
int raw = palette.idAt(j);
finalBuf.writeByte(raw >> 4);
}
}
for (int i = 0; i < 16; i++) {
if ((primaryBitMask & 1 << i) == 0) continue;
ChunkSection section = sections[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < 4096; j += 2) {
int meta0 = palette.idAt(j) & 0xF;
int meta1 = palette.idAt(j + 1) & 0xF;
finalBuf.writeByte(meta1 << 4 | meta0);
}
}
int columnCount = Integer.bitCount(primaryBitMask);
// Block light
finalBuf.writeBytes(inputData, 2048 * columnCount);
// Skylight
if (skyLight) {
finalBuf.writeBytes(inputData, 2048 * columnCount);
}
if (groundUp && inputData.isReadable(256)) {
finalBuf.writeBytes(inputData, 256);
}
return Type.REMAINING_BYTES.read(finalBuf);
} finally {
finalBuf.release();
}
}
private static int calcSize(int i, boolean hasSkyLight, boolean hasBiome) {
int blocks = i * 2 * 16 * 16 * 16;
int blockLight = i * 16 * 16 * 16 / 2;
int skyLight = hasSkyLight ? i * 16 * 16 * 16 / 2 : 0;
int biome = hasBiome ? 256 : 0;
return blocks + blockLight + skyLight + biome;
}
public static void transformChunkBulk(PacketWrapper packetWrapper) throws Exception {
boolean skyLightSent = packetWrapper.read(Type.BOOLEAN);
int columnCount = packetWrapper.read(Type.VAR_INT);
int[] chunkX = new int[columnCount];
int[] chunkZ = new int[columnCount];
int[] primaryBitMask = new int[columnCount];
byte[][] data = new byte[columnCount][];
for (int i = 0; i < columnCount; i++) {
chunkX[i] = packetWrapper.read(Type.INT);
chunkZ[i] = packetWrapper.read(Type.INT);
primaryBitMask[i] = packetWrapper.read(Type.UNSIGNED_SHORT);
}
for (int i = 0; i < columnCount; i++) {
int size = calcSize(Integer.bitCount(primaryBitMask[i]), skyLightSent, true);
CustomByteType customByteType = new CustomByteType(size);
data[i] = transformChunkData(packetWrapper.read(customByteType), primaryBitMask[i], skyLightSent, true);
}
ByteArrayOutputStream compressedData = new ByteArrayOutputStream();
// todo compression level config
try (DeflaterOutputStream deflaterStream = new DeflaterOutputStream(compressedData)) {
for (int i = 0; i < columnCount; ++i) {
deflaterStream.write(data[i]);
}
}
packetWrapper.write(Type.SHORT, (short) columnCount);
packetWrapper.write(Type.INT, compressedData.size());
packetWrapper.write(Type.BOOLEAN, skyLightSent);
CustomByteType customByteType = new CustomByteType(compressedData.size());
packetWrapper.write(customByteType, compressedData.toByteArray());
for (int i = 0; i < columnCount; i++) {
packetWrapper.write(Type.INT, chunkX[i]);
packetWrapper.write(Type.INT, chunkZ[i]);
packetWrapper.write(Type.SHORT, (short) primaryBitMask[i]);
packetWrapper.write(Type.SHORT, (short) 0);
}
}
}
@@ -1,121 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.chunks;
import com.viaversion.viaversion.api.minecraft.chunks.NibbleArray;
public class ExtendedBlockStorage {
private final int yBase;
private byte[] blockLSBArray;
private NibbleArray blockMSBArray;
private NibbleArray blockMetadataArray;
private NibbleArray blocklightArray;
private NibbleArray skylightArray;
public ExtendedBlockStorage(int paramInt, boolean paramBoolean) {
this.yBase = paramInt;
this.blockLSBArray = new byte[4096];
this.blockMetadataArray = new NibbleArray(this.blockLSBArray.length);
this.blocklightArray = new NibbleArray(this.blockLSBArray.length);
if (paramBoolean) {
this.skylightArray = new NibbleArray(this.blockLSBArray.length);
}
}
public int getExtBlockMetadata(int paramInt1, int paramInt2, int paramInt3) {
return this.blockMetadataArray.get(paramInt1, paramInt2, paramInt3);
}
public void setExtBlockMetadata(int paramInt1, int paramInt2, int paramInt3, int paramInt4) {
this.blockMetadataArray.set(paramInt1, paramInt2, paramInt3, paramInt4);
}
public int getYLocation() {
return this.yBase;
}
public void setExtSkylightValue(int paramInt1, int paramInt2, int paramInt3, int paramInt4) {
this.skylightArray.set(paramInt1, paramInt2, paramInt3, paramInt4);
}
public int getExtSkylightValue(int paramInt1, int paramInt2, int paramInt3) {
return this.skylightArray.get(paramInt1, paramInt2, paramInt3);
}
public void setExtBlocklightValue(int paramInt1, int paramInt2, int paramInt3, int paramInt4) {
this.blocklightArray.set(paramInt1, paramInt2, paramInt3, paramInt4);
}
public int getExtBlocklightValue(int paramInt1, int paramInt2, int paramInt3) {
return this.blocklightArray.get(paramInt1, paramInt2, paramInt3);
}
public byte[] getBlockLSBArray() {
return this.blockLSBArray;
}
public boolean isEmpty() {
return this.blockMSBArray==null;
}
public void clearMSBArray() {
this.blockMSBArray = null;
}
public NibbleArray getBlockMSBArray() {
return this.blockMSBArray;
}
public NibbleArray getMetadataArray() {
return this.blockMetadataArray;
}
public NibbleArray getBlocklightArray() {
return this.blocklightArray;
}
public NibbleArray getSkylightArray() {
return this.skylightArray;
}
public void setBlockLSBArray(byte[] paramArrayOfByte) {
this.blockLSBArray = paramArrayOfByte;
}
public void setBlockMSBArray(NibbleArray paramNibbleArray) {
this.blockMSBArray = paramNibbleArray;
}
public void setBlockMetadataArray(NibbleArray paramNibbleArray) {
this.blockMetadataArray = paramNibbleArray;
}
public void setBlocklightArray(NibbleArray paramNibbleArray) {
this.blocklightArray = paramNibbleArray;
}
public void setSkylightArray(NibbleArray paramNibbleArray) {
this.skylightArray = paramNibbleArray;
}
public NibbleArray createBlockMSBArray() {
this.blockMSBArray = new NibbleArray(this.blockLSBArray.length);
return this.blockMSBArray;
}
}
@@ -1,280 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Vector3d;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.MetaType1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.ArrayList;
import java.util.List;
public class ArmorStandReplacement extends EntityReplacement1_7to1_8 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private int[] entityIds = null;
private double locX, locY, locZ;
private State currentState = null;
private boolean invisible = false;
private boolean nameTagVisible = false;
private String name = null;
private float yaw, pitch;
private float headYaw;
private boolean small = false;
private boolean marker = false;
public int getEntityId() {
return this.entityId;
}
private enum State {
HOLOGRAM, ZOMBIE
}
public ArmorStandReplacement(int entityId, UserConnection user) {
super(user);
this.entityId = entityId;
}
public void setLocation(double x, double y, double z) {
if (x != this.locX || y != this.locY || z != this.locZ) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation(false);
}
}
public void relMove(double x, double y, double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) return;
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation(false);
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw && this.pitch != pitch || this.headYaw != yaw) {
this.yaw = yaw;
this.headYaw = yaw;
this.pitch = pitch;
updateLocation(false);
}
}
public void setHeadYaw(float yaw) {
if (this.headYaw != yaw) {
this.headYaw = yaw;
updateLocation(false);
}
}
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateState();
}
public void updateState() {
byte flags = 0;
byte armorStandFlags = 0;
for (Metadata metadata : datawatcher) {
if (metadata.id() == 0 && metadata.metaType() == MetaType1_8.Byte) {
flags = ((Number) metadata.getValue()).byteValue();
} else if (metadata.id() == 2 && metadata.metaType() == MetaType1_8.String) {
name = metadata.getValue().toString();
if (name != null && name.equals("")) name = null;
} else if (metadata.id() == 10 && metadata.metaType() == MetaType1_8.Byte) {
armorStandFlags = ((Number) metadata.getValue()).byteValue();
} else if (metadata.id() == 3 && metadata.metaType() == MetaType1_8.Byte) {
nameTagVisible = ((Number) metadata.getValue()).byteValue() != 0;
}
}
invisible = (flags & 0x20) != 0;
small = (armorStandFlags & 0x01) != 0;
marker = (armorStandFlags & 0x10) != 0;
State prevState = currentState;
if (invisible && marker) {
currentState = State.HOLOGRAM;
} else {
currentState = State.ZOMBIE;
}
if (currentState != prevState) {
despawn();
spawn();
} else {
updateMetadata();
updateLocation(false);
}
}
public void updateLocation(boolean remount) {
if (entityIds == null) return;
if (currentState == State.ZOMBIE) {
updateZombieLocation();
} else if (currentState == State.HOLOGRAM) {
updateHologramLocation(remount);
}
}
private void updateZombieLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
private void updateHologramLocation(boolean remount) {
if(remount) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7.ATTACH_ENTITY, null, user);
detach.write(Type.INT, entityIds[1]);
detach.write(Type.INT, -1);
detach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(detach, Protocol1_7_6_10To1_8.class, true, true);
}
// Don't ask me where this offset is coming from
sendTeleport(entityIds[0], locX, (locY + (marker ? 54.85 : small ? 56 : 57)), locZ, 0, 0); // Skull
if(remount) {
sendTeleport(entityIds[1], locX, locY + 56.75, locZ, 0, 0); // Horse
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7.ATTACH_ENTITY, null, user);
attach.write(Type.INT, entityIds[1]);
attach.write(Type.INT, entityIds[0]);
attach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(attach, Protocol1_7_6_10To1_8.class, true, true);
}
}
public void updateMetadata() {
if (entityIds == null) return;
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_METADATA, null, user);
if (currentState == State.ZOMBIE) {
writeZombieMeta(metadataPacket);
} else if (currentState == State.HOLOGRAM) {
writeHologramMeta(metadataPacket);
} else {
return;
}
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class, true, true);
}
private void writeZombieMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[0]);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
if (metadata.id() < 0 || metadata.id() > 9) continue;
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
if (small) metadataList.add(new Metadata(12, MetaType1_8.Byte, (byte) 1));
MetadataRewriter.transform(Entity1_10Types.EntityType.ZOMBIE, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
private void writeHologramMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[1]);
List<Metadata> metadataList = new ArrayList<>();
metadataList.add(new Metadata(12, MetaType1_7_6_10.Int, -1700000));
metadataList.add(new Metadata(10, MetaType1_7_6_10.String, name));
metadataList.add(new Metadata(11, MetaType1_7_6_10.Byte, (byte) 1));
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
public void spawn() {
if (entityIds != null) despawn();
if (currentState == State.ZOMBIE) {
spawnZombie();
} else if (currentState == State.HOLOGRAM) {
spawnHologram();
}
updateMetadata();
updateLocation(true);
}
private void spawnZombie() {
sendSpawn(entityId, 54, locX, locY, locZ);
entityIds = new int[] {entityId};
}
private void spawnHologram() {
int[] entityIds = {entityId, additionalEntityId()};
PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7.SPAWN_ENTITY, null, user);
spawnSkull.write(Type.VAR_INT, entityIds[0]);
spawnSkull.write(Type.BYTE, (byte) 66);
spawnSkull.write(Type.INT, (int) (locX * 32.0));
spawnSkull.write(Type.INT, (int) (locY * 32.0));
spawnSkull.write(Type.INT, (int) (locZ * 32.0));
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.INT, 0);
PacketUtil.sendPacket(spawnSkull, Protocol1_7_6_10To1_8.class, true, true);
sendSpawn(entityIds[1], 100, locX, locY, locZ); // Horse
this.entityIds = entityIds;
}
private int additionalEntityId() {
return Integer.MAX_VALUE - 16000 - entityId;
}
public AABB getBoundingBox() {
double w = this.small ? 0.25 : 0.5;
double h = this.small ? 0.9875 : 1.975;
Vector3d min = new Vector3d(this.locX - w / 2, this.locY, this.locZ - w / 2);
Vector3d max = new Vector3d(this.locX + w / 2, this.locY + h, this.locZ + w / 2);
return new AABB(min, max);
}
public void despawn() {
if (entityIds == null) return;
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, user);
despawn.write(Type.BYTE, (byte) entityIds.length);
for (int id : entityIds) {
despawn.write(Type.INT, id);
}
entityIds = null;
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
}
}
@@ -1,121 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.ArrayList;
import java.util.List;
public class EndermiteReplacement extends EntityReplacement1_7to1_8 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
private float yaw, pitch;
private float headYaw;
public EndermiteReplacement(int entityId, UserConnection user) {
super(user);
this.entityId = entityId;
spawn();
}
public void setLocation(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
public void relMove(double x, double y, double z) {
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw || this.pitch != pitch) {
this.yaw = yaw;
this.pitch = pitch;
updateLocation();
}
}
public void setHeadYaw(float yaw) {
if (this.headYaw != yaw) {
this.headYaw = yaw;
updateLocation();
}
}
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateMetadata();
}
public void updateLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
public void updateMetadata() {
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_METADATA, user);
metadataPacket.write(Type.INT, entityId);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
MetadataRewriter.transform(Entity1_10Types.EntityType.SQUID, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class);
}
@Override
public void spawn() {
sendSpawn(entityId, 60, locX, locY, locZ);
}
@Override
public void despawn() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, user);
despawn.write(Types1_7_6_10.INT_ARRAY, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
}
public int getEntityId() {
return this.entityId;
}
}
@@ -1,80 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.ArrayList;
public abstract class EntityReplacement1_7to1_8 implements EntityReplacement {
protected final UserConnection user;
public EntityReplacement1_7to1_8(UserConnection user) {
this.user = user;
}
protected void sendTeleportWithHead(int entityId, double locX, double locY, double locZ, float yaw, float pitch, float headYaw) {
sendTeleport(entityId, locX, locY, locZ, yaw, pitch);
sendHeadYaw(entityId, headYaw);
}
protected void sendTeleport(int entityId, double locX, double locY, double locZ, float yaw, float pitch) {
PacketWrapper teleport = PacketWrapper.create(ClientboundPackets1_7.ENTITY_TELEPORT, null, user);
teleport.write(Type.INT, entityId);
teleport.write(Type.INT, (int) (locX * 32.0));
teleport.write(Type.INT, (int) (locY * 32.0));
teleport.write(Type.INT, (int) (locZ * 32.0));
teleport.write(Type.BYTE, (byte) ((yaw / 360f) * 256));
teleport.write(Type.BYTE, (byte) ((pitch / 360f) * 256));
PacketUtil.sendPacket(teleport, Protocol1_7_6_10To1_8.class, true, true);
}
protected void sendHeadYaw(int entityId, float headYaw) {
PacketWrapper head = PacketWrapper.create(ClientboundPackets1_7.ENTITY_HEAD_LOOK, null, user);
head.write(Type.INT, entityId);
head.write(Type.BYTE, (byte) ((headYaw / 360f) * 256));
PacketUtil.sendPacket(head, Protocol1_7_6_10To1_8.class, true, true);
}
protected void sendSpawn(int entityId, int type, double locX, double locY, double locZ) {
PacketWrapper spawn = PacketWrapper.create(ClientboundPackets1_7.SPAWN_MOB, null, user);
spawn.write(Type.VAR_INT, entityId);
spawn.write(Type.UNSIGNED_BYTE, (short) type); // type
spawn.write(Type.INT, (int) (locX * 32.0));
spawn.write(Type.INT, (int) (locY * 32.0));
spawn.write(Type.INT, (int) (locZ * 32.0));
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.BYTE, (byte) 0);
spawn.write(Type.SHORT, (short) 0);
spawn.write(Type.SHORT, (short) 0);
spawn.write(Type.SHORT, (short) 0);
spawn.write(Types1_7_6_10.METADATA_LIST, new ArrayList<>());
PacketUtil.sendPacket(spawn, Protocol1_7_6_10To1_8.class, true, true);
}
}
@@ -1,122 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.ArrayList;
import java.util.List;
public class GuardianReplacement extends EntityReplacement1_7to1_8 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
private float yaw, pitch;
private float headYaw;
public GuardianReplacement(int entityId, UserConnection user) {
super(user);
this.entityId = entityId;
spawn();
}
public void setLocation(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
public void relMove(double x, double y, double z) {
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw || this.pitch != pitch) {
this.yaw = yaw;
this.pitch = pitch;
updateLocation();
}
}
public void setHeadYaw(float yaw) {
if (this.headYaw != yaw) {
this.headYaw = yaw;
updateLocation();
}
}
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateMetadata();
}
public void updateLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
public void updateMetadata() {
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_METADATA, null, user);
metadataPacket.write(Type.INT, entityId);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
if (metadata.id() == 16 || metadata.id() == 17) continue;
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
MetadataRewriter.transform(Entity1_10Types.EntityType.SQUID, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class);
}
@Override
public void spawn() {
sendSpawn(entityId, 94, locX, locY, locZ);
}
@Override
public void despawn() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, user);
despawn.write(Types1_7_6_10.INT_ARRAY, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
}
public int getEntityId() {
return this.entityId;
}
}
@@ -1,121 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.ArrayList;
import java.util.List;
public class RabbitReplacement extends EntityReplacement1_7to1_8 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
private float yaw, pitch;
private float headYaw;
public RabbitReplacement(int entityId, UserConnection user) {
super(user);
this.entityId = entityId;
spawn();
}
public void setLocation(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
public void relMove(double x, double y, double z) {
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw || this.pitch != pitch) {
this.yaw = yaw;
this.pitch = pitch;
updateLocation();
}
}
public void setHeadYaw(float yaw) {
if (this.headYaw != yaw) {
this.headYaw = yaw;
updateLocation();
}
}
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
datawatcher.add(metadata);
}
updateMetadata();
}
public void updateLocation() {
sendTeleportWithHead(entityId, locX, locY, locZ, yaw, pitch, headYaw);
}
public void updateMetadata() {
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_METADATA, null, user);
metadataPacket.write(Type.INT, entityId);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : datawatcher) {
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
MetadataRewriter.transform(Entity1_10Types.EntityType.CHICKEN, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class, true, true);
}
@Override
public void spawn() {
sendSpawn(entityId, 93, locX, locY, locZ); // Chicken
}
@Override
public void despawn() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, user);
despawn.write(Types1_7_6_10.INT_ARRAY, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
}
public int getEntityId() {
return this.entityId;
}
}
@@ -1,136 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import java.util.ArrayList;
import java.util.List;
public class ItemRewriter {
public static Item toClient(Item item) {
if (item==null) return null;
CompoundTag tag = item.tag();
if (tag==null) item.setTag(tag = new CompoundTag());
CompoundTag viaVersionTag = new CompoundTag();
tag.put("ViaRewind1_7_6_10to1_8", viaVersionTag);
viaVersionTag.put("id", new ShortTag((short) item.identifier()));
viaVersionTag.put("data", new ShortTag(item.data()));
CompoundTag display = tag.get("display");
if (display!=null && display.contains("Name")) {
viaVersionTag.put("displayName", new StringTag((String) display.get("Name").getValue()));
}
if (display!=null && display.contains("Lore")) {
viaVersionTag.put("lore", new ListTag(((ListTag)display.get("Lore")).getValue()));
}
if (tag.contains("ench") || tag.contains("StoredEnchantments")) {
ListTag enchTag = tag.contains("ench") ? tag.get("ench") : tag.get("StoredEnchantments");
List<Tag> lore = new ArrayList<>();
for (Tag ench : new ArrayList<>(enchTag.getValue())) {
short id = ((NumberTag) ((CompoundTag)ench).get("id")).asShort();
short lvl = ((NumberTag) ((CompoundTag)ench).get("lvl")).asShort();
String s;
if (id==8) {
s = "§r§7Depth Strider ";
} else {
continue;
}
enchTag.remove(ench);
s += Enchantments.ENCHANTMENTS.getOrDefault(lvl, "enchantment.level." + lvl);
lore.add(new StringTag(s));
}
if (!lore.isEmpty()) {
if (display==null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag==null) display.put("Lore", loreTag = new ListTag(StringTag.class));
lore.addAll(loreTag.getValue());
loreTag.setValue(lore);
}
}
if (item.identifier()==387 && tag.contains("pages")) {
ListTag pages = tag.get("pages");
ListTag oldPages = new ListTag(StringTag.class);
viaVersionTag.put("pages", oldPages);
for (int i = 0; i<pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
oldPages.add(new StringTag(value));
value = ChatUtil.jsonToLegacy(value);
page.setValue(value);
}
}
ReplacementRegistry1_7_6_10to1_8.replace(item);
if (viaVersionTag.size()==2 && (short)viaVersionTag.get("id").getValue()==item.identifier() && (short)viaVersionTag.get("data").getValue()==item.data()) {
item.tag().remove("ViaRewind1_7_6_10to1_8");
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
public static Item toServer(Item item) {
if (item==null) return null;
CompoundTag tag = item.tag();
if (tag==null || !item.tag().contains("ViaRewind1_7_6_10to1_8")) return item;
CompoundTag viaVersionTag = tag.remove("ViaRewind1_7_6_10to1_8");
item.setIdentifier((short) viaVersionTag.get("id").getValue());
item.setData((Short) viaVersionTag.get("data").getValue());
if (viaVersionTag.contains("noDisplay")) tag.remove("display");
if (viaVersionTag.contains("displayName")) {
CompoundTag display = tag.get("display");
if (display==null) tag.put("display", display = new CompoundTag());
StringTag name = display.get("Name");
if (name==null) display.put("Name", new StringTag((String) viaVersionTag.get("displayName").getValue()));
else name.setValue((String) viaVersionTag.get("displayName").getValue());
} else if (tag.contains("display")) {
((CompoundTag)tag.get("display")).remove("Name");
}
if (item.identifier()==387) {
ListTag oldPages = viaVersionTag.get("pages");
tag.remove("pages");
tag.put("pages", oldPages);
}
return item;
}
}
@@ -1,123 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items;
import com.viaversion.viarewind.replacement.Replacement;
import com.viaversion.viarewind.storage.BlockState;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viarewind.replacement.ReplacementRegistry;
public class ReplacementRegistry1_7_6_10to1_8 {
private static final ReplacementRegistry registry = new ReplacementRegistry();
static {
registry.registerBlock(176, new Replacement(63));
registry.registerBlock(177, new Replacement(68));
registry.registerBlock(193, new Replacement(64));
registry.registerBlock(194, new Replacement(64));
registry.registerBlock(195, new Replacement(64));
registry.registerBlock(196, new Replacement(64));
registry.registerBlock(197, new Replacement(64));
registry.registerBlock(77, 5, new Replacement(69, 6));
registry.registerBlock(77, 13, new Replacement(69, 14));
registry.registerBlock(77, 0, new Replacement(69, 0));
registry.registerBlock(77, 8, new Replacement(69, 8));
registry.registerBlock(143, 5, new Replacement(69, 6));
registry.registerBlock(143, 13, new Replacement(69, 14));
registry.registerBlock(143, 0, new Replacement(69, 0));
registry.registerBlock(143, 8, new Replacement(69, 8));
registry.registerBlock(178, new Replacement(151));
registry.registerBlock(182, 0, new Replacement(44, 1));
registry.registerBlock(182, 8, new Replacement(44, 9));
registry.registerItem(425, new Replacement(323, "Banner"));
registry.registerItem(409, new Replacement(406, "Prismarine Shard"));
registry.registerItem(410, new Replacement(406, "Prismarine Crystal"));
registry.registerItem(416, new Replacement(280, "Armor Stand"));
registry.registerItem(423, new Replacement(363, "Raw Mutton"));
registry.registerItem(424, new Replacement(364, "Cooked Mutton"));
registry.registerItem(411, new Replacement(365, "Raw Rabbit"));
registry.registerItem(412, new Replacement(366, "Cooked Rabbit"));
registry.registerItem(413, new Replacement(282, "Rabbit Stew"));
registry.registerItem(414, new Replacement(375, "Rabbit's Foot"));
registry.registerItem(415, new Replacement(334, "Rabbit Hide"));
registry.registerItem(373, 8203, new Replacement(373, 0, "Potion of Leaping"));
registry.registerItem(373, 8235, new Replacement(373, 0, "Potion of Leaping"));
registry.registerItem(373, 8267, new Replacement(373, 0, "Potion of Leaping"));
registry.registerItem(373, 16395, new Replacement(373, 0, "Splash Potion of Leaping"));
registry.registerItem(373, 16427, new Replacement(373, 0, "Splash Potion of Leaping"));
registry.registerItem(373, 16459, new Replacement(373, 0, "Splash Potion of Leaping"));
registry.registerItem(383, 30, new Replacement(383, "Spawn ArmorStand"));
registry.registerItem(383, 67, new Replacement(383, "Spawn Endermite"));
registry.registerItem(383, 68, new Replacement(383, "Spawn Guardian"));
registry.registerItem(383, 101, new Replacement(383, "Spawn Rabbit"));
registry.registerItem(19, 1, new Replacement(19, 0, "Wet Sponge"));
registry.registerItem(182, new Replacement(44, 1, "Red Sandstone Slab"));
registry.registerItemBlock(166, new Replacement(20, "Barrier"));
registry.registerItemBlock(167, new Replacement(96, "Iron Trapdoor"));
registry.registerItemBlock(1, 1, new Replacement(1, 0, "Granite"));
registry.registerItemBlock(1, 2, new Replacement(1, 0, "Polished Granite"));
registry.registerItemBlock(1, 3, new Replacement(1, 0, "Diorite"));
registry.registerItemBlock(1, 4, new Replacement(1, 0, "Polished Diorite"));
registry.registerItemBlock(1, 5, new Replacement(1, 0, "Andesite"));
registry.registerItemBlock(1, 6, new Replacement(1, 0, "Polished Andesite"));
registry.registerItemBlock(168, 0, new Replacement(1, 0, "Prismarine"));
registry.registerItemBlock(168, 1, new Replacement(98, 0, "Prismarine Bricks"));
registry.registerItemBlock(168, 2, new Replacement(98, 1, "Dark Prismarine"));
registry.registerItemBlock(169, new Replacement(89, "Sea Lantern"));
registry.registerItemBlock(165, new Replacement(95, 5, "Slime Block"));
registry.registerItemBlock(179, 0, new Replacement(24, "Red Sandstone"));
registry.registerItemBlock(179, 1, new Replacement(24, "Chiseled Red Sandstone"));
registry.registerItemBlock(179, 2, new Replacement(24, "Smooth Sandstone"));
registry.registerItemBlock(181, new Replacement(43, 1, "Double Red Sandstone Slab"));
registry.registerItemBlock(180, new Replacement(128, "Red Sandstone Stairs"));
registry.registerItemBlock(188, new Replacement(85, "Spruce Fence"));
registry.registerItemBlock(189, new Replacement(85, "Birch Fence"));
registry.registerItemBlock(190, new Replacement(85, "Jungle Fence"));
registry.registerItemBlock(191, new Replacement(85, "Dark Oak Fence"));
registry.registerItemBlock(192, new Replacement(85, "Acacia Fence"));
registry.registerItemBlock(183, new Replacement(107, "Spruce Fence Gate"));
registry.registerItemBlock(184, new Replacement(107, "Birch Fence Gate"));
registry.registerItemBlock(185, new Replacement(107, "Jungle Fence Gate"));
registry.registerItemBlock(186, new Replacement(107, "Dark Oak Fence Gate"));
registry.registerItemBlock(187, new Replacement(107, "Acacia Fence Gate"));
registry.registerItemBlock(427, new Replacement(324, "Spruce Door"));
registry.registerItemBlock(428, new Replacement(324, "Birch Door"));
registry.registerItemBlock(429, new Replacement(324, "Jungle Door"));
registry.registerItemBlock(430, new Replacement(324, "Dark Oak Door"));
registry.registerItemBlock(431, new Replacement(324, "Acacia Door"));
registry.registerItemBlock(157, new Replacement(28, "Activator Rail"));
}
public static Item replace(Item item) {
return registry.replace(item);
}
public static int replace(int raw) {
int data = BlockState.extractData(raw);
Replacement replace = registry.replace(BlockState.extractId(raw), data);
return replace != null ? BlockState.stateToRaw(replace.getId(), replace.replaceData(data)) : raw;
}
public static Replacement getReplacement(int id, int data) {
return registry.replace(id, data);
}
}
@@ -1,60 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata;
import com.viaversion.viarewind.protocol.protocol1_8to1_7_6_10.metadata.MetaIndex1_8To1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.Optional;
public class MetaIndex1_7_6_10to1_8 {
private static final HashMap<Pair<Entity1_10Types.EntityType, Integer>, MetaIndex1_8To1_7_6_10> metadataRewrites = new HashMap<>();
static {
for (MetaIndex1_8To1_7_6_10 index : MetaIndex1_8To1_7_6_10.values())
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
private static Optional<MetaIndex1_8To1_7_6_10> getIndex(Entity1_10Types.EntityType type, int index) {
Pair pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
return Optional.empty();
}
public static MetaIndex1_8To1_7_6_10 searchIndex(Entity1_10Types.EntityType type, int index) {
Entity1_10Types.EntityType currentType = type;
do {
Optional<MetaIndex1_8To1_7_6_10> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
}
currentType = currentType.getParent();
} while (currentType != null);
return null;
}
}
@@ -0,0 +1,9 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
public class FurnaceData {
public short fuelLeft = 0;
public short maxFuel = 0;
public short progress = 0;
public short maxProgress = 200;
}
@@ -0,0 +1,184 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.Optional;
public enum MetaIndex1_7_6_10To1_8 {
ENTITY_FLAGS(EntityTypes1_10.EntityType.ENTITY, 0, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_AIR(EntityTypes1_10.EntityType.ENTITY, 1, MetaType1_7_6_10.Short, MetaType1_8.Short),
ENTITY_NAME_TAG(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 2, MetaType1_8.String),
ENTITY_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 3, MetaType1_8.Byte),
ENTITY_SILENT(EntityTypes1_10.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 4, MetaType1_8.Byte),
ENTITY_LIVING_HEALTH(EntityTypes1_10.EntityType.ENTITY_LIVING, 6, MetaType1_7_6_10.Float, MetaType1_8.Float),
ENTITY_LIVING_POTION_EFFECT_COLOR(EntityTypes1_10.EntityType.ENTITY_LIVING, 7, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENTITY_LIVING_IS_POTION_EFFECT_AMBIENT(EntityTypes1_10.EntityType.ENTITY_LIVING, 8, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_ARROWS(EntityTypes1_10.EntityType.ENTITY_LIVING, 9, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_NAME_TAG(EntityTypes1_10.EntityType.ENTITY_LIVING, 10, MetaType1_7_6_10.String, 2, MetaType1_8.String),
ENTITY_LIVING_NAME_TAG_VISIBILITY(EntityTypes1_10.EntityType.ENTITY_LIVING, 11, MetaType1_7_6_10.Byte, 3, MetaType1_8.Byte),
ENTITY_LIVING_AI(EntityTypes1_10.EntityType.ENTITY_LIVING, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Byte),
ENTITY_AGEABLE_AGE(EntityTypes1_10.EntityType.ENTITY_AGEABLE, 12, MetaType1_7_6_10.Int, MetaType1_8.Byte),
ARMOR_STAND_FLAGS(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 10, MetaType1_8.Byte),
ARMOR_STAND_HEAD_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 11, MetaType1_8.Rotation),
ARMOR_STAND_BODY_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 12, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 13, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_ARM_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 14, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_LEG_POSITION(EntityTypes1_10.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Rotation),
HUMAN_SKIN_FLAGS(EntityTypes1_10.EntityType.ENTITY_HUMAN, 16, MetaType1_7_6_10.Byte, 10, MetaType1_8.Byte),
HUMAN_UNUSED(EntityTypes1_10.EntityType.ENTITY_HUMAN, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Byte),
HUMAN_ABSORPTION_HEATS(EntityTypes1_10.EntityType.ENTITY_HUMAN, 17, MetaType1_7_6_10.Float, MetaType1_8.Float),
HUMAN_SCORE(EntityTypes1_10.EntityType.ENTITY_HUMAN, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_FLAGS(EntityTypes1_10.EntityType.HORSE, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_TYPE(EntityTypes1_10.EntityType.HORSE, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
HORSE_COLOR(EntityTypes1_10.EntityType.HORSE, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_OWNER(EntityTypes1_10.EntityType.HORSE, 21, MetaType1_7_6_10.String, MetaType1_8.String),
HORSE_ARMOR(EntityTypes1_10.EntityType.HORSE, 22, MetaType1_7_6_10.Int, MetaType1_8.Int),
BAT_HANGING(EntityTypes1_10.EntityType.BAT, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_FLAGS(EntityTypes1_10.EntityType.ENTITY_TAMEABLE_ANIMAL, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_OWNER(EntityTypes1_10.EntityType.ENTITY_TAMEABLE_ANIMAL, 17, MetaType1_7_6_10.String, MetaType1_8.String),
OCELOT_TYPE(EntityTypes1_10.EntityType.OCELOT, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_FLAGS(EntityTypes1_10.EntityType.WOLF, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_HEALTH(EntityTypes1_10.EntityType.WOLF, 18, MetaType1_7_6_10.Float, MetaType1_8.Float),
WOLF_BEGGING(EntityTypes1_10.EntityType.WOLF, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_COLLAR_COLOR(EntityTypes1_10.EntityType.WOLF, 20, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
PIG_SADDLE(EntityTypes1_10.EntityType.PIG, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SHEEP_COLOR_OR_SHEARED(EntityTypes1_10.EntityType.SHEEP, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
VILLAGER_TYPE(EntityTypes1_10.EntityType.VILLAGER, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENDERMAN_CARRIED_BLOCK(EntityTypes1_10.EntityType.ENDERMAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Short),
ENDERMAN_CARRIED_BLOCK_DATA(EntityTypes1_10.EntityType.ENDERMAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
ENDERMAN_IS_SCREAMING(EntityTypes1_10.EntityType.ENDERMAN, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CHILD(EntityTypes1_10.EntityType.ZOMBIE, 12, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_VILLAGER(EntityTypes1_10.EntityType.ZOMBIE, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CONVERTING(EntityTypes1_10.EntityType.ZOMBIE, 14, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
BLAZE_ON_FIRE(EntityTypes1_10.EntityType.BLAZE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SPIDER_CLIMBING(EntityTypes1_10.EntityType.SPIDER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_STATE(EntityTypes1_10.EntityType.CREEPER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_POWERED(EntityTypes1_10.EntityType.CREEPER, 17, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_STATE(EntityTypes1_10.EntityType.GHAST, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_IS_POWERED(EntityTypes1_10.EntityType.GHAST, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
SLIME_SIZE(EntityTypes1_10.EntityType.SLIME, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SKELETON_TYPE(EntityTypes1_10.EntityType.SKELETON, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITCH_AGGRESSIVE(EntityTypes1_10.EntityType.WITCH, 21, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
IRON_GOLEM_IS_PLAYER_CREATED(EntityTypes1_10.EntityType.IRON_GOLEM, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITHER_WATCHED_TARGET_1(EntityTypes1_10.EntityType.WITHER, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TARGET_2(EntityTypes1_10.EntityType.WITHER, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TARGET_3(EntityTypes1_10.EntityType.WITHER, 19, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_INVULNERABLE_TIME(EntityTypes1_10.EntityType.WITHER, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
GUARDIAN_FLAGS(EntityTypes1_10.EntityType.GUARDIAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
GUARDIAN_TARGET(EntityTypes1_10.EntityType.GUARDIAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Int),
BOAT_TIME_SINCE_HIT(EntityTypes1_10.EntityType.BOAT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_FORWARD_DIRECTION(EntityTypes1_10.EntityType.BOAT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_DAMAGE_TAKEN(EntityTypes1_10.EntityType.BOAT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_SHAKING_POWER(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHAKING_DIRECTION(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_DAMAGE_TAKEN(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_BLOCK_INSIDE(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_BLOCK_Y(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 21, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHOW_BLOCK(EntityTypes1_10.EntityType.MINECART_ABSTRACT, 22, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FURNACE_MINECART_IS_POWERED(EntityTypes1_10.EntityType.MINECART_FURNACE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ITEM_ITEM(EntityTypes1_10.EntityType.DROPPED_ITEM, 10, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ARROW_IS_CRITICAL(EntityTypes1_10.EntityType.ARROW, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FIREWORK_INFO(EntityTypes1_10.EntityType.FIREWORK, 8, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ITEM_FRAME_ITEM(EntityTypes1_10.EntityType.ITEM_FRAME, 2, MetaType1_7_6_10.Slot, 8, MetaType1_8.Slot),
ITEM_FRAME_ROTATION(EntityTypes1_10.EntityType.ITEM_FRAME, 3, MetaType1_7_6_10.Byte, 9, MetaType1_8.Byte),
ENDER_CRYSTAL_HEALTH(EntityTypes1_10.EntityType.ENDER_CRYSTAL, 8, MetaType1_7_6_10.Int, 9, MetaType1_8.Int),
;
private final static HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex1_7_6_10To1_8> metadataRewrites = new HashMap<>();
static {
for (MetaIndex1_7_6_10To1_8 index : MetaIndex1_7_6_10To1_8.values()) {
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
}
private final EntityTypes1_10.EntityType clazz;
private final int newIndex;
private final MetaType1_8 newType;
private final MetaType1_7_6_10 oldType;
private final int index;
MetaIndex1_7_6_10To1_8(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.newIndex = index;
this.oldType = oldType;
this.newType = newType;
}
MetaIndex1_7_6_10To1_8(EntityTypes1_10.EntityType type, int index, MetaType1_7_6_10 oldType, int newIndex, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.oldType = oldType;
this.newIndex = newIndex;
this.newType = newType;
}
private static Optional<MetaIndex1_7_6_10To1_8> getIndex(EntityTypes1_10.EntityType type, int index) {
Pair<EntityTypes1_10.EntityType, Integer> pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
return Optional.empty();
}
public EntityTypes1_10.EntityType getClazz() {
return clazz;
}
public int getNewIndex() {
return newIndex;
}
public MetaType1_8 getNewType() {
return newType;
}
public MetaType1_7_6_10 getOldType() {
return oldType;
}
public int getIndex() {
return index;
}
public static MetaIndex1_7_6_10To1_8 searchIndex(EntityTypes1_10.EntityType type, int index) {
EntityTypes1_10.EntityType currentType = type;
do {
Optional<MetaIndex1_7_6_10To1_8> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
}
currentType = currentType.getParent();
} while (currentType != null);
return null;
}
}
@@ -16,11 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
import java.util.HashMap;
public enum Particle {
public enum ParticleIndex1_7_6_10 {
EXPLOSION_NORMAL("explode"),
EXPLOSION_LARGE("largeexplode"),
EXPLOSION_HUGE("hugeexplosion"),
@@ -66,33 +66,32 @@ public enum Particle {
public final String name;
public final int extra;
private static final HashMap<String, Particle> particleMap = new HashMap();
private final static HashMap<String, ParticleIndex1_7_6_10> particleMap = new HashMap<>();
Particle(String name) {
ParticleIndex1_7_6_10(String name) {
this(name, 0);
}
Particle(String name, int extra) {
ParticleIndex1_7_6_10(String name, int extra) {
this.name = name;
this.extra = extra;
}
public static Particle find(String part) {
public static ParticleIndex1_7_6_10 find(String part) {
return particleMap.get(part);
}
public static Particle find(int id) {
if (id<0) return null;
Particle[] values = Particle.values();
return id>=values.length ? null : values[id];
public static ParticleIndex1_7_6_10 find(int id) {
if (id < 0) return null;
ParticleIndex1_7_6_10[] values = ParticleIndex1_7_6_10.values();
return id >= values.length ? null : values[id];
}
static {
Particle[] particles = values();
ParticleIndex1_7_6_10[] particles = values();
for (Particle particle : particles) {
for (ParticleIndex1_7_6_10 particle : particles) {
particleMap.put(particle.name, particle);
}
}
}
@@ -0,0 +1,318 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Vector3d;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import java.util.ArrayList;
import java.util.List;
public class VirtualHologramEntity {
private final List<Metadata> metadataTracker = new ArrayList<>();
private double locX, locY, locZ;
private final UserConnection user;
private final MetadataRewriter metadataRewriter;
private final int entityId;
private int[] entityIds = null;
private State currentState = null;
private boolean invisible = false;
private String name = null;
private float yaw, pitch;
private float headYaw;
private boolean small = false;
private boolean marker = false;
public VirtualHologramEntity(final UserConnection user, final MetadataRewriter metadataRewriter, final int entityId) {
this.user = user;
this.metadataRewriter = metadataRewriter;
this.entityId = entityId;
}
public void updateReplacementPosition(double x, double y, double z) {
if (x == this.locX && y == this.locY && z == this.locZ) {
return;
}
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation(false);
}
public void handleOriginalMovementPacket(double x, double y, double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) {
return;
}
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation(false);
}
public void setYawPitch(float yaw, float pitch) {
if (this.yaw == yaw || this.headYaw == yaw || this.pitch == pitch) {
return;
}
this.yaw = yaw;
this.headYaw = yaw;
this.pitch = pitch;
updateLocation(false);
}
public void setHeadYaw(float yaw) {
if (this.headYaw == yaw) {
return;
}
this.headYaw = yaw;
updateLocation(false);
}
public void updateMetadata(final List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
metadataTracker.removeIf(m -> m.id() == metadata.id());
metadataTracker.add(metadata);
}
updateState();
}
public void updateState() {
byte flags = 0;
byte armorStandFlags = 0;
for (Metadata metadata : metadataTracker) {
if (metadata.id() == 0 && metadata.metaType() == MetaType1_8.Byte) {
flags = ((Number) metadata.getValue()).byteValue();
} else if (metadata.id() == 2 && metadata.metaType() == MetaType1_8.String) {
name = metadata.getValue().toString();
if (name != null && name.isEmpty()) name = null;
} else if (metadata.id() == 10 && metadata.metaType() == MetaType1_8.Byte) {
armorStandFlags = ((Number) metadata.getValue()).byteValue();
}
}
invisible = (flags & 0x20) != 0;
small = (armorStandFlags & 0x01) != 0;
marker = (armorStandFlags & 0x10) != 0;
State prevState = currentState;
if (invisible && name != null) {
currentState = State.HOLOGRAM;
} else {
currentState = State.ZOMBIE;
}
if (currentState != prevState) {
deleteEntity();
sendSpawnPacket();
} else {
updateMetadata();
updateLocation(false);
}
}
public void updateLocation(boolean remount) {
if (entityIds == null) return;
if (currentState == State.ZOMBIE) {
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
final PacketWrapper entityHeadLook = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_HEAD_LOOK, user);
entityHeadLook.write(Type.INT, entityId);
entityHeadLook.write(Type.BYTE, (byte) ((headYaw / 360f) * 256));
PacketUtil.sendPacket(entityHeadLook, Protocol1_7_6_10To1_8.class, true, true);
} else if (currentState == State.HOLOGRAM) {
if (remount) {
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, null, user);
detach.write(Type.INT, entityIds[1]);
detach.write(Type.INT, -1);
detach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(detach, Protocol1_7_6_10To1_8.class, true, true);
}
// Don't ask me where this offset is coming from
teleportEntity(entityIds[0], locX, (locY + (marker ? 54.85 : small ? 56 : 57) - 0.16), locZ, 0, 0); // Skull
if (remount) {
teleportEntity(entityIds[1], locX, locY + 56.75, locZ, 0, 0); // Horse
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7_2_5.ATTACH_ENTITY, null, user);
attach.write(Type.INT, entityIds[1]);
attach.write(Type.INT, entityIds[0]);
attach.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(attach, Protocol1_7_6_10To1_8.class, true, true);
}
}
}
protected void teleportEntity(final int entityId, final double x, final double y, final double z, final float yaw, final float pitch) {
final PacketWrapper entityTeleport = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_TELEPORT, user);
entityTeleport.write(Type.INT, entityId); // entity id
entityTeleport.write(Type.INT, (int) (x * 32.0)); // x
entityTeleport.write(Type.INT, (int) (y * 32.0)); // y
entityTeleport.write(Type.INT, (int) (z * 32.0)); // z
entityTeleport.write(Type.BYTE, (byte) ((yaw / 360f) * 256)); // yaw
entityTeleport.write(Type.BYTE, (byte) ((pitch / 360f) * 256)); // pitch
PacketUtil.sendPacket(entityTeleport, Protocol1_7_6_10To1_8.class, true, true);
}
protected void spawnEntity(final int entityId, final int type, final double locX, final double locY, final double locZ) {
final PacketWrapper spawnMob = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_MOB, null, user);
spawnMob.write(Type.VAR_INT, entityId); // entity id
spawnMob.write(Type.UNSIGNED_BYTE, (short) type); // type
spawnMob.write(Type.INT, (int) (locX * 32.0)); // x
spawnMob.write(Type.INT, (int) (locY * 32.0)); // y
spawnMob.write(Type.INT, (int) (locZ * 32.0)); // z
spawnMob.write(Type.BYTE, (byte) 0); // yaw
spawnMob.write(Type.BYTE, (byte) 0); // pitch
spawnMob.write(Type.BYTE, (byte) 0); // head pitch
spawnMob.write(Type.SHORT, (short) 0); // velocity x
spawnMob.write(Type.SHORT, (short) 0); // velocity y
spawnMob.write(Type.SHORT, (short) 0); // velocity z
spawnMob.write(Types1_7_6_10.METADATA_LIST, new ArrayList<>()); // metadata
PacketUtil.sendPacket(spawnMob, Protocol1_7_6_10To1_8.class, true, true);
}
public void updateMetadata() {
if (entityIds == null) return;
PacketWrapper metadataPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_METADATA, null, user);
if (currentState == State.ZOMBIE) {
writeZombieMeta(metadataPacket);
} else if (currentState == State.HOLOGRAM) {
writeHologramMeta(metadataPacket);
} else {
return;
}
PacketUtil.sendPacket(metadataPacket, Protocol1_7_6_10To1_8.class, true, true);
}
private void writeZombieMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[0]);
List<Metadata> metadataList = new ArrayList<>();
for (Metadata metadata : metadataTracker) {
if (metadata.id() < 0 || metadata.id() > 9) continue;
metadataList.add(new Metadata(metadata.id(), metadata.metaType(), metadata.getValue()));
}
if (small) metadataList.add(new Metadata(12, MetaType1_8.Byte, (byte) 1));
metadataRewriter.transform(EntityTypes1_10.EntityType.ZOMBIE, metadataList);
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
private void writeHologramMeta(PacketWrapper metadataPacket) {
metadataPacket.write(Type.INT, entityIds[1]);
List<Metadata> metadataList = new ArrayList<>();
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_AGEABLE_AGE.getIndex(), MetaType1_7_6_10.Int, -1700000));
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG.getIndex(), MetaType1_7_6_10.String, name));
metadataList.add(new Metadata(MetaIndex1_7_6_10To1_8.ENTITY_LIVING_NAME_TAG_VISIBILITY.getIndex(), MetaType1_7_6_10.Byte, (byte) 1));
metadataPacket.write(Types1_7_6_10.METADATA_LIST, metadataList);
}
public void sendSpawnPacket() {
if (entityIds != null) deleteEntity();
if (currentState == State.ZOMBIE) {
spawnEntity(entityId, 54, locX, locY, locZ);
entityIds = new int[]{entityId};
} else if (currentState == State.HOLOGRAM) {
int[] entityIds = {entityId, additionalEntityId()};
PacketWrapper spawnSkull = PacketWrapper.create(ClientboundPackets1_7_2_5.SPAWN_ENTITY, null, user);
spawnSkull.write(Type.VAR_INT, entityIds[0]);
spawnSkull.write(Type.BYTE, (byte) 66);
spawnSkull.write(Type.INT, (int) (locX * 32.0));
spawnSkull.write(Type.INT, (int) (locY * 32.0));
spawnSkull.write(Type.INT, (int) (locZ * 32.0));
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.BYTE, (byte) 0);
spawnSkull.write(Type.INT, 0);
PacketUtil.sendPacket(spawnSkull, Protocol1_7_6_10To1_8.class, true, true);
spawnEntity(entityIds[1], 100, locX, locY, locZ); // Horse
this.entityIds = entityIds;
}
updateMetadata();
updateLocation(true);
}
public AABB getBoundingBox() {
final double width = this.small ? 0.25 : 0.5;
final double height = this.small ? 0.9875 : 1.975;
final Vector3d min = new Vector3d(this.locX - width / 2, this.locY, this.locZ - width / 2);
final Vector3d max = new Vector3d(this.locX + width / 2, this.locY + height, this.locZ + width / 2);
return new AABB(min, max);
}
private int additionalEntityId() {
return Integer.MAX_VALUE - 16000 - entityId;
}
public void deleteEntity() {
if (entityIds == null) return;
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.DESTROY_ENTITIES, null, user);
despawn.write(Type.BYTE, (byte) entityIds.length);
for (int id : entityIds) {
despawn.write(Type.INT, id);
}
entityIds = null;
PacketUtil.sendPacket(despawn, Protocol1_7_6_10To1_8.class, true, true);
}
private enum State {
HOLOGRAM, ZOMBIE
}
public int getEntityId() {
return entityId;
}
}
@@ -18,26 +18,19 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ItemRewriter;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.List;
import java.util.UUID;
@@ -45,39 +38,33 @@ import java.util.UUID;
public class EntityPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
/* OUTGOING */
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EQUIPMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.SHORT); //Slot
map(Type.ITEM, Types1_7_6_10.COMPRESSED_NBT_ITEM); //Item
handler(packetWrapper -> {
Item item = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
ItemRewriter.toClient(item);
packetWrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.SHORT); // slot
map(Type.ITEM1_8, Types1_7_6_10.COMPRESSED_NBT_ITEM); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int id = packetWrapper.get(Type.INT, 0);
int limit = tracker.getPlayerId() == id ? 3 : 4;
if (packetWrapper.get(Type.SHORT, 0) > limit) packetWrapper.cancel();
});
handler(packetWrapper -> {
short slot = packetWrapper.get(Type.SHORT, 0);
if (packetWrapper.isCancelled()) return;
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
UUID uuid = tracker.getPlayerUUID(packetWrapper.get(Type.INT, 0));
handler(wrapper -> {
final short slot = wrapper.get(Type.SHORT, 0);
final UUID uuid = wrapper.user().get(EntityTracker1_7_6_10.class).getPlayerUUID(wrapper.get(Type.INT, 0));
if (uuid == null) return;
Item item = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
tracker.setPlayerEquipment(uuid, item, slot);
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
wrapper.user().get(PlayerSessionStorage.class).setPlayerEquipment(uuid, item, slot);
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
final GameProfileStorage storage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile profile = storage.get(uuid);
if (profile != null && profile.gamemode == 3) packetWrapper.cancel();
if (profile != null && profile.gamemode == 3) { // spectator mode didn't exist in 1.7.10
wrapper.cancel();
}
});
}
});
@@ -85,84 +72,74 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.USE_BED, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.UNSIGNED_BYTE, (short) position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.VAR_INT, Type.INT); // entity id
map(Type.POSITION1_8, Types1_7_6_10.U_BYTE_POSITION); // position
}
});
protocol.registerClientbound(ClientboundPackets1_8.COLLECT_ITEM, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Collected Entity ID
map(Type.VAR_INT, Type.INT); //Collector Entity ID
map(Type.VAR_INT, Type.INT); // collected entity id
map(Type.VAR_INT, Type.INT); // collector entity id
handler(wrapper -> wrapper.user().get(EntityTracker1_7_6_10.class).removeEntity(wrapper.get(Type.INT, 0)));
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_VELOCITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.SHORT); //velX
map(Type.SHORT); //velY
map(Type.SHORT); //velZ
map(Type.VAR_INT, Type.INT); // entity id
map(Type.SHORT); // velocity x
map(Type.SHORT); // velocity y
map(Type.SHORT); // velocity z
}
});
protocol.registerClientbound(ClientboundPackets1_8.DESTROY_ENTITIES, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int[] entityIds = packetWrapper.read(Type.VAR_INT_ARRAY_PRIMITIVE);
map(Type.VAR_INT_ARRAY_PRIMITIVE, Types1_7_6_10.BYTE_INT_ARRAY); // entity ids
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
for (int entityId : entityIds) tracker.removeEntity(entityId);
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
List<List<Integer>> parts = Lists.partition(Ints.asList(entityIds), Byte.MAX_VALUE);
for (int i = 0; i < parts.size() - 1; i++) {
PacketWrapper destroy = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES,
packetWrapper.user());
destroy.write(Types1_7_6_10.INT_ARRAY, parts.get(i).stream()
.mapToInt(Integer::intValue).toArray());
PacketUtil.sendPacket(destroy, Protocol1_7_6_10To1_8.class);
for (int entityId : wrapper.get(Types1_7_6_10.BYTE_INT_ARRAY, 0)) {
tracker.removeEntity(entityId);
}
packetWrapper.write(Types1_7_6_10.INT_ARRAY, parts.get(parts.size() - 1).stream()
.mapToInt(Integer::intValue).toArray());
}); //Entity Id Array
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.VAR_INT, Type.INT); // entity id
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //x
map(Type.BYTE); //y
map(Type.BYTE); //z
map(Type.BOOLEAN, Type.NOTHING);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.BYTE, 0);
int y = packetWrapper.get(Type.BYTE, 1);
int z = packetWrapper.get(Type.BYTE, 2);
replacement.relMove(x / 32.0, y / 32.0, z / 32.0);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // x
map(Type.BYTE); // y
map(Type.BYTE); // z
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.BYTE, 0);
final int y = wrapper.get(Type.BYTE, 1);
final int z = wrapper.get(Type.BYTE, 2);
hologram.handleOriginalMovementPacket(x / 32.0, y / 32.0, z / 32.0);
}
});
}
@@ -171,19 +148,21 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //yaw
map(Type.BYTE); //pitch
map(Type.BOOLEAN, Type.NOTHING);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
int pitch = packetWrapper.get(Type.BYTE, 1);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int yaw = wrapper.get(Type.BYTE, 0);
final int pitch = wrapper.get(Type.BYTE, 1);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
@@ -192,26 +171,29 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //x
map(Type.BYTE); //y
map(Type.BYTE); //z
map(Type.BYTE); //yaw
map(Type.BYTE); //pitch
map(Type.BOOLEAN, Type.NOTHING);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.BYTE, 0);
int y = packetWrapper.get(Type.BYTE, 1);
int z = packetWrapper.get(Type.BYTE, 2);
int yaw = packetWrapper.get(Type.BYTE, 3);
int pitch = packetWrapper.get(Type.BYTE, 4);
replacement.relMove(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // x
map(Type.BYTE); // y
map(Type.BYTE); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.BYTE, 0);
final int y = wrapper.get(Type.BYTE, 1);
final int z = wrapper.get(Type.BYTE, 2);
final int yaw = wrapper.get(Type.BYTE, 3);
final int pitch = wrapper.get(Type.BYTE, 4);
hologram.handleOriginalMovementPacket(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
@@ -220,36 +202,37 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_TELEPORT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.INT); //x
map(Type.INT); //y
map(Type.INT); //z
map(Type.BYTE); //yaw
map(Type.BYTE); //pitch
map(Type.BOOLEAN, Type.NOTHING);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
Entity1_10Types.EntityType type = tracker.getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.MINECART_ABSTRACT) {
int y = packetWrapper.get(Type.INT, 2);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
read(Type.BOOLEAN); // on ground
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final int entityId = wrapper.get(Type.INT, 0);
final EntityTypes1_10.EntityType type = tracker.getEntityMap().get(entityId);
if (type == EntityTypes1_10.EntityType.MINECART_ABSTRACT) { // TODO | Realign all entities?
int y = wrapper.get(Type.INT, 2);
y += 12;
packetWrapper.set(Type.INT, 2, y);
wrapper.set(Type.INT, 2, y);
}
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.INT, 1);
int y = packetWrapper.get(Type.INT, 2);
int z = packetWrapper.get(Type.INT, 3);
int yaw = packetWrapper.get(Type.BYTE, 0);
int pitch = packetWrapper.get(Type.BYTE, 1);
replacement.setLocation(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(entityId);
if (hologram != null) {
wrapper.cancel();
final int x = wrapper.get(Type.INT, 1);
final int y = wrapper.get(Type.INT, 2);
final int z = wrapper.get(Type.INT, 3);
final int yaw = wrapper.get(Type.BYTE, 0);
final int pitch = wrapper.get(Type.BYTE, 1);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
}
@@ -258,16 +241,18 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_HEAD_LOOK, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //Head yaw
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
replacement.setHeadYaw(yaw * 360f / 256);
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // head yaw
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final VirtualHologramEntity hologram = tracker.getVirtualHologramMap().get(wrapper.get(Type.INT, 0));
if (hologram != null) {
wrapper.cancel();
final int yaw = wrapper.get(Type.BYTE, 0);
hologram.setHeadYaw(yaw * 360f / 256);
}
});
}
@@ -276,16 +261,19 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ATTACH_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.INT);
map(Type.BOOLEAN);
map(Type.INT); // riding entity id
map(Type.INT); // vehicle entity id
map(Type.BOOLEAN); // leash state
handler(packetWrapper -> {
boolean leash = packetWrapper.get(Type.BOOLEAN, 0);
if (leash) return;
int passenger = packetWrapper.get(Type.INT, 0);
int vehicle = packetWrapper.get(Type.INT, 1);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.setPassenger(vehicle, passenger);
final boolean leash = packetWrapper.get(Type.BOOLEAN, 0);
if (!leash) {
final EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
final int passenger = packetWrapper.get(Type.INT, 0);
final int vehicle = packetWrapper.get(Type.INT, 1);
tracker.setPassenger(vehicle, passenger);
}
});
}
});
@@ -293,23 +281,24 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_METADATA, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); //Metadata
map(Type.VAR_INT, Type.INT); // entity id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
int entityId = wrapper.get(Type.INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (tracker.getClientEntityTypes().containsKey(entityId)) {
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
final int entityId = wrapper.get(Type.INT, 0);
final List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.getEntityReplacementMap().containsKey(entityId)) {
tracker.updateMetadata(entityId, metadataList);
wrapper.cancel();
return;
}
if (tracker.getEntityMap().containsKey(entityId)) {
protocol.getMetadataRewriter().transform(tracker.getEntityMap().get(entityId), metadataList);
if (metadataList.isEmpty()) {
wrapper.cancel();
replacement.updateMetadata(metadataList);
} else {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityId), metadataList);
if (metadataList.isEmpty()) wrapper.cancel();
}
} else {
tracker.addMetadataToBuffer(entityId, metadataList);
wrapper.cancel();
}
});
@@ -319,43 +308,44 @@ public class EntityPackets {
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //Effect Id
map(Type.BYTE); //Amplifier
map(Type.VAR_INT, Type.SHORT); //Duration
map(Type.BYTE, Type.NOTHING); //Hide Particles
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // effect id
map(Type.BYTE); // amplifier
map(Type.VAR_INT, Type.SHORT); // duration
read(Type.BYTE); // hide particles
}
});
protocol.registerClientbound(ClientboundPackets1_8.REMOVE_ENTITY_EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
map(Type.BYTE); //Effect Id
map(Type.VAR_INT, Type.INT); // entity id
map(Type.BYTE); // effect id
}
});
protocol.registerClientbound(ClientboundPackets1_8.ENTITY_PROPERTIES, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT, Type.INT); //Entity Id
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (tracker.getEntityReplacement(entityId) != null) {
packetWrapper.cancel();
map(Type.VAR_INT, Type.INT); // entity id
handler(wrapper -> {
final int entityId = wrapper.get(Type.INT, 0);
if (wrapper.user().get(EntityTracker1_7_6_10.class).getEntityReplacementMap().containsKey(entityId)) {
wrapper.cancel();
return;
}
int amount = packetWrapper.passthrough(Type.INT);
final int amount = wrapper.passthrough(Type.INT);
for (int i = 0; i < amount; i++) {
packetWrapper.passthrough(Type.STRING);
packetWrapper.passthrough(Type.DOUBLE);
int modifierlength = packetWrapper.read(Type.VAR_INT);
packetWrapper.write(Type.SHORT, (short) modifierlength);
for (int j = 0; j < modifierlength; j++) {
packetWrapper.passthrough(Type.UUID);
packetWrapper.passthrough(Type.DOUBLE);
packetWrapper.passthrough(Type.BYTE);
wrapper.passthrough(Type.STRING); // id
wrapper.passthrough(Type.DOUBLE); // value
int modifierLength = wrapper.read(Type.VAR_INT);
wrapper.write(Type.SHORT, (short) modifierLength);
for (int j = 0; j < modifierLength; j++) {
wrapper.passthrough(Type.UUID); // modifier uuid
wrapper.passthrough(Type.DOUBLE); // modifier amount
wrapper.passthrough(Type.BYTE); // modifier operation
}
}
});
@@ -18,98 +18,98 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.Windows;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ServerboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.FurnaceData;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.InventoryTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.UUID;
public class InventoryPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.OPEN_WINDOW, wrapper -> {
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
/* OUTGOING */
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE); // window id
final short windowTypeId = InventoryTracker.getInventoryType(wrapper.read(Type.STRING)); // window type
protocol.registerClientbound(ClientboundPackets1_8.OPEN_WINDOW, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
short windowId = packetWrapper.passthrough(Type.UNSIGNED_BYTE);
String windowType = packetWrapper.read(Type.STRING);
short windowtypeId = (short) Windows.getInventoryType(windowType);
packetWrapper.user().get(Windows.class).types.put(windowId, windowtypeId);
packetWrapper.write(Type.UNSIGNED_BYTE, windowtypeId);
windowTracker.getWindowTypeMap().put(windowId, windowTypeId);
wrapper.write(Type.UNSIGNED_BYTE, windowTypeId); // window type id
JsonElement titleComponent = packetWrapper.read(Type.COMPONENT); //Title
String title = ChatUtil.jsonToLegacy(titleComponent);
title = ChatUtil.removeUnusedColor(title, '8');
if (title.length() > 32) {
title = title.substring(0, 32);
}
packetWrapper.write(Type.STRING, title); //Window title
final JsonElement titleComponent = wrapper.read(Type.COMPONENT); // Title
String title = ChatUtil.jsonToLegacy(titleComponent);
title = ChatUtil.removeUnusedColor(title, '8');
if (title.length() > 32) {
title = title.substring(0, 32);
}
wrapper.write(Type.STRING, title); // window title
packetWrapper.passthrough(Type.UNSIGNED_BYTE);
packetWrapper.write(Type.BOOLEAN, true);
if (windowtypeId == 11) packetWrapper.passthrough(Type.INT); //Entity Id
});
wrapper.passthrough(Type.UNSIGNED_BYTE); // slots count
wrapper.write(Type.BOOLEAN, true); // use provided window title
if (windowTypeId == 11) { // Horse
wrapper.passthrough(Type.INT); // entity id
}
});
protocol.registerClientbound(ClientboundPackets1_8.CLOSE_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowsId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
packetWrapper.user().get(Windows.class).remove(windowsId);
});
}
protocol.registerClientbound(ClientboundPackets1_8.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE); // window id
wrapper.user().get(InventoryTracker.class).remove(windowId);
});
protocol.registerClientbound(ClientboundPackets1_8.SET_SLOT, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
short windowId = packetWrapper.read(Type.UNSIGNED_BYTE); //Window Id
short windowType = packetWrapper.user().get(Windows.class).get(windowId);
packetWrapper.write(Type.UNSIGNED_BYTE, windowId);
short slot = packetWrapper.read(Type.SHORT);
if (windowType == 4) {
map(Type.UNSIGNED_BYTE); // window id
map(Type.SHORT); // slot
handler(wrapper -> {
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Type.UNSIGNED_BYTE, 0));
final short slot = wrapper.get(Type.SHORT, 0);
if (windowType == 4) { // Enchantment Table
if (slot == 1) {
packetWrapper.cancel();
return;
wrapper.cancel();
} else if (slot >= 2) {
slot -= 1;
wrapper.set(Type.SHORT, 0, (short) (slot - 1));
}
}
packetWrapper.write(Type.SHORT, slot); //Slot
});
map(Type.ITEM, Types1_7_6_10.COMPRESSED_NBT_ITEM); //Item
handler(packetWrapper -> {
Item item = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
ItemRewriter.toClient(item);
packetWrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
map(Type.ITEM1_8, Types1_7_6_10.COMPRESSED_NBT_ITEM); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
protocol.getItemRewriter().handleItemToClient(item);
wrapper.set(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0, item);
});
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
short slot = packetWrapper.get(Type.SHORT, 0);
final short slot = wrapper.get(Type.SHORT, 0);
if (slot < 5 || slot > 8) return;
Item item = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
UUID myId = packetWrapper.user().getProtocolInfo().getUuid();
tracker.setPlayerEquipment(myId, item, 8 - slot);
if (tracker.getGamemode() == 3) packetWrapper.cancel();
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final Item item = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM, 0);
playerSession.setPlayerEquipment(wrapper.user().getProtocolInfo().getUuid(), item, 8 - slot);
if (playerSession.isSpectator()) { // Spectator mode didn't exist in 1.7.10
wrapper.cancel();
}
});
}
});
@@ -117,33 +117,44 @@ public class InventoryPackets {
protocol.registerClientbound(ClientboundPackets1_8.WINDOW_ITEMS, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
short windowId = packetWrapper.read(Type.UNSIGNED_BYTE); //Window Id
short windowType = packetWrapper.user().get(Windows.class).get(windowId);
packetWrapper.write(Type.UNSIGNED_BYTE, windowId);
Item[] items = packetWrapper.read(Type.ITEM_ARRAY);
if (windowType == 4) {
map(Type.UNSIGNED_BYTE); // window id
// remap enchantment table items
handler(wrapper -> {
final short windowType = wrapper.user().get(InventoryTracker.class).get(wrapper.get(Type.UNSIGNED_BYTE, 0));
Item[] items = wrapper.read(Type.ITEM1_8_SHORT_ARRAY);
if (windowType == 4) { // Enchantment Table
Item[] old = items;
items = new Item[old.length - 1];
items[0] = old[0];
System.arraycopy(old, 2, items, 1, old.length - 3);
}
for (int i = 0; i < items.length; i++) items[i] = ItemRewriter.toClient(items[i]);
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, items); //Items
});
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
Item[] items = packetWrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
UUID myId = packetWrapper.user().getProtocolInfo().getUuid();
for (int i = 5; i < 9; i++) {
tracker.setPlayerEquipment(myId, items[i], 8 - i);
if (tracker.getGamemode() == 3) items[i] = null;
for (int i = 0; i < items.length; i++) {
items[i] = protocol.getItemRewriter().handleItemToClient(items[i]);
}
if (tracker.getGamemode() == 3) {
GameProfileStorage.GameProfile profile = packetWrapper.user().get(GameProfileStorage.class).get(myId);
if (profile != null) items[5] = profile.getSkull();
wrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, items); // items
});
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (windowId != 0) return;
final UUID userId = wrapper.user().getProtocolInfo().getUuid();
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final Item[] items = wrapper.get(Types1_7_6_10.COMPRESSED_NBT_ITEM_ARRAY, 0);
for (int i = 5; i < 9; i++) {
playerSession.setPlayerEquipment(userId, items[i], 8 - i);
if (playerSession.isSpectator()) {
items[i] = null;
}
}
if (playerSession.isSpectator()) {
final GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(userId);
if (profile != null) {
items[5] = profile.getSkull();
}
}
});
}
@@ -152,112 +163,107 @@ public class InventoryPackets {
protocol.registerClientbound(ClientboundPackets1_8.WINDOW_PROPERTY, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.SHORT);
map(Type.SHORT);
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
Windows windows = packetWrapper.user().get(Windows.class);
short windowType = windows.get(windowId);
map(Type.UNSIGNED_BYTE); // window id
map(Type.SHORT); // progress bar id
map(Type.SHORT); // progress bar value
short property = packetWrapper.get(Type.SHORT, 0);
short value = packetWrapper.get(Type.SHORT, 1);
handler(wrapper -> {
final InventoryTracker windowTracker = wrapper.user().get(InventoryTracker.class);
if (windowType == -1) return;
if (windowType == 2) { //Furnace
Windows.Furnace furnace = windows.furnace.computeIfAbsent(windowId, x -> new Windows.Furnace());
if (property == 0 || property == 1) {
if (property == 0) {
furnace.setFuelLeft(value);
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0);
final short windowType = windowTracker.get(windowId);
final short progressBarId = wrapper.get(Type.SHORT, 0);
short progress = wrapper.get(Type.SHORT, 1);
if (windowType == 2) { // Furnace
final FurnaceData furnace = windowTracker.getFurnaceData().computeIfAbsent(windowId, x -> new FurnaceData());
if (progressBarId == 0 || progressBarId == 1) {
if (progressBarId == 0) {
furnace.fuelLeft = progress;
} else {
furnace.setMaxFuel(value);
furnace.maxFuel = progress;
}
if (furnace.getMaxFuel() == 0) {
packetWrapper.cancel();
if (furnace.maxFuel == 0) {
wrapper.cancel();
return;
}
value = (short) (200 * furnace.getFuelLeft() / furnace.getMaxFuel());
packetWrapper.set(Type.SHORT, 0, (short) 1);
packetWrapper.set(Type.SHORT, 1, value);
} else if (property == 2 || property == 3) {
if (property == 2) {
furnace.setProgress(value);
progress = (short) (200 * furnace.fuelLeft / furnace.maxFuel);
wrapper.set(Type.SHORT, 0, (short) 1);
wrapper.set(Type.SHORT, 1, progress);
} else if (progressBarId == 2 || progressBarId == 3) {
if (progressBarId == 2) {
furnace.progress = progress;
} else {
furnace.setMaxProgress(value);
furnace.maxProgress = progress;
}
if (furnace.getMaxProgress() == 0) {
packetWrapper.cancel();
if (furnace.maxProgress == 0) {
wrapper.cancel();
return;
}
value = (short) (200 * furnace.getProgress() / furnace.getMaxProgress());
packetWrapper.set(Type.SHORT, 0, (short) 0);
packetWrapper.set(Type.SHORT, 1, value);
progress = (short) (200 * furnace.progress / furnace.maxProgress);
wrapper.set(Type.SHORT, 0, (short) 0);
wrapper.set(Type.SHORT, 1, progress);
}
} else if (windowType == 4) { //Enchanting Table
if (property > 2) {
packetWrapper.cancel();
}
} else if (windowType == 8) {
windows.levelCost = value;
windows.anvilId = windowId;
} else if (windowType == 4 && progressBarId > 2) { // Enchanting Table
wrapper.cancel();
} else if (windowType == 8) { // Anvil
windowTracker.levelCost = progress;
windowTracker.anvilId = windowId;
}
});
}
});
/* INCOMING */
protocol.registerServerbound(ServerboundPackets1_7_2_5.CLOSE_WINDOW, wrapper -> {
final short windowId = wrapper.passthrough(Type.UNSIGNED_BYTE);
protocol.registerServerbound(ServerboundPackets1_7.CLOSE_WINDOW, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowsId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
packetWrapper.user().get(Windows.class).remove(windowsId);
});
}
wrapper.user().get(InventoryTracker.class).remove(windowId);
});
protocol.registerServerbound(ServerboundPackets1_7.CLICK_WINDOW, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.CLICK_WINDOW, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
short windowId = packetWrapper.read(Type.BYTE); //Window Id
packetWrapper.write(Type.UNSIGNED_BYTE, windowId);
short windowType = packetWrapper.user().get(Windows.class).get(windowId);
short slot = packetWrapper.read(Type.SHORT);
if (windowType == 4) {
map(Type.BYTE, Type.UNSIGNED_BYTE); // window id
map(Type.SHORT); // slot
handler(wrapper -> {
final short windowId = wrapper.get(Type.UNSIGNED_BYTE, 0); //Window Id
final short slot = wrapper.get(Type.SHORT, 0);
final short windowType = wrapper.user().get(InventoryTracker.class).get(windowId);
if (windowType == 4) { // Enchantment Table
if (slot > 0) {
slot += 1;
wrapper.set(Type.SHORT, 0, (short) (slot + 1));
}
}
packetWrapper.write(Type.SHORT, slot);
});
map(Type.BYTE); //Button
map(Type.SHORT); //Action Number
map(Type.BYTE); //Mode
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM);
handler(packetWrapper -> {
Item item = packetWrapper.get(Type.ITEM, 0);
ItemRewriter.toServer(item);
packetWrapper.set(Type.ITEM, 0, item);
map(Type.BYTE); // button
map(Type.SHORT); // action number
map(Type.BYTE); // mode
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM1_8); // clicked item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Type.ITEM1_8, 0);
protocol.getItemRewriter().handleItemToServer(item);
wrapper.set(Type.ITEM1_8, 0, item);
});
}
});
//Creative Inventory Action
protocol.registerServerbound(ServerboundPackets1_7.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT); //Slot
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM); //Item
handler(packetWrapper -> {
Item item = packetWrapper.get(Type.ITEM, 0);
ItemRewriter.toServer(item);
packetWrapper.set(Type.ITEM, 0, item);
map(Type.SHORT); // slot
map(Types1_7_6_10.COMPRESSED_NBT_ITEM, Type.ITEM1_8); // item
// remap item
handler(wrapper -> {
final Item item = wrapper.get(Type.ITEM1_8, 0);
protocol.getItemRewriter().handleItemToServer(item);
wrapper.set(Type.ITEM1_8, 0, item);
});
}
});
}
}
@@ -18,24 +18,23 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.ArmorStandReplacement;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.TitleRenderProvider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.*;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.math.AABB;
import com.viaversion.viarewind.utils.math.Ray3d;
import com.viaversion.viarewind.utils.math.RayTracing;
import com.viaversion.viarewind.utils.math.Vector3d;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ServerboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ItemRewriter;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
@@ -46,8 +45,7 @@ import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
@@ -59,38 +57,31 @@ import java.util.UUID;
public class PlayerPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
/* OUTGOING */
protocol.registerClientbound(ClientboundPackets1_8.JOIN_GAME, new PacketHandlers() {
@Override
public void register() {
map(Type.INT); //Entiy Id
map(Type.UNSIGNED_BYTE); //Gamemode
map(Type.BYTE); //Dimension
map(Type.UNSIGNED_BYTE); //Difficulty
map(Type.UNSIGNED_BYTE); //Max players
map(Type.STRING); //Level Type
map(Type.BOOLEAN, Type.NOTHING);//Reduced Debug Info
handler(packetWrapper -> {
if (!ViaRewind.getConfig().isReplaceAdventureMode()) return;
if (packetWrapper.get(Type.UNSIGNED_BYTE, 0) == 2) {
packetWrapper.set(Type.UNSIGNED_BYTE, 0, (short) 0);
}
});
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.setGamemode(packetWrapper.get(Type.UNSIGNED_BYTE, 0));
tracker.setPlayerId(packetWrapper.get(Type.INT, 0));
tracker.getClientEntityTypes().put(tracker.getPlayerId(), Entity1_10Types.EntityType.ENTITY_HUMAN);
tracker.setDimension(packetWrapper.get(Type.BYTE, 0));
tracker.addPlayer(tracker.getPlayerId(), packetWrapper.user().getProtocolInfo().getUuid());
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
world.setEnvironment(packetWrapper.get(Type.BYTE, 0));
});
map(Type.INT); // entity id
map(Type.UNSIGNED_BYTE);// game mode
map(Type.BYTE); // dimension
map(Type.UNSIGNED_BYTE); // difficulty
map(Type.UNSIGNED_BYTE); // max players
map(Type.STRING); // level type
read(Type.BOOLEAN); // reduced debug info
handler(wrapper -> {
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 2) { // adventure
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) 0); // survival
}
}
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.setClientEntityId(wrapper.get(Type.INT, 0));
tracker.addPlayer(wrapper.get(Type.INT, 0), wrapper.user().getProtocolInfo().getUuid());
wrapper.user().get(PlayerSessionStorage.class).gameMode = wrapper.get(Type.UNSIGNED_BYTE, 0);
wrapper.user().get(ClientWorld.class).setEnvironment(wrapper.get(Type.BYTE, 0));
// Reset on Velocity server change
wrapper.user().put(new Scoreboard(wrapper.user()));
});
@@ -100,10 +91,12 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.COMPONENT); //Chat Message
handler(packetWrapper -> {
int position = packetWrapper.read(Type.BYTE);
if (position == 2) packetWrapper.cancel();
map(Type.COMPONENT); // chat message
handler(wrapper -> {
final int position = wrapper.read(Type.BYTE);
if (position == 2) { // above hotbar
wrapper.cancel();
}
});
}
});
@@ -111,102 +104,87 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_POSITION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.INT, position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // spawn position
}
});
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_HEALTH, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT); //Health
map(Type.VAR_INT, Type.SHORT); //Food
map(Type.FLOAT); //Food Saturation
map(Type.FLOAT); // health
map(Type.VAR_INT, Type.SHORT); // food
map(Type.FLOAT); // food saturation
}
});
protocol.registerClientbound(ClientboundPackets1_8.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.STRING);
handler(packetWrapper -> {
if (!ViaRewind.getConfig().isReplaceAdventureMode()) return;
if (packetWrapper.get(Type.UNSIGNED_BYTE, 1) == 2) {
packetWrapper.set(Type.UNSIGNED_BYTE, 1, (short) 0);
map(Type.INT); // dimension
map(Type.UNSIGNED_BYTE); // difficulty
map(Type.UNSIGNED_BYTE); // game mode
map(Type.STRING); // level type
handler(wrapper -> {
if (ViaRewind.getConfig().isReplaceAdventureMode()) {
if (wrapper.get(Type.UNSIGNED_BYTE, 1) == 2) {
wrapper.set(Type.UNSIGNED_BYTE, 1, (short) 0);
}
}
});
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.setGamemode(packetWrapper.get(Type.UNSIGNED_BYTE, 1));
if (tracker.getDimension() != packetWrapper.get(Type.INT, 0)) {
tracker.setDimension(packetWrapper.get(Type.INT, 0));
tracker.clearEntities();
tracker.getClientEntityTypes().put(tracker.getPlayerId(), Entity1_10Types.EntityType.ENTITY_HUMAN);
wrapper.user().get(PlayerSessionStorage.class).gameMode = wrapper.get(Type.UNSIGNED_BYTE, 1);
final ClientWorld world = wrapper.user().get(ClientWorld.class);
final Environment dimension = Environment.getEnvironmentById(wrapper.get(Type.INT, 0));
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (world.getEnvironment() != dimension) {
world.setEnvironment(dimension.id());
// Reset on dimension change
tracker.clear();
tracker.getEntityMap().put(tracker.getPlayerId(), EntityTypes1_10.EntityType.ENTITY_HUMAN);
}
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
world.setEnvironment(packetWrapper.get(Type.INT, 0));
});
}
});
protocol.registerClientbound(ClientboundPackets1_8.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); //x
map(Type.DOUBLE); //y
map(Type.DOUBLE); //z
map(Type.FLOAT); //yaw
map(Type.FLOAT); //pitch
handler(packetWrapper -> {
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
playerPosition.setPositionPacketReceived(true);
map(Type.DOUBLE); // x
map(Type.DOUBLE); // y
map(Type.DOUBLE); // z
map(Type.FLOAT); // yaw
map(Type.FLOAT); // pitch
handler(wrapper -> {
final double x = wrapper.get(Type.DOUBLE, 0);
double y = wrapper.get(Type.DOUBLE, 1);
final double z = wrapper.get(Type.DOUBLE, 2);
int flags = packetWrapper.read(Type.BYTE);
if ((flags & 0x01) == 0x01) {
double x = packetWrapper.get(Type.DOUBLE, 0);
x += playerPosition.getPosX();
packetWrapper.set(Type.DOUBLE, 0, x);
}
double y = packetWrapper.get(Type.DOUBLE, 1);
if ((flags & 0x02) == 0x02) {
y += playerPosition.getPosY();
}
playerPosition.setReceivedPosY(y);
y += 1.62F;
packetWrapper.set(Type.DOUBLE, 1, y);
if ((flags & 0x04) == 0x04) {
double z = packetWrapper.get(Type.DOUBLE, 2);
z += playerPosition.getPosZ();
packetWrapper.set(Type.DOUBLE, 2, z);
}
if ((flags & 0x08) == 0x08) {
float yaw = packetWrapper.get(Type.FLOAT, 0);
yaw += playerPosition.getYaw();
packetWrapper.set(Type.FLOAT, 0, yaw);
}
if ((flags & 0x10) == 0x10) {
float pitch = packetWrapper.get(Type.FLOAT, 1);
pitch += playerPosition.getPitch();
packetWrapper.set(Type.FLOAT, 1, pitch);
}
});
handler(packetWrapper -> {
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
packetWrapper.write(Type.BOOLEAN, playerPosition.isOnGround());
});
handler(packetWrapper -> {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (tracker.getSpectating() != tracker.getPlayerId()) {
packetWrapper.cancel();
final float yaw = wrapper.get(Type.FLOAT, 0);
final float pitch = wrapper.get(Type.FLOAT, 1);
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
final int flags = wrapper.read(Type.BYTE);
// x, y, and z
if ((flags & 0x01) == 0x01) wrapper.set(Type.DOUBLE, 0, x + playerSession.getPosX());
if ((flags & 0x02) == 0x02) y += playerSession.getPosY();
playerSession.receivedPosY = y;
wrapper.set(Type.DOUBLE, 1, y + 1.62F);
if ((flags & 0x04) == 0x04) wrapper.set(Type.DOUBLE, 2, z + playerSession.getPosZ());
// yaw and pitch
if ((flags & 0x08) == 0x08) wrapper.set(Type.FLOAT, 0, yaw + playerSession.yaw);
if ((flags & 0x10) == 0x10) wrapper.set(Type.FLOAT, 1, pitch + playerSession.pitch);
wrapper.write(Type.BOOLEAN, playerSession.onGround);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.spectatingPlayerId != tracker.getPlayerId()) {
wrapper.cancel();
}
});
}
@@ -215,53 +193,48 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.SET_EXPERIENCE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT); //Experience bar
map(Type.VAR_INT, Type.SHORT); //Level
map(Type.VAR_INT, Type.SHORT); //Total Experience
map(Type.FLOAT); // experience bar
map(Type.VAR_INT, Type.SHORT); // level
map(Type.VAR_INT, Type.SHORT); // total experience
}
});
protocol.registerClientbound(ClientboundPackets1_8.GAME_EVENT, new PacketHandlers() {
@Override
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.FLOAT);
handler(packetWrapper -> {
int mode = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
if (mode != 3) return;
int gamemode = packetWrapper.get(Type.FLOAT, 0).intValue();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (gamemode == 3 || tracker.getGamemode() == 3) {
UUID myId = packetWrapper.user().getProtocolInfo().getUuid();
map(Type.UNSIGNED_BYTE); // reason
map(Type.FLOAT); // value
handler(wrapper -> {
if (wrapper.get(Type.UNSIGNED_BYTE, 0) != 3) return; // Change game mode
int gameMode = wrapper.get(Type.FLOAT, 0).intValue();
final PlayerSessionStorage playerSession = wrapper.user().get(PlayerSessionStorage.class);
if (gameMode == 3 || playerSession.gameMode == 3) {
UUID myId = wrapper.user().getProtocolInfo().getUuid();
Item[] equipment = new Item[4];
if (gamemode == 3) {
GameProfileStorage.GameProfile profile = packetWrapper.user().get(GameProfileStorage.class).get(myId);
equipment[3] = profile.getSkull();
if (gameMode == 3) {
GameProfileStorage.GameProfile profile = wrapper.user().get(GameProfileStorage.class).get(myId);
equipment[3] = profile == null ? null : profile.getSkull();
} else {
for (int i = 0; i < equipment.length; i++) {
equipment[i] = tracker.getPlayerEquipment(myId, i);
equipment[i] = playerSession.getPlayerEquipment(myId, i);
}
}
for (int i = 0; i < equipment.length; i++) {
PacketWrapper setSlot = PacketWrapper.create(ClientboundPackets1_7.SET_SLOT, packetWrapper.user());
PacketWrapper setSlot = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_SLOT, wrapper.user());
setSlot.write(Type.BYTE, (byte) 0);
setSlot.write(Type.SHORT, (short) (8 - i));
setSlot.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, equipment[i]);
PacketUtil.sendPacket(setSlot, Protocol1_7_6_10To1_8.class);
}
}
});
handler(packetWrapper -> {
int mode = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
if (mode == 3) {
int gamemode = packetWrapper.get(Type.FLOAT, 0).intValue();
if (gamemode == 2 && ViaRewind.getConfig().isReplaceAdventureMode()) {
gamemode = 0;
packetWrapper.set(Type.FLOAT, 0, 0.0f);
}
packetWrapper.user().get(EntityTracker.class).setGamemode(gamemode);
if (gameMode == 2 && ViaRewind.getConfig().isReplaceAdventureMode()) {
gameMode = 0;
wrapper.set(Type.FLOAT, 0, 0.0f);
}
wrapper.user().get(PlayerSessionStorage.class).gameMode = gameMode;
});
}
});
@@ -269,12 +242,7 @@ public class PlayerPackets {
protocol.registerClientbound(ClientboundPackets1_8.OPEN_SIGN_EDITOR, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.INT, position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // position
}
});
@@ -311,7 +279,7 @@ public class PlayerPackets {
gameProfile.setDisplayName(ChatUtil.jsonToLegacy(displayName));
}
PacketWrapper packet = PacketWrapper.create(0x38, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
@@ -323,7 +291,7 @@ public class PlayerPackets {
if (gameProfile == null || gameProfile.gamemode == gamemode) continue;
if (gamemode == 3 || gameProfile.gamemode == 3) {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
int entityId = tracker.getPlayerEntityId(uuid);
boolean isOwnPlayer = entityId == tracker.getPlayerId();
if (entityId != -1) {
@@ -333,12 +301,12 @@ public class PlayerPackets {
equipment[isOwnPlayer ? 3 : 4] = gameProfile.getSkull();
} else {
for (int j = 0; j < equipment.length; j++) {
equipment[j] = tracker.getPlayerEquipment(uuid, j);
equipment[j] = packetWrapper.user().get(PlayerSessionStorage.class).getPlayerEquipment(uuid, j);
}
}
for (short slot = 0; slot < equipment.length; slot++) {
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_EQUIPMENT, packetWrapper.user());
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, packetWrapper.user());
equipmentPacket.write(Type.INT, entityId);
equipmentPacket.write(Type.SHORT, slot);
equipmentPacket.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, equipment[slot]);
@@ -353,16 +321,16 @@ public class PlayerPackets {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(0x38, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
PacketUtil.sendPacket(packet, Protocol1_7_6_10To1_8.class);
gameProfile.ping = ping;
packet = PacketWrapper.create(0x38, null, packetWrapper.user());
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) ping);
@@ -373,8 +341,8 @@ public class PlayerPackets {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null || gameProfile.displayName == null && displayName == null) continue;
PacketWrapper packet = PacketWrapper.create(0x38, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
@@ -383,8 +351,8 @@ public class PlayerPackets {
if (gameProfile.displayName == null && displayName != null || gameProfile.displayName != null && displayName == null || !gameProfile.displayName.equals(displayName)) {
gameProfile.setDisplayName(displayName);
}
packet = PacketWrapper.create(0x38, null, packetWrapper.user());
packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, true);
packet.write(Type.SHORT, (short) gameProfile.ping);
@@ -393,7 +361,7 @@ public class PlayerPackets {
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.remove(uuid);
if (gameProfile == null) continue;
PacketWrapper packet = PacketWrapper.create(0x38, null, packetWrapper.user());
PacketWrapper packet = PacketWrapper.create(ClientboundPackets1_7_2_5.PLAYER_INFO, null, packetWrapper.user());
packet.write(Type.STRING, gameProfile.getDisplayName());
packet.write(Type.BOOLEAN, false);
packet.write(Type.SHORT, (short) gameProfile.ping);
@@ -414,15 +382,16 @@ public class PlayerPackets {
byte flags = packetWrapper.get(Type.BYTE, 0);
float flySpeed = packetWrapper.get(Type.FLOAT, 0);
float walkSpeed = packetWrapper.get(Type.FLOAT, 1);
PlayerAbilities abilities = packetWrapper.user().get(PlayerAbilities.class);
abilities.setInvincible((flags & 8) == 8);
abilities.setAllowFly((flags & 4) == 4);
abilities.setFlying((flags & 2) == 2);
abilities.setCreative((flags & 1) == 1);
abilities.setFlySpeed(flySpeed);
abilities.setWalkSpeed(walkSpeed);
if (abilities.isSprinting() && abilities.isFlying()) {
packetWrapper.set(Type.FLOAT, 0, abilities.getFlySpeed() * 2.0f);
PlayerSessionStorage abilities = packetWrapper.user().get(PlayerSessionStorage.class);
abilities.invincible = (flags & 8) == 8;
abilities.allowFly = (flags & 4) == 4;
abilities.flying = (flags & 2) == 2;
abilities.creative = (flags & 1) == 1;
abilities.flySpeed = flySpeed;
abilities.walkSpeed = walkSpeed;
if (abilities.sprinting && abilities.flying) {
packetWrapper.set(Type.FLOAT, 0, abilities.flySpeed * 2.0f);
}
});
}
@@ -445,15 +414,15 @@ public class PlayerPackets {
}
for (int i = 0; i < size; i++) {
Item item = ItemRewriter.toClient(packetWrapper.read(Type.ITEM));
Item item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 1
item = ItemRewriter.toClient(packetWrapper.read(Type.ITEM));
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 3
boolean has3Items = packetWrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
item = ItemRewriter.toClient(packetWrapper.read(Type.ITEM));
item = protocol.getItemRewriter().handleItemToClient(packetWrapper.read(Type.ITEM1_8));
packetWrapper.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, item); //Buy Item 2
}
@@ -466,10 +435,10 @@ public class PlayerPackets {
}
packetWrapper.cancel();
packetWrapper.setId(-1);
packetWrapper.setPacketType(null);
ByteBuf newPacketBuf = Unpooled.buffer();
packetWrapper.writeToBuffer(newPacketBuf);
PacketWrapper newWrapper = PacketWrapper.create(0x3F, newPacketBuf, packetWrapper.user());
PacketWrapper newWrapper = PacketWrapper.create(ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, newPacketBuf, packetWrapper.user());
newWrapper.passthrough(Type.STRING);
if (newPacketBuf.readableBytes() <= Short.MAX_VALUE) {
newWrapper.write(Type.SHORT, (short) newPacketBuf.readableBytes());
@@ -486,10 +455,10 @@ public class PlayerPackets {
handler(packetWrapper -> {
packetWrapper.cancel();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
int entityId = packetWrapper.read(Type.VAR_INT);
int spectating = tracker.getSpectating();
int spectating = tracker.spectatingPlayerId;
if (spectating != entityId) {
tracker.setSpectating(entityId);
@@ -533,7 +502,7 @@ public class PlayerPackets {
protocol.cancelClientbound(ClientboundPackets1_8.TAB_LIST);
//Resource Pack Send
protocol.registerClientbound(ClientboundPackets1_8.RESOURCE_PACK, ClientboundPackets1_7.PLUGIN_MESSAGE, new PacketHandlers() {
protocol.registerClientbound(ClientboundPackets1_8.RESOURCE_PACK, ClientboundPackets1_7_2_5.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
create(Type.STRING, "MC|RPack");
@@ -548,19 +517,19 @@ public class PlayerPackets {
buf.release();
}
});
map(Type.STRING, Type.NOTHING); // Hash
read(Type.STRING); // Hash
}
});
/* INCOMING */
protocol.registerServerbound(ServerboundPackets1_7.CHAT_MESSAGE, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.CHAT_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
int gamemode = packetWrapper.user().get(EntityTracker.class).getGamemode();
int gamemode = packetWrapper.user().get(PlayerSessionStorage.class).gameMode;
if (gamemode == 3 && msg.toLowerCase().startsWith("/stp ")) {
String username = msg.split(" ")[1];
GameProfileStorage storage = packetWrapper.user().get(GameProfileStorage.class);
@@ -578,55 +547,63 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.INTERACT_ENTITY, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.INTERACT_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT);
map(Type.BYTE, Type.VAR_INT);
handler(packetWrapper -> {
int mode = packetWrapper.get(Type.VAR_INT, 1);
if (mode != 0) return;
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
if (!(replacement instanceof ArmorStandReplacement)) return;
ArmorStandReplacement armorStand = (ArmorStandReplacement) replacement;
AABB boundingBox = armorStand.getBoundingBox();
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
Vector3d pos = new Vector3d(playerPosition.getPosX(), playerPosition.getPosY() + 1.8, playerPosition.getPosZ());
double yaw = Math.toRadians(playerPosition.getYaw());
double pitch = Math.toRadians(playerPosition.getPitch());
Vector3d dir = new Vector3d(-Math.cos(pitch) * Math.sin(yaw), -Math.sin(pitch), Math.cos(pitch) * Math.cos(yaw));
Ray3d ray = new Ray3d(pos, dir);
Vector3d intersection = RayTracing.trace(ray, boundingBox, 5.0);
if (intersection == null) return;
intersection.substract(boundingBox.getMin());
mode = 2;
packetWrapper.set(Type.VAR_INT, 1, mode);
packetWrapper.write(Type.FLOAT, (float) intersection.getX());
packetWrapper.write(Type.FLOAT, (float) intersection.getY());
packetWrapper.write(Type.FLOAT, (float) intersection.getZ());
handler(wrapper -> {
int mode = wrapper.get(Type.VAR_INT, 1);
if (mode != 0) {
return;
}
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final PlayerSessionStorage position = wrapper.user().get(PlayerSessionStorage.class);
if (tracker.getVirtualHologramMap().containsKey(entityId)) {
final AABB boundingBox = tracker.getVirtualHologramMap().get(entityId).getBoundingBox();
Vector3d pos = new Vector3d(position.getPosX(), position.getPosY() + 1.8, position.getPosZ());
double yaw = Math.toRadians(position.yaw);
double pitch = Math.toRadians(position.pitch);
Vector3d dir = new Vector3d(-Math.cos(pitch) * Math.sin(yaw), -Math.sin(pitch), Math.cos(pitch) * Math.cos(yaw));
Ray3d ray = new Ray3d(pos, dir);
Vector3d intersection = RayTracing.trace(ray, boundingBox, 5.0);
if (intersection == null) {
return;
}
intersection.substract(boundingBox.getMin());
mode = 2;
wrapper.set(Type.VAR_INT, 1, mode);
wrapper.write(Type.FLOAT, (float) intersection.getX());
wrapper.write(Type.FLOAT, (float) intersection.getY());
wrapper.write(Type.FLOAT, (float) intersection.getZ());
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_MOVEMENT, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_MOVEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
playerPosition.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_POSITION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_POSITION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); //X
map(Type.DOUBLE); //Y
map(Type.DOUBLE, Type.NOTHING);
read(Type.DOUBLE);
map(Type.DOUBLE); //Z
map(Type.BOOLEAN); //OnGround
handler(packetWrapper -> {
@@ -634,35 +611,35 @@ public class PlayerPackets {
double feetY = packetWrapper.get(Type.DOUBLE, 1);
double z = packetWrapper.get(Type.DOUBLE, 2);
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerPosition.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
playerPosition.setPos(x, feetY, z);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_ROTATION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
playerPosition.setYaw(packetWrapper.get(Type.FLOAT, 0));
playerPosition.setPitch(packetWrapper.get(Type.FLOAT, 1));
playerPosition.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.yaw = packetWrapper.get(Type.FLOAT, 0);
playerSession.pitch = packetWrapper.get(Type.FLOAT, 1);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_POSITION_AND_ROTATION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_POSITION_AND_ROTATION, new PacketHandlers() {
@Override
public void register() {
map(Type.DOUBLE); //X
map(Type.DOUBLE); //Y
map(Type.DOUBLE, Type.NOTHING);
read(Type.DOUBLE);
map(Type.DOUBLE); //Z
map(Type.FLOAT); //Yaw
map(Type.FLOAT); //Pitch
@@ -675,17 +652,17 @@ public class PlayerPackets {
float yaw = packetWrapper.get(Type.FLOAT, 0);
float pitch = packetWrapper.get(Type.FLOAT, 1);
PlayerPosition playerPosition = packetWrapper.user().get(PlayerPosition.class);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerPosition.setOnGround(packetWrapper.get(Type.BOOLEAN, 0));
playerPosition.setPos(x, feetY, z);
playerPosition.setYaw(yaw);
playerPosition.setPitch(pitch);
playerSession.onGround = packetWrapper.get(Type.BOOLEAN, 0);
playerSession.setPos(x, feetY, z);
playerSession.yaw = yaw;
playerSession.pitch = pitch;
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_DIGGING, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_DIGGING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); //Status
@@ -693,24 +670,24 @@ public class PlayerPackets {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.UNSIGNED_BYTE);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION, new Position(x, y, z));
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.UNSIGNED_BYTE);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION, new Position(x, y, z));
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
packetWrapper.passthrough(Type.BYTE); //Direction
Item item = packetWrapper.read(Types1_7_6_10.COMPRESSED_NBT_ITEM);
item = ItemRewriter.toServer(item);
packetWrapper.write(Type.ITEM, item);
item = protocol.getItemRewriter().handleItemToServer(item);
packetWrapper.write(Type.ITEM1_8, item);
for (int i = 0; i < 3; i++) {
packetWrapper.passthrough(Type.BYTE);
@@ -719,7 +696,7 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.ANIMATION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.ANIMATION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
@@ -750,28 +727,28 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.ENTITY_ACTION, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.ENTITY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.INT, Type.VAR_INT); //Entity Id
handler(packetWrapper -> packetWrapper.write(Type.VAR_INT, packetWrapper.read(Type.BYTE) - 1)); //Action Id
map(Type.INT, Type.VAR_INT); //Action Paramter
map(Type.INT, Type.VAR_INT); //Action Parameter
handler(packetWrapper -> {
int action = packetWrapper.get(Type.VAR_INT, 1);
if (action == 3 || action == 4) {
PlayerAbilities abilities = packetWrapper.user().get(PlayerAbilities.class);
abilities.setSprinting(action == 3);
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
playerSession.sprinting = action == 3;
PacketWrapper abilitiesPacket = PacketWrapper.create(0x39, null, packetWrapper.user());
abilitiesPacket.write(Type.BYTE, abilities.getFlags());
abilitiesPacket.write(Type.FLOAT, abilities.isSprinting() ? abilities.getFlySpeed() * 2.0f : abilities.getFlySpeed());
abilitiesPacket.write(Type.FLOAT, abilities.getWalkSpeed());
abilitiesPacket.write(Type.BYTE, playerSession.combineAbilities());
abilitiesPacket.write(Type.FLOAT, playerSession.sprinting ? playerSession.flySpeed * 2.0f : playerSession.flySpeed);
abilitiesPacket.write(Type.FLOAT, playerSession.walkSpeed);
PacketUtil.sendPacket(abilitiesPacket, Protocol1_7_6_10To1_8.class);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.STEER_VEHICLE, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.STEER_VEHICLE, new PacketHandlers() {
@Override
public void register() {
map(Type.FLOAT); //Sideways
@@ -785,8 +762,8 @@ public class PlayerPackets {
packetWrapper.write(Type.UNSIGNED_BYTE, flags);
if (unmount) {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (tracker.getSpectating() != tracker.getPlayerId()) {
EntityTracker1_7_6_10 tracker = packetWrapper.user().get(EntityTracker1_7_6_10.class);
if (tracker.spectatingPlayerId != tracker.getPlayerId()) {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, packetWrapper.user());
sneakPacket.write(Type.VAR_INT, tracker.getPlayerId());
sneakPacket.write(Type.VAR_INT, 0); //Start sneaking
@@ -804,14 +781,14 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.UPDATE_SIGN, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int x = packetWrapper.read(Type.INT);
int y = packetWrapper.read(Type.SHORT);
int z = packetWrapper.read(Type.INT);
packetWrapper.write(Type.POSITION, new Position(x, y, z));
packetWrapper.write(Type.POSITION1_8, new Position(x, y, z));
for (int i = 0; i < 4; i++) {
String line = packetWrapper.read(Type.STRING);
line = ChatUtil.legacyToJson(line);
@@ -821,28 +798,28 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLAYER_ABILITIES, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLAYER_ABILITIES, new PacketHandlers() {
@Override
public void register() {
map(Type.BYTE);
map(Type.FLOAT);
map(Type.FLOAT);
handler(packetWrapper -> {
PlayerAbilities abilities = packetWrapper.user().get(PlayerAbilities.class);
if (abilities.isAllowFly()) {
PlayerSessionStorage playerSession = packetWrapper.user().get(PlayerSessionStorage.class);
if (playerSession.allowFly) {
byte flags = packetWrapper.get(Type.BYTE, 0);
abilities.setFlying((flags & 2) == 2);
playerSession.flying = (flags & 2) == 2;
}
packetWrapper.set(Type.FLOAT, 0, abilities.getFlySpeed());
packetWrapper.set(Type.FLOAT, 0, playerSession.flySpeed);
});
}
});
protocol.registerServerbound(ServerboundPackets1_7.TAB_COMPLETE, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.TAB_COMPLETE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
create(Type.OPTIONAL_POSITION, null);
create(Type.OPTIONAL_POSITION1_8, null);
handler(packetWrapper -> {
String msg = packetWrapper.get(Type.STRING, 0);
if (msg.toLowerCase().startsWith("/stp ")) {
@@ -867,14 +844,14 @@ public class PlayerPackets {
});
//Client Settings
protocol.registerServerbound(ServerboundPackets1_7.CLIENT_SETTINGS, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.CLIENT_SETTINGS, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BOOLEAN);
map(Type.BYTE, Type.NOTHING);
read(Type.BYTE);
handler(packetWrapper -> {
boolean cape = packetWrapper.read(Type.BOOLEAN);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) (cape ? 127 : 126));
@@ -882,11 +859,11 @@ public class PlayerPackets {
}
});
protocol.registerServerbound(ServerboundPackets1_7.PLUGIN_MESSAGE, new PacketHandlers() {
protocol.registerServerbound(ServerboundPackets1_7_2_5.PLUGIN_MESSAGE, new PacketHandlers() {
@Override
public void register() {
map(Type.STRING);
map(Type.SHORT, Type.NOTHING); // Length
read(Type.SHORT); // Length
handler(packetWrapper -> {
String channel = packetWrapper.get(Type.STRING, 0);
@@ -902,11 +879,11 @@ public class PlayerPackets {
packetWrapper.write(Type.STRING, name);
Windows windows = packetWrapper.user().get(Windows.class);
InventoryTracker windowTracker = packetWrapper.user().get(InventoryTracker.class);
PacketWrapper updateCost = PacketWrapper.create(0x31, null, packetWrapper.user());
updateCost.write(Type.UNSIGNED_BYTE, windows.anvilId);
updateCost.write(Type.UNSIGNED_BYTE, windowTracker.anvilId);
updateCost.write(Type.SHORT, (short) 0);
updateCost.write(Type.SHORT, windows.levelCost);
updateCost.write(Type.SHORT, windowTracker.levelCost);
PacketUtil.sendPacket(updateCost, Protocol1_7_6_10To1_8.class, true, true);
break;
@@ -924,7 +901,7 @@ public class PlayerPackets {
page.setValue(value);
}
}
packetWrapper.write(Type.ITEM, book);
packetWrapper.write(Type.ITEM1_8, book);
break;
}
case "MC|Brand": {
@@ -18,9 +18,9 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.Scoreboard;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
@@ -18,28 +18,21 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.ArmorStandReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.EndermiteReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.GuardianReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.entityreplacements.RabbitReplacement;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.replacement.Replacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ReplacementRegistry1_7_6_10to1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.GameProfileStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.EntityTracker1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import java.util.List;
import java.util.UUID;
@@ -47,63 +40,64 @@ import java.util.UUID;
public class SpawnPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
/* OUTGOING */
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PLAYER, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
handler(packetWrapper -> {
UUID uuid = packetWrapper.read(Type.UUID);
packetWrapper.write(Type.STRING, uuid.toString());
map(Type.VAR_INT); // entity id
handler(wrapper -> {
final UUID uuid = wrapper.read(Type.UUID);
wrapper.write(Type.STRING, uuid.toString()); // map to string
GameProfileStorage gameProfileStorage = packetWrapper.user().get(GameProfileStorage.class);
final GameProfileStorage gameProfileStorage = wrapper.user().get(GameProfileStorage.class);
GameProfileStorage.GameProfile gameProfile = gameProfileStorage.get(uuid);
if (gameProfile == null) {
packetWrapper.write(Type.STRING, "");
packetWrapper.write(Type.VAR_INT, 0);
wrapper.write(Type.STRING, ""); // name
wrapper.write(Type.VAR_INT, 0); // properties count
} else {
packetWrapper.write(Type.STRING, gameProfile.name.length() > 16 ? gameProfile.name.substring(0, 16) : gameProfile.name);
packetWrapper.write(Type.VAR_INT, gameProfile.properties.size());
wrapper.write(Type.STRING, gameProfile.name.length() > 16 ? gameProfile.name.substring(0, 16) : gameProfile.name); // name
wrapper.write(Type.VAR_INT, gameProfile.properties.size()); // properties count
for (GameProfileStorage.Property property : gameProfile.properties) {
packetWrapper.write(Type.STRING, property.name);
packetWrapper.write(Type.STRING, property.value);
packetWrapper.write(Type.STRING, property.signature == null ? "" : property.signature);
wrapper.write(Type.STRING, property.name); // property name
wrapper.write(Type.STRING, property.value); // property value
wrapper.write(Type.STRING, property.signature == null ? "" : property.signature); // property signature
}
}
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
if (gameProfile != null && gameProfile.gamemode == 3) {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
final int entityId = wrapper.get(Type.VAR_INT, 0);
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (gameProfile != null && gameProfile.gamemode == 3) { // Spectator mode
for (short i = 0; i < 5; i++) {
PacketWrapper equipmentPacket = PacketWrapper.create(ClientboundPackets1_7.ENTITY_EQUIPMENT, packetWrapper.user());
equipmentPacket.write(Type.INT, entityId);
equipmentPacket.write(Type.SHORT, i);
equipmentPacket.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, i == 4 ? gameProfile.getSkull() :null);
PacketUtil.sendPacket(equipmentPacket, Protocol1_7_6_10To1_8.class);
final PacketWrapper entityEquipment = PacketWrapper.create(ClientboundPackets1_7_2_5.ENTITY_EQUIPMENT, wrapper.user());
entityEquipment.write(Type.INT, entityId);
entityEquipment.write(Type.SHORT, i);
entityEquipment.write(Types1_7_6_10.COMPRESSED_NBT_ITEM, i == 4 ? gameProfile.getSkull() : null);
entityEquipment.scheduleSend(Protocol1_7_6_10To1_8.class, true);
}
}
tracker.addPlayer(packetWrapper.get(Type.VAR_INT, 0), uuid);
tracker.addPlayer(entityId, uuid);
});
map(Type.INT);
map(Type.INT);
map(Type.INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.SHORT);
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST);
handler(packetWrapper -> {
List<Metadata> metadata = packetWrapper.get(Types1_7_6_10.METADATA_LIST, 0); //Metadata
MetadataRewriter.transform(Entity1_10Types.EntityType.PLAYER, metadata);
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.SHORT); // item in hand id
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
final List<Metadata> metadata = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
protocol.getMetadataRewriter().transform(EntityTypes1_10.EntityType.PLAYER, metadata);
wrapper.set(Types1_7_6_10.METADATA_LIST, 0, metadata);
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.PLAYER);
tracker.sendMetadataBuffer(entityId);
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.PLAYER);
});
}
});
@@ -111,25 +105,31 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.INT);
map(Type.INT);
map(Type.INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.INT);
map(Type.VAR_INT); // entity id
map(Type.BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // pitch
map(Type.BYTE); // yaw
map(Type.INT); // data
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
byte typeId = packetWrapper.get(Type.BYTE, 0);
int x = packetWrapper.get(Type.INT, 0);
int y = packetWrapper.get(Type.INT, 1);
int z = packetWrapper.get(Type.INT, 2);
byte pitch = packetWrapper.get(Type.BYTE, 1);
byte yaw = packetWrapper.get(Type.BYTE, 2);
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
if (typeId == 71) {
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(wrapper.get(Type.BYTE, 0), true);
final int entityId = wrapper.get(Type.VAR_INT, 0);
int x = wrapper.get(Type.INT, 0);
int y = wrapper.get(Type.INT, 1);
int z = wrapper.get(Type.INT, 2);
byte pitch = wrapper.get(Type.BYTE, 1);
byte yaw = wrapper.get(Type.BYTE, 2);
int data = wrapper.get(Type.INT, 3);
if (type == EntityTypes1_10.ObjectType.ITEM_FRAME.getType()) {
switch (yaw) {
case -128:
z += 32;
@@ -148,47 +148,39 @@ public class SpawnPackets {
yaw = 64;
break;
}
} else if (typeId == 78) {
packetWrapper.cancel();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
ArmorStandReplacement armorStand = new ArmorStandReplacement(entityId, packetWrapper.user());
armorStand.setLocation(x / 32.0, y / 32.0, z / 32.0);
armorStand.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
armorStand.setHeadYaw(yaw * 360f / 256);
tracker.addEntityReplacement(armorStand);
} else if (typeId == 10) {
y += 12;
} else if (type == EntityTypes1_10.ObjectType.ARMOR_STAND.getType()) {
wrapper.cancel();
final VirtualHologramEntity hologram = new VirtualHologramEntity(wrapper.user(), protocol.getMetadataRewriter(), entityId);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(yaw * 360f / 256);
tracker.trackHologram(entityId, hologram);
}
// TODO | Realign all entities
packetWrapper.set(Type.BYTE, 0, typeId);
packetWrapper.set(Type.INT, 0, x);
packetWrapper.set(Type.INT, 1, y);
packetWrapper.set(Type.INT, 2, z);
packetWrapper.set(Type.BYTE, 1, pitch);
packetWrapper.set(Type.BYTE, 2, yaw);
wrapper.set(Type.INT, 0, x);
wrapper.set(Type.INT, 1, y);
wrapper.set(Type.INT, 2, z);
wrapper.set(Type.BYTE, 2, yaw);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
Entity1_10Types.EntityType type = Entity1_10Types.getTypeFromId(typeId, true);
tracker.getClientEntityTypes().put(entityId, type);
tracker.sendMetadataBuffer(entityId);
tracker.addEntity(entityId, type);
int data = packetWrapper.get(Type.INT, 3);
if (type != null && type.isOrHasParent(Entity1_10Types.EntityType.FALLING_BLOCK)) {
if (type != null && type.isOrHasParent(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
Replacement replace = ReplacementRegistry1_7_6_10to1_8.getReplacement(blockId, blockData);
final Replacement replace = protocol.getItemRewriter().replace(blockId, blockData);
if (replace != null) {
blockId = replace.getId();
blockData = replace.replaceData(blockData);
}
packetWrapper.set(Type.INT, 3, data = (blockId | blockData << 16));
wrapper.set(Type.INT, 3, data = (blockId | blockData << 16));
}
if (data > 0) {
packetWrapper.passthrough(Type.SHORT);
packetWrapper.passthrough(Type.SHORT);
packetWrapper.passthrough(Type.SHORT);
wrapper.passthrough(Type.SHORT); // velocity x
wrapper.passthrough(Type.SHORT); // velocity y
wrapper.passthrough(Type.SHORT); // velocity z
}
});
}
@@ -197,68 +189,58 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_MOB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.UNSIGNED_BYTE);
map(Type.INT);
map(Type.INT);
map(Type.INT);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BYTE);
map(Type.SHORT);
map(Type.SHORT);
map(Type.SHORT);
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int typeId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
int x = packetWrapper.get(Type.INT, 0);
int y = packetWrapper.get(Type.INT, 1);
int z = packetWrapper.get(Type.INT, 2);
byte pitch = packetWrapper.get(Type.BYTE, 1);
byte yaw = packetWrapper.get(Type.BYTE, 0);
byte headYaw = packetWrapper.get(Type.BYTE, 2);
if (typeId == 30 || typeId == 68 || typeId == 67 || typeId == 101) {
packetWrapper.cancel();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = null;
if (typeId == 30) {
replacement = new ArmorStandReplacement(entityId, packetWrapper.user());
} else if (typeId == 68) {
replacement = new GuardianReplacement(entityId, packetWrapper.user());
} else if (typeId == 67) {
replacement = new EndermiteReplacement(entityId, packetWrapper.user());
} else if (typeId == 101){
replacement = new RabbitReplacement(entityId, packetWrapper.user());
}
replacement.setLocation(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
replacement.setHeadYaw(headYaw * 360f / 256);
tracker.addEntityReplacement(replacement);
} else if (typeId == 255 || typeId == -1) {
packetWrapper.cancel();
}
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int typeId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.getTypeFromId(typeId, false));
tracker.sendMetadataBuffer(entityId);
});
map(Type.VAR_INT); // entity id
map(Type.UNSIGNED_BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.BYTE); // yaw
map(Type.BYTE); // pitch
map(Type.BYTE); // head yaw
map(Type.SHORT); // velocity x
map(Type.SHORT); // velocity y
map(Type.SHORT); // velocity z
map(Types1_8.METADATA_LIST, Types1_7_6_10.METADATA_LIST); // metadata
handler(wrapper -> {
List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (tracker.getEntityReplacement(entityId) != null) {
tracker.getEntityReplacement(entityId).updateMetadata(metadataList);
} else if (tracker.getClientEntityTypes().containsKey(entityId)) {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityId), metadataList);
} else {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
final short typeId = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (typeId == 255 || typeId == -1) {
wrapper.cancel();
}
final EntityTypes1_10.EntityType type = EntityTypes1_10.getTypeFromId(typeId, false);
final int entityId = wrapper.get(Type.VAR_INT, 0);
final int x = wrapper.get(Type.INT, 0);
final int y = wrapper.get(Type.INT, 1);
final int z = wrapper.get(Type.INT, 2);
final byte pitch = wrapper.get(Type.BYTE, 1);
final byte yaw = wrapper.get(Type.BYTE, 0);
final byte headYaw = wrapper.get(Type.BYTE, 2);
final List<Metadata> metadataList = wrapper.get(Types1_7_6_10.METADATA_LIST, 0);
if (type == EntityTypes1_10.EntityType.ARMOR_STAND) {
final VirtualHologramEntity hologram = new VirtualHologramEntity(wrapper.user(), protocol.getMetadataRewriter(), entityId);
hologram.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
hologram.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
hologram.setHeadYaw(headYaw * 360f / 256);
tracker.trackHologram(entityId, hologram);
tracker.updateMetadata(entityId, metadataList); // Track and remap hologram <-> zombie metadata
wrapper.cancel();
} else {
protocol.getMetadataRewriter().transform(type, metadataList);
tracker.addEntity(entityId, type);
if (tracker.isReplaced(type)) {
final int newTypeId = tracker.replaceEntity(entityId, type);
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) newTypeId);
tracker.updateMetadata(entityId, metadataList);
}
}
});
}
});
@@ -266,20 +248,20 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PAINTING, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); //Entity Id
map(Type.STRING); //Title
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.INT, position.y());
packetWrapper.write(Type.INT, position.z());
map(Type.VAR_INT); // entity id
map(Type.STRING); // title
handler(wrapper -> {
final Position position = wrapper.read(Type.POSITION1_8);
wrapper.write(Type.INT, position.x());
wrapper.write(Type.INT, position.y());
wrapper.write(Type.INT, position.z());
});
map(Type.UNSIGNED_BYTE, Type.INT); //Rotation
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.PAINTING);
tracker.sendMetadataBuffer(entityId);
map(Type.UNSIGNED_BYTE, Type.INT); // rotation
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.PAINTING);
});
}
});
@@ -287,16 +269,15 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_EXPERIENCE_ORB, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.INT);
map(Type.INT);
map(Type.INT);
map(Type.SHORT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.EXPERIENCE_ORB);
tracker.sendMetadataBuffer(entityId);
map(Type.VAR_INT); // entity id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
map(Type.SHORT); // count
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.EXPERIENCE_ORB);
});
}
});
@@ -304,16 +285,15 @@ public class SpawnPackets {
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_GLOBAL_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.INT);
map(Type.INT);
map(Type.INT);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.LIGHTNING);
tracker.sendMetadataBuffer(entityId);
map(Type.VAR_INT); // entity id
map(Type.BYTE); // type id
map(Type.INT); // x
map(Type.INT); // y
map(Type.INT); // z
handler(wrapper -> {
final EntityTracker1_7_6_10 tracker = wrapper.user().get(EntityTracker1_7_6_10.class);
tracker.addEntity(wrapper.get(Type.VAR_INT, 0), EntityTypes1_10.EntityType.LIGHTNING);
});
}
});
@@ -18,14 +18,14 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.packets;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.chunks.ChunkPacketTransformer;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.WorldBorder;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ReplacementRegistry1_7_6_10to1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.WorldBorderEmulator;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk.ChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk.BulkChunkType1_7_6;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.ParticleIndex1_7_6_10;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
@@ -33,55 +33,50 @@ import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.CustomByteType;
import com.viaversion.viaversion.api.type.types.FixedByteArrayType;
import com.viaversion.viaversion.api.type.types.chunk.BulkChunkType1_8;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.types.Chunk1_8Type;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.util.ChatColorUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Chunk1_7_10Type;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Particle;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
public class WorldPackets {
public static void register(Protocol1_7_6_10To1_8 protocol) {
private static void rewriteBlockIds(final Protocol1_7_6_10To1_8 protocol, final Chunk chunk) {
for (ChunkSection section : chunk.getSections()) {
if (section == null) continue;
final DataPalette palette = section.palette(PaletteType.BLOCKS);
/* OUTGOING */
protocol.registerClientbound(ClientboundPackets1_8.CHUNK_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
Chunk chunk = packetWrapper.read(new Chunk1_8Type(world));
packetWrapper.write(new Chunk1_7_10Type(world), chunk);
for (ChunkSection section : chunk.getSections()) {
if (section == null) continue;
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < palette.size(); i++) {
int block = palette.idByIndex(i);
int replacedBlock = ReplacementRegistry1_7_6_10to1_8.replace(block);
palette.setIdByIndex(i, replacedBlock);
}
}
});
for (int i = 0; i < palette.size(); i++) {
palette.setIdByIndex(i, protocol.getItemRewriter().replace(palette.idByIndex(i)));
}
}
}
public static void register(Protocol1_7_6_10To1_8 protocol) {
protocol.registerClientbound(ClientboundPackets1_8.CHUNK_DATA, wrapper -> {
final ClientWorld world = wrapper.user().get(ClientWorld.class);
final Chunk chunk = wrapper.read(ChunkType1_8.forEnvironment(world.getEnvironment()));
rewriteBlockIds(protocol, chunk);
wrapper.write(ChunkType1_7_6.TYPE, chunk);
});
protocol.registerClientbound(ClientboundPackets1_8.MULTI_BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
map(Type.INT);
handler(packetWrapper -> {
final BlockChangeRecord[] records = packetWrapper.read(Type.BLOCK_CHANGE_RECORD_ARRAY);
packetWrapper.write(Type.SHORT, (short) records.length);
packetWrapper.write(Type.INT, records.length * 4);
map(Type.INT); // chunk x
map(Type.INT); // chunk z
handler(wrapper -> {
final BlockChangeRecord[] records = wrapper.read(Type.BLOCK_CHANGE_RECORD_ARRAY);
wrapper.write(Type.SHORT, (short) records.length); // record count
wrapper.write(Type.INT, records.length * 4); // data array length (position + block id)
for (BlockChangeRecord record : records) {
short data = (short) (record.getSectionX() << 12 | record.getSectionZ() << 8 | record.getY());
packetWrapper.write(Type.SHORT, data);
int replacedBlock = ReplacementRegistry1_7_6_10to1_8.replace(record.getBlockId());
packetWrapper.write(Type.SHORT, (short) replacedBlock);
wrapper.write(Type.SHORT, (short) (record.getSectionX() << 12 | record.getSectionZ() << 8 | record.getY())); // position
wrapper.write(Type.SHORT, (short) protocol.getItemRewriter().replace(record.getBlockId())); // block id
}
});
}
@@ -89,114 +84,95 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.UNSIGNED_BYTE, (short) position.y());
packetWrapper.write(Type.INT, position.z());
protected void register() {
map(Type.POSITION1_8, Types1_7_6_10.U_BYTE_POSITION); // position
handler(wrapper -> {
int data = wrapper.read(Type.VAR_INT); // block data
data = protocol.getItemRewriter().replace(data);
wrapper.write(Type.VAR_INT, data >> 4); // block id
wrapper.write(Type.UNSIGNED_BYTE, (short) (data & 0xF)); // block data
});
handler(packetWrapper -> {
int data = packetWrapper.read(Type.VAR_INT);
data = ReplacementRegistry1_7_6_10to1_8.replace(data);
packetWrapper.write(Type.VAR_INT, data >> 4);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) (data & 0xF));
}); //Block Data
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ACTION, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.SHORT, (short) position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.VAR_INT);
map(Type.POSITION1_8, Types1_7_6_10.SHORT_POSITION); // position
map(Type.UNSIGNED_BYTE); // type
map(Type.UNSIGNED_BYTE); // data
map(Type.VAR_INT); // block id
}
});
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_BREAK_ANIMATION, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT); //Entity Id
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.INT, position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.BYTE); //Progress
map(Type.VAR_INT); // entity id
map(Type.POSITION1_8, Types1_7_6_10.INT_POSITION); // position
map(Type.BYTE); // progress
}
});
protocol.registerClientbound(ClientboundPackets1_8.MAP_BULK_CHUNK, new PacketHandlers() {
@Override
public void register() {
handler(ChunkPacketTransformer::transformChunkBulk);
protocol.registerClientbound(ClientboundPackets1_8.MAP_BULK_CHUNK, wrapper -> {
final Chunk[] chunks = wrapper.read(BulkChunkType1_8.TYPE);
for (Chunk chunk : chunks) {
rewriteBlockIds(protocol, chunk);
}
wrapper.write(BulkChunkType1_7_6.TYPE, chunks);
});
//Effect
protocol.registerClientbound(ClientboundPackets1_8.EFFECT, new PacketHandlers() {
@Override
public void register() {
map(Type.INT);
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.BYTE, (byte) position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.INT);
map(Type.BOOLEAN);
map(Type.INT); // effect id
map(Type.POSITION1_8, Types1_7_6_10.BYTE_POSITION); // position
map(Type.INT); // data
map(Type.BOOLEAN); // disable relative volume
}
});
protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PARTICLE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int particleId = packetWrapper.read(Type.INT);
Particle particle = Particle.find(particleId);
if (particle == null) particle = Particle.CRIT;
packetWrapper.write(Type.STRING, particle.name);
handler(wrapper -> {
final int particleId = wrapper.read(Type.INT); // particle id
ParticleIndex1_7_6_10 particle = ParticleIndex1_7_6_10.find(particleId);
if (particle == null) particle = ParticleIndex1_7_6_10.CRIT;
wrapper.write(Type.STRING, particle.name); // particle name
packetWrapper.read(Type.BOOLEAN);
});
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.INT);
handler(packetWrapper -> {
String name = packetWrapper.get(Type.STRING, 0);
Particle particle = Particle.find(name);
read(Type.BOOLEAN); // long distance
map(Type.FLOAT); // x
map(Type.FLOAT); // y
map(Type.FLOAT); // z
map(Type.FLOAT); // offset x
map(Type.FLOAT); // offset y
map(Type.FLOAT); // offset z
map(Type.FLOAT); // particle data
map(Type.INT); // particle count
handler(wrapper -> {
String name = wrapper.get(Type.STRING, 0);
ParticleIndex1_7_6_10 particle = ParticleIndex1_7_6_10.find(name);
if (particle == Particle.ICON_CRACK || particle == Particle.BLOCK_CRACK || particle == Particle.BLOCK_DUST) {
int id = packetWrapper.read(Type.VAR_INT);
int data = particle == Particle.ICON_CRACK ? packetWrapper.read(Type.VAR_INT) : 0;
if (particle == ParticleIndex1_7_6_10.ICON_CRACK || particle == ParticleIndex1_7_6_10.BLOCK_CRACK || particle == ParticleIndex1_7_6_10.BLOCK_DUST) {
int id = wrapper.read(Type.VAR_INT);
int data = particle == ParticleIndex1_7_6_10.ICON_CRACK ? wrapper.read(Type.VAR_INT) : id / 4096;
id %= 4096;
if (id >= 256 && id <= 422 || id >= 2256 && id <= 2267) { //item
particle = Particle.ICON_CRACK;
particle = ParticleIndex1_7_6_10.ICON_CRACK;
} else if (id >= 0 && id <= 164 || id >= 170 && id <= 175) {
if (particle == Particle.ICON_CRACK) particle = Particle.BLOCK_CRACK;
if (particle == ParticleIndex1_7_6_10.ICON_CRACK) particle = ParticleIndex1_7_6_10.BLOCK_CRACK;
} else {
packetWrapper.cancel();
wrapper.cancel();
return;
}
name = particle.name + "_" + id + "_" + data;
}
packetWrapper.set(Type.STRING, 0, name);
wrapper.set(Type.STRING, 0, name);
});
}
});
@@ -204,22 +180,18 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.SHORT, (short) position.y());
packetWrapper.write(Type.INT, position.z());
});
handler(packetWrapper -> {
map(Type.POSITION1_8, Types1_7_6_10.SHORT_POSITION); // position
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
String line = packetWrapper.read(Type.STRING);
String line = wrapper.read(Type.STRING);
line = ChatUtil.jsonToLegacy(line);
line = ChatUtil.removeUnusedColor(line, '0');
if (line.length() > 15) {
line = ChatColorUtil.stripColor(line);
if (line.length() > 15) line = line.substring(0, 15);
}
packetWrapper.write(Type.STRING, line);
wrapper.write(Type.STRING, line);
}
});
}
@@ -228,27 +200,28 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.MAP_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
packetWrapper.cancel();
int id = packetWrapper.read(Type.VAR_INT);
byte scale = packetWrapper.read(Type.BYTE);
handler(wrapper -> {
wrapper.cancel();
final int id = wrapper.read(Type.VAR_INT);
final byte scale = wrapper.read(Type.BYTE);
int count = packetWrapper.read(Type.VAR_INT);
byte[] icons = new byte[count * 4];
for (int i = 0; i < count; i++) {
int j = packetWrapper.read(Type.BYTE);
icons[i * 4] = (byte) (j >> 4 & 0xF);
icons[i * 4 + 1] = packetWrapper.read(Type.BYTE);
icons[i * 4 + 2] = packetWrapper.read(Type.BYTE);
icons[i * 4 + 3] = (byte) (j & 0xF);
final int iconCount = wrapper.read(Type.VAR_INT);
byte[] icons = new byte[iconCount * 4];
for (int i = 0; i < iconCount; i++) {
final int directionAndType = wrapper.read(Type.BYTE);
icons[i * 4] = (byte) (directionAndType >> 4 & 0xF);
icons[i * 4 + 1] = wrapper.read(Type.BYTE); // x
icons[i * 4 + 2] = wrapper.read(Type.BYTE); // z
icons[i * 4 + 3] = (byte) (directionAndType & 0xF);
}
short columns = packetWrapper.read(Type.UNSIGNED_BYTE);
final short columns = wrapper.read(Type.UNSIGNED_BYTE);
if (columns > 0) {
short rows = packetWrapper.read(Type.UNSIGNED_BYTE);
short x = packetWrapper.read(Type.UNSIGNED_BYTE);
short z = packetWrapper.read(Type.UNSIGNED_BYTE);
byte[] data = packetWrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
final short rows = wrapper.read(Type.UNSIGNED_BYTE);
final short x = wrapper.read(Type.UNSIGNED_BYTE);
final short z = wrapper.read(Type.UNSIGNED_BYTE);
final byte[] data = wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
for (int column = 0; column < columns; column++) {
byte[] columnData = new byte[rows + 3];
columnData[0] = 0;
@@ -259,36 +232,39 @@ public class WorldPackets {
columnData[i + 3] = data[column + i * columns];
}
PacketWrapper columnUpdate = PacketWrapper.create(0x34, null, packetWrapper.user());
columnUpdate.write(Type.VAR_INT, id);
columnUpdate.write(Type.SHORT, (short) columnData.length);
columnUpdate.write(new CustomByteType(columnData.length), columnData);
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_DATA, wrapper.user());
mapData.write(Type.VAR_INT, id); // map id
mapData.write(Type.SHORT, (short) columnData.length); // data length
mapData.write(new FixedByteArrayType(columnData.length), columnData); // data
PacketUtil.sendPacket(columnUpdate, Protocol1_7_6_10To1_8.class, true, true);
mapData.send(Protocol1_7_6_10To1_8.class, true);
}
}
if (count > 0) {
byte[] iconData = new byte[count * 3 + 1];
if (iconCount > 0) {
final byte[] iconData = new byte[iconCount * 3 + 1];
iconData[0] = 1;
for (int i = 0; i < count; i++) {
for (int i = 0; i < iconCount; i++) {
iconData[i * 3 + 1] = (byte) (icons[i * 4] << 4 | icons[i * 4 + 3] & 0xF);
iconData[i * 3 + 2] = icons[i * 4 + 1];
iconData[i * 3 + 3] = icons[i * 4 + 2];
}
PacketWrapper iconUpdate = PacketWrapper.create(0x34, null, packetWrapper.user());
iconUpdate.write(Type.VAR_INT, id);
iconUpdate.write(Type.SHORT, (short) iconData.length);
CustomByteType customByteType = new CustomByteType(iconData.length);
iconUpdate.write(customByteType, iconData);
PacketUtil.sendPacket(iconUpdate, Protocol1_7_6_10To1_8.class, true, true);
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_DATA, wrapper.user());
mapData.write(Type.VAR_INT, id); // map id
mapData.write(Type.SHORT, (short) iconData.length); // data length
mapData.write(new FixedByteArrayType(iconData.length), iconData); // data
mapData.send(Protocol1_7_6_10To1_8.class, true);
}
PacketWrapper scaleUpdate = PacketWrapper.create(0x34, null, packetWrapper.user());
scaleUpdate.write(Type.VAR_INT, id);
scaleUpdate.write(Type.SHORT, (short) 2);
scaleUpdate.write(new CustomByteType(2), new byte[]{2, scale});
PacketUtil.sendPacket(scaleUpdate, Protocol1_7_6_10To1_8.class, true, true);
// Update scale
final PacketWrapper mapData = PacketWrapper.create(ClientboundPackets1_8.MAP_DATA, wrapper.user());
mapData.write(Type.VAR_INT, id); // map id
mapData.write(Type.SHORT, (short) 2); // data length
mapData.write(new FixedByteArrayType(2), new byte[]{ 2, scale }); // data
mapData.send(Protocol1_7_6_10To1_8.class, true);
});
}
});
@@ -296,50 +272,33 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_8.BLOCK_ENTITY_DATA, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Position position = packetWrapper.read(Type.POSITION);
packetWrapper.write(Type.INT, position.x());
packetWrapper.write(Type.SHORT, (short) position.y());
packetWrapper.write(Type.INT, position.z());
});
map(Type.UNSIGNED_BYTE); //Action
map(Type.NBT, Types1_7_6_10.COMPRESSED_NBT);
map(Type.POSITION1_8, Types1_7_6_10.SHORT_POSITION); // position
map(Type.UNSIGNED_BYTE); // action
map(Type.NAMED_COMPOUND_TAG, Types1_7_6_10.COMPRESSED_NBT); // nbt
}
});
protocol.cancelClientbound(ClientboundPackets1_8.SERVER_DIFFICULTY);
protocol.cancelClientbound(ClientboundPackets1_8.COMBAT_EVENT);
protocol.registerClientbound(ClientboundPackets1_8.WORLD_BORDER, null, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int action = packetWrapper.read(Type.VAR_INT);
WorldBorder worldBorder = packetWrapper.user().get(WorldBorder.class);
if (action == 0) {
worldBorder.setSize(packetWrapper.read(Type.DOUBLE));
} else if (action == 1) {
worldBorder.lerpSize(packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.VAR_LONG));
} else if (action == 2) {
worldBorder.setCenter(packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.DOUBLE));
} else if (action == 3) {
worldBorder.init(
packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.DOUBLE),
packetWrapper.read(Type.DOUBLE), packetWrapper.read(Type.DOUBLE),
packetWrapper.read(Type.VAR_LONG),
packetWrapper.read(Type.VAR_INT),
packetWrapper.read(Type.VAR_INT), packetWrapper.read(Type.VAR_INT)
);
} else if (action == 4) {
worldBorder.setWarningTime(packetWrapper.read(Type.VAR_INT));
} else if (action == 5) {
worldBorder.setWarningBlocks(packetWrapper.read(Type.VAR_INT));
}
protocol.registerClientbound(ClientboundPackets1_8.WORLD_BORDER, null, wrapper -> {
final WorldBorderEmulator emulator = wrapper.user().get(WorldBorderEmulator.class);
wrapper.cancel();
packetWrapper.cancel();
});
final int action = wrapper.read(Type.VAR_INT);
if (action == 0) { // set size
emulator.setSize(wrapper.read(Type.DOUBLE)); // radius
} else if (action == 1) { // lerp size
emulator.lerpSize(wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE), wrapper.read(Type.VAR_LONG)); // old radius, new radius, speed
} else if (action == 2) { // set center
emulator.setCenter(wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE)); // x, z
} else if (action == 3) { // initialize
emulator.init(
wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE), // x, z
wrapper.read(Type.DOUBLE), wrapper.read(Type.DOUBLE), // old radius, new radius
wrapper.read(Type.VAR_LONG) // speed
);
}
});
}
}
@@ -18,159 +18,24 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.CompressionSendStorage;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.CompressionStatusTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.platform.providers.Provider;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viarewind.netty.EmptyChannelHandler;
import com.viaversion.viarewind.netty.ForwardMessageToByteEncoder;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
public abstract class CompressionHandlerProvider implements Provider {
public class CompressionHandlerProvider implements Provider {
public void handleSetCompression(UserConnection user, int threshold) {
ChannelPipeline pipeline = user.getChannel().pipeline();
if (user.isClientSide()) {
pipeline.addBefore(Via.getManager().getInjector().getEncoderName(), "compress", getEncoder(threshold));
pipeline.addBefore(Via.getManager().getInjector().getDecoderName(), "decompress", getDecoder(threshold));
} else {
CompressionSendStorage storage = user.get(CompressionSendStorage.class);
storage.setRemoveCompression(true);
}
public abstract void onHandleLoginCompressionPacket(UserConnection user, int threshold);
public abstract void onTransformPacket(UserConnection user);
public abstract ChannelHandler getEncoder(int threshold);
public abstract ChannelHandler getDecoder(int threshold);
public boolean isCompressionEnabled(UserConnection user) {
return user.get(CompressionStatusTracker.class).removeCompression;
}
public void handleTransform(UserConnection user) {
CompressionSendStorage storage = user.get(CompressionSendStorage.class);
if (storage.isRemoveCompression()) {
ChannelPipeline pipeline = user.getChannel().pipeline();
String compressor = null;
String decompressor = null;
if (pipeline.get("compress") != null) {
compressor = "compress";
decompressor = "decompress";
} else if (pipeline.get("compression-encoder") != null) { // Velocity
compressor = "compression-encoder";
decompressor = "compression-decoder";
}
if (compressor != null) { // We can neutralize the effect of compressor to the client
pipeline.replace(decompressor, decompressor, new EmptyChannelHandler());
pipeline.replace(compressor, compressor, new ForwardMessageToByteEncoder());
} else {
throw new IllegalStateException("Couldn't remove compression for 1.7!");
}
storage.setRemoveCompression(false);
}
}
protected ChannelHandler getEncoder(int threshold) {
return new Compressor(threshold);
}
protected ChannelHandler getDecoder(int threshold) {
return new Decompressor(threshold);
}
private static class Decompressor extends MessageToMessageDecoder<ByteBuf> {
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
private final Inflater inflater;
private final int threshold;
public Decompressor(int var1) {
this.threshold = var1;
this.inflater = new Inflater();
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (!in.isReadable()) return;
int outLength = Type.VAR_INT.readPrimitive(in);
if (outLength == 0) {
out.add(in.readBytes(in.readableBytes()));
return;
}
if (outLength < this.threshold) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is below server threshold of " + this.threshold);
} else if (outLength > 2097152) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is larger than protocol maximum of " + 2097152);
}
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer(outLength, outLength);
try {
this.inflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
output.writerIndex(output.writerIndex() + this.inflater.inflate(
output.array(), output.arrayOffset(), outLength));
out.add(output.retain());
} finally {
output.release();
temp.release();
this.inflater.reset();
}
}
}
private static class Compressor extends MessageToByteEncoder<ByteBuf> {
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
private final Deflater deflater;
private final int threshold;
public Compressor(int var1) {
this.threshold = var1;
this.deflater = new Deflater();
}
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
int frameLength = in.readableBytes();
if (frameLength < this.threshold) {
out.writeByte(0); // varint
out.writeBytes(in);
return;
}
Type.VAR_INT.writePrimitive(out, frameLength);
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer();
try {
this.deflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
deflater.finish();
while (!deflater.finished()) {
output.ensureWritable(4096);
output.writerIndex(output.writerIndex() + this.deflater.deflate(output.array(),
output.arrayOffset() + output.writerIndex(), output.writableBytes()));
}
out.writeBytes(output);
} finally {
output.release();
temp.release();
this.deflater.reset();
}
}
public void setCompressionEnabled(UserConnection user, boolean enabled) {
user.get(CompressionStatusTracker.class).removeCompression = enabled;
}
}
@@ -39,7 +39,7 @@ public abstract class TitleRenderProvider implements Provider {
setFadeOut(uuid, fadeOut);
AtomicInteger time = getTime(uuid);
if (time.get()>0) time.set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
if (time.get() > 0) time.set(getFadeIn(uuid) + getStay(uuid) + getFadeOut(uuid));
}
public void reset(UUID uuid) {
@@ -83,17 +83,17 @@ public abstract class TitleRenderProvider implements Provider {
}
public void setFadeIn(UUID uuid, int fadeIn) {
if (fadeIn>=0) this.fadeIn.put(uuid, fadeIn);
if (fadeIn >= 0) this.fadeIn.put(uuid, fadeIn);
else this.fadeIn.remove(uuid);
}
public void setStay(UUID uuid, int stay) {
if (stay>=0) this.stay.put(uuid, stay);
if (stay >= 0) this.stay.put(uuid, stay);
else this.stay.remove(uuid);
}
public void setFadeOut(UUID uuid, int fadeOut) {
if (fadeOut>=0) this.fadeOut.put(uuid, fadeOut);
if (fadeOut >= 0) this.fadeOut.put(uuid, fadeOut);
else this.fadeOut.remove(uuid);
}
}
@@ -0,0 +1,56 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
import java.util.zip.Inflater;
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionDecoder.java
public class CompressionDecoder extends MessageToMessageDecoder<ByteBuf> {
private final Inflater inflater = new Inflater();
private final int threshold;
public CompressionDecoder(final int threshold) {
this.threshold = threshold;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (!in.isReadable()) return;
int outLength = Type.VAR_INT.readPrimitive(in);
if (outLength == 0) {
out.add(in.readBytes(in.readableBytes()));
return;
}
if (outLength < this.threshold) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is below server threshold of " + this.threshold);
} else if (outLength > 2097152) {
throw new DecoderException("Badly compressed packet - size of " + outLength + " is larger than protocol maximum of " + 2097152);
}
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer(outLength, outLength);
try {
this.inflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
output.writerIndex(output.writerIndex() + this.inflater.inflate(output.array(), output.arrayOffset(), outLength));
out.add(output.retain());
} finally {
output.release();
temp.release();
this.inflater.reset();
}
}
}
@@ -0,0 +1,54 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import java.util.zip.Deflater;
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
private final Deflater deflater = new Deflater();
private final int threshold;
public CompressionEncoder(final int threshold) {
this.threshold = threshold;
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
int frameLength = in.readableBytes();
if (frameLength < this.threshold) {
out.writeByte(0); // VarInt
out.writeBytes(in);
return;
}
Type.VAR_INT.writePrimitive(out, frameLength);
ByteBuf temp = in;
if (!in.hasArray()) {
temp = ByteBufAllocator.DEFAULT.heapBuffer().writeBytes(in);
} else {
in.retain();
}
ByteBuf output = ByteBufAllocator.DEFAULT.heapBuffer();
try {
this.deflater.setInput(temp.array(), temp.arrayOffset() + temp.readerIndex(), temp.readableBytes());
deflater.finish();
while (!deflater.finished()) {
output.ensureWritable(4096);
output.writerIndex(output.writerIndex() + this.deflater.deflate(output.array(), output.arrayOffset() + output.writerIndex(), output.writableBytes()));
}
out.writeBytes(output);
} finally {
output.release();
temp.release();
this.deflater.reset();
}
}
}
@@ -0,0 +1,61 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.compression;
import com.viaversion.viarewind.api.netty.EmptyChannelHandler;
import com.viaversion.viarewind.api.netty.ForwardMessageToByteEncoder;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.CompressionHandlerProvider;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
public class TrackingCompressionHandlerProvider extends CompressionHandlerProvider {
public final static String COMPRESS_HANDLER_NAME = "compress";
public final static String DECOMPRESS_HANDLER_NAME = "decompress";
@Override
public void onHandleLoginCompressionPacket(UserConnection user, int threshold) {
final ChannelPipeline pipeline = user.getChannel().pipeline();
if (user.isClientSide()) {
pipeline.addBefore(Via.getManager().getInjector().getEncoderName(), COMPRESS_HANDLER_NAME, getEncoder(threshold));
pipeline.addBefore(Via.getManager().getInjector().getDecoderName(), DECOMPRESS_HANDLER_NAME, getDecoder(threshold));
} else {
setCompressionEnabled(user, true); // We need to remove compression for 1.7 clients
}
}
@Override
public void onTransformPacket(UserConnection user) {
if (isCompressionEnabled(user)) {
final ChannelPipeline pipeline = user.getChannel().pipeline();
String compressor = null;
String decompressor = null;
if (pipeline.get(COMPRESS_HANDLER_NAME) != null) { // ViaVersion
compressor = COMPRESS_HANDLER_NAME;
decompressor = DECOMPRESS_HANDLER_NAME;
} else if (pipeline.get("compression-encoder") != null) { // Velocity
compressor = "compression-encoder";
decompressor = "compression-decoder";
}
if (compressor != null) { // We can neutralize the effect of compressor to the client
pipeline.replace(decompressor, decompressor, new EmptyChannelHandler());
pipeline.replace(compressor, compressor, new ForwardMessageToByteEncoder());
} else {
throw new IllegalStateException("Couldn't remove compression for 1.7!");
}
setCompressionEnabled(user, false);
}
}
@Override
public ChannelHandler getEncoder(int threshold) {
return new CompressionEncoder(threshold);
}
@Override
public ChannelHandler getDecoder(int threshold) {
return new CompressionDecoder(threshold);
}
}
@@ -16,43 +16,53 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.items.ItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_7_6_10.metadata.MetaIndex1_8To1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.MetaIndex1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.MetaType1_7_6_10;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
@SuppressWarnings({"deprecation"})
public class MetadataRewriter {
public static void transform(Entity1_10Types.EntityType type, List<Metadata> list) {
private final Protocol1_7_6_10To1_8 protocol;
public MetadataRewriter(Protocol1_7_6_10To1_8 protocol) {
this.protocol = protocol;
}
public void transform(EntityTypes1_10.EntityType type, List<Metadata> list) {
for (Metadata entry : new ArrayList<>(list)) {
MetaIndex1_8To1_7_6_10 metaIndex = MetaIndex1_7_6_10to1_8.searchIndex(type, entry.id());
final MetaIndex1_7_6_10To1_8 metaIndex = MetaIndex1_7_6_10To1_8.searchIndex(type, entry.id());
try {
if (metaIndex == null) throw new Exception("Could not find valid metadata");
if (metaIndex == null) {
ViaRewind.getPlatform().getLogger().warning("Could not find 1.8 metadata for " + type + " with index " + entry.id());
list.remove(entry);
continue;
}
if (metaIndex.getOldType() == MetaType1_7_6_10.NonExistent) {
list.remove(entry);
continue;
}
Object value = entry.getValue();
if (!metaIndex.getNewType().type().getOutputClass().isAssignableFrom(value.getClass())) {
list.remove(entry);
continue;
}
final Object value = entry.getValue();
entry.setTypeAndValue(metaIndex.getNewType(), value);
entry.setMetaTypeUnsafe(metaIndex.getOldType());
entry.setId(metaIndex.getIndex());
switch (metaIndex.getOldType()) {
case Int:
if (metaIndex.getNewType() == MetaType1_8.Byte) {
entry.setValue(((Byte) value).intValue());
if (metaIndex == MetaIndex1_8To1_7_6_10.ENTITY_AGEABLE_AGE) {
if (metaIndex == MetaIndex1_7_6_10To1_8.ENTITY_AGEABLE_AGE) {
if ((Integer) entry.getValue() < 0) {
entry.setValue(-25000);
}
@@ -70,12 +80,13 @@ public class MetadataRewriter {
entry.setValue(((Integer) value).byteValue());
}
if (metaIndex.getNewType() == MetaType1_8.Byte) {
if (metaIndex == MetaIndex1_8To1_7_6_10.ITEM_FRAME_ROTATION) {
value = ((Integer) ((Byte) value / 2)).byteValue();
if (metaIndex == MetaIndex1_7_6_10To1_8.ITEM_FRAME_ROTATION) {
entry.setValue(Integer.valueOf((Byte) value % 4).byteValue());
} else {
entry.setValue(value);
}
entry.setValue(value);
}
if (metaIndex == MetaIndex1_8To1_7_6_10.HUMAN_SKIN_FLAGS) {
if (metaIndex == MetaIndex1_7_6_10To1_8.HUMAN_SKIN_FLAGS) {
byte flags = (byte) value;
boolean cape = (flags & 0x01) != 0;
flags = (byte) (cape ? 0x00 : 0x02);
@@ -83,26 +94,20 @@ public class MetadataRewriter {
}
break;
case Slot:
entry.setValue(ItemRewriter.toClient((Item) value));
entry.setValue(protocol.getItemRewriter().handleItemToClient((Item) value));
break;
case Float:
entry.setValue(value);
break;
case Short:
entry.setValue(value);
break;
case String:
entry.setValue(value);
break;
case Short:
case Position:
entry.setValue(value);
break;
default:
ViaRewind.getPlatform().getLogger().warning("[Out] Unhandled MetaDataType: " + metaIndex.getNewType());
ViaRewind.getPlatform().getLogger().warning("Could not transform metadata for " + type + " with index " + entry.id() + " and type " + metaIndex.getOldType());
list.remove(entry);
break;
}
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.WARNING, "Unable to transform metadata", e);
list.remove(entry);
}
}
@@ -0,0 +1,230 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import java.util.ArrayList;
import java.util.List;
public class ReplacementItemRewriter1_7_6_10 extends ReplacementItemRewriter<Protocol1_7_6_10To1_8> {
private final static String VIA_REWIND_TAG_KEY = "ViaRewind1_7_6_10to1_8";
public ReplacementItemRewriter1_7_6_10(Protocol1_7_6_10To1_8 protocol) {
super(protocol, ProtocolVersion.v1_8);
}
@Override
public void register() {
registerBlock(176, new Replacement(63));
registerBlock(177, new Replacement(68));
registerBlock(193, new Replacement(64));
registerBlock(194, new Replacement(64));
registerBlock(195, new Replacement(64));
registerBlock(196, new Replacement(64));
registerBlock(197, new Replacement(64));
registerBlock(77, 5, new Replacement(69, 6));
registerBlock(77, 13, new Replacement(69, 14));
registerBlock(77, 0, new Replacement(69, 0));
registerBlock(77, 8, new Replacement(69, 8));
registerBlock(143, 5, new Replacement(69, 6));
registerBlock(143, 13, new Replacement(69, 14));
registerBlock(143, 0, new Replacement(69, 0));
registerBlock(143, 8, new Replacement(69, 8));
registerBlock(178, new Replacement(151));
registerBlock(182, 0, new Replacement(44, 1));
registerBlock(182, 8, new Replacement(44, 9));
registerItem(425, new Replacement(323, "Banner"));
registerItem(409, new Replacement(406, "Prismarine Shard"));
registerItem(410, new Replacement(406, "Prismarine Crystal"));
registerItem(416, new Replacement(280, "Armor Stand"));
registerItem(423, new Replacement(363, "Raw Mutton"));
registerItem(424, new Replacement(364, "Cooked Mutton"));
registerItem(411, new Replacement(365, "Raw Rabbit"));
registerItem(412, new Replacement(366, "Cooked Rabbit"));
registerItem(413, new Replacement(282, "Rabbit Stew"));
registerItem(414, new Replacement(375, "Rabbit's Foot"));
registerItem(415, new Replacement(334, "Rabbit Hide"));
registerItem(373, 8203, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 8235, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 8267, new Replacement(373, 0, "Potion of Leaping"));
registerItem(373, 16395, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(373, 16427, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(373, 16459, new Replacement(373, 0, "Splash Potion of Leaping"));
registerItem(383, 30, new Replacement(383, "Spawn ArmorStand"));
registerItem(383, 67, new Replacement(383, "Spawn Endermite"));
registerItem(383, 68, new Replacement(383, "Spawn Guardian"));
registerItem(383, 101, new Replacement(383, "Spawn Rabbit"));
registerItem(19, 1, new Replacement(19, 0, "Wet Sponge"));
registerItem(182, new Replacement(44, 1, "Red Sandstone Slab"));
registerItemBlock(166, new Replacement(20, "Barrier"));
registerItemBlock(167, new Replacement(96, "Iron Trapdoor"));
registerItemBlock(1, 1, new Replacement(1, 0, "Granite"));
registerItemBlock(1, 2, new Replacement(1, 0, "Polished Granite"));
registerItemBlock(1, 3, new Replacement(1, 0, "Diorite"));
registerItemBlock(1, 4, new Replacement(1, 0, "Polished Diorite"));
registerItemBlock(1, 5, new Replacement(1, 0, "Andesite"));
registerItemBlock(1, 6, new Replacement(1, 0, "Polished Andesite"));
registerItemBlock(168, 0, new Replacement(1, 0, "Prismarine"));
registerItemBlock(168, 1, new Replacement(98, 0, "Prismarine Bricks"));
registerItemBlock(168, 2, new Replacement(98, 1, "Dark Prismarine"));
registerItemBlock(169, new Replacement(89, "Sea Lantern"));
registerItemBlock(165, new Replacement(95, 5, "Slime Block"));
registerItemBlock(179, 0, new Replacement(24, "Red Sandstone"));
registerItemBlock(179, 1, new Replacement(24, "Chiseled Red Sandstone"));
registerItemBlock(179, 2, new Replacement(24, "Smooth Sandstone"));
registerItemBlock(181, new Replacement(43, 1, "Double Red Sandstone Slab"));
registerItemBlock(180, new Replacement(128, "Red Sandstone Stairs"));
registerItemBlock(188, new Replacement(85, "Spruce Fence"));
registerItemBlock(189, new Replacement(85, "Birch Fence"));
registerItemBlock(190, new Replacement(85, "Jungle Fence"));
registerItemBlock(191, new Replacement(85, "Dark Oak Fence"));
registerItemBlock(192, new Replacement(85, "Acacia Fence"));
registerItemBlock(183, new Replacement(107, "Spruce Fence Gate"));
registerItemBlock(184, new Replacement(107, "Birch Fence Gate"));
registerItemBlock(185, new Replacement(107, "Jungle Fence Gate"));
registerItemBlock(186, new Replacement(107, "Dark Oak Fence Gate"));
registerItemBlock(187, new Replacement(107, "Acacia Fence Gate"));
registerItemBlock(427, new Replacement(324, "Spruce Door"));
registerItemBlock(428, new Replacement(324, "Birch Door"));
registerItemBlock(429, new Replacement(324, "Jungle Door"));
registerItemBlock(430, new Replacement(324, "Dark Oak Door"));
registerItemBlock(431, new Replacement(324, "Acacia Door"));
registerItemBlock(157, new Replacement(28, "Activator Rail"));
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
CompoundTag viaRewindTag = new CompoundTag();
tag.put(VIA_REWIND_TAG_KEY, viaRewindTag);
viaRewindTag.put("id", new ShortTag((short) item.identifier()));
viaRewindTag.put("data", new ShortTag(item.data()));
CompoundTag display = tag.get("display");
if (display != null && display.contains("Name")) {
viaRewindTag.put("displayName", new StringTag((String) display.get("Name").getValue()));
}
if (display != null && display.contains("Lore")) {
viaRewindTag.put("lore", new ListTag(((ListTag) display.get("Lore")).getValue()));
}
if (tag.contains("ench") || tag.contains("StoredEnchantments")) {
ListTag enchTag = tag.contains("ench") ? tag.get("ench") : tag.get("StoredEnchantments");
List<Tag> lore = new ArrayList<>();
for (Tag ench : new ArrayList<>(enchTag.getValue())) {
short id = ((NumberTag) ((CompoundTag) ench).get("id")).asShort();
short lvl = ((NumberTag) ((CompoundTag) ench).get("lvl")).asShort();
String s;
if (id == 8) {
s = "§r§7Depth Strider ";
} else {
continue;
}
enchTag.remove(ench);
s += Enchantments.ENCHANTMENTS.getOrDefault(lvl, "enchantment.level." + lvl);
lore.add(new StringTag(s));
}
if (!lore.isEmpty()) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaRewindTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
lore.addAll(loreTag.getValue());
loreTag.setValue(lore);
}
}
if (item.identifier() == 387 && tag.contains("pages")) {
ListTag pages = tag.get("pages");
ListTag oldPages = new ListTag(StringTag.class);
viaRewindTag.put("pages", oldPages);
for (int i = 0; i < pages.size(); i++) {
StringTag page = pages.get(i);
String value = page.getValue();
oldPages.add(new StringTag(value));
value = ChatUtil.jsonToLegacy(value);
page.setValue(value);
}
}
replace(item);
if (viaRewindTag.size() == 2 && (short) viaRewindTag.get("id").getValue() == item.identifier() && (short) viaRewindTag.get("data").getValue() == item.data()) {
item.tag().remove(VIA_REWIND_TAG_KEY);
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null || !item.tag().contains(VIA_REWIND_TAG_KEY)) return item;
CompoundTag viaVersionTag = tag.remove(VIA_REWIND_TAG_KEY);
item.setIdentifier((short) viaVersionTag.get("id").getValue());
item.setData((Short) viaVersionTag.get("data").getValue());
if (viaVersionTag.contains("noDisplay")) tag.remove("display");
if (viaVersionTag.contains("displayName")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
StringTag name = display.get("Name");
if (name == null) display.put("Name", new StringTag((String) viaVersionTag.get("displayName").getValue()));
else name.setValue((String) viaVersionTag.get("displayName").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Name");
}
if (item.identifier() == 387) {
ListTag oldPages = viaVersionTag.get("pages");
tag.remove("pages");
tag.put("pages", oldPages);
}
return item;
}
}
@@ -21,18 +21,13 @@ package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class CompressionSendStorage extends StoredObject {
private boolean removeCompression = false;
/**
* @see com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.provider.CompressionHandlerProvider
*/
public class CompressionStatusTracker extends StoredObject {
public boolean removeCompression = false;
public CompressionSendStorage(UserConnection user) {
public CompressionStatusTracker(UserConnection user) {
super(user);
}
public boolean isRemoveCompression() {
return removeCompression;
}
public void setRemoveCompression(boolean removeCompression) {
this.removeCompression = removeCompression;
}
}
@@ -1,258 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.metadata.MetadataRewriter;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.ClientEntityIdChangeListener;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class EntityTracker extends StoredObject implements ClientEntityIdChangeListener {
private final Map<Integer, Entity1_10Types.EntityType> clientEntityTypes = new ConcurrentHashMap();
private final Map<Integer, List<Metadata>> metadataBuffer = new ConcurrentHashMap();
private final Map<Integer, Integer> vehicles = new ConcurrentHashMap<>();
private final Map<Integer, EntityReplacement> entityReplacements = new ConcurrentHashMap<>();
private final Map<Integer, UUID> playersByEntityId = new HashMap<>();
private final Map<UUID, Integer> playersByUniqueId = new HashMap<>();
private final Map<UUID, Item[]> playerEquipment = new HashMap<>();
private int gamemode = 0;
private int playerId = -1;
private int spectating = -1;
private int dimension = 0;
public EntityTracker(UserConnection user) {
super(user);
}
public void removeEntity(int entityId) {
clientEntityTypes.remove(entityId);
if (entityReplacements.containsKey(entityId)) {
entityReplacements.remove(entityId).despawn();
}
if (playersByEntityId.containsKey(entityId)) {
UUID playerId = playersByEntityId.remove(entityId);
playersByUniqueId.remove(playerId);
playerEquipment.remove(playerId);
}
}
public void addPlayer(Integer entityId, UUID uuid) {
playersByUniqueId.put(uuid, entityId);
playersByEntityId.put(entityId, uuid);
}
public UUID getPlayerUUID(int entityId) {
return playersByEntityId.get(entityId);
}
public int getPlayerEntityId(UUID uuid) {
return playersByUniqueId.getOrDefault(uuid, -1);
}
public Item getPlayerEquipment(UUID uuid, int slot) {
Item[] items = playerEquipment.get(uuid);
if (items == null || slot < 0 || slot >= items.length) return null;
return items[slot];
}
public void setPlayerEquipment(UUID uuid, Item equipment, int slot) {
// Please note that when referring to the client player, it has an Item[4] array
Item[] items = playerEquipment.computeIfAbsent(uuid, it -> new Item[5]);
if (slot < 0 || slot >= items.length) return;
items[slot] = equipment;
}
public Map<Integer, Entity1_10Types.EntityType> getClientEntityTypes() {
return this.clientEntityTypes;
}
public void addMetadataToBuffer(int entityID, List<Metadata> metadataList) {
if (this.metadataBuffer.containsKey(entityID)) {
this.metadataBuffer.get(entityID).addAll(metadataList);
} else if (!metadataList.isEmpty()) {
this.metadataBuffer.put(entityID, metadataList);
}
}
public void addEntityReplacement(EntityReplacement entityReplacement) {
entityReplacements.put(entityReplacement.getEntityId(), entityReplacement);
}
public EntityReplacement getEntityReplacement(int entityId) {
return entityReplacements.get(entityId);
}
public List<Metadata> getBufferedMetadata(int entityId) {
return metadataBuffer.get(entityId);
}
public void sendMetadataBuffer(int entityId) {
if (!this.metadataBuffer.containsKey(entityId)) return;
if (entityReplacements.containsKey(entityId)) {
entityReplacements.get(entityId).updateMetadata(this.metadataBuffer.remove(entityId));
} else {
Entity1_10Types.EntityType type = this.getClientEntityTypes().get(entityId);
PacketWrapper wrapper = PacketWrapper.create(0x1C, null, this.getUser());
wrapper.write(Type.VAR_INT, entityId);
wrapper.write(Types1_8.METADATA_LIST, this.metadataBuffer.get(entityId));
MetadataRewriter.transform(type, this.metadataBuffer.get(entityId));
if (!this.metadataBuffer.get(entityId).isEmpty()) {
PacketUtil.sendPacket(wrapper, Protocol1_7_6_10To1_8.class);
}
this.metadataBuffer.remove(entityId);
}
}
public int getVehicle(int passengerId) {
for (Map.Entry<Integer, Integer> vehicle : vehicles.entrySet()) {
if (vehicle.getValue()==passengerId) return vehicle.getValue();
}
return -1;
}
public int getPassenger(int vehicleId) {
return vehicles.getOrDefault(vehicleId, -1);
}
public void setPassenger(int vehicleId, int passengerId) {
if (vehicleId==this.spectating && this.spectating!=this.playerId) {
try {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, getUser());
sneakPacket.write(Type.VAR_INT, playerId);
sneakPacket.write(Type.VAR_INT, 0); //Start sneaking
sneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketWrapper unsneakPacket = PacketWrapper.create(0x0B, null, getUser());
unsneakPacket.write(Type.VAR_INT, playerId);
unsneakPacket.write(Type.VAR_INT, 1); //Stop sneaking
unsneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketUtil.sendToServer(sneakPacket, Protocol1_7_6_10To1_8.class, true, true);
setSpectating(playerId);
} catch (Exception ex) {ex.printStackTrace();}
}
if (vehicleId==-1) {
int oldVehicleId = getVehicle(passengerId);
vehicles.remove(oldVehicleId);
} else if (passengerId==-1) {
vehicles.remove(vehicleId);
} else {
vehicles.put(vehicleId, passengerId);
}
}
public int getSpectating() {
return spectating;
}
public boolean setSpectating(int spectating) {
if (spectating!=this.playerId && getPassenger(spectating)!=-1) {
PacketWrapper sneakPacket = PacketWrapper.create(0x0B, null, getUser());
sneakPacket.write(Type.VAR_INT, playerId);
sneakPacket.write(Type.VAR_INT, 0); //Start sneaking
sneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketWrapper unsneakPacket = PacketWrapper.create(0x0B, null, getUser());
unsneakPacket.write(Type.VAR_INT, playerId);
unsneakPacket.write(Type.VAR_INT, 1); //Stop sneaking
unsneakPacket.write(Type.VAR_INT, 0); //Action Parameter
PacketUtil.sendToServer(sneakPacket, Protocol1_7_6_10To1_8.class, true, true);
setSpectating(this.playerId);
return false; //Entity has Passenger
}
if (this.spectating!=spectating && this.spectating!=this.playerId) {
PacketWrapper unmount = PacketWrapper.create(0x1B, null, this.getUser());
unmount.write(Type.INT, this.playerId);
unmount.write(Type.INT, -1);
unmount.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(unmount, Protocol1_7_6_10To1_8.class);
}
this.spectating = spectating;
if (spectating!=this.playerId) {
PacketWrapper mount = PacketWrapper.create(0x1B, null, this.getUser());
mount.write(Type.INT, this.playerId);
mount.write(Type.INT, this.spectating);
mount.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(mount, Protocol1_7_6_10To1_8.class);
}
return true;
}
public int getGamemode() {
return gamemode;
}
public void setGamemode(int gamemode) {
this.gamemode = gamemode;
}
public int getPlayerId() {
return playerId;
}
public void setPlayerId(int playerId) {
this.playerId = this.spectating = playerId;
}
public void clearEntities() {
clientEntityTypes.clear();
entityReplacements.clear();
vehicles.clear();
metadataBuffer.clear();
}
public int getDimension() {
return dimension;
}
public void setDimension(int dimension) {
this.dimension = dimension;
}
@Override
public void setClientEntityId(int playerEntityId) {
if (this.spectating == this.playerId) {
this.spectating = playerEntityId;
}
clientEntityTypes.remove(this.playerId);
this.playerId = playerEntityId;
clientEntityTypes.put(this.playerId, Entity1_10Types.EntityType.ENTITY_HUMAN);
}
}
@@ -0,0 +1,174 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.rewriter.ReplacementEntityTracker;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ServerboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.VirtualHologramEntity;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.rewriter.MetadataRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
public class EntityTracker1_7_6_10 extends ReplacementEntityTracker {
protected final MetadataRewriter metadataRewriter;
private final Map<Integer, Integer> vehicleMap = new ConcurrentHashMap<>();
private final Map<Integer, VirtualHologramEntity> virtualHologramMap = new HashMap<>();
private final Map<Integer, UUID> playersByEntityId = new HashMap<>();
private final Map<UUID, Integer> playersByUniqueId = new HashMap<>();
public int spectatingPlayerId = -1;
public EntityTracker1_7_6_10(UserConnection user, final MetadataRewriter metadataRewriter) {
super(user, ProtocolVersion.v1_8);
this.metadataRewriter = metadataRewriter;
registerEntity(EntityTypes1_10.EntityType.GUARDIAN, EntityTypes1_10.EntityType.SQUID, "Guardian");
registerEntity(EntityTypes1_10.EntityType.ENDERMITE, EntityTypes1_10.EntityType.SQUID, "Endermite");
registerEntity(EntityTypes1_10.EntityType.RABBIT, EntityTypes1_10.EntityType.CHICKEN, "Rabbit");
}
public void trackHologram(final int entityId, final VirtualHologramEntity hologram) {
addEntity(entityId, EntityTypes1_10.EntityType.ARMOR_STAND);
getEntityReplacementMap().put(entityId, EntityTypes1_10.EntityType.ARMOR_STAND);
virtualHologramMap.put(entityId, hologram);
}
@Override
public void updateMetadata(int entityId, List<Metadata> metadata) throws Exception {
if (virtualHologramMap.containsKey(entityId)) {
virtualHologramMap.get(entityId).updateMetadata(metadata);
return;
}
super.updateMetadata(entityId, metadata);
}
@Override
public void removeEntity(int entityId) {
super.removeEntity(entityId);
if (playersByEntityId.containsKey(entityId)) {
final UUID playerId = playersByEntityId.remove(entityId);
playersByUniqueId.remove(playerId);
getUser().get(PlayerSessionStorage.class).getPlayerEquipment().remove(playerId);
}
}
@Override
public void clear() {
super.clear();
vehicleMap.clear();
}
@Override
public void setClientEntityId(int entityId) {
if (this.spectatingPlayerId == this.getPlayerId()) {
this.spectatingPlayerId = entityId;
}
super.setClientEntityId(entityId);
}
public void addPlayer(final Integer entityId, final UUID uuid) {
playersByUniqueId.put(uuid, entityId);
playersByEntityId.put(entityId, uuid);
}
public UUID getPlayerUUID(final int entityId) {
return playersByEntityId.get(entityId);
}
public int getPlayerEntityId(final UUID uuid) {
return playersByUniqueId.getOrDefault(uuid, -1);
}
public int getVehicle(final int passengerId) {
for (Map.Entry<Integer, Integer> vehicle : vehicleMap.entrySet()) {
if (vehicle.getValue() == passengerId) {
return vehicle.getValue();
}
}
return -1;
}
public int getPassenger(int vehicleId) {
return vehicleMap.getOrDefault(vehicleId, -1);
}
protected void startSneaking() {
try {
final PacketWrapper entityAction = PacketWrapper.create(ServerboundPackets1_7_2_5.ENTITY_ACTION, getUser());
entityAction.write(Type.VAR_INT, this.getPlayerId()); // entity id
entityAction.write(Type.VAR_INT, 0); // action id, start sneaking
entityAction.write(Type.VAR_INT, 0); // jump boost
entityAction.sendToServer(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send sneak packet", e);
}
}
public void setPassenger(int vehicleId, int passengerId) {
if (vehicleId == this.spectatingPlayerId && this.spectatingPlayerId != this.getPlayerId()) {
startSneaking();
setSpectating(this.getPlayerId());
}
if (vehicleId == -1) {
vehicleMap.remove(getVehicle(passengerId));
} else if (passengerId == -1) {
vehicleMap.remove(vehicleId);
} else {
vehicleMap.put(vehicleId, passengerId);
}
}
protected void attachEntity(final int target) {
try {
final PacketWrapper attachEntity = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, getUser());
attachEntity.write(Type.INT, this.getPlayerId()); // vehicle id
attachEntity.write(Type.INT, target); // passenger id
attachEntity.write(Type.BOOLEAN, false); // leash
attachEntity.scheduleSend(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send attach packet", e);
}
}
public void setSpectating(int spectating) {
if (spectating != this.getPlayerId() && getPassenger(spectating) != -1) {
startSneaking();
setSpectating(this.getPlayerId());
return;
}
if (this.spectatingPlayerId != spectating && this.spectatingPlayerId != this.getPlayerId()) {
attachEntity(-1);
}
this.spectatingPlayerId = spectating;
if (spectating != this.getPlayerId()) {
attachEntity(this.spectatingPlayerId);
}
}
public Map<Integer, VirtualHologramEntity> getVirtualHologramMap() {
return virtualHologramMap;
}
}
@@ -43,14 +43,6 @@ public class GameProfileStorage extends StoredObject {
return gameProfile;
}
public void putProperty(UUID uuid, Property property) {
properties.computeIfAbsent(uuid, profile -> new GameProfile(uuid, null)).properties.add(property);
}
public void putProperty(UUID uuid, String name, String value, String signature) {
putProperty(uuid, new Property(name, value, signature));
}
public GameProfile get(UUID uuid) {
return properties.get(uuid);
}
@@ -0,0 +1,79 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.model.FurnaceData;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class InventoryTracker extends StoredObject {
public final static Map<String, Integer> WINDOW_TYPE_REGISTRY = new HashMap<>();
static {
WINDOW_TYPE_REGISTRY.put("minecraft:container", 0);
WINDOW_TYPE_REGISTRY.put("minecraft:chest", 0);
WINDOW_TYPE_REGISTRY.put("minecraft:crafting_table", 1);
WINDOW_TYPE_REGISTRY.put("minecraft:furnace", 2);
WINDOW_TYPE_REGISTRY.put("minecraft:dispenser", 3);
WINDOW_TYPE_REGISTRY.put("minecraft:enchanting_table", 4);
WINDOW_TYPE_REGISTRY.put("minecraft:brewing_stand", 5);
WINDOW_TYPE_REGISTRY.put("minecraft:villager", 6);
WINDOW_TYPE_REGISTRY.put("minecraft:beacon", 7);
WINDOW_TYPE_REGISTRY.put("minecraft:anvil", 8);
WINDOW_TYPE_REGISTRY.put("minecraft:hopper", 9);
WINDOW_TYPE_REGISTRY.put("minecraft:dropper", 10);
WINDOW_TYPE_REGISTRY.put("EntityHorse", 11);
}
private final HashMap<Short, Short> windowTypeMap = new HashMap<>();
private final HashMap<Short, FurnaceData> furnaceData = new HashMap<>();
public short levelCost = 0;
public short anvilId = -1;
public InventoryTracker(UserConnection user) {
super(user);
}
public short get(short windowId) {
return windowTypeMap.getOrDefault(windowId, (short) -1);
}
public void remove(short windowId) {
windowTypeMap.remove(windowId);
furnaceData.remove(windowId);
}
public static short getInventoryType(String name) {
return WINDOW_TYPE_REGISTRY.getOrDefault(name, -1).shortValue();
}
public HashMap<Short, Short> getWindowTypeMap() {
return windowTypeMap;
}
public HashMap<Short, FurnaceData> getFurnaceData() {
return furnaceData;
}
}
@@ -1,132 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class PlayerAbilities extends StoredObject {
private boolean sprinting, allowFly, flying, invincible, creative;
private float flySpeed, walkSpeed;
public PlayerAbilities(UserConnection user) {
super(user);
}
public byte getFlags() {
byte flags = 0;
if (invincible) flags |= 8;
if (allowFly) flags |= 4;
if (flying) flags |= 2;
if (creative) flags |= 1;
return flags;
}
public boolean isSprinting() {
return this.sprinting;
}
public boolean isAllowFly() {
return this.allowFly;
}
public boolean isFlying() {
return this.flying;
}
public boolean isInvincible() {
return this.invincible;
}
public boolean isCreative() {
return this.creative;
}
public float getFlySpeed() {
return this.flySpeed;
}
public float getWalkSpeed() {
return this.walkSpeed;
}
public void setSprinting(boolean sprinting) {
this.sprinting = sprinting;
}
public void setAllowFly(boolean allowFly) {
this.allowFly = allowFly;
}
public void setFlying(boolean flying) {
this.flying = flying;
}
public void setInvincible(boolean invincible) {
this.invincible = invincible;
}
public void setCreative(boolean creative) {
this.creative = creative;
}
public void setFlySpeed(float flySpeed) {
this.flySpeed = flySpeed;
}
public void setWalkSpeed(float walkSpeed) {
this.walkSpeed = walkSpeed;
}
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof PlayerAbilities))
return false;
final PlayerAbilities other = (PlayerAbilities) o;
if (!other.canEqual(this)) return false;
if (this.isSprinting() != other.isSprinting()) return false;
if (this.isAllowFly() != other.isAllowFly()) return false;
if (this.isFlying() != other.isFlying()) return false;
if (this.isInvincible() != other.isInvincible()) return false;
if (this.isCreative() != other.isCreative()) return false;
if (Float.compare(this.getFlySpeed(), other.getFlySpeed()) != 0) return false;
return Float.compare(this.getWalkSpeed(), other.getWalkSpeed()) == 0;
}
protected boolean canEqual(final Object other) {
return other instanceof PlayerAbilities;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + (this.isSprinting() ? 79 : 97);
result = result * PRIME + (this.isAllowFly() ? 79 : 97);
result = result * PRIME + (this.isFlying() ? 79 : 97);
result = result * PRIME + (this.isInvincible() ? 79 : 97);
result = result * PRIME + (this.isCreative() ? 79 : 97);
result = result * PRIME + Float.floatToIntBits(this.getFlySpeed());
result = result * PRIME + Float.floatToIntBits(this.getWalkSpeed());
return result;
}
public String toString() {
return "PlayerAbilities(sprinting=" + this.isSprinting() + ", allowFly=" + this.isAllowFly() + ", flying=" + this.isFlying() + ", invincible=" + this.isInvincible() + ", creative=" + this.isCreative() + ", flySpeed=" + this.getFlySpeed() + ", walkSpeed=" + this.getWalkSpeed() + ")";
}
}
@@ -1,104 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class PlayerPosition extends StoredObject {
private double posX, posY, posZ;
private float yaw, pitch;
private boolean onGround;
private boolean positionPacketReceived;
private double receivedPosY;
public PlayerPosition(UserConnection user) {
super(user);
}
public void setPos(double x, double y, double z) {
posX = x;
posY = y;
posZ = z;
}
public boolean isPositionPacketReceived() {
return positionPacketReceived;
}
public void setPositionPacketReceived(boolean positionPacketReceived) {
this.positionPacketReceived = positionPacketReceived;
}
public double getReceivedPosY() {
return receivedPosY;
}
public void setReceivedPosY(double receivedPosY) {
this.receivedPosY = receivedPosY;
}
public double getPosX() {
return posX;
}
public void setPosX(double posX) {
this.posX = posX;
}
public double getPosY() {
return posY;
}
public void setPosY(double posY) {
this.posY = posY;
}
public double getPosZ() {
return posZ;
}
public void setPosZ(double posZ) {
this.posZ = posZ;
}
public float getYaw() {
return yaw;
}
public void setYaw(float yaw) {
this.yaw = yaw;
}
public float getPitch() {
return pitch;
}
public void setPitch(float pitch) {
this.pitch = pitch;
}
public boolean isOnGround() {
return onGround;
}
public void setOnGround(boolean onGround) {
this.onGround = onGround;
}
}
@@ -0,0 +1,87 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class PlayerSessionStorage extends StoredObject {
// Player info
public int gameMode;
// Player abilities
public boolean sprinting, allowFly, flying, invincible, creative;
public float flySpeed, walkSpeed;
// Player position, rotation and data
private double posX, posY, posZ;
public double receivedPosY;
public float yaw, pitch;
public boolean onGround;
// Player inventory
private final Map<UUID, Item[]> playerEquipment = new HashMap<>();
public PlayerSessionStorage(UserConnection user) {
super(user);
}
public byte combineAbilities() {
byte flags = 0;
if (invincible) flags |= 8;
if (allowFly) flags |= 4;
if (flying) flags |= 2;
if (creative) flags |= 1;
return flags;
}
public double getPosX() {
return posX;
}
public double getPosY() {
return posY;
}
public double getPosZ() {
return posZ;
}
public void setPos(double x, double y, double z) {
posX = x;
posY = y;
posZ = z;
}
public Item getPlayerEquipment(final UUID uuid, final int slot) {
final Item[] items = playerEquipment.get(uuid);
if (items == null || slot < 0 || slot >= items.length) {
return null;
}
return items[slot];
}
public void setPlayerEquipment(final UUID uuid, final Item equipment, final int slot) {
final Item[] items = playerEquipment.computeIfAbsent(uuid, it -> new Item[5]);
if (slot < 0 || slot >= items.length) {
return;
}
items[slot] = equipment;
}
public boolean isSpectator() {
return gameMode == 3;
}
public Map<UUID, Item[]> getPlayerEquipment() {
return playerEquipment;
}
}
@@ -18,9 +18,9 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -134,7 +134,7 @@ public class Scoreboard extends StoredObject {
scoreTeams.put(score, scoreTeam);
scoreTeamNames.add(name);
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7.TEAMS, getUser());
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.TEAMS, getUser());
teamPacket.write(Type.STRING, name);
teamPacket.write(Type.BYTE, (byte) 0);
teamPacket.write(Type.STRING, "ViaRewind");
@@ -153,7 +153,7 @@ public class Scoreboard extends StoredObject {
if (scoreTeam == null) return score;
scoreTeamNames.remove(scoreTeam.name);
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7.TEAMS, getUser());
PacketWrapper teamPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.TEAMS, getUser());
teamPacket.write(Type.STRING, scoreTeam.name);
teamPacket.write(Type.BYTE, (byte) 1);
PacketUtil.sendPacket(teamPacket, Protocol1_7_6_10To1_8.class, true, true);
@@ -1,149 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import java.util.HashMap;
public class Windows extends StoredObject {
public HashMap<Short, Short> types = new HashMap<>();
public HashMap<Short, Furnace> furnace = new HashMap<>();
public short levelCost = 0;
public short anvilId = -1;
public Windows(UserConnection user) {
super(user);
}
public short get(short windowId) {
return types.getOrDefault(windowId, (short)-1);
}
public void remove(short windowId) {
types.remove(windowId);
furnace.remove(windowId);
}
public static int getInventoryType(String name) {
switch(name) {
case "minecraft:container":
return 0;
case "minecraft:chest":
return 0;
case "minecraft:crafting_table":
return 1;
case "minecraft:furnace":
return 2;
case "minecraft:dispenser":
return 3;
case "minecraft:enchanting_table":
return 4;
case "minecraft:brewing_stand":
return 5;
case "minecraft:villager":
return 6;
case "minecraft:beacon":
return 7;
case "minecraft:anvil":
return 8;
case "minecraft:hopper":
return 9;
case "minecraft:dropper":
return 10;
case "EntityHorse":
return 11;
default:
throw new IllegalArgumentException("Unknown type " + name);
}
}
public static class Furnace {
private short fuelLeft = 0;
private short maxFuel = 0;
private short progress = 0;
private short maxProgress = 200;
public Furnace() {
}
public short getFuelLeft() {
return this.fuelLeft;
}
public short getMaxFuel() {
return this.maxFuel;
}
public short getProgress() {
return this.progress;
}
public short getMaxProgress() {
return this.maxProgress;
}
public void setFuelLeft(short fuelLeft) {
this.fuelLeft = fuelLeft;
}
public void setMaxFuel(short maxFuel) {
this.maxFuel = maxFuel;
}
public void setProgress(short progress) {
this.progress = progress;
}
public void setMaxProgress(short maxProgress) {
this.maxProgress = maxProgress;
}
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof Furnace))
return false;
final Furnace other = (Furnace) o;
if (!other.canEqual(this)) return false;
if (this.getFuelLeft() != other.getFuelLeft()) return false;
if (this.getMaxFuel() != other.getMaxFuel()) return false;
if (this.getProgress() != other.getProgress()) return false;
return this.getMaxProgress() == other.getMaxProgress();
}
protected boolean canEqual(final Object other) {
return other instanceof Furnace;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.getFuelLeft();
result = result * PRIME + this.getMaxFuel();
result = result * PRIME + this.getProgress();
result = result * PRIME + this.getMaxProgress();
return result;
}
public String toString() {
return "Windows.Furnace(fuelLeft=" + this.getFuelLeft() + ", maxFuel=" + this.getMaxFuel() + ", progress=" + this.getProgress() + ", maxProgress=" + this.getMaxProgress() + ")";
}
}
}
@@ -1,210 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viarewind.utils.Tickable;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
public class WorldBorder extends StoredObject implements Tickable {
private double x, z;
private double oldDiameter, newDiameter;
private long lerpTime;
private long lerpStartTime;
private int portalTeleportBoundary;
private int warningTime, warningBlocks;
private boolean init = false;
private static final int VIEW_DISTANCE = 16;
public WorldBorder(UserConnection user) {
super(user);
}
@Override
public void tick() {
if (!isInit()) {
return;
}
sendPackets();
}
private enum Side {
NORTH(0, -1),
EAST(1, 0),
SOUTH(0, 1),
WEST(-1, 0),
;
private final int modX;
private final int modZ;
Side(int modX, int modZ) {
this.modX = modX;
this.modZ = modZ;
}
}
private void sendPackets() {
PlayerPosition position = getUser().get(PlayerPosition.class);
double radius = getSize() / 2.0;
for (Side side : Side.values()) {
double d;
double pos;
double center;
if (side.modX!=0) {
pos = position.getPosZ();
center = z;
d = Math.abs(x + radius * side.modX - position.getPosX());
} else {
center = x;
pos = position.getPosX();
d = Math.abs(z + radius * side.modZ - position.getPosZ());
}
if (d >= VIEW_DISTANCE) continue;
double r = Math.sqrt(VIEW_DISTANCE * VIEW_DISTANCE - d * d);
double minH = Math.ceil(pos - r);
double maxH = Math.floor(pos + r);
double minV = Math.ceil(position.getPosY() - r);
double maxV = Math.floor(position.getPosY() + r);
if (minH<center-radius) minH = Math.ceil(center-radius);
if (maxH>center+radius) maxH = Math.floor(center+radius);
if (minV<0.0) minV = 0.0;
double centerH = (minH+maxH) / 2.0;
double centerV = (minV+maxV) / 2.0;
int a = (int) Math.floor((maxH-minH) * (maxV-minV) * 0.5);
double b = 2.5;
PacketWrapper particles = PacketWrapper.create(0x2A, null, getUser());
particles.write(Type.STRING, "fireworksSpark");
particles.write(Type.FLOAT, (float)(side.modX!=0 ? x + (radius * side.modX) : centerH));
particles.write(Type.FLOAT, (float)centerV);
particles.write(Type.FLOAT, (float)(side.modX==0 ? z + (radius * side.modZ) : centerH));
particles.write(Type.FLOAT, (float)(side.modX!=0 ? 0f : (maxH-minH) / b));
particles.write(Type.FLOAT, (float)((maxV-minV) / b));
particles.write(Type.FLOAT, (float)(side.modX==0 ? 0f : (maxH-minH) / b));
particles.write(Type.FLOAT, 0f);
particles.write(Type.INT, a);
PacketUtil.sendPacket(particles, Protocol1_7_6_10To1_8.class, true, true);
}
}
private boolean isInit() {
return init;
}
public void init(double x, double z, double oldDiameter, double newDiameter, long lerpTime, int portalTeleportBoundary, int warningTime, int warningBlocks) {
this.x = x;
this.z = z;
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
this.portalTeleportBoundary = portalTeleportBoundary;
this.warningTime = warningTime;
this.warningBlocks = warningBlocks;
init = true;
}
public double getX() {
return x;
}
public double getZ() {
return z;
}
public void setCenter(double x, double z) {
this.x = x;
this.z = z;
}
public double getOldDiameter() {
return oldDiameter;
}
public double getNewDiameter() {
return newDiameter;
}
public long getLerpTime() {
return lerpTime;
}
public void lerpSize(double oldDiameter, double newDiameter, long lerpTime) {
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
this.lerpStartTime = System.currentTimeMillis();
}
public void setSize(double size) {
this.oldDiameter = size;
this.newDiameter = size;
this.lerpTime = 0;
}
public double getSize() {
if (lerpTime==0) return newDiameter;
long time = System.currentTimeMillis() - lerpStartTime;
double percent = ((double)(time) / (double)(lerpTime));
if (percent>1.0d) percent = 1.0d;
else if (percent<0.0d) percent = 0.0d;
return oldDiameter + (newDiameter-oldDiameter) * percent;
}
public int getPortalTeleportBoundary() {
return portalTeleportBoundary;
}
public void setPortalTeleportBoundary(int portalTeleportBoundary) {
this.portalTeleportBoundary = portalTeleportBoundary;
}
public int getWarningTime() {
return warningTime;
}
public void setWarningTime(int warningTime) {
this.warningTime = warningTime;
}
public int getWarningBlocks() {
return warningBlocks;
}
public void setWarningBlocks(int warningBlocks) {
this.warningBlocks = warningBlocks;
}
}
@@ -0,0 +1,108 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class WorldBorderEmulator extends StoredObject {
private double x, z;
private double oldDiameter, newDiameter;
private long lerpTime;
private long lerpStartTime;
private boolean init = false;
public WorldBorderEmulator(UserConnection user) {
super(user);
}
public void init(double x, double z, double oldDiameter, double newDiameter, long lerpTime) {
this.x = x;
this.z = z;
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
init = true;
}
public void setCenter(double x, double z) {
this.x = x;
this.z = z;
}
public void lerpSize(double oldDiameter, double newDiameter, long lerpTime) {
this.oldDiameter = oldDiameter;
this.newDiameter = newDiameter;
this.lerpTime = lerpTime;
this.lerpStartTime = System.currentTimeMillis();
}
public void setSize(double size) {
this.oldDiameter = size;
this.newDiameter = size;
this.lerpTime = 0;
}
public double getSize() {
if (lerpTime == 0) {
return newDiameter;
}
double percent = ((double) (System.currentTimeMillis() - lerpStartTime) / (double) (lerpTime));
// Clamp value
if (percent > 1.0D) percent = 1.0d;
else if (percent < 0.0D) percent = 0.0d;
return oldDiameter + (newDiameter - oldDiameter) * percent;
}
public double getX() {
return x;
}
public double getZ() {
return z;
}
public boolean isInit() {
return init;
}
public enum Side {
NORTH(0, -1),
EAST(1, 0),
SOUTH(0, 1),
WEST(-1, 0);
public final int modX;
public final int modZ;
Side(int modX, int modZ) {
this.modX = modX;
this.modZ = modZ;
}
}
}
@@ -0,0 +1,78 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.task;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.Protocol1_7_6_10To1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.PlayerSessionStorage;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.storage.WorldBorderEmulator;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.logging.Level;
public class WorldBorderUpdateTask implements Runnable {
public final static int VIEW_DISTANCE = 16;
@Override
public void run() {
for (UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final WorldBorderEmulator worldBorderEmulatorTracker = connection.get(WorldBorderEmulator.class);
if (!worldBorderEmulatorTracker.isInit()) continue;
final PlayerSessionStorage playerSession = connection.get(PlayerSessionStorage.class);
double radius = worldBorderEmulatorTracker.getSize() / 2.0;
for (WorldBorderEmulator.Side side : WorldBorderEmulator.Side.values()) {
double d;
double pos;
double center;
if (side.modX != 0) {
pos = playerSession.getPosZ();
center = worldBorderEmulatorTracker.getZ();
d = Math.abs(worldBorderEmulatorTracker.getX() + radius * side.modX - playerSession.getPosX());
} else {
center = worldBorderEmulatorTracker.getX();
pos = playerSession.getPosX();
d = Math.abs(worldBorderEmulatorTracker.getZ() + radius * side.modZ - playerSession.getPosZ());
}
if (d >= VIEW_DISTANCE) continue;
double r = Math.sqrt(VIEW_DISTANCE * VIEW_DISTANCE - d * d);
double minH = Math.ceil(pos - r);
double maxH = Math.floor(pos + r);
double minV = Math.ceil(playerSession.getPosY() - r);
double maxV = Math.floor(playerSession.getPosY() + r);
if (minH < center - radius) minH = Math.ceil(center - radius);
if (maxH > center + radius) maxH = Math.floor(center + radius);
if (minV < 0.0) minV = 0.0;
double centerH = (minH + maxH) / 2.0;
double centerV = (minV + maxV) / 2.0;
double particleOffset = 2.5;
final PacketWrapper spawnParticle = PacketWrapper.create(ClientboundPackets1_8.SPAWN_PARTICLE, connection);
spawnParticle.write(Type.STRING, ViaRewind.getConfig().getWorldBorderParticle()); // particle name
spawnParticle.write(Type.FLOAT, (float) (side.modX != 0 ? worldBorderEmulatorTracker.getX() + (radius * side.modX) : centerH)); // x
spawnParticle.write(Type.FLOAT, (float) centerV); // y
spawnParticle.write(Type.FLOAT, (float) (side.modX == 0 ? worldBorderEmulatorTracker.getZ() + (radius * side.modZ) : centerH)); // z
spawnParticle.write(Type.FLOAT, (float) (side.modX != 0 ? 0f : (maxH - minH) / particleOffset)); // offset x
spawnParticle.write(Type.FLOAT, (float) ((maxV - minV) / particleOffset)); // offset y
spawnParticle.write(Type.FLOAT, (float) (side.modX == 0 ? 0f : (maxH - minH) / particleOffset)); // offset z
spawnParticle.write(Type.FLOAT, 0F); // particle data
spawnParticle.write(Type.INT, (int) Math.floor((maxH - minH) * (maxV - minV) * 0.5));
try {
spawnParticle.send(Protocol1_7_6_10To1_8.class, true);
} catch (Exception e) {
ViaRewind.getPlatform().getLogger().log(Level.SEVERE, "Failed to send world border particle", e);
}
}
}
}
}
@@ -1,108 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.type.PartialType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import io.netty.buffer.ByteBuf;
import java.io.ByteArrayOutputStream;
import java.util.zip.DeflaterOutputStream;
public class Chunk1_7_10Type extends PartialType<Chunk, ClientWorld> {
public Chunk1_7_10Type(ClientWorld param) {
super(param, Chunk.class);
}
@Override
public Chunk read(ByteBuf byteBuf, ClientWorld clientWorld) throws Exception {
throw new UnsupportedOperationException();
}
@Override
public void write(ByteBuf output, ClientWorld clientWorld, Chunk chunk) throws Exception {
output.writeInt(chunk.getX());
output.writeInt(chunk.getZ());
output.writeBoolean(chunk.isFullChunk());
output.writeShort(chunk.getBitmask());
output.writeShort(0);
ByteBuf dataToCompress = output.alloc().buffer();
try {
for (int i = 0; i < chunk.getSections().length; i++) {
if ((chunk.getBitmask() & 1 << i) == 0) continue;
ChunkSection section = chunk.getSections()[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < 4096; j++) {
int block = palette.idAt(j);
dataToCompress.writeByte(block >> 4);
}
}
for (int i = 0; i < chunk.getSections().length; i++) {
if ((chunk.getBitmask() & 1 << i) == 0) continue;
ChunkSection section = chunk.getSections()[i];
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < 4096; j += 2) {
int data0 = palette.idAt(j) & 0xF;
int data1 = palette.idAt(j + 1) & 0xF;
dataToCompress.writeByte((data1 << 4) | data0);
}
}
for (int i = 0; i < chunk.getSections().length; i++) {
if ((chunk.getBitmask() & 1 << i) == 0) continue;
chunk.getSections()[i].getLight().writeBlockLight(dataToCompress);
}
boolean skyLight = clientWorld != null && clientWorld.getEnvironment() == Environment.NORMAL;
if (skyLight) {
for (int i = 0; i < chunk.getSections().length; i++) {
if ((chunk.getBitmask() & 1 << i) == 0) continue;
chunk.getSections()[i].getLight().writeSkyLight(dataToCompress);
}
}
if (chunk.isFullChunk() && chunk.isBiomeData()) {
for (int biome : chunk.getBiomeData()) {
dataToCompress.writeByte(biome);
}
}
ByteArrayOutputStream compressedStream = new ByteArrayOutputStream();
// todo config for compression level
try (DeflaterOutputStream compressorStream = new DeflaterOutputStream(compressedStream)) {
compressorStream.write(Type.REMAINING_BYTES.read(dataToCompress));
}
output.writeInt(compressedStream.size());
output.writeBytes(compressedStream.toByteArray());
} finally {
dataToCompress.release();
}
}
}
@@ -1,46 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
import com.viaversion.viaversion.api.type.PartialType;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class CustomStringType extends PartialType<String[], Integer> {
public CustomStringType(Integer param) {
super(param, String[].class);
}
public String[] read(ByteBuf buffer, Integer size) throws Exception {
if (buffer.readableBytes() < size/4) {
throw new RuntimeException("Readable bytes does not match expected!");
} else {
String[] array = new String[size];
for (int i = 0; i<size; i++) {
array[i] = Type.STRING.read(buffer);
}
return array;
}
}
public void write(ByteBuf buffer, Integer size, String[] strings) throws Exception {
for (String s : strings) Type.STRING.write(buffer, s);
}
}
@@ -18,6 +18,15 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.CompressedNBTType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.ItemArrayType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.ItemType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item.NBTType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetadataListType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata.MetadataType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive.ByteIntArrayType;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive.PositionUYType;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.Type;
@@ -26,16 +35,26 @@ import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import java.util.List;
public class Types1_7_6_10 {
public static final Type<CompoundTag> COMPRESSED_NBT = new CompressedNBTType();
public static final Type<Item[]> ITEM_ARRAY = new ItemArrayType(false);
public static final Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType(true);
public static final Type<Item> ITEM = new ItemType(false);
public static final Type<Item> COMPRESSED_NBT_ITEM = new ItemType(true);
public static final Type<List<Metadata>> METADATA_LIST = new MetadataListType();
public static final Type<Metadata> METADATA = new MetadataType();
public static final Type<CompoundTag> NBT = new NBTType();
/**
* An int array prefixed with byte representing the size
*/
public static final Type<int[]> INT_ARRAY = new IntArrayType();
// Primitives
public final static Type<int[]> BYTE_INT_ARRAY = new ByteIntArrayType(); // Integer array with byte as length indicator
// Positions /shrug
public final static Type<Position> SHORT_POSITION = new PositionUYType<>(Type.SHORT, value -> (short) value);
public final static Type<Position> INT_POSITION = new PositionUYType<>(Type.INT, value -> value);
public final static Type<Position> BYTE_POSITION = new PositionUYType<>(Type.BYTE, value -> (byte) value);
public final static Type<Position> U_BYTE_POSITION = new PositionUYType<>(Type.UNSIGNED_BYTE, value -> (short) value);
// Uncompressed Items
public final static Type<CompoundTag> NBT = new NBTType();
public final static Type<Item> ITEM = new ItemType(false);
// Compressed Items
public final static Type<CompoundTag> COMPRESSED_NBT = new CompressedNBTType();
public final static Type<Item> COMPRESSED_NBT_ITEM = new ItemType(true);
public final static Type<Item[]> COMPRESSED_NBT_ITEM_ARRAY = new ItemArrayType(true);
// Metadata
public final static Type<Metadata> METADATA = new MetadataType();
public final static Type<List<Metadata>> METADATA_LIST = new MetadataListType();
}
@@ -0,0 +1,80 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Pair;
import io.netty.buffer.ByteBuf;
import java.io.ByteArrayOutputStream;
import java.util.zip.Deflater;
public class BulkChunkType1_7_6 extends Type<Chunk[]> {
public final static BulkChunkType1_7_6 TYPE = new BulkChunkType1_7_6();
public BulkChunkType1_7_6() {
super(Chunk[].class);
}
@Override
public Chunk[] read(ByteBuf byteBuf) throws Exception {
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/ChunkBulk1_7_6Type.java
}
@Override
public void write(ByteBuf byteBuf, Chunk[] chunks) throws Exception {
final int chunkCount = chunks.length;
final ByteArrayOutputStream output = new ByteArrayOutputStream();
final int[] chunkX = new int[chunkCount];
final int[] chunkZ = new int[chunkCount];
final short[] primaryBitMask = new short[chunkCount];
final short[] additionalBitMask = new short[chunkCount];
for (int i = 0; i < chunkCount; i++) {
final Chunk chunk = chunks[i];
final Pair<byte[], Short> chunkData = ChunkType1_7_6.serialize(chunk);
output.write(chunkData.key());
chunkX[i] = chunk.getX();
chunkZ[i] = chunk.getZ();
primaryBitMask[i] = (short) chunk.getBitmask();
additionalBitMask[i] = chunkData.value();
}
final byte[] data = output.toByteArray();
final Deflater deflater = new Deflater();
byte[] compressedData;
int compressedSize;
try {
deflater.setInput(data, 0, data.length);
deflater.finish();
compressedData = new byte[data.length];
compressedSize = deflater.deflate(compressedData);
} finally {
deflater.end();
}
byteBuf.writeShort(chunkCount);
byteBuf.writeInt(compressedSize);
boolean skyLight = false;
for (Chunk chunk : chunks) {
for (ChunkSection section : chunk.getSections()) {
if (section != null && section.getLight().hasSkyLight()) {
skyLight = true;
break;
}
}
}
byteBuf.writeBoolean(skyLight); // hasSkyLight
byteBuf.writeBytes(compressedData, 0, compressedSize);
for (int i = 0; i < chunkCount; i++) {
byteBuf.writeInt(chunkX[i]);
byteBuf.writeInt(chunkZ[i]);
byteBuf.writeShort(primaryBitMask[i]);
byteBuf.writeShort(additionalBitMask[i]);
}
}
}
@@ -0,0 +1,135 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.chunk;
import com.viaversion.viarewind.api.minecraft.ExtendedBlockStorage;
import com.viaversion.viaversion.api.minecraft.chunks.*;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Pair;
import io.netty.buffer.ByteBuf;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.Deflater;
public class ChunkType1_7_6 extends Type<Chunk> {
public final static ChunkType1_7_6 TYPE = new ChunkType1_7_6();
public ChunkType1_7_6() {
super(Chunk.class);
}
@Override
public Chunk read(ByteBuf byteBuf) throws Exception {
throw new UnsupportedOperationException(); // Not needed, see https://github.com/ViaVersion/ViaLegacy/blob/main/src/main/java/net/raphimc/vialegacy/protocols/release/protocol1_8to1_7_6_10/types/Chunk1_7_6Type.java
}
@Override
public void write(ByteBuf output, Chunk chunk) throws Exception {
final Pair<byte[], Short> chunkData = serialize(chunk);
final byte[] data = chunkData.key();
final short additionalBitMask = chunkData.value();
final Deflater deflater = new Deflater();
byte[] compressedData;
int compressedSize;
try {
deflater.setInput(data, 0, data.length);
deflater.finish();
compressedData = new byte[data.length];
compressedSize = deflater.deflate(compressedData);
} finally {
deflater.end();
}
output.writeInt(chunk.getX());
output.writeInt(chunk.getZ());
output.writeBoolean(chunk.isFullChunk());
output.writeShort(chunk.getBitmask());
output.writeShort(additionalBitMask);
output.writeInt(compressedSize);
output.writeBytes(compressedData, 0, compressedSize);
}
public static Pair<byte[], Short> serialize(final Chunk chunk) throws IOException {
final ExtendedBlockStorage[] storageArrays = new ExtendedBlockStorage[16];
for (int i = 0; i < storageArrays.length; i++) {
final ChunkSection section = chunk.getSections()[i];
if (section != null) {
final ExtendedBlockStorage storage = storageArrays[i] = new ExtendedBlockStorage(section.getLight().hasSkyLight());
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = 0; y < 16; y++) {
final int flatBlock = section.palette(PaletteType.BLOCKS).idAt(x, y, z);
storage.setBlockId(x, y, z, flatBlock >> 4);
storage.setBlockMetadata(x, y, z, flatBlock & 15);
}
}
}
storage.getBlockLightArray().setHandle(section.getLight().getBlockLight());
if (section.getLight().hasSkyLight()) {
storage.getSkyLightArray().setHandle(section.getLight().getSkyLight());
}
}
}
final ByteArrayOutputStream output = new ByteArrayOutputStream();
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0) {
output.write(storageArrays[i].getBlockLSBArray());
}
}
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0) {
output.write(storageArrays[i].getBlockMetadataArray().getHandle());
}
}
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0) {
output.write(storageArrays[i].getBlockLightArray().getHandle());
}
}
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0 && storageArrays[i].getSkyLightArray() != null) {
output.write(storageArrays[i].getSkyLightArray().getHandle());
}
}
short additionalBitMask = 0;
for (int i = 0; i < storageArrays.length; i++) {
if ((chunk.getBitmask() & 1 << i) != 0 && storageArrays[i].hasBlockMSBArray()) {
additionalBitMask |= (short) (1 << i);
output.write(storageArrays[i].getOrCreateBlockMSBArray().getHandle());
}
}
if (chunk.isFullChunk() && chunk.getBiomeData() != null) {
for (int biome : chunk.getBiomeData()) {
output.write(biome);
}
}
return new Pair<>(output.toByteArray(), additionalBitMask);
}
}
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.NBTIO;
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
@@ -35,7 +36,7 @@ public class ItemArrayType extends Type<Item[]> {
int amount = Type.SHORT.readPrimitive(buffer);
Item[] items = new Item[amount];
for(int i = 0; i < amount; ++i) {
for (int i = 0; i < amount; ++i) {
items[i] = (compressed ? Types1_7_6_10.COMPRESSED_NBT_ITEM : Types1_7_6_10.ITEM).read(buffer);
}
return items;
@@ -43,7 +44,7 @@ public class ItemArrayType extends Type<Item[]> {
@Override
public void write(ByteBuf buffer, Item[] items) throws Exception {
Type.SHORT.writePrimitive(buffer, (short)items.length);
Type.SHORT.writePrimitive(buffer, (short) items.length);
for (Item item : items) {
(compressed ? Types1_7_6_10.COMPRESSED_NBT_ITEM : Types1_7_6_10.ITEM).write(buffer, item);
}
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
@@ -33,7 +34,6 @@ public class ItemType extends Type<Item> {
@Override
public Item read(ByteBuf buffer) throws Exception {
int readerIndex = buffer.readerIndex();
short id = buffer.readShort();
if (id < 0) {
return null;
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.NBTIO;
@@ -35,16 +35,21 @@ public class NBTType extends Type<CompoundTag> {
@Override
public CompoundTag read(ByteBuf buffer) {
short length = buffer.readShort();
if (length < 0) {return null;}
if (length < 0) {
return null;
}
ByteBufInputStream byteBufInputStream = new ByteBufInputStream(buffer);
DataInputStream dataInputStream = new DataInputStream(byteBufInputStream);
try {
return NBTIO.readTag((DataInput) dataInputStream);
} catch (Throwable throwable) {throwable.printStackTrace();}
finally {
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
try {
dataInputStream.close();
} catch (IOException e) {e.printStackTrace();}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@@ -55,8 +60,8 @@ public class NBTType extends Type<CompoundTag> {
buffer.writeShort(-1);
} else {
ByteBuf buf = buffer.alloc().buffer();
ByteBufOutputStream bytebufStream = new ByteBufOutputStream(buf);
DataOutputStream dataOutputStream = new DataOutputStream(bytebufStream);
ByteBufOutputStream byteBufStream = new ByteBufOutputStream(buf);
DataOutputStream dataOutputStream = new DataOutputStream(byteBufStream);
NBTIO.writeTag((DataOutput) dataOutputStream, nbt);
dataOutputStream.close();
buffer.writeShort(buf.readableBytes());
@@ -16,10 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.VoidType;
public enum MetaType1_7_6_10 implements MetaType {
Byte(0, Type.BYTE),
@@ -29,25 +31,27 @@ public enum MetaType1_7_6_10 implements MetaType {
String(4, Type.STRING),
Slot(5, Types1_7_6_10.COMPRESSED_NBT_ITEM),
Position(6, Type.VECTOR),
NonExistent(-1, Type.NOTHING);
NonExistent(-1, new VoidType());
private final int typeID;
private final Type type;
private final Type<?> type;
MetaType1_7_6_10(int typeID, Type<?> type) {
this.typeID = typeID;
this.type = type;
}
public static MetaType1_7_6_10 byId(int id) {
return values()[id];
}
MetaType1_7_6_10(int typeID, Type type) {
this.typeID = typeID;
this.type = type;
}
@Override
public int typeId() {
return this.typeID;
}
public Type type() {
@Override
public Type<?> type() {
return this.type;
}
}
@@ -16,18 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.Types1_7_6_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.types.minecraft.MetaListTypeTemplate;
import com.viaversion.viaversion.api.type.types.metadata.MetaListTypeTemplate;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public class MetadataListType extends MetaListTypeTemplate {
private final MetadataType metadataType = new MetadataType();
@Override
public List<Metadata> read(ByteBuf buffer) throws Exception {
ArrayList<Metadata> list = new ArrayList<>();
@@ -38,7 +37,7 @@ public class MetadataListType extends MetaListTypeTemplate {
if (m != null) {
list.add(m);
}
} while(m != null);
} while (m != null);
return list;
}
@@ -49,7 +48,7 @@ public class MetadataListType extends MetaListTypeTemplate {
Types1_7_6_10.METADATA.write(buffer, meta);
}
if (metadata.isEmpty()) {
Types1_7_6_10.METADATA.write(buffer, new Metadata(0, MetaType1_7_6_10.Byte, (byte)0));
Types1_7_6_10.METADATA.write(buffer, new Metadata(0, MetaType1_7_6_10.Byte, (byte) 0));
}
buffer.writeByte(127);
}
@@ -16,10 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.metadata;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.types.minecraft.MetaTypeTemplate;
import com.viaversion.viaversion.api.type.types.metadata.MetaTypeTemplate;
import io.netty.buffer.ByteBuf;
public class MetadataType extends MetaTypeTemplate {
@@ -16,14 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types;
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class IntArrayType extends Type<int[]> {
public class ByteIntArrayType extends Type<int[]> {
public IntArrayType() {
public ByteIntArrayType() {
super(int[].class);
}
@@ -0,0 +1,36 @@
package com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.primitive;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import java.util.function.IntFunction;
public class PositionUYType<T extends Number> extends Type<Position> {
private final Type<T> yType;
private final IntFunction<T> toY;
public PositionUYType(final Type<T> yType, final IntFunction<T> toY) {
super(Position.class);
this.yType = yType;
this.toY = toY;
}
@Override
public Position read(ByteBuf buffer) throws Exception {
final int x = buffer.readInt();
final int y = yType.read(buffer).intValue();
final int z = buffer.readInt();
return new Position(x, y, z);
}
@Override
public void write(ByteBuf buffer, Position value) throws Exception {
buffer.writeInt(value.x());
yType.write(buffer, this.toY.apply(value.y()));
buffer.writeInt(value.z());
}
}
@@ -1,184 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_7_6_10.metadata;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.types.MetaType1_7_6_10;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.Optional;
public enum MetaIndex1_8To1_7_6_10 {
ENTITY_FLAGS(Entity1_10Types.EntityType.ENTITY, 0, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_AIR(Entity1_10Types.EntityType.ENTITY, 1, MetaType1_7_6_10.Short, MetaType1_8.Short),
ENTITY_NAME_TAG(Entity1_10Types.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 2, MetaType1_8.String),
ENTITY_NAME_TAG_VISIBILITY(Entity1_10Types.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 3, MetaType1_8.Byte),
ENTITY_SILENT(Entity1_10Types.EntityType.ENTITY, -1, MetaType1_7_6_10.NonExistent, 4, MetaType1_8.Byte),
ENTITY_LIVING_HEALTH(Entity1_10Types.EntityType.ENTITY_LIVING, 6, MetaType1_7_6_10.Float, MetaType1_8.Float),
ENTITY_LIVING_POTION_EFFECT_COLOR(Entity1_10Types.EntityType.ENTITY_LIVING, 7, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENTITY_LIVING_IS_POTION_EFFECT_AMBIENT(Entity1_10Types.EntityType.ENTITY_LIVING, 8, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_ARROWS(Entity1_10Types.EntityType.ENTITY_LIVING, 9, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ENTITY_LIVING_NAME_TAG(Entity1_10Types.EntityType.ENTITY_LIVING, 10, MetaType1_7_6_10.String, 2, MetaType1_8.String),
ENTITY_LIVING_NAME_TAG_VISIBILITY(Entity1_10Types.EntityType.ENTITY_LIVING, 11, MetaType1_7_6_10.Byte, 3, MetaType1_8.Byte),
ENTITY_LIVING_AI(Entity1_10Types.EntityType.ENTITY_LIVING, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Byte),
ENTITY_AGEABLE_AGE(Entity1_10Types.EntityType.ENTITY_AGEABLE, 12, MetaType1_7_6_10.Int, MetaType1_8.Byte),
ARMOR_STAND_FLAGS(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 10, MetaType1_8.Byte),
ARMOR_STAND_HEAD_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 11, MetaType1_8.Rotation),
ARMOR_STAND_BODY_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 12, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_ARM_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 13, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_ARM_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 14, MetaType1_8.Rotation),
ARMOR_STAND_LEFT_LEG_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 15, MetaType1_8.Rotation),
ARMOR_STAND_RIGHT_LEG_POSITION(Entity1_10Types.EntityType.ARMOR_STAND, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Rotation),
HUMAN_SKIN_FLAGS(Entity1_10Types.EntityType.ENTITY_HUMAN, 16, MetaType1_7_6_10.Byte, 10, MetaType1_8.Byte),
HUMAN_UNUSED(Entity1_10Types.EntityType.ENTITY_HUMAN, -1, MetaType1_7_6_10.NonExistent, 16, MetaType1_8.Byte),
HUMAN_ABSORPTION_HEATS(Entity1_10Types.EntityType.ENTITY_HUMAN, 17, MetaType1_7_6_10.Float, MetaType1_8.Float),
HUMAN_SCORE(Entity1_10Types.EntityType.ENTITY_HUMAN, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_FLAGS(Entity1_10Types.EntityType.HORSE, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_TYPE(Entity1_10Types.EntityType.HORSE, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
HORSE_COLOR(Entity1_10Types.EntityType.HORSE, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
HORSE_OWNER(Entity1_10Types.EntityType.HORSE, 21, MetaType1_7_6_10.String, MetaType1_8.String),
HORSE_ARMOR(Entity1_10Types.EntityType.HORSE, 22, MetaType1_7_6_10.Int, MetaType1_8.Int),
BAT_HANGING(Entity1_10Types.EntityType.BAT, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_FLAGS(Entity1_10Types.EntityType.ENTITY_TAMEABLE_ANIMAL, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
TAMEABLE_OWNER(Entity1_10Types.EntityType.ENTITY_TAMEABLE_ANIMAL, 17, MetaType1_7_6_10.String, MetaType1_8.String),
OCELOT_TYPE(Entity1_10Types.EntityType.OCELOT, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_FLAGS(Entity1_10Types.EntityType.WOLF, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_HEALTH(Entity1_10Types.EntityType.WOLF, 18, MetaType1_7_6_10.Float, MetaType1_8.Float),
WOLF_BEGGING(Entity1_10Types.EntityType.WOLF, 19, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WOLF_COLLAR_COLOR(Entity1_10Types.EntityType.WOLF, 20, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
PIG_SADDLE(Entity1_10Types.EntityType.PIG, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SHEEP_COLOR_OR_SHEARED(Entity1_10Types.EntityType.SHEEP, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
VILLAGER_TYPE(Entity1_10Types.EntityType.VILLAGER, 16, MetaType1_7_6_10.Int, MetaType1_8.Int),
ENDERMAN_CARRIED_BLOCK(Entity1_10Types.EntityType.ENDERMAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Short),
ENDERMAN_CARRIED_BLOCK_DATA(Entity1_10Types.EntityType.ENDERMAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
ENDERMAN_IS_SCREAMING(Entity1_10Types.EntityType.ENDERMAN, 18, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CHILD(Entity1_10Types.EntityType.ZOMBIE, 12, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_VILLAGER(Entity1_10Types.EntityType.ZOMBIE, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ZOMBIE_CONVERTING(Entity1_10Types.EntityType.ZOMBIE, 14, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
BLAZE_ON_FIRE(Entity1_10Types.EntityType.BLAZE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SPIDER_CLIMBING(Entity1_10Types.EntityType.SPIDER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_STATE(Entity1_10Types.EntityType.CREEPER, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
CREEPER_POWERED(Entity1_10Types.EntityType.CREEPER, 17, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_STATE(Entity1_10Types.EntityType.GHAST, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
GHAST_IS_POWERED(Entity1_10Types.EntityType.GHAST, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
SLIME_SIZE(Entity1_10Types.EntityType.SLIME, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
SKELETON_TYPE(Entity1_10Types.EntityType.SKELETON, 13, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITCH_AGRESSIVE(Entity1_10Types.EntityType.WITCH, 21, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
IRON_GOLEM_IS_PLAYER_CREATED(Entity1_10Types.EntityType.IRON_GOLEM, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
WITHER_WATCHED_TAGRET_1(Entity1_10Types.EntityType.WITHER, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TAGRET_2(Entity1_10Types.EntityType.WITHER, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_WATCHED_TAGRET_3(Entity1_10Types.EntityType.WITHER, 19, MetaType1_7_6_10.Int, MetaType1_8.Int),
WITHER_INVULNERABLE_TIME(Entity1_10Types.EntityType.WITHER, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
GUARDIAN_FLAGS(Entity1_10Types.EntityType.GUARDIAN, 16, MetaType1_7_6_10.NonExistent, MetaType1_8.Byte),
GUARDIAN_TARGET(Entity1_10Types.EntityType.GUARDIAN, 17, MetaType1_7_6_10.NonExistent, MetaType1_8.Int),
BOAT_TIME_SINCE_HIT(Entity1_10Types.EntityType.BOAT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_FORWARD_DIRECTION(Entity1_10Types.EntityType.BOAT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
BOAT_DAMAGE_TAKEN(Entity1_10Types.EntityType.BOAT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_SHAKING_POWER(Entity1_10Types.EntityType.MINECART_ABSTRACT, 17, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHAKING_DIRECTION(Entity1_10Types.EntityType.MINECART_ABSTRACT, 18, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_DAMAGE_TAKEN(Entity1_10Types.EntityType.MINECART_ABSTRACT, 19, MetaType1_7_6_10.Float, MetaType1_8.Float),
MINECART_BLOCK_INSIDE(Entity1_10Types.EntityType.MINECART_ABSTRACT, 20, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_BLOCK_Y(Entity1_10Types.EntityType.MINECART_ABSTRACT, 21, MetaType1_7_6_10.Int, MetaType1_8.Int),
MINECART_SHOW_BLOCK(Entity1_10Types.EntityType.MINECART_ABSTRACT, 22, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FURNACE_MINECART_IS_POWERED(Entity1_10Types.EntityType.MINECART_FURNACE, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
ITEM_ITEM(Entity1_10Types.EntityType.DROPPED_ITEM, 10, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ARROW_IS_CRITICAL(Entity1_10Types.EntityType.ARROW, 16, MetaType1_7_6_10.Byte, MetaType1_8.Byte),
FIREWORK_INFO(Entity1_10Types.EntityType.FIREWORK, 8, MetaType1_7_6_10.Slot, MetaType1_8.Slot),
ITEM_FRAME_ITEM(Entity1_10Types.EntityType.ITEM_FRAME, 2, MetaType1_7_6_10.Slot, 8, MetaType1_8.Slot),
ITEM_FRAME_ROTATION(Entity1_10Types.EntityType.ITEM_FRAME, 3, MetaType1_7_6_10.Byte, 9, MetaType1_8.Byte),
ENDER_CRYSTAL_HEALTH(Entity1_10Types.EntityType.ENDER_CRYSTAL, 8, MetaType1_7_6_10.Int, 9, MetaType1_8.Int),
;
private static final HashMap<Pair<Entity1_10Types.EntityType, Integer>, MetaIndex1_8To1_7_6_10> metadataRewrites = new HashMap<>();
static {
for (MetaIndex1_8To1_7_6_10 index : MetaIndex1_8To1_7_6_10.values())
metadataRewrites.put(new Pair<>(index.getClazz(), index.getIndex()), index);
}
private final Entity1_10Types.EntityType clazz;
private final int newIndex;
private final MetaType1_8 newType;
private final MetaType1_7_6_10 oldType;
private final int index;
MetaIndex1_8To1_7_6_10(Entity1_10Types.EntityType type, int index, MetaType1_7_6_10 oldType, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.newIndex = index;
this.oldType = oldType;
this.newType = newType;
}
MetaIndex1_8To1_7_6_10(Entity1_10Types.EntityType type, int index, MetaType1_7_6_10 oldType, int newIndex, MetaType1_8 newType) {
this.clazz = type;
this.index = index;
this.oldType = oldType;
this.newIndex = newIndex;
this.newType = newType;
}
private static Optional<MetaIndex1_8To1_7_6_10> getIndex(Entity1_10Types.EntityType type, int index) {
Pair pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
return Optional.empty();
}
public Entity1_10Types.EntityType getClazz() {
return clazz;
}
public int getNewIndex() {
return newIndex;
}
public MetaType1_8 getNewType() {
return newType;
}
public MetaType1_7_6_10 getOldType() {
return oldType;
}
public int getIndex() {
return index;
}
public static MetaIndex1_8To1_7_6_10 searchIndex(Entity1_10Types.EntityType type, int index) {
Entity1_10Types.EntityType currentType = type;
do {
Optional<MetaIndex1_8To1_7_6_10> optMeta = getIndex(currentType, index);
if (optMeta.isPresent()) {
return optMeta.get();
}
currentType = currentType.getParent();
} while (currentType != null);
return null;
}
}
@@ -18,10 +18,12 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.rewriter.ReplacementItemRewriter1_8;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.packets.*;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.packets.*;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.utils.Ticker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -29,25 +31,29 @@ import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import com.viaversion.viarewind.utils.Ticker;
import java.util.*;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, ClientboundPackets1_8, ServerboundPackets1_9, ServerboundPackets1_8> {
private final ReplacementItemRewriter<Protocol1_8To1_9> itemRewriter = new ReplacementItemRewriter1_8(this);
private final MetadataRewriter metadataRewriter = new MetadataRewriter(this);
public Queue<PacketWrapper> animationsToSend = new ConcurrentLinkedQueue<>();
public static final Set<String> VALID_ATTRIBUTES = new HashSet<>();
public static final ValueTransformer<Double, Integer> TO_OLD_INT = new ValueTransformer<Double, Integer>(Type.INT) {
public final static Set<String> VALID_ATTRIBUTES = new HashSet<>();
public final static ValueTransformer<Double, Integer> TO_OLD_INT = new ValueTransformer<Double, Integer>(Type.INT) {
@Override
public Integer transform(PacketWrapper wrapper, Double inputValue) {
return (int) (inputValue * 32.0D);
}
};
public static final ValueTransformer<Float, Byte> DEGREES_TO_ANGLE = new ValueTransformer<Float, Byte>(Type.BYTE) {
public final static ValueTransformer<Float, Byte> DEGREES_TO_ANGLE = new ValueTransformer<Float, Byte>(Type.BYTE) {
@Override
public Byte transform(PacketWrapper packetWrapper, Float degrees) throws Exception {
return (byte) ((degrees / 360F) * 256);
@@ -70,6 +76,8 @@ public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, Cl
@Override
protected void registerPackets() {
itemRewriter.register();
EntityPackets.register(this);
InventoryPackets.register(this);
PlayerPackets.register(this);
@@ -83,7 +91,7 @@ public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, Cl
Ticker.init();
userConnection.put(new Windows(userConnection));
userConnection.put(new EntityTracker(userConnection));
userConnection.put(new EntityTracker(userConnection, this));
userConnection.put(new Levitation(userConnection));
userConnection.put(new PlayerPosition(userConnection));
userConnection.put(new Cooldown(userConnection));
@@ -91,4 +99,13 @@ public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_9, Cl
userConnection.put(new BossBarStorage(userConnection));
userConnection.put(new ClientWorld(userConnection));
}
@Override
public ReplacementItemRewriter<Protocol1_8To1_9> getItemRewriter() {
return itemRewriter;
}
public MetadataRewriter getMetadataRewriter() {
return metadataRewriter;
}
}
@@ -34,7 +34,7 @@ import com.viaversion.viarewind.utils.PacketUtil;
import java.util.*;
public class WitherBossBar implements BossBar {
private static int highestId = Integer.MAX_VALUE-10000;
private static int highestId = Integer.MAX_VALUE - 10000;
private final UUID uuid;
private String title;
@@ -72,8 +72,8 @@ public class WitherBossBar implements BossBar {
@Override
public BossBar setHealth(float health) {
this.health = health;
if (this.health<=0) this.health = 0.0001f;
this.health = health;
if (this.health <= 0) this.health = 0.0001f;
if (this.visible) updateMetadata();
return this;
}
@@ -103,22 +103,22 @@ public class WitherBossBar implements BossBar {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public BossBar addConnection(UserConnection userConnection) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public BossBar addConnection(UserConnection userConnection) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
@Override
public BossBar removePlayer(UUID uuid) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public BossBar removeConnection(UserConnection userConnection) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public BossBar removeConnection(UserConnection userConnection) {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
@Override
public BossBar addFlag(BossFlag bossFlag) {
throw new UnsupportedOperationException(this.getClass().getName() + " does not support flags");
}
@@ -138,12 +138,12 @@ public class WitherBossBar implements BossBar {
return Collections.singleton(connection.getProtocolInfo().getUuid());
}
@Override
public Set<UserConnection> getConnections() {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
public Set<UserConnection> getConnections() {
throw new UnsupportedOperationException(this.getClass().getName() + " is only for one UserConnection!");
}
@Override
@Override
public BossBar show() {
if (!this.visible) {
this.visible = true;
@@ -181,16 +181,16 @@ public class WitherBossBar implements BossBar {
private void spawnWither() {
PacketWrapper packetWrapper = PacketWrapper.create(0x0F, null, this.connection);
packetWrapper.write(Type.VAR_INT, entityId);
packetWrapper.write(Type.UNSIGNED_BYTE, (short)64);
packetWrapper.write(Type.UNSIGNED_BYTE, (short) 64);
packetWrapper.write(Type.INT, (int) (locX * 32d));
packetWrapper.write(Type.INT, (int) (locY * 32d));
packetWrapper.write(Type.INT, (int) (locZ * 32d));
packetWrapper.write(Type.BYTE, (byte)0);
packetWrapper.write(Type.BYTE, (byte)0);
packetWrapper.write(Type.BYTE, (byte)0);
packetWrapper.write(Type.SHORT, (short)0);
packetWrapper.write(Type.SHORT, (short)0);
packetWrapper.write(Type.SHORT, (short)0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.SHORT, (short) 0);
packetWrapper.write(Type.SHORT, (short) 0);
packetWrapper.write(Type.SHORT, (short) 0);
List<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata(0, MetaType1_8.Byte, (byte) 0x20));
@@ -209,8 +209,8 @@ public class WitherBossBar implements BossBar {
packetWrapper.write(Type.INT, (int) (locX * 32d));
packetWrapper.write(Type.INT, (int) (locY * 32d));
packetWrapper.write(Type.INT, (int) (locZ * 32d));
packetWrapper.write(Type.BYTE, (byte)0);
packetWrapper.write(Type.BYTE, (byte)0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BYTE, (byte) 0);
packetWrapper.write(Type.BOOLEAN, false);
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
@@ -231,7 +231,7 @@ public class WitherBossBar implements BossBar {
private void despawnWither() {
PacketWrapper packetWrapper = PacketWrapper.create(0x13, null, this.connection);
packetWrapper.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[] {entityId});
packetWrapper.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(packetWrapper, Protocol1_8To1_9.class, true, false);
}
@@ -0,0 +1,33 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
public class ActionBarVisualization implements CooldownVisualization {
private final UserConnection user;
public ActionBarVisualization(UserConnection user) {
this.user = user;
}
@Override
public void show(double progress) throws Exception {
sendActionBar(CooldownVisualization.buildProgressText("■", progress));
}
@Override
public void hide() throws Exception {
sendActionBar("§r");
}
private void sendActionBar(String bar) throws Exception {
PacketWrapper actionBarPacket = PacketWrapper.create(ClientboundPackets1_8.CHAT_MESSAGE, user);
actionBarPacket.write(Type.COMPONENT, new JsonPrimitive(bar));
actionBarPacket.write(Type.BYTE, (byte) 2); // Position - above hotbar
actionBarPacket.scheduleSend(Protocol1_8To1_9.class);
}
}
@@ -0,0 +1,50 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import java.util.UUID;
public class BossBarVisualization implements CooldownVisualization {
private final UserConnection user;
private UUID bossUUID;
public BossBarVisualization(UserConnection user) {
this.user = user;
}
@Override
public void show(double progress) throws Exception {
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_9.BOSSBAR, user);
if (bossUUID == null) {
bossUUID = UUID.randomUUID();
wrapper.write(Type.UUID, bossUUID);
wrapper.write(Type.VAR_INT, 0); // Action - add
wrapper.write(Type.COMPONENT, new JsonPrimitive(" ")); // Title
wrapper.write(Type.FLOAT, (float) progress); // Health
wrapper.write(Type.VAR_INT, 0); // Color
wrapper.write(Type.VAR_INT, 0); // Division
wrapper.write(Type.UNSIGNED_BYTE, (short) 0); // Flags
} else {
wrapper.write(Type.UUID, bossUUID);
wrapper.write(Type.VAR_INT, 2); // Action - update health
wrapper.write(Type.FLOAT, (float) progress); // Health
}
wrapper.scheduleSend(Protocol1_8To1_9.class, false);
}
@Override
public void hide() throws Exception {
if (bossUUID == null) {
return;
}
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_9.BOSSBAR, null, user);
wrapper.write(Type.UUID, bossUUID);
wrapper.write(Type.VAR_INT, 1); // Action - remove
wrapper.scheduleSend(Protocol1_8To1_9.class, false);
bossUUID = null;
}
}
@@ -0,0 +1,54 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.api.ViaRewindConfig.CooldownIndicator;
import com.viaversion.viaversion.api.connection.UserConnection;
public interface CooldownVisualization {
void show(double progress) throws Exception;
void hide() throws Exception;
int MAX_PROGRESS_TEXT_LENGTH = 10;
static String buildProgressText(String symbol, double cooldown) {
int green = (int) Math.floor(((double) MAX_PROGRESS_TEXT_LENGTH) * cooldown);
int grey = MAX_PROGRESS_TEXT_LENGTH - green;
StringBuilder builder = new StringBuilder("§8");
while (green-- > 0) builder.append(symbol);
builder.append("§7");
while (grey-- > 0) builder.append(symbol);
return builder.toString();
}
interface Factory {
CooldownVisualization create(UserConnection user);
static Factory fromConfiguration() {
try {
return fromIndicator(ViaRewind.getConfig().getCooldownIndicator());
} catch (IllegalArgumentException e) {
ViaRewind.getPlatform().getLogger().warning("Invalid cooldown-indicator setting");
return DISABLED;
}
}
static Factory fromIndicator(CooldownIndicator indicator) {
switch (indicator) {
case TITLE:
return TitleCooldownVisualization::new;
case BOSS_BAR:
return BossBarVisualization::new;
case ACTION_BAR:
return ActionBarVisualization::new;
case DISABLED:
return DISABLED;
default:
throw new IllegalArgumentException("Unexpected: " + indicator);
}
}
Factory DISABLED = user -> new DisabledCooldownVisualization();
}
}
@@ -0,0 +1,13 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
public class DisabledCooldownVisualization implements CooldownVisualization {
@Override
public void show(double progress) {
}
@Override
public void hide() {
}
}
@@ -0,0 +1,59 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.cooldown;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.function.Consumer;
public class TitleCooldownVisualization implements CooldownVisualization {
private final UserConnection user;
public TitleCooldownVisualization(UserConnection user) {
this.user = user;
}
@Override
public void show(double progress) throws Exception {
String text = CooldownVisualization.buildProgressText("˙", progress);
sendTitle("", text, 0, 2, 5);
}
@Override
public void hide() throws Exception {
sendTitlePacket(ACTION_HIDE, wrapper -> {});
}
private static final int ACTION_SET_TITLE = 0;
private static final int ACTION_SET_SUBTITLE = 1;
private static final int ACTION_SET_TIMES_AND_DISPLAY = 2;
private static final int ACTION_HIDE = 3;
private void sendTitle(String titleText, String subTitleText, int fadeIn, int stay, int fadeOut) throws Exception {
sendTitlePacket(
ACTION_SET_TITLE,
packet -> packet.write(Type.COMPONENT, new JsonPrimitive(titleText))
);
sendTitlePacket(
ACTION_SET_SUBTITLE,
packet -> packet.write(Type.COMPONENT, new JsonPrimitive(subTitleText))
);
sendTitlePacket(
ACTION_SET_TIMES_AND_DISPLAY,
packet -> {
packet.write(Type.INT, fadeIn);
packet.write(Type.INT, stay);
packet.write(Type.INT, fadeOut);
}
);
}
private void sendTitlePacket(int action, Consumer<PacketWrapper> writer) throws Exception {
PacketWrapper titlePacket = PacketWrapper.create(ClientboundPackets1_8.TITLE, user);
titlePacket.write(Type.VAR_INT, action);
writer.accept(titlePacket);
titlePacket.scheduleSend(Protocol1_8To1_9.class);
}
}
@@ -19,10 +19,11 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
@@ -31,19 +32,18 @@ import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public abstract class EntityReplacement1_8to1_9 implements EntityReplacement {
protected final UserConnection user;
public abstract class EntityModel1_8To1_9 extends EntityModel<Protocol1_8To1_9> {
protected EntityReplacement1_8to1_9(UserConnection user) {
this.user = user;
public EntityModel1_8To1_9(UserConnection user, Protocol1_8To1_9 protocol) {
super(user, protocol);
}
protected void sendTeleportWithHead(int entityId, double locX, double locY, double locZ, float yaw, float pitch, float headYaw) {
sendTeleport(entityId, locX, locY, locZ, yaw, pitch);
teleportEntity(entityId, locX, locY, locZ, yaw, pitch);
sendHeadYaw(entityId, headYaw);
}
protected void sendTeleport(int entityId, double locX, double locY, double locZ, float yaw, float pitch) {
protected void teleportEntity(int entityId, double locX, double locY, double locZ, float yaw, float pitch) {
PacketWrapper teleport = PacketWrapper.create(ClientboundPackets1_8.ENTITY_TELEPORT, null, user);
teleport.write(Type.VAR_INT, entityId);
teleport.write(Type.INT, (int) (locX * 32.0));
@@ -29,20 +29,21 @@ import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import java.util.ArrayList;
import java.util.List;
public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
public class ShulkerBulletModel extends EntityModel1_8To1_9 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
private float yaw, pitch;
private float headYaw;
public ShulkerBulletReplacement(int entityId, UserConnection user) {
super(user);
public ShulkerBulletModel(UserConnection user, Protocol1_8To1_9 protocol, int entityId) {
super(user, protocol);
this.entityId = entityId;
spawn();
sendSpawnPacket();
}
public void setLocation(double x, double y, double z) {
@Override
public void updateReplacementPosition(double x, double y, double z) {
if (x != this.locX || y != this.locY || z != this.locZ) {
this.locX = x;
this.locY = y;
@@ -51,7 +52,8 @@ public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
}
}
public void relMove(double x, double y, double z) {
@Override
public void handleOriginalMovementPacket(double x, double y, double z) {
if (x == 0.0 && y == 0.0 && z == 0.0) return;
this.locX += x;
this.locY += y;
@@ -59,6 +61,7 @@ public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
updateLocation();
}
@Override
public void setYawPitch(float yaw, float pitch) {
if (this.yaw != yaw && this.pitch != pitch) {
this.yaw = yaw;
@@ -67,10 +70,12 @@ public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
}
}
@Override
public void setHeadYaw(float yaw) {
this.headYaw = yaw;
}
@Override
public void updateMetadata(List<Metadata> metadataList) {
}
@@ -79,18 +84,19 @@ public class ShulkerBulletReplacement extends EntityReplacement1_8to1_9 {
}
@Override
public void spawn() {
public void sendSpawnPacket() {
sendSpawnEntity(entityId, 66);
}
@Override
public void despawn() {
public void deleteEntity() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_8.DESTROY_ENTITIES, null, user);
despawn.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_8To1_9.class, true, true);
}
@Override
public int getEntityId() {
return this.entityId;
}
@@ -18,53 +18,57 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement;
import com.viaversion.viarewind.protocol.protocol1_7_2_5to1_7_6_10.ClientboundPackets1_7_2_5;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_9;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viarewind.protocol.protocol1_7_6_10to1_8.ClientboundPackets1_7;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata.MetadataRewriter;
import java.util.ArrayList;
import java.util.List;
public class ShulkerReplacement extends EntityReplacement1_8to1_9 {
public class ShulkerModel extends EntityModel1_8To1_9 {
private final int entityId;
private final List<Metadata> datawatcher = new ArrayList<>();
private double locX, locY, locZ;
public ShulkerReplacement(int entityId, UserConnection user) {
super(user);
public ShulkerModel(UserConnection user, Protocol1_8To1_9 protocol, int entityId) {
super(user, protocol);
this.entityId = entityId;
spawn();
sendSpawnPacket();
}
public void setLocation(double x, double y, double z) {
@Override
public void updateReplacementPosition(double x, double y, double z) {
this.locX = x;
this.locY = y;
this.locZ = z;
updateLocation();
}
public void relMove(double x, double y, double z) {
@Override
public void handleOriginalMovementPacket(double x, double y, double z) {
this.locX += x;
this.locY += y;
this.locZ += z;
updateLocation();
}
@Override
public void setYawPitch(float yaw, float pitch) {
}
@Override
public void setHeadYaw(float yaw) {
}
@Override
public void updateMetadata(List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
datawatcher.removeIf(m -> m.id() == metadata.id());
@@ -74,7 +78,7 @@ public class ShulkerReplacement extends EntityReplacement1_8to1_9 {
}
public void updateLocation() {
sendTeleport(entityId, locX, locY, locZ, 0, 0);
teleportEntity(entityId, locX, locY, locZ, 0, 0);
}
public void updateMetadata() {
@@ -88,7 +92,7 @@ public class ShulkerReplacement extends EntityReplacement1_8to1_9 {
}
metadataList.add(new Metadata(11, MetaType1_9.VarInt, 2));
MetadataRewriter.transform(Entity1_10Types.EntityType.MAGMA_CUBE, metadataList);
getProtocol().getMetadataRewriter().transform(EntityTypes1_10.EntityType.MAGMA_CUBE, metadataList);
metadataPacket.write(Types1_8.METADATA_LIST, metadataList);
@@ -96,19 +100,20 @@ public class ShulkerReplacement extends EntityReplacement1_8to1_9 {
}
@Override
public void spawn() {
public void sendSpawnPacket() {
sendSpawn(entityId, 62);
// Old clients don't like empty metadata
}
@Override
public void despawn() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7.DESTROY_ENTITIES, null, user);
public void deleteEntity() {
PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.DESTROY_ENTITIES, null, user);
despawn.write(Type.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
PacketUtil.sendPacket(despawn, Protocol1_8To1_9.class, true, true);
}
@Override
public int getEntityId() {
return this.entityId;
}
@@ -1,310 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.items;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viarewind.utils.Enchantments;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter.potionNameFromDamage;
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "unused"})
public class ItemRewriter {
private static Map<String, Integer> ENTTIY_NAME_TO_ID;
private static Map<Integer, String> ENTTIY_ID_TO_NAME;
private static Map<String, Integer> POTION_NAME_TO_ID;
private static Map<Integer, String> POTION_ID_TO_NAME;
private static final Map<String, String> POTION_NAME_INDEX = new HashMap<>();
static {
for (Field field : ItemRewriter.class.getDeclaredFields()) {
try {
Field other = com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter.class.getDeclaredField(field.getName());
other.setAccessible(true);
field.setAccessible(true);
field.set(null, other.get(null));
} catch (Exception ignored) {}
}
POTION_NAME_TO_ID.put("luck", 8203);
POTION_NAME_INDEX.put("water", "§rWater Bottle");
POTION_NAME_INDEX.put("mundane", "§rMundane Potion");
POTION_NAME_INDEX.put("thick", "§rThick Potion");
POTION_NAME_INDEX.put("awkward", "§rAwkward Potion");
POTION_NAME_INDEX.put("water_splash", "§rSplash Water Bottle");
POTION_NAME_INDEX.put("mundane_splash", "§rMundane Splash Potion");
POTION_NAME_INDEX.put("thick_splash", "§rThick Splash Potion");
POTION_NAME_INDEX.put("awkward_splash", "§rAwkward Splash Potion");
POTION_NAME_INDEX.put("water_lingering", "§rLingering Water Bottle");
POTION_NAME_INDEX.put("mundane_lingering", "§rMundane Lingering Potion");
POTION_NAME_INDEX.put("thick_lingering", "§rThick Lingering Potion");
POTION_NAME_INDEX.put("awkward_lingering", "§rAwkward Lingering Potion");
POTION_NAME_INDEX.put("night_vision_lingering", "§rLingering Potion of Night Vision");
POTION_NAME_INDEX.put("long_night_vision_lingering", "§rLingering Potion of Night Vision");
POTION_NAME_INDEX.put("invisibility_lingering", "§rLingering Potion of Invisibility");
POTION_NAME_INDEX.put("long_invisibility_lingering", "§rLingering Potion of Invisibility");
POTION_NAME_INDEX.put("leaping_lingering", "§rLingering Potion of Leaping");
POTION_NAME_INDEX.put("long_leaping_lingering", "§rLingering Potion of Leaping");
POTION_NAME_INDEX.put("strong_leaping_lingering", "§rLingering Potion of Leaping");
POTION_NAME_INDEX.put("fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
POTION_NAME_INDEX.put("long_fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
POTION_NAME_INDEX.put("swiftness_lingering", "§rLingering Potion of Swiftness");
POTION_NAME_INDEX.put("long_swiftness_lingering", "§rLingering Potion of Swiftness");
POTION_NAME_INDEX.put("strong_swiftness_lingering", "§rLingering Potion of Swiftness");
POTION_NAME_INDEX.put("slowness_lingering", "§rLingering Potion of Slowness");
POTION_NAME_INDEX.put("long_slowness_lingering", "§rLingering Potion of Slowness");
POTION_NAME_INDEX.put("water_breathing_lingering", "§rLingering Potion of Water Breathing");
POTION_NAME_INDEX.put("long_water_breathing_lingering", "§rLingering Potion of Water Breathing");
POTION_NAME_INDEX.put("healing_lingering", "§rLingering Potion of Healing");
POTION_NAME_INDEX.put("strong_healing_lingering", "§rLingering Potion of Healing");
POTION_NAME_INDEX.put("harming_lingering", "§rLingering Potion of Harming");
POTION_NAME_INDEX.put("strong_harming_lingering", "§rLingering Potion of Harming");
POTION_NAME_INDEX.put("poison_lingering", "§rLingering Potion of Poisen");
POTION_NAME_INDEX.put("long_poison_lingering", "§rLingering Potion of Poisen");
POTION_NAME_INDEX.put("strong_poison_lingering", "§rLingering Potion of Poisen");
POTION_NAME_INDEX.put("regeneration_lingering", "§rLingering Potion of Regeneration");
POTION_NAME_INDEX.put("long_regeneration_lingering", "§rLingering Potion of Regeneration");
POTION_NAME_INDEX.put("strong_regeneration_lingering", "§rLingering Potion of Regeneration");
POTION_NAME_INDEX.put("strength_lingering", "§rLingering Potion of Strength");
POTION_NAME_INDEX.put("long_strength_lingering", "§rLingering Potion of Strength");
POTION_NAME_INDEX.put("strong_strength_lingering", "§rLingering Potion of Strength");
POTION_NAME_INDEX.put("weakness_lingering", "§rLingering Potion of Weakness");
POTION_NAME_INDEX.put("long_weakness_lingering", "§rLingering Potion of Weakness");
POTION_NAME_INDEX.put("luck_lingering", "§rLingering Potion of Luck");
POTION_NAME_INDEX.put("luck", "§rPotion of Luck");
POTION_NAME_INDEX.put("luck_splash", "§rSplash Potion of Luck");
}
public static Item toClient(Item item) {
if (item==null) return null;
CompoundTag tag = item.tag();
if (tag==null) item.setTag(tag = new CompoundTag());
CompoundTag viaVersionTag = new CompoundTag();
tag.put("ViaRewind1_8to1_9", viaVersionTag);
viaVersionTag.put("id", new ShortTag((short) item.identifier()));
viaVersionTag.put("data", new ShortTag(item.data()));
CompoundTag display = tag.get("display");
if (display!=null && display.contains("Name")) {
viaVersionTag.put("displayName", new StringTag((String) display.get("Name").getValue()));
}
if (display!=null && display.contains("Lore")) {
viaVersionTag.put("lore", new ListTag(((ListTag)display.get("Lore")).getValue()));
}
if (tag.contains("ench") || tag.contains("StoredEnchantments")) {
ListTag enchTag = tag.contains("ench") ? tag.get("ench") : tag.get("StoredEnchantments");
List<Tag> lore = new ArrayList<>();
for (Tag ench : new ArrayList<>(enchTag.getValue())) {
short id = ((NumberTag) ((CompoundTag)ench).get("id")).asShort();
short lvl = ((NumberTag) ((CompoundTag)ench).get("lvl")).asShort();
String s;
if (id==70) {
s = "§r§7Mending ";
} else if (id==9) {
s = "§r§7Frost Walker ";
} else {
continue;
}
enchTag.remove(ench);
s += Enchantments.ENCHANTMENTS.getOrDefault(lvl, "enchantment.level." + lvl);
lore.add(new StringTag(s));
}
if (!lore.isEmpty()) {
if (display==null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag==null) display.put("Lore", loreTag = new ListTag(StringTag.class));
lore.addAll(loreTag.getValue());
loreTag.setValue(lore);
}
}
if (item.data()!=0 && tag.contains("Unbreakable")) {
ByteTag unbreakable = tag.get("Unbreakable");
if (unbreakable.asByte()!=0) {
viaVersionTag.put("Unbreakable", new ByteTag(unbreakable.asByte()));
tag.remove("Unbreakable");
if (display==null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag==null) display.put("Lore", loreTag = new ListTag(StringTag.class));
loreTag.add(new StringTag("§9Unbreakable"));
}
}
if (tag.contains("AttributeModifiers")) {
viaVersionTag.put("AttributeModifiers", tag.get("AttributeModifiers").clone());
}
if (item.identifier()==383 && item.data()==0) {
int data = 0;
if (tag.contains("EntityTag")) {
CompoundTag entityTag = tag.get("EntityTag");
if (entityTag.contains("id")) {
StringTag id = entityTag.get("id");
if (ENTTIY_NAME_TO_ID.containsKey(id.getValue())) {
data = ENTTIY_NAME_TO_ID.get(id.getValue());
} else if (display==null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
display.put("Name", new StringTag("§rSpawn " + id.getValue()));
}
}
}
item.setData((short)data);
}
ReplacementRegistry1_8to1_9.replace(item);
if (item.identifier()==373 || item.identifier()==438 || item.identifier()==441) {
int data = 0;
if (tag.contains("Potion")) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (POTION_NAME_TO_ID.containsKey(potionName)) {
data = POTION_NAME_TO_ID.get(potionName);
}
if (item.identifier()==438) potionName += "_splash";
else if (item.identifier()==441) potionName += "_lingering";
if ((display==null || !display.contains("Name")) && POTION_NAME_INDEX.containsKey(potionName)) {
if (display==null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
display.put("Name", new StringTag(POTION_NAME_INDEX.get(potionName)));
}
}
if (item.identifier()==438 || item.identifier()==441) {
item.setIdentifier(373);
data += 8192;
}
item.setData((short)data);
}
if (tag.contains("AttributeModifiers")) {
ListTag attributes = tag.get("AttributeModifiers");
for (int i = 0; i<attributes.size(); i++) {
CompoundTag attribute = attributes.get(i);
String name = (String) attribute.get("AttributeName").getValue();
if (!Protocol1_8To1_9.VALID_ATTRIBUTES.contains(name)) {
attributes.remove(attribute);
i--;
}
}
}
if (viaVersionTag.size()==2 && (short)viaVersionTag.get("id").getValue()==item.identifier() && (short)viaVersionTag.get("data").getValue()==item.data()) {
item.tag().remove("ViaRewind1_8to1_9");
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
public static Item toServer(Item item) {
if (item==null) return null;
CompoundTag tag = item.tag();
if (item.identifier() == 383 && item.data() != 0) {
if (tag == null) item.setTag(tag = new CompoundTag());
if (!tag.contains("EntityTag") && ENTTIY_ID_TO_NAME.containsKey((int) item.data())) {
CompoundTag entityTag = new CompoundTag();
entityTag.put("id", new StringTag(ENTTIY_ID_TO_NAME.get((int) item.data())));
tag.put("EntityTag", entityTag);
}
item.setData((short) 0);
}
if (item.identifier() == 373 && (tag==null || !tag.contains("Potion"))) {
if (tag == null) item.setTag(tag = new CompoundTag());
if (item.data() >= 16384) {
item.setIdentifier(438);
item.setData((short) (item.data() - 8192));
}
String name = item.data() == 8192 ? "water" : potionNameFromDamage(item.data());
tag.put("Potion", new StringTag("minecraft:" + name));
item.setData((short) 0);
}
if (tag==null || !item.tag().contains("ViaRewind1_8to1_9")) return item;
CompoundTag viaVersionTag = tag.remove("ViaRewind1_8to1_9");
item.setIdentifier((short) viaVersionTag.get("id").getValue());
item.setData((Short) viaVersionTag.get("data").getValue());
if (viaVersionTag.contains("noDisplay")) tag.remove("display");
if (viaVersionTag.contains("Unbreakable")) {
tag.put("Unbreakable", viaVersionTag.get("Unbreakable").clone());
}
if (viaVersionTag.contains("displayName")) {
CompoundTag display = tag.get("display");
if (display==null) tag.put("display", display = new CompoundTag());
StringTag name = display.get("Name");
if (name==null) display.put("Name", new StringTag((String) viaVersionTag.get("displayName").getValue()));
else name.setValue((String) viaVersionTag.get("displayName").getValue());
} else if (tag.contains("display")) {
((CompoundTag)tag.get("display")).remove("Name");
}
if (viaVersionTag.contains("lore")) {
CompoundTag display = tag.get("display");
if (display==null) tag.put("display", display = new CompoundTag());
ListTag lore = display.get("Lore");
if (lore==null) display.put("Lore", new ListTag((List<Tag>) viaVersionTag.get("lore").getValue()));
else lore.setValue((List<Tag>) viaVersionTag.get("lore").getValue());
} else if (tag.contains("display")) {
((CompoundTag)tag.get("display")).remove("Lore");
}
tag.remove("AttributeModifiers");
if (viaVersionTag.contains("AttributeModifiers")) {
tag.put("AttributeModifiers", viaVersionTag.get("AttributeModifiers"));
}
return item;
}
}
@@ -1,105 +0,0 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.items;
import com.viaversion.viarewind.replacement.Replacement;
import com.viaversion.viarewind.replacement.ReplacementRegistry;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viarewind.storage.BlockState;
public class ReplacementRegistry1_8to1_9 {
private static final ReplacementRegistry registry = new ReplacementRegistry();
static {
registry.registerItem(198, new Replacement(50, 0, "End Rod"));
registry.registerItem(434, new Replacement(391, "Beetroot"));
registry.registerItem(435, new Replacement(361, "Beetroot Seeds"));
registry.registerItem(436, new Replacement(282, "Beetroot Soup"));
registry.registerItem(432, new Replacement(322, "Chorus Fruit"));
registry.registerItem(433, new Replacement(393, "Popped Chorus Fruit"));
registry.registerItem(437, new Replacement(373, "Dragons Breath"));
registry.registerItem(443, new Replacement(299, "Elytra"));
registry.registerItem(426, new Replacement(410, "End Crystal"));
registry.registerItem(442, new Replacement(425, "Shield"));
registry.registerItem(439, new Replacement(262, "Spectral Arrow"));
registry.registerItem(440, new Replacement(262, "Tipped Arrow"));
registry.registerItem(444, new Replacement(333, "Spruce Boat"));
registry.registerItem(445, new Replacement(333, "Birch Boat"));
registry.registerItem(446, new Replacement(333, "Jungle Boat"));
registry.registerItem(447, new Replacement(333, "Acacia Boat"));
registry.registerItem(448, new Replacement(333, "Dark Oak Boat"));
registry.registerItem(204, new Replacement(43, 7, "Purpur Double Slab"));
registry.registerItem(205, new Replacement(44, 7, "Purpur Slab"));
registry.registerBlock(209, new Replacement(119));
registry.registerBlock(198, 0, new Replacement(50, 5));
registry.registerBlock(198, 1, new Replacement(50, 5));
registry.registerBlock(198, 2, new Replacement(50, 4));
registry.registerBlock(198, 3, new Replacement(50, 3));
registry.registerBlock(198, 4, new Replacement(50, 2));
registry.registerBlock(198, 5, new Replacement(50, 1));
registry.registerBlock(204, new Replacement(43, 7));
registry.registerBlock(205, 0, new Replacement(44, 7));
registry.registerBlock(205, 8, new Replacement(44, 15));
registry.registerBlock(207, new Replacement(141));
registry.registerBlock(137, new Replacement(137, 0));
registry.registerItemBlock(199, new Replacement(35, 10, "Chorus Plant"));
registry.registerItemBlock(200, new Replacement(35, 2, "Chorus Flower"));
registry.registerItemBlock(201, new Replacement(155, 0, "Purpur Block"));
registry.registerItemBlock(202, new Replacement(155, 2, "Purpur Pillar"));
registry.registerItemBlock(203, 0, new Replacement(156, 0, "Purpur Stairs"));
registry.registerItemBlock(203, 1, new Replacement(156, 1, "Purpur Stairs"));
registry.registerItemBlock(203, 2, new Replacement(156, 2, "Purpur Stairs"));
registry.registerItemBlock(203, 3, new Replacement(156, 3, "Purpur Stairs"));
registry.registerItemBlock(203, 4, new Replacement(156, 4, "Purpur Stairs"));
registry.registerItemBlock(203, 5, new Replacement(156, 5, "Purpur Stairs"));
registry.registerItemBlock(203, 6, new Replacement(156, 6, "Purpur Stairs"));
registry.registerItemBlock(203, 7, new Replacement(156, 7, "Purpur Stairs"));
registry.registerItemBlock(203, 8, new Replacement(156, 8, "Purpur Stairs"));
registry.registerItemBlock(206, new Replacement(121, 0, "Endstone Bricks"));
registry.registerItemBlock(207, new Replacement(141, "Beetroot Block"));
registry.registerItemBlock(208, new Replacement(2, 0, "Grass Path"));
registry.registerItemBlock(209, new Replacement(90, "End Gateway"));
registry.registerItemBlock(210, new Replacement(137, 0, "Repeating Command Block"));
registry.registerItemBlock(211, new Replacement(137, 0, "Chain Command Block"));
registry.registerItemBlock(212, new Replacement(79, 0, "Frosted Ice"));
registry.registerItemBlock(214, new Replacement(87, 0, "Nether Wart Block"));
registry.registerItemBlock(215, new Replacement(112, 0, "Red Nether Brick"));
registry.registerItemBlock(217, new Replacement(166, 0, "Structure Void"));
registry.registerItemBlock(255, new Replacement(137, 0, "Structure Block"));
registry.registerItemBlock(397, 5, new Replacement(397, 0, "Dragon Head"));
}
public static Item replace(Item item) {
return registry.replace(item);
}
public static int replace(int raw) {
int data = BlockState.extractData(raw);
Replacement replace = registry.replace(BlockState.extractId(raw), data);
if (replace == null) return raw;
return BlockState.stateToRaw(replace.getId(), replace.replaceData(data));
}
public static Replacement getReplacement(int id, int data) {
return registry.replace(id, data);
}
}
@@ -18,7 +18,7 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetaIndex;
import com.viaversion.viaversion.util.Pair;
@@ -27,15 +27,15 @@ import java.util.Optional;
public class MetaIndex1_8to1_9 {
private static final HashMap<Pair<Entity1_10Types.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
private final static HashMap<Pair<EntityTypes1_10.EntityType, Integer>, MetaIndex> metadataRewrites = new HashMap<>();
static {
for (MetaIndex index : MetaIndex.values())
metadataRewrites.put(new Pair<>(index.getClazz(), index.getNewIndex()), index);
}
private static Optional<MetaIndex> getIndex(Entity1_10Types.EntityType type, int index) {
Pair pair = new Pair<>(type, index);
private static Optional<MetaIndex> getIndex(EntityTypes1_10.EntityType type, int index) {
Pair<EntityTypes1_10.EntityType, Integer> pair = new Pair<>(type, index);
if (metadataRewrites.containsKey(pair)) {
return Optional.of(metadataRewrites.get(pair));
}
@@ -43,8 +43,8 @@ public class MetaIndex1_8to1_9 {
return Optional.empty();
}
public static MetaIndex searchIndex(Entity1_10Types.EntityType type, int index) {
Entity1_10Types.EntityType currentType = type;
public static MetaIndex searchIndex(EntityTypes1_10.EntityType type, int index) {
EntityTypes1_10.EntityType currentType = type;
do {
Optional<MetaIndex> optMeta = getIndex(currentType, index);
@@ -57,5 +57,4 @@ public class MetaIndex1_8to1_9 {
return null;
}
}
@@ -18,27 +18,33 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.items.ItemRewriter;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.api.minecraft.EulerAngle;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetaIndex;
import com.viaversion.viarewind.ViaRewind;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MetadataRewriter {
public static void transform(Entity1_10Types.EntityType type, List<Metadata> list) {
private final Protocol1_8To1_9 protocol;
public MetadataRewriter(Protocol1_8To1_9 protocol) {
this.protocol = protocol;
}
public void transform(EntityTypes1_10.EntityType type, List<Metadata> list) {
for (Metadata entry : new ArrayList<>(list)) {
MetaIndex metaIndex = MetaIndex1_8to1_9.searchIndex(type, entry.id());
try {
if (metaIndex != null) {
if (metaIndex.getOldType() == MetaType1_8.NonExistent || metaIndex.getNewType()==null) {
if (metaIndex.getOldType() == MetaType1_8.NonExistent || metaIndex.getNewType() == null) {
list.remove(entry);
continue;
}
@@ -55,7 +61,7 @@ public class MetadataRewriter {
}
break;
case OptUUID:
if (metaIndex.getOldType()!=MetaType1_8.String) {
if (metaIndex.getOldType() != MetaType1_8.String) {
list.remove(entry);
break;
}
@@ -85,11 +91,11 @@ public class MetadataRewriter {
entry.setValue(value);
break;
case Boolean:
if (metaIndex == MetaIndex.AGEABLE_AGE) entry.setValue((byte)((Boolean) value ? -1 : 0));
else entry.setValue((byte)((Boolean) value ? 1 : 0));
if (metaIndex == MetaIndex.AGEABLE_AGE) entry.setValue((byte) ((Boolean) value ? -1 : 0));
else entry.setValue((byte) ((Boolean) value ? 1 : 0));
break;
case Slot:
entry.setValue(ItemRewriter.toClient((Item) value));
entry.setValue(protocol.getItemRewriter().handleItemToClient((Item) value));
break;
case Position:
Vector vector = (Vector) value;
@@ -19,29 +19,24 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata.MetadataRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.Cooldown;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.EntityTracker;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.Levitation;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.PlayerPosition;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.util.RelativeMoveUtil;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import com.viaversion.viaversion.util.Pair;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.items.ItemRewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.util.RelativeMoveUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import java.util.ArrayList;
import java.util.List;
@@ -49,11 +44,7 @@ import java.util.UUID;
public class EntityPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
//Entity Status
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.ENTITY_STATUS, new PacketHandlers() {
@Override
public void register() {
@@ -81,10 +72,10 @@ public class EntityPackets {
int relZ = packetWrapper.read(Type.SHORT);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
replacement.relMove(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
replacement.handleOriginalMovementPacket(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
return;
}
@@ -97,7 +88,7 @@ public class EntityPackets {
boolean onGround = packetWrapper.passthrough(Type.BOOLEAN);
if (moves.length > 1) {
PacketWrapper secondPacket = PacketWrapper.create(0x15, null, packetWrapper.user());
PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION, null, packetWrapper.user());
secondPacket.write(Type.VAR_INT, packetWrapper.get(Type.VAR_INT, 0));
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
@@ -122,10 +113,10 @@ public class EntityPackets {
int relZ = packetWrapper.read(Type.SHORT);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
replacement.relMove(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
replacement.handleOriginalMovementPacket(relX / 4096.0, relY / 4096.0, relZ / 4096.0);
replacement.setYawPitch(packetWrapper.read(Type.BYTE) * 360f / 256, packetWrapper.read(Type.BYTE) * 360f / 256);
return;
}
@@ -140,14 +131,14 @@ public class EntityPackets {
byte pitch = packetWrapper.passthrough(Type.BYTE);
boolean onGround = packetWrapper.passthrough(Type.BOOLEAN);
Entity1_10Types.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.BOAT) {
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
yaw -= 64;
packetWrapper.set(Type.BYTE, 3, yaw);
}
if (moves.length > 1) {
PacketWrapper secondPacket = PacketWrapper.create(0x17, null, packetWrapper.user());
PacketWrapper secondPacket = PacketWrapper.create(ClientboundPackets1_8.ENTITY_POSITION_AND_ROTATION, null, packetWrapper.user());
secondPacket.write(Type.VAR_INT, packetWrapper.get(Type.VAR_INT, 0));
secondPacket.write(Type.BYTE, (byte) moves[1].blockX());
secondPacket.write(Type.BYTE, (byte) moves[1].blockY());
@@ -173,7 +164,7 @@ public class EntityPackets {
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
@@ -183,8 +174,8 @@ public class EntityPackets {
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
Entity1_10Types.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.BOAT) {
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = packetWrapper.get(Type.BYTE, 0);
yaw -= 64;
packetWrapper.set(Type.BYTE, 0, yaw);
@@ -221,8 +212,8 @@ public class EntityPackets {
create(Type.BOOLEAN, true);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
Entity1_10Types.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.BOAT) {
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = packetWrapper.get(Type.BYTE, 1);
yaw -= 64;
packetWrapper.set(Type.BYTE, 0, yaw);
@@ -277,7 +268,7 @@ public class EntityPackets {
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int yaw = packetWrapper.get(Type.BYTE, 0);
@@ -298,7 +289,7 @@ public class EntityPackets {
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (tracker.getClientEntityTypes().containsKey(entityId)) {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityId), metadataList);
protocol.getMetadataRewriter().transform(tracker.getClientEntityTypes().get(entityId), metadataList);
if (metadataList.isEmpty()) wrapper.cancel();
} else {
tracker.addMetadataToBuffer(entityId, metadataList);
@@ -335,8 +326,8 @@ public class EntityPackets {
}
packetWrapper.write(Type.SHORT, (short) slot);
});
map(Type.ITEM);
handler(packetWrapper -> packetWrapper.set(Type.ITEM, 0, ItemRewriter.toClient(packetWrapper.get(Type.ITEM, 0))));
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToClient(packetWrapper.get(Type.ITEM1_8, 0))));
}
});
@@ -355,7 +346,7 @@ public class EntityPackets {
entityTracker.setPassengers(vehicle, passengers);
if (!oldPassengers.isEmpty()) {
for (Integer passenger : oldPassengers) {
PacketWrapper detach = PacketWrapper.create(0x1B, null, packetWrapper.user());
PacketWrapper detach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, null, packetWrapper.user());
detach.write(Type.INT, passenger);
detach.write(Type.INT, -1);
detach.write(Type.BOOLEAN, false);
@@ -365,7 +356,7 @@ public class EntityPackets {
for (int i = 0; i < count; i++) {
int v = i == 0 ? vehicle : passengers.get(i - 1);
int p = passengers.get(i);
PacketWrapper attach = PacketWrapper.create(0x1B, null, packetWrapper.user());
PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_8.ATTACH_ENTITY, null, packetWrapper.user());
attach.write(Type.INT, p);
attach.write(Type.INT, v);
attach.write(Type.BOOLEAN, false);
@@ -390,8 +381,8 @@ public class EntityPackets {
map(Type.BOOLEAN);
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
Entity1_10Types.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == Entity1_10Types.EntityType.BOAT) {
EntityTypes1_10.EntityType type = packetWrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId);
if (type == EntityTypes1_10.EntityType.BOAT) {
byte yaw = packetWrapper.get(Type.BYTE, 1);
yaw -= 64;
packetWrapper.set(Type.BYTE, 0, yaw);
@@ -407,7 +398,7 @@ public class EntityPackets {
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
EntityReplacement replacement = tracker.getEntityReplacement(entityId);
EntityModel replacement = tracker.getEntityReplacement(entityId);
if (replacement != null) {
packetWrapper.cancel();
int x = packetWrapper.get(Type.INT, 0);
@@ -415,7 +406,7 @@ public class EntityPackets {
int z = packetWrapper.get(Type.INT, 2);
int yaw = packetWrapper.get(Type.BYTE, 0);
int pitch = packetWrapper.get(Type.BYTE, 1);
replacement.setLocation(x / 32.0, y / 32.0, z / 32.0);
replacement.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
replacement.setYawPitch(yaw * 360f / 256, pitch * 360f / 256);
}
});
@@ -436,16 +427,16 @@ public class EntityPackets {
String key = packetWrapper.read(Type.STRING);
boolean skip = !Protocol1_8To1_9.VALID_ATTRIBUTES.contains(key);
double value = packetWrapper.read(Type.DOUBLE);
int modifiersize = packetWrapper.read(Type.VAR_INT);
int modifierSize = packetWrapper.read(Type.VAR_INT);
if (!skip) {
packetWrapper.write(Type.STRING, key);
packetWrapper.write(Type.DOUBLE, value);
packetWrapper.write(Type.VAR_INT, modifiersize);
packetWrapper.write(Type.VAR_INT, modifierSize);
} else {
removed++;
}
ArrayList<Pair<Byte, Double>> modifiers = new ArrayList<>();
for (int j = 0; j < modifiersize; j++) {
for (int j = 0; j < modifierSize; j++) {
UUID uuid = packetWrapper.read(Type.UUID);
double amount = packetWrapper.read(Type.DOUBLE);
byte operation = packetWrapper.read(Type.BYTE);
@@ -18,27 +18,18 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.Windows;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.items.ItemRewriter;
public class InventoryPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
//Confirm Transaction
//Close Window
public static void register(final Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.CLOSE_WINDOW, new PacketHandlers() {
@Override
public void register() {
@@ -87,9 +78,9 @@ public class InventoryPackets {
map(Type.UNSIGNED_BYTE);
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
Item[] items = packetWrapper.read(Type.ITEM_ARRAY);
Item[] items = packetWrapper.read(Type.ITEM1_8_SHORT_ARRAY);
for (int i = 0; i < items.length; i++) {
items[i] = ItemRewriter.toClient(items[i]);
items[i] = protocol.getItemRewriter().handleItemToClient(items[i]);
}
if (windowId == 0 && items.length == 46) {
Item[] old = items;
@@ -106,7 +97,7 @@ public class InventoryPackets {
System.arraycopy(old, 5, items, 4, old.length - 5);
}
}
packetWrapper.write(Type.ITEM_ARRAY, items);
packetWrapper.write(Type.ITEM1_8_SHORT_ARRAY, items);
});
}
});
@@ -119,9 +110,9 @@ public class InventoryPackets {
public void register() {
map(Type.UNSIGNED_BYTE);
map(Type.SHORT);
map(Type.ITEM);
map(Type.ITEM1_8);
handler(packetWrapper -> {
packetWrapper.set(Type.ITEM, 0, ItemRewriter.toClient(packetWrapper.get(Type.ITEM, 0)));
packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToClient(packetWrapper.get(Type.ITEM1_8, 0)));
byte windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0).byteValue();
short slot = packetWrapper.get(Type.SHORT, 0);
if (windowId == 0 && slot == 45) {
@@ -135,16 +126,16 @@ public class InventoryPackets {
packetWrapper.set(Type.SHORT, 0, slot -= 1);
} else if (slot == 4) {
packetWrapper.cancel();
Windows.updateBrewingStand(packetWrapper.user(), packetWrapper.get(Type.ITEM, 0), windowId);
Windows.updateBrewingStand(packetWrapper.user(), packetWrapper.get(Type.ITEM1_8, 0), windowId);
} else {
packetWrapper.user().get(Windows.class).getBrewingItems(windowId)[slot] = packetWrapper.get(Type.ITEM, 0);
packetWrapper.user().get(Windows.class).getBrewingItems(windowId)[slot] = packetWrapper.get(Type.ITEM1_8, 0);
}
}
});
}
});
/* INCMOING */
/* INCOMING */
//Close Window
protocol.registerServerbound(ServerboundPackets1_8.CLOSE_WINDOW, new PacketHandlers() {
@@ -167,8 +158,8 @@ public class InventoryPackets {
map(Type.BYTE);
map(Type.SHORT);
map(Type.BYTE, Type.VAR_INT);
map(Type.ITEM);
handler(packetWrapper -> packetWrapper.set(Type.ITEM, 0, ItemRewriter.toServer(packetWrapper.get(Type.ITEM, 0))));
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToServer(packetWrapper.get(Type.ITEM1_8, 0))));
handler(packetWrapper -> {
short windowId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
Windows windows = packetWrapper.user().get(Windows.class);
@@ -184,16 +175,13 @@ public class InventoryPackets {
}
});
//Creative Inventory Action
protocol.registerServerbound(ServerboundPackets1_8.CREATIVE_INVENTORY_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.SHORT);
map(Type.ITEM);
handler(packetWrapper -> packetWrapper.set(Type.ITEM, 0, ItemRewriter.toServer(packetWrapper.get(Type.ITEM, 0))));
map(Type.ITEM1_8);
handler(packetWrapper -> packetWrapper.set(Type.ITEM1_8, 0, protocol.getItemRewriter().handleItemToServer(packetWrapper.get(Type.ITEM1_8, 0))));
}
});
//Enchant Item
}
}
@@ -21,42 +21,32 @@ package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.ViaRewind;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.storage.*;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_8;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.items.ItemRewriter;
import com.viaversion.viarewind.utils.ChatUtil;
import com.viaversion.viarewind.utils.PacketUtil;
import java.util.ArrayList;
import java.util.UUID;
public class PlayerPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
public static void register(final Protocol1_8To1_9 protocol) {
//Animation
//Statistics
//Boss Bar
protocol.registerClientbound(ClientboundPackets1_9.BOSSBAR, null, new PacketHandlers() {
@Override
public void register() {
@@ -106,13 +96,15 @@ public class PlayerPackets {
size = packetWrapper.passthrough(Type.UNSIGNED_BYTE);
}
final ItemRewriter<?> itemRewriter = protocol.getItemRewriter();
for (int i = 0; i < size; i++) {
packetWrapper.write(Type.ITEM, ItemRewriter.toClient(packetWrapper.read(Type.ITEM))); //Buy Item 1
packetWrapper.write(Type.ITEM, ItemRewriter.toClient(packetWrapper.read(Type.ITEM))); //Buy Item 3
packetWrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(packetWrapper.read(Type.ITEM1_8))); //Buy Item 1
packetWrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(packetWrapper.read(Type.ITEM1_8))); //Buy Item 3
boolean has3Items = packetWrapper.passthrough(Type.BOOLEAN);
if (has3Items) {
packetWrapper.write(Type.ITEM, ItemRewriter.toClient(packetWrapper.read(Type.ITEM))); //Buy Item 2
packetWrapper.write(Type.ITEM1_8, itemRewriter.handleItemToClient(packetWrapper.read(Type.ITEM1_8))); //Buy Item 2
}
packetWrapper.passthrough(Type.BOOLEAN); //Unavailable
@@ -156,7 +148,7 @@ public class PlayerPackets {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.setPlayerId(packetWrapper.get(Type.INT, 0));
tracker.setPlayerGamemode(packetWrapper.get(Type.UNSIGNED_BYTE, 0));
tracker.getClientEntityTypes().put(tracker.getPlayerId(), Entity1_10Types.EntityType.ENTITY_HUMAN);
tracker.getClientEntityTypes().put(tracker.getPlayerId(), EntityTypes1_10.EntityType.ENTITY_HUMAN);
});
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
@@ -254,7 +246,7 @@ public class PlayerPackets {
//Title
//Player List Header And Footer
/* INCMOING */
/* INCOMING */
//Chat Message
protocol.registerServerbound(ServerboundPackets1_8.CHAT_MESSAGE, new PacketHandlers() {
@@ -267,7 +259,7 @@ public class PlayerPackets {
packetWrapper.cancel();
PacketWrapper swapItems = PacketWrapper.create(0x13, null, packetWrapper.user());
swapItems.write(Type.VAR_INT, 6);
swapItems.write(Type.POSITION, new Position(0, 0, 0));
swapItems.write(Type.POSITION1_8, new Position(0, 0, 0));
swapItems.write(Type.BYTE, (byte) 255);
PacketUtil.sendToServer(swapItems, Protocol1_8To1_9.class, true, true);
@@ -306,7 +298,7 @@ public class PlayerPackets {
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while((animation = ((Protocol1_8To1_9)protocol).animationsToSend.poll()) != null) {
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
@@ -328,9 +320,8 @@ public class PlayerPackets {
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while((animation = ((Protocol1_8To1_9)protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class,
true, true);
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
PlayerPosition pos = packetWrapper.user().get(PlayerPosition.class);
@@ -353,7 +344,7 @@ public class PlayerPackets {
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while((animation = ((Protocol1_8To1_9)protocol).animationsToSend.poll()) != null) {
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
@@ -380,7 +371,7 @@ public class PlayerPackets {
handler(packetWrapper -> {
//Sending any queued animations.
PacketWrapper animation = null;
while((animation = ((Protocol1_8To1_9)protocol).animationsToSend.poll()) != null) {
while ((animation = ((Protocol1_8To1_9) protocol).animationsToSend.poll()) != null) {
PacketUtil.sendToServer(animation, Protocol1_8To1_9.class, true, true);
}
@@ -418,7 +409,7 @@ public class PlayerPackets {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.POSITION);
map(Type.POSITION1_8);
handler(packetWrapper -> {
int state = packetWrapper.get(Type.VAR_INT, 0);
if (state == 0) {
@@ -442,9 +433,9 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_8.PLAYER_BLOCK_PLACEMENT, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION);
map(Type.POSITION1_8);
map(Type.BYTE, Type.VAR_INT);
map(Type.ITEM, Type.NOTHING);
read(Type.ITEM1_8);
create(Type.VAR_INT, 0); //Main Hand
map(Type.BYTE, Type.UNSIGNED_BYTE);
map(Type.BYTE, Type.UNSIGNED_BYTE);
@@ -493,7 +484,7 @@ public class PlayerPackets {
null, packetWrapper.user());
delayedPacket.write(Type.VAR_INT, 0); //Main Hand
((Protocol1_8To1_9)protocol).animationsToSend.add(delayedPacket);
((Protocol1_8To1_9) protocol).animationsToSend.add(delayedPacket);
});
handler(packetWrapper -> {
packetWrapper.user().get(BlockPlaceDestroyTracker.class).updateMining();
@@ -538,7 +529,7 @@ public class PlayerPackets {
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
int playerId = tracker.getPlayerId();
int vehicle = tracker.getVehicle(playerId);
if (vehicle != -1 && tracker.getClientEntityTypes().get(vehicle) == Entity1_10Types.EntityType.BOAT) {
if (vehicle != -1 && tracker.getClientEntityTypes().get(vehicle) == EntityTypes1_10.EntityType.BOAT) {
PacketWrapper steerBoat = PacketWrapper.create(0x11, null, packetWrapper.user());
float left = packetWrapper.get(Type.FLOAT, 0);
float forward = packetWrapper.get(Type.FLOAT, 1);
@@ -554,7 +545,7 @@ public class PlayerPackets {
protocol.registerServerbound(ServerboundPackets1_8.UPDATE_SIGN, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION);
map(Type.POSITION1_8);
handler(packetWrapper -> {
for (int i = 0; i < 4; i++) {
packetWrapper.write(Type.STRING, ChatUtil.jsonToLegacy(packetWrapper.read(Type.COMPONENT)));
@@ -571,7 +562,7 @@ public class PlayerPackets {
public void register() {
map(Type.STRING);
handler(packetWrapper -> packetWrapper.write(Type.BOOLEAN, false));
map(Type.OPTIONAL_POSITION);
map(Type.OPTIONAL_POSITION1_8);
}
});
@@ -18,43 +18,33 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.packets;
import com.viaversion.viarewind.replacement.EntityReplacement;
import com.viaversion.viarewind.replacement.Replacement;
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.ShulkerBulletReplacement;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.entityreplacement.ShulkerReplacement;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.metadata.MetadataRewriter;
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.viaversion.api.minecraft.entities.Entity1_10Types;
import com.viaversion.viarewind.api.minecraft.EntityModel;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viarewind.utils.PacketUtil;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_8;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.items.ReplacementRegistry1_8to1_9;
import com.viaversion.viarewind.utils.PacketUtil;
import java.util.List;
public class SpawnPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
//Spawn Object
public static void register(Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.SPAWN_ENTITY, new PacketHandlers() {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.UUID, Type.NOTHING);
read(Type.UUID);
map(Type.BYTE);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
map(Type.DOUBLE, Protocol1_8To1_9.TO_OLD_INT);
@@ -67,7 +57,7 @@ public class SpawnPackets {
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 Entity1_10Types.EntityType type = Entity1_10Types.getTypeFromId(typeId, true);
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) {
@@ -85,16 +75,16 @@ public class SpawnPackets {
int y = packetWrapper.get(Type.INT, 1);
int z = packetWrapper.get(Type.INT, 2);
if (type.is(Entity1_10Types.EntityType.BOAT)) {
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(Entity1_10Types.EntityType.SHULKER_BULLET)) {
} else if (type.is(EntityTypes1_10.EntityType.SHULKER_BULLET)) {
packetWrapper.cancel();
ShulkerBulletReplacement shulkerBulletReplacement = new ShulkerBulletReplacement(entityId, packetWrapper.user());
shulkerBulletReplacement.setLocation(x / 32.0, y / 32.0, z / 32.0);
ShulkerBulletModel shulkerBulletReplacement = new ShulkerBulletModel(packetWrapper.user(), protocol, entityId);
shulkerBulletReplacement.updateReplacementPosition(x / 32.0, y / 32.0, z / 32.0);
tracker.addEntityReplacement(shulkerBulletReplacement);
return;
}
@@ -102,13 +92,13 @@ public class SpawnPackets {
int data = packetWrapper.get(Type.INT, 3);
//Rewrite Object Data
if (type.isOrHasParent(Entity1_10Types.EntityType.ARROW) && data != 0) {
if (type.isOrHasParent(EntityTypes1_10.EntityType.ARROW) && data != 0) {
packetWrapper.set(Type.INT, 3, --data);
}
if (type.is(Entity1_10Types.EntityType.FALLING_BLOCK)) {
if (type.is(EntityTypes1_10.EntityType.FALLING_BLOCK)) {
int blockId = data & 0xFFF;
int blockData = data >> 12 & 0xF;
Replacement replace = ReplacementRegistry1_8to1_9.getReplacement(blockId, blockData);
Replacement replace = protocol.getItemRewriter().replace(blockId, blockData);
if (replace != null) {
packetWrapper.set(Type.INT, 3, replace.getId() | replace.replaceData(data) << 12);
}
@@ -148,7 +138,7 @@ public class SpawnPackets {
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.EXPERIENCE_ORB);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.EXPERIENCE_ORB);
tracker.sendMetadataBuffer(entityId);
});
}
@@ -166,7 +156,7 @@ public class SpawnPackets {
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.LIGHTNING);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.LIGHTNING);
tracker.sendMetadataBuffer(entityId);
});
}
@@ -177,7 +167,7 @@ public class SpawnPackets {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.UUID, Type.NOTHING);
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);
@@ -202,8 +192,8 @@ public class SpawnPackets {
if (typeId == 69) {
packetWrapper.cancel();
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
ShulkerReplacement shulkerReplacement = new ShulkerReplacement(entityId, packetWrapper.user());
shulkerReplacement.setLocation(x / 32.0, y / 32.0, z / 32.0);
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);
@@ -215,18 +205,18 @@ public class SpawnPackets {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
int typeId = packetWrapper.get(Type.UNSIGNED_BYTE, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.getTypeFromId(typeId, false));
tracker.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);
EntityReplacement replacement;
EntityModel replacement;
if ((replacement = tracker.getEntityReplacement(entityId)) != null) {
replacement.updateMetadata(metadataList);
} else if (tracker.getClientEntityTypes().containsKey(entityId)) {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityId), metadataList);
protocol.getMetadataRewriter().transform(tracker.getClientEntityTypes().get(entityId), metadataList);
} else {
wrapper.cancel();
}
@@ -239,14 +229,14 @@ public class SpawnPackets {
@Override
public void register() {
map(Type.VAR_INT);
map(Type.UUID, Type.NOTHING);
read(Type.UUID);
map(Type.STRING);
map(Type.POSITION);
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, Entity1_10Types.EntityType.PAINTING);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.PAINTING);
tracker.sendMetadataBuffer(entityId);
});
}
@@ -267,12 +257,12 @@ public class SpawnPackets {
map(Types1_9.METADATA_LIST, Types1_8.METADATA_LIST);
this.handler(wrapper -> {
List<Metadata> metadataList = wrapper.get(Types1_8.METADATA_LIST, 0);
MetadataRewriter.transform(Entity1_10Types.EntityType.PLAYER, metadataList);
protocol.getMetadataRewriter().transform(EntityTypes1_10.EntityType.PLAYER, metadataList);
});
handler(packetWrapper -> {
int entityId = packetWrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = packetWrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityId, Entity1_10Types.EntityType.PLAYER);
tracker.getClientEntityTypes().put(entityId, EntityTypes1_10.EntityType.PLAYER);
tracker.sendMetadataBuffer(entityId);
});
}
@@ -18,12 +18,11 @@
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.items.ReplacementRegistry1_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.ViaRewind;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.Environment;
@@ -34,39 +33,30 @@ import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_8;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_9_1;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_8.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.types.Chunk1_9_1_2Type;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ServerboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.types.Chunk1_8Type;
import java.util.ArrayList;
public class WorldPackets {
public static void register(Protocol<ClientboundPackets1_9, ClientboundPackets1_8,
ServerboundPackets1_9, ServerboundPackets1_8> protocol) {
/* OUTGOING */
//Block Break Animation
//Update Block Entity
public static void register(Protocol1_8To1_9 protocol) {
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_ENTITY_DATA, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION);
map(Type.POSITION1_8);
map(Type.UNSIGNED_BYTE);
map(Type.NBT);
map(Type.NAMED_COMPOUND_TAG);
handler(packetWrapper -> {
CompoundTag tag = packetWrapper.get(Type.NBT, 0);
CompoundTag tag = packetWrapper.get(Type.NAMED_COMPOUND_TAG, 0);
if (tag != null && tag.contains("SpawnData")) {
CompoundTag spawnData = tag.get("SpawnData");
if (spawnData.contains("id")) {
@@ -83,7 +73,7 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_ACTION, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION);
map(Type.POSITION1_8);
map(Type.UNSIGNED_BYTE);
map(Type.UNSIGNED_BYTE);
map(Type.VAR_INT);
@@ -100,11 +90,11 @@ public class WorldPackets {
protocol.registerClientbound(ClientboundPackets1_9.BLOCK_CHANGE, new PacketHandlers() {
@Override
public void register() {
map(Type.POSITION);
map(Type.POSITION1_8);
map(Type.VAR_INT);
handler(packetWrapper -> {
int combined = packetWrapper.get(Type.VAR_INT, 0);
int replacedCombined = ReplacementRegistry1_8to1_9.replace(combined);
int replacedCombined = protocol.getItemRewriter().replace(combined);
packetWrapper.set(Type.VAR_INT, 0, replacedCombined);
});
}
@@ -121,7 +111,7 @@ public class WorldPackets {
map(Type.BLOCK_CHANGE_RECORD_ARRAY);
handler(packetWrapper -> {
for (BlockChangeRecord record : packetWrapper.get(Type.BLOCK_CHANGE_RECORD_ARRAY, 0)) {
int replacedCombined = ReplacementRegistry1_8to1_9.replace(record.getBlockId());
int replacedCombined = protocol.getItemRewriter().replace(record.getBlockId());
record.setBlockId(replacedCombined);
}
});
@@ -142,7 +132,7 @@ public class WorldPackets {
packetWrapper.set(Type.STRING, 0, name);
}
});
map(Type.VAR_INT, Type.NOTHING);
read(Type.VAR_INT);
map(Type.INT);
map(Type.INT);
map(Type.INT);
@@ -179,10 +169,12 @@ public class WorldPackets {
@Override
public void register() {
handler(packetWrapper -> {
int chunkX = packetWrapper.read(Type.INT);
int chunkZ = packetWrapper.read(Type.INT);
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
packetWrapper.write(new Chunk1_8Type(world), new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], null, new ArrayList<>()));
final Environment environment = packetWrapper.user().get(ClientWorld.class).getEnvironment();
final int chunkX = packetWrapper.read(Type.INT);
final int chunkZ = packetWrapper.read(Type.INT);
packetWrapper.write(ChunkType1_8.forEnvironment(environment), new BaseChunk(chunkX, chunkZ, true, false, 0, new ChunkSection[16], null, new ArrayList<>()));
});
}
});
@@ -192,22 +184,22 @@ public class WorldPackets {
@Override
public void register() {
handler(packetWrapper -> {
ClientWorld world = packetWrapper.user().get(ClientWorld.class);
final Environment environment = packetWrapper.user().get(ClientWorld.class).getEnvironment();
Chunk chunk = packetWrapper.read(new Chunk1_9_1_2Type(world));
Chunk chunk = packetWrapper.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 = ReplacementRegistry1_8to1_9.replace(block);
int replacedBlock = protocol.getItemRewriter().replace(block);
palette.setIdByIndex(i, replacedBlock);
}
}
if (chunk.isFullChunk() && chunk.getBitmask() == 0) { //This would be an unload packet for 1.8 clients. Just set one air section
boolean skylight = world.getEnvironment() == Environment.NORMAL;
boolean skylight = environment == Environment.NORMAL;
ChunkSection[] sections = new ChunkSection[16];
ChunkSection section = new ChunkSectionImpl(true);
sections[0] = section;
@@ -216,7 +208,7 @@ public class WorldPackets {
chunk = new BaseChunk(chunk.getX(), chunk.getZ(), true, false, 1, sections, chunk.getBiomeData(), chunk.getBlockEntities());
}
packetWrapper.write(new Chunk1_8Type(world), chunk);
packetWrapper.write(ChunkType1_8.forEnvironment(environment), chunk);
final UserConnection user = packetWrapper.user();
chunk.getBlockEntities().forEach(nbt -> {
@@ -250,7 +242,7 @@ public class WorldPackets {
}
PacketWrapper updateTileEntity = PacketWrapper.create(0x09, null, user);
updateTileEntity.write(Type.POSITION, position);
updateTileEntity.write(Type.POSITION1_8, position);
updateTileEntity.write(Type.UNSIGNED_BYTE, action);
updateTileEntity.write(Type.NBT, nbt);
@@ -265,7 +257,7 @@ public class WorldPackets {
@Override
public void register() {
map(Type.INT);
map(Type.POSITION);
map(Type.POSITION1_8);
map(Type.INT);
map(Type.BOOLEAN);
handler(packetWrapper -> {
@@ -277,7 +269,7 @@ public class WorldPackets {
}
packetWrapper.set(Type.INT, 0, id);
if (id == 2001) {
int replacedBlock = ReplacementRegistry1_8to1_9.replace(packetWrapper.get(Type.INT, 1));
int replacedBlock = protocol.getItemRewriter().replace(packetWrapper.get(Type.INT, 1));
packetWrapper.set(Type.INT, 1, replacedBlock);
}
});
@@ -314,7 +306,7 @@ public class WorldPackets {
public void register() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.BOOLEAN, Type.NOTHING);
read(Type.BOOLEAN);
}
});
@@ -0,0 +1,63 @@
package com.viaversion.viarewind.protocol.protocol1_8to1_9.rewriter;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
import java.util.HashMap;
import java.util.Map;
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<>();
static {
POTION_NAME_TO_ID.putAll(ItemRewriter.POTION_NAME_TO_ID);
POTION_NAME_TO_ID.put("luck", 8203);
POTION_NAME_INDEX.put("water", "§rWater Bottle");
POTION_NAME_INDEX.put("mundane", "§rMundane Potion");
POTION_NAME_INDEX.put("thick", "§rThick Potion");
POTION_NAME_INDEX.put("awkward", "§rAwkward Potion");
POTION_NAME_INDEX.put("water_splash", "§rSplash Water Bottle");
POTION_NAME_INDEX.put("mundane_splash", "§rMundane Splash Potion");
POTION_NAME_INDEX.put("thick_splash", "§rThick Splash Potion");
POTION_NAME_INDEX.put("awkward_splash", "§rAwkward Splash Potion");
POTION_NAME_INDEX.put("water_lingering", "§rLingering Water Bottle");
POTION_NAME_INDEX.put("mundane_lingering", "§rMundane Lingering Potion");
POTION_NAME_INDEX.put("thick_lingering", "§rThick Lingering Potion");
POTION_NAME_INDEX.put("awkward_lingering", "§rAwkward Lingering Potion");
POTION_NAME_INDEX.put("night_vision_lingering", "§rLingering Potion of Night Vision");
POTION_NAME_INDEX.put("long_night_vision_lingering", "§rLingering Potion of Night Vision");
POTION_NAME_INDEX.put("invisibility_lingering", "§rLingering Potion of Invisibility");
POTION_NAME_INDEX.put("long_invisibility_lingering", "§rLingering Potion of Invisibility");
POTION_NAME_INDEX.put("leaping_lingering", "§rLingering Potion of Leaping");
POTION_NAME_INDEX.put("long_leaping_lingering", "§rLingering Potion of Leaping");
POTION_NAME_INDEX.put("strong_leaping_lingering", "§rLingering Potion of Leaping");
POTION_NAME_INDEX.put("fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
POTION_NAME_INDEX.put("long_fire_resistance_lingering", "§rLingering Potion of Fire Resistance");
POTION_NAME_INDEX.put("swiftness_lingering", "§rLingering Potion of Swiftness");
POTION_NAME_INDEX.put("long_swiftness_lingering", "§rLingering Potion of Swiftness");
POTION_NAME_INDEX.put("strong_swiftness_lingering", "§rLingering Potion of Swiftness");
POTION_NAME_INDEX.put("slowness_lingering", "§rLingering Potion of Slowness");
POTION_NAME_INDEX.put("long_slowness_lingering", "§rLingering Potion of Slowness");
POTION_NAME_INDEX.put("water_breathing_lingering", "§rLingering Potion of Water Breathing");
POTION_NAME_INDEX.put("long_water_breathing_lingering", "§rLingering Potion of Water Breathing");
POTION_NAME_INDEX.put("healing_lingering", "§rLingering Potion of Healing");
POTION_NAME_INDEX.put("strong_healing_lingering", "§rLingering Potion of Healing");
POTION_NAME_INDEX.put("harming_lingering", "§rLingering Potion of Harming");
POTION_NAME_INDEX.put("strong_harming_lingering", "§rLingering Potion of Harming");
POTION_NAME_INDEX.put("poison_lingering", "§rLingering Potion of Poisen");
POTION_NAME_INDEX.put("long_poison_lingering", "§rLingering Potion of Poisen");
POTION_NAME_INDEX.put("strong_poison_lingering", "§rLingering Potion of Poisen");
POTION_NAME_INDEX.put("regeneration_lingering", "§rLingering Potion of Regeneration");
POTION_NAME_INDEX.put("long_regeneration_lingering", "§rLingering Potion of Regeneration");
POTION_NAME_INDEX.put("strong_regeneration_lingering", "§rLingering Potion of Regeneration");
POTION_NAME_INDEX.put("strength_lingering", "§rLingering Potion of Strength");
POTION_NAME_INDEX.put("long_strength_lingering", "§rLingering Potion of Strength");
POTION_NAME_INDEX.put("strong_strength_lingering", "§rLingering Potion of Strength");
POTION_NAME_INDEX.put("weakness_lingering", "§rLingering Potion of Weakness");
POTION_NAME_INDEX.put("long_weakness_lingering", "§rLingering Potion of Weakness");
POTION_NAME_INDEX.put("luck_lingering", "§rLingering Potion of Luck");
POTION_NAME_INDEX.put("luck", "§rPotion of Luck");
POTION_NAME_INDEX.put("luck_splash", "§rSplash Potion of Luck");
}
}
@@ -0,0 +1,314 @@
/*
* This file is part of ViaRewind - https://github.com/ViaVersion/ViaRewind
* Copyright (C) 2016-2023 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viarewind.protocol.protocol1_8to1_9.rewriter;
import com.viaversion.viarewind.protocol.protocol1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viarewind.api.rewriter.item.Replacement;
import com.viaversion.viarewind.api.rewriter.item.ReplacementItemRewriter;
import com.viaversion.viarewind.utils.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.*;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter;
import java.util.ArrayList;
import java.util.List;
import static com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter.potionNameFromDamage;
public class ReplacementItemRewriter1_8 extends ReplacementItemRewriter<Protocol1_8To1_9> {
public final static String VIA_REWIND_TAG_KEY = "ViaRewind1_8to1_9";
public ReplacementItemRewriter1_8(Protocol1_8To1_9 protocol) {
super(protocol, ProtocolVersion.v1_9);
}
@Override
public void register() {
registerItem(198, new Replacement(50, 0, "End Rod"));
registerItem(434, new Replacement(391, "Beetroot"));
registerItem(435, new Replacement(361, "Beetroot Seeds"));
registerItem(436, new Replacement(282, "Beetroot Soup"));
registerItem(432, new Replacement(322, "Chorus Fruit"));
registerItem(433, new Replacement(393, "Popped Chorus Fruit"));
registerItem(437, new Replacement(373, "Dragons Breath"));
registerItem(443, new Replacement(299, "Elytra"));
registerItem(426, new Replacement(410, "End Crystal"));
registerItem(442, new Replacement(425, "Shield"));
registerItem(439, new Replacement(262, "Spectral Arrow"));
registerItem(440, new Replacement(262, "Tipped Arrow"));
registerItem(444, new Replacement(333, "Spruce Boat"));
registerItem(445, new Replacement(333, "Birch Boat"));
registerItem(446, new Replacement(333, "Jungle Boat"));
registerItem(447, new Replacement(333, "Acacia Boat"));
registerItem(448, new Replacement(333, "Dark Oak Boat"));
registerItem(204, new Replacement(43, 7, "Purpur Double Slab"));
registerItem(205, new Replacement(44, 7, "Purpur Slab"));
registerBlock(209, new Replacement(119));
registerBlock(198, 0, new Replacement(50, 5));
registerBlock(198, 1, new Replacement(50, 5));
registerBlock(198, 2, new Replacement(50, 4));
registerBlock(198, 3, new Replacement(50, 3));
registerBlock(198, 4, new Replacement(50, 2));
registerBlock(198, 5, new Replacement(50, 1));
registerBlock(204, new Replacement(43, 7));
registerBlock(205, 0, new Replacement(44, 7));
registerBlock(205, 8, new Replacement(44, 15));
registerBlock(207, new Replacement(141));
registerBlock(137, new Replacement(137, 0));
registerItemBlock(199, new Replacement(35, 10, "Chorus Plant"));
registerItemBlock(200, new Replacement(35, 2, "Chorus Flower"));
registerItemBlock(201, new Replacement(155, 0, "Purpur Block"));
registerItemBlock(202, new Replacement(155, 2, "Purpur Pillar"));
registerItemBlock(203, 0, new Replacement(156, 0, "Purpur Stairs"));
registerItemBlock(203, 1, new Replacement(156, 1, "Purpur Stairs"));
registerItemBlock(203, 2, new Replacement(156, 2, "Purpur Stairs"));
registerItemBlock(203, 3, new Replacement(156, 3, "Purpur Stairs"));
registerItemBlock(203, 4, new Replacement(156, 4, "Purpur Stairs"));
registerItemBlock(203, 5, new Replacement(156, 5, "Purpur Stairs"));
registerItemBlock(203, 6, new Replacement(156, 6, "Purpur Stairs"));
registerItemBlock(203, 7, new Replacement(156, 7, "Purpur Stairs"));
registerItemBlock(203, 8, new Replacement(156, 8, "Purpur Stairs"));
registerItemBlock(206, new Replacement(121, 0, "Endstone Bricks"));
registerItemBlock(207, new Replacement(141, "Beetroot Block"));
registerItemBlock(208, new Replacement(2, 0, "Grass Path"));
registerItemBlock(209, new Replacement(90, "End Gateway"));
registerItemBlock(210, new Replacement(137, 0, "Repeating Command Block"));
registerItemBlock(211, new Replacement(137, 0, "Chain Command Block"));
registerItemBlock(212, new Replacement(79, 0, "Frosted Ice"));
registerItemBlock(214, new Replacement(87, 0, "Nether Wart Block"));
registerItemBlock(215, new Replacement(112, 0, "Red Nether Brick"));
registerItemBlock(217, new Replacement(166, 0, "Structure Void"));
registerItemBlock(255, new Replacement(137, 0, "Structure Block"));
registerItemBlock(397, 5, new Replacement(397, 0, "Dragon Head"));
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (tag == null) item.setTag(tag = new CompoundTag());
CompoundTag viaVersionTag = new CompoundTag();
tag.put(VIA_REWIND_TAG_KEY, viaVersionTag);
viaVersionTag.put("id", new ShortTag((short) item.identifier()));
viaVersionTag.put("data", new ShortTag(item.data()));
CompoundTag display = tag.get("display");
if (display != null && display.contains("Name")) {
viaVersionTag.put("displayName", new StringTag((String) display.get("Name").getValue()));
}
if (display != null && display.contains("Lore")) {
viaVersionTag.put("lore", new ListTag(((ListTag) display.get("Lore")).getValue()));
}
if (tag.contains("ench") || tag.contains("StoredEnchantments")) {
ListTag enchTag = tag.contains("ench") ? tag.get("ench") : tag.get("StoredEnchantments");
List<Tag> lore = new ArrayList<>();
for (Tag ench : new ArrayList<>(enchTag.getValue())) {
short id = ((NumberTag) ((CompoundTag) ench).get("id")).asShort();
short lvl = ((NumberTag) ((CompoundTag) ench).get("lvl")).asShort();
String s;
if (id == 70) {
s = "§r§7Mending ";
} else if (id == 9) {
s = "§r§7Frost Walker ";
} else {
continue;
}
enchTag.remove(ench);
s += Enchantments.ENCHANTMENTS.getOrDefault(lvl, "enchantment.level." + lvl);
lore.add(new StringTag(s));
}
if (!lore.isEmpty()) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
lore.addAll(loreTag.getValue());
loreTag.setValue(lore);
}
}
if (item.data() != 0 && tag.contains("Unbreakable")) {
ByteTag unbreakable = tag.get("Unbreakable");
if (unbreakable.asByte() != 0) {
viaVersionTag.put("Unbreakable", new ByteTag(unbreakable.asByte()));
tag.remove("Unbreakable");
if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
ListTag loreTag = display.get("Lore");
if (loreTag == null) display.put("Lore", loreTag = new ListTag(StringTag.class));
loreTag.add(new StringTag("§9Unbreakable"));
}
}
if (tag.contains("AttributeModifiers")) {
viaVersionTag.put("AttributeModifiers", tag.get("AttributeModifiers").clone());
}
if (item.identifier() == 383 && item.data() == 0) {
int data = 0;
if (tag.contains("EntityTag")) {
CompoundTag entityTag = tag.get("EntityTag");
if (entityTag.contains("id")) {
StringTag id = entityTag.get("id");
if (ItemRewriter.ENTITY_NAME_TO_ID.containsKey(id.getValue())) {
data = ItemRewriter.ENTITY_NAME_TO_ID.get(id.getValue());
} else if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
display.put("Name", new StringTag("§rSpawn " + id.getValue()));
}
}
}
item.setData((short) data);
}
replace(item);
if (item.identifier() == 373 || item.identifier() == 438 || item.identifier() == 441) {
int data = 0;
if (tag.contains("Potion")) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (PotionMappings.POTION_NAME_TO_ID.containsKey(potionName)) {
data = PotionMappings.POTION_NAME_TO_ID.get(potionName);
}
if (item.identifier() == 438) potionName += "_splash";
else if (item.identifier() == 441) potionName += "_lingering";
if ((display == null || !display.contains("Name")) && PotionMappings.POTION_NAME_INDEX.containsKey(potionName)) {
if (display == null) {
tag.put("display", display = new CompoundTag());
viaVersionTag.put("noDisplay", new ByteTag());
}
display.put("Name", new StringTag(PotionMappings.POTION_NAME_INDEX.get(potionName)));
}
}
if (item.identifier() == 438 || item.identifier() == 441) {
item.setIdentifier(373);
data += 8192;
}
item.setData((short) data);
}
if (tag.contains("AttributeModifiers")) {
ListTag attributes = tag.get("AttributeModifiers");
for (int i = 0; i < attributes.size(); i++) {
CompoundTag attribute = attributes.get(i);
String name = (String) attribute.get("AttributeName").getValue();
if (!Protocol1_8To1_9.VALID_ATTRIBUTES.contains(name)) {
attributes.remove(attribute);
i--;
}
}
}
if (viaVersionTag.size() == 2 && (short) viaVersionTag.get("id").getValue() == item.identifier() && (short) viaVersionTag.get("data").getValue() == item.data()) {
item.tag().remove(VIA_REWIND_TAG_KEY);
if (item.tag().isEmpty()) item.setTag(null);
}
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
CompoundTag tag = item.tag();
if (item.identifier() == 383 && item.data() != 0) {
if (tag == null) item.setTag(tag = new CompoundTag());
if (!tag.contains("EntityTag") && ItemRewriter.ENTITY_ID_TO_NAME.containsKey((int) item.data())) {
CompoundTag entityTag = new CompoundTag();
entityTag.put("id", new StringTag(ItemRewriter.ENTITY_ID_TO_NAME.get((int) item.data())));
tag.put("EntityTag", entityTag);
}
item.setData((short) 0);
}
if (item.identifier() == 373 && (tag == null || !tag.contains("Potion"))) {
if (tag == null) item.setTag(tag = new CompoundTag());
if (item.data() >= 16384) {
item.setIdentifier(438);
item.setData((short) (item.data() - 8192));
}
String name = item.data() == 8192 ? "water" : potionNameFromDamage(item.data());
tag.put("Potion", new StringTag("minecraft:" + name));
item.setData((short) 0);
}
if (tag == null || !item.tag().contains("ViaRewind1_8to1_9")) return item;
CompoundTag viaVersionTag = tag.remove("ViaRewind1_8to1_9");
item.setIdentifier((short) viaVersionTag.get("id").getValue());
item.setData((Short) viaVersionTag.get("data").getValue());
if (viaVersionTag.contains("noDisplay")) tag.remove("display");
if (viaVersionTag.contains("Unbreakable")) {
tag.put("Unbreakable", viaVersionTag.get("Unbreakable").clone());
}
if (viaVersionTag.contains("displayName")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
StringTag name = display.get("Name");
if (name == null) display.put("Name", new StringTag((String) viaVersionTag.get("displayName").getValue()));
else name.setValue((String) viaVersionTag.get("displayName").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Name");
}
if (viaVersionTag.contains("lore")) {
CompoundTag display = tag.get("display");
if (display == null) tag.put("display", display = new CompoundTag());
ListTag lore = display.get("Lore");
if (lore == null) display.put("Lore", new ListTag((List<Tag>) viaVersionTag.get("lore").getValue()));
else lore.setValue((List<Tag>) viaVersionTag.get("lore").getValue());
} else if (tag.contains("display")) {
((CompoundTag) tag.get("display")).remove("Lore");
}
tag.remove("AttributeModifiers");
if (viaVersionTag.contains("AttributeModifiers")) {
tag.put("AttributeModifiers", viaVersionTag.get("AttributeModifiers"));
}
return item;
}
}
@@ -21,7 +21,7 @@ package com.viaversion.viarewind.protocol.protocol1_8to1_9.sound;
import java.util.HashMap;
public class Effect {
private static final HashMap<Integer, Integer> effects = new HashMap<>();
private final static HashMap<Integer, Integer> effects = new HashMap<>();
public static int getOldId(int id) {
return effects.getOrDefault(id, id);
@@ -21,8 +21,8 @@ package com.viaversion.viarewind.protocol.protocol1_8to1_9.sound;
import java.util.HashMap;
public class SoundRemapper {
private static final HashMap<Integer, String> sounds1_9 = new HashMap<>();
private static final HashMap<String, String> sound1_9to1_8 = new HashMap<>();
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) {
@@ -35,7 +35,7 @@ public class SoundRemapper {
public static String oldNameFromId(int id) {
String sound1_9 = sounds1_9.get(id);
if (sound1_9==null) return null;
if (sound1_9 == null) return null;
return getOldName(sound1_9);
}
@@ -38,12 +38,12 @@ public class BlockPlaceDestroyTracker extends StoredObject {
}
public boolean isMining() {
long time = System.currentTimeMillis()-lastMining;
long time = System.currentTimeMillis() - lastMining;
return time < 75;
}
public void setMining(boolean mining) {
this.mining = mining && getUser().get(EntityTracker.class).getPlayerGamemode()!=1;
this.mining = mining && getUser().get(EntityTracker.class).getPlayerGamemode() != 1;
lastMining = System.currentTimeMillis();
}
@@ -43,7 +43,7 @@ public class BossBarStorage extends StoredObject {
public void remove(UUID uuid) {
WitherBossBar bossBar = bossBars.remove(uuid);
if (bossBar==null) return;
if (bossBar == null) return;
bossBar.hide();
}
@@ -61,13 +61,13 @@ public class BossBarStorage extends StoredObject {
public void updateHealth(UUID uuid, float health) {
WitherBossBar bossBar = bossBars.get(uuid);
if (bossBar==null) return;
if (bossBar == null) return;
bossBar.setHealth(health);
}
public void updateTitle(UUID uuid, String title) {
WitherBossBar bossBar = bossBars.get(uuid);
if (bossBar==null) return;
if (bossBar == null) return;
bossBar.setTitle(title);
}
}
Loaded 100 of 123 files, more files were not shown because too many files have changed in this diff. Show more