Compare commits

..
53 Commits
Author SHA1 Message Date
Myles 4cdfd72700 Ensure no bytes are left on the bytebufs and ensure it is cancelled properly. Update Version to 0.4.2 2016-03-02 18:41:47 +00:00
Myles ccd6987f11 Bump to 0.4.1, Fixes bungee issues :) (Some chunk stuff, me being an idiot) 2016-03-02 17:03:32 +00:00
Myles 6c96271925 Bump the version, we now support ProtocolLib (hopefully it works properly) 2016-03-02 15:26:32 +00:00
Myles 318db73f3c This is a huge commit, adds ProtocolLib support. (To the best extent I can):
Channels now work as proxies for the minecraft encoder and decoder, this allows better compatibility when transforming packets.
ConnectionInfo now holds an activate state to deactivate.
Now only 2 handlers
We now use info.getChannel().pipeline().writeAndFlush to ensure we catch it ourselves.
Fix EntityMetadata from last commit so it sends empty metadata instead of cancelling whole packet.
Warn if they reload and don't reinject.
2016-03-02 15:21:07 +00:00
Myles b5b0117fa9 Merge pull request #36 from Mystalion/drop-metadata
Drop MetadataPacket where metadata could not be rewritten
2016-03-02 14:45:50 +00:00
Paulomart 79e5555d42 Drop MetadataPacket where metadata could not be rewritten 2016-03-02 13:31:15 +01:00
Myles 114a7b6bd6 Format some lines properly 2016-03-02 10:19:36 +00:00
Myles 8e6d76296d Update contributors 2016-03-02 10:16:27 +00:00
Myles 153a68bf06 Credits to @SanderGielisse, change how netty information is stored so it's not constant and is now attached to ConnectionInfo 2016-03-02 10:12:43 +00:00
Myles 6199e1d8ce Correct last commit to make it work. 2016-03-02 10:09:04 +00:00
Myles 0db43e612e Merge pull request #25 from HugoDaBosss/master
Fix USE_ITEM using correct item. Fix SPAWN_OBJECT velocity.
2016-03-02 10:07:09 +00:00
Myles 06296ead77 Merge pull request #32 from StamBoom/master
Fix TabList header/footer gives (By non-json Strings) MalformedJsonException
2016-03-02 10:05:26 +00:00
Mats dac9bd58e5 Fix TabList header/footer gives (By non-json Strings) MalformedJsonException 2016-03-02 10:27:17 +01:00
Myles 8e0833ca6b Fix nether & end #30 bump to 0.3.7 2016-03-02 00:23:33 +00:00
Myles 88086e00d0 Bump to 0.3.6 2016-03-02 00:09:12 +00:00
Myles 9368347b56 Fix chat which is not got proper JSON 2016-03-01 23:35:16 +00:00
Myles 6828425d72 Update version to 0.3.5 2016-03-01 23:16:49 +00:00
Myles f9da275358 Fix lightning, track entities sent to the client and use them for mapping MetaIndex instead of previous method. (Allows custom entities and client side packets properly. Echo Pet works!!! + fixes some latency with methods) 2016-03-01 23:16:10 +00:00
Myles 1445bd37c3 Remove unused method from MetaIndex 2016-03-01 23:15:08 +00:00
Myles 2de176e55c Fixed guardian info. 2016-03-01 23:09:55 +00:00
Myles b785fe0515 Add EntityUtil & move utils to util package. 2016-03-01 23:09:29 +00:00
Myles 984176d53b Merge pull request #27 from Mystalion/api
Reflector Main Class and add API framework.
2016-03-01 21:43:44 +00:00
Paulomart bd46c3f5a0 Reflector Main Class and add API framework. 2016-03-01 22:28:18 +01:00
Myles 0209c51d10 Merge pull request #26 from Mystalion/fix-paintings
Fix support for paintings, also add a read and write position method.
2016-03-01 20:56:13 +00:00
Paulomart 3425ed94e0 Fix support for paintings, also add a read and write position method. 2016-03-01 21:38:35 +01:00
Myles 8ceee31299 Fix JSON for title packet, #24. Also implement method for generic JSON fixing woo! 2016-03-01 19:20:54 +00:00
HugoDaBosss db9cd296ee Fix USE_ITEM using correct item. Fix SPAWN_OBJECT velocity. 2016-03-01 19:56:48 +01:00
Myles 6b3fb6424c Update version to 0.3.4, as it should fix JSON data bug. 2016-03-01 18:06:39 +00:00
Myles e43968c142 Merge pull request #18 from StamBoom/master
Fix MalformedJsonException when opening renamed containers
2016-03-01 17:08:47 +00:00
Myles 5c0ba593da Bump version to 0.3.3 2016-03-01 16:58:56 +01:00
Mats 1f51cf8416 Fix MalformedJsonException on opening renamed containers 2016-03-01 16:51:13 +01:00
HugoDaBosss 442d4de74b Merge pull request #1 from MylesIsCool/master
Update From Original
2016-03-01 15:47:15 +01:00
Myles 2a67301642 Bump version to 0.3.3 2016-03-01 14:40:53 +00:00
Myles 46ec24a686 Merge pull request #17 from StamBoom/master
Fixed riding on entities. (To some extent)
2016-03-01 14:35:59 +00:00
Mats 6f25090c01 Fixed riding on entities. 2016-03-01 15:28:17 +01:00
Myles dd36686f1c Merge pull request #14 from HugoDaBosss/master
Fixed: ItemFrame crash, remaining missing sounds and Horse Metadata
2016-03-01 14:24:51 +00:00
Myles 2b980a3cfc Merge pull request #13 from StamBoom/master
Fix MalformedJsonException on Kick / Disconnect
2016-03-01 14:23:50 +00:00
HugoDaBosss 43aaa728b5 Fix Horse Metadata Error 2016-03-01 15:09:21 +01:00
HugoDaBosss 45dfe7261b Added remaining missing sounds 2016-03-01 14:48:00 +01:00
Mats 7831dc0082 Fix MalformedJsonException on Kick / Disconnect 2016-03-01 14:25:26 +01:00
HugoDaBosss ba4e6e5d2f Fixed ItemFrame crash 2016-03-01 14:24:58 +01:00
Myles 68bfaf6d23 Tiny bit of bracket reformatting just for format consistency 2016-03-01 11:00:06 +00:00
Myles 954dfb74e5 Refactor sounds into its own package, update README and version to 0.3.2 (Now with working sounds, thanks HugoDaBosss!) 2016-03-01 10:58:39 +00:00
Myles f95e7f98b7 Merge pull request #9 from HugoDaBosss/master
Added support for named sound effect packet.
2016-03-01 10:54:25 +00:00
Myles aabd79e6c7 Force entity meta data remapper to check all non living entity metadata first. (Fixes ArmorStands) 2016-03-01 10:50:21 +00:00
HugoDaBosss db7daaa6ca Update OutgoingTransformer.java 2016-03-01 11:48:52 +01:00
HugoDaBosss b66ea090c2 Added support for named sound effect packet. 2016-03-01 11:43:34 +01:00
Myles ad3317f8d8 Update version number 2016-02-29 22:51:46 +00:00
Myles 3b480a61bd Correct boots so they display correctly 2016-02-29 22:48:29 +00:00
Myles c0296f04a1 Allow sharing of protocol packet handler and be more verbose to do with metaindex data 2016-02-29 22:43:53 +00:00
Myles 6f605e8d6c Fix signs correcting any json issues. 2016-02-29 21:27:17 +00:00
Myles a6cfcac675 Merge pull request #6 from Zbob750/master
Add Spigot's maven repo, so this is actually useful.
2016-02-29 20:50:07 +00:00
Zach Brown 8e717bb023 Add Spigot's maven repo, so this is actually useful 2016-02-29 14:38:54 -06:00
24 changed files with 1141 additions and 515 deletions

No files matched your search

+11 -4
View File
@@ -1,9 +1,9 @@
# ViaVersion 0.3
# ViaVersion 0.4.2
**Allows the connection of 1.8 clients to 1.9**
This plugin modifies netty to allow connection of 1.9 clients to 1.8,
**Don't use late bind nor ProtocolLib**
**Don't use late bind*
**As of this point it doesn't have everything, I need to fix:**
@@ -11,22 +11,29 @@ Attempt to make boats nicer when they don't work
Remap spawn eggs
If you have a bug with entities, please report the full stack trace
This took hours of work, so if you enjoy this consider looking into contacting me and supporting my projects.
Credits:
Sources:
--------
**wiki.vg** (Protocol info, though I did have to find a lot myself)
**MCProtocolLib** (used for chunk reading & some of writing.)
Contributors:
--------
**Myself** (harhar)
**Matsv** (Movement Fix)
**Matsv/StamBoom**
**HugoDaBosss**
**SanderGielisse**
License:
--------
+7 -2
View File
@@ -45,5 +45,10 @@
<scope>provided</scope>
</dependency>
</dependencies>
</project>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
</project>
@@ -1,7 +1,7 @@
package org.spacehq.mc.protocol.data.game.chunk;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.PacketUtil;
import us.myles.ViaVersion.util.PacketUtil;
import java.io.IOException;
import java.util.ArrayList;
@@ -39,7 +39,7 @@ public class NetUtil {
public static Column readOldChunkData(int x, int z, boolean isFullChunk, int bitmask, byte[] input, boolean checkForSky, boolean hasSkyLight) {
int pos = 0;
int expected = 0;
int expected = isFullChunk ? 256 : 0;
boolean sky = false;
ShortBuffer buf = ByteBuffer.wrap(input).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
// 0 = Calculate expected length and determine if the packet has skylight.
@@ -85,7 +85,7 @@ public class NetUtil {
}
if(pass == 3) {
if(chunks[ind].getSkyLight() != null) {
if(sky) {
NibbleArray3d skylight = chunks[ind].getSkyLight();
System.arraycopy(input, pos, skylight.getData(), 0, skylight.getData().length);
pos += skylight.getData().length;
@@ -1,5 +1,6 @@
package us.myles.ViaVersion;
import io.netty.channel.socket.SocketChannel;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.packets.State;
@@ -7,11 +8,17 @@ import us.myles.ViaVersion.packets.State;
import java.util.UUID;
public class ConnectionInfo {
private int protocol = 0;
private State state = State.HANDSHAKE;
private int compression = 0;
private final SocketChannel channel;
private Object lastPacket;
private java.util.UUID UUID;
private State state = State.HANDSHAKE;
private int protocol = 0;
private int compression = 0;
private boolean active = true;
public ConnectionInfo(SocketChannel socketChannel) {
this.channel = socketChannel;
}
public int getProtocol() {
return protocol;
@@ -56,4 +63,16 @@ public class ConnectionInfo {
public Player getPlayer() {
return UUID == null ? null : Bukkit.getPlayer(UUID);
}
public SocketChannel getChannel() {
return channel;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}
@@ -6,30 +6,52 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.ViaVersionAPI;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class Core extends JavaPlugin {
public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
private final Set<UUID> portedPlayers = Collections.newSetFromMap(new ConcurrentHashMap<UUID, Boolean>());
@Override
public void onEnable() {
System.out.println("ViaVersion enabled, injecting. (Allows 1.8 to be accessed via 1.9)");
ViaVersion.setInstance(this);
if(System.getProperty("ViaVersion") != null){
getLogger().severe("ViaVersion is already loaded, we don't support reloads. Please reboot if you wish to update.");
return;
}
getLogger().info("ViaVersion enabled, injecting. (Allows 1.8 to be accessed via 1.9)");
try {
injectPacketHandler();
System.setProperty("ViaVersion", getDescription().getVersion());
} catch (Exception e) {
if(Bukkit.getPluginManager().getPlugin("ProtocolLib") != null){
System.out.println("This plugin is not compatible with protocol lib.");
}
System.out.println("Unable to inject handlers, are you on 1.8? ");
getLogger().severe("Unable to inject handlers, are you on 1.8? ");
e.printStackTrace();
}
Bukkit.getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
setPorted(e.getPlayer().getUniqueId(), false);
}
}, this);
}
public void injectPacketHandler() throws Exception {
@@ -39,7 +61,7 @@ public class Core extends JavaPlugin {
List<ChannelFuture> futures = ReflectionUtil.get(connection, "g", List.class);
if (futures.size() == 0) {
throw new Exception("Could not find server to inject (late bind?)");
throw new Exception("Could not find server to inject (Please ensure late-bind in your spigot.yml is false)");
}
for (ChannelFuture future : futures) {
@@ -51,32 +73,22 @@ public class Core extends JavaPlugin {
}
}
@Override
public boolean isPorted(Player player) {
return portedPlayers.contains(player.getUniqueId());
}
public static Entity getEntity(final UUID player, final int id) {
try {
return Bukkit.getScheduler().callSyncMethod(getPlugin(Core.class), new Callable<Entity>() {
@Override
public Entity call() throws Exception {
Player p = Bukkit.getPlayer(player);
if (p == null) return null;
for (Entity e : p.getWorld().getEntities()) {
if (e.getEntityId() == id) {
return e;
}
}
return null;
}
}).get(10, TimeUnit.SECONDS);
} catch (Exception e) {
System.out.println("Error fetching entity ");
e.printStackTrace();
return null;
public void setPorted(UUID id, boolean value) {
if (value) {
portedPlayers.add(id);
} else {
portedPlayers.remove(id);
}
}
public static ItemStack getHandItem(final ConnectionInfo info) {
try {
return Bukkit.getScheduler().callSyncMethod(getPlugin(Core.class), new Callable<ItemStack>() {
return Bukkit.getScheduler().callSyncMethod(getPlugin(ViaVersionPlugin.class), new Callable<ItemStack>() {
@Override
public ItemStack call() throws Exception {
if (info.getPlayer() != null) {
@@ -0,0 +1,17 @@
package us.myles.ViaVersion.api;
public class ViaVersion {
private static ViaVersionAPI INSTANCE;
public static void setInstance(ViaVersionAPI api) {
if (INSTANCE != null) {
throw new IllegalStateException("Instance already set.");
}
INSTANCE = api;
}
public static ViaVersionAPI getInstance() {
return INSTANCE;
}
}
@@ -0,0 +1,8 @@
package us.myles.ViaVersion.api;
import org.bukkit.entity.Player;
public interface ViaVersionAPI {
boolean isPorted(Player player);
}
@@ -0,0 +1,54 @@
package us.myles.ViaVersion.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.transformers.IncomingTransformer;
import us.myles.ViaVersion.util.PacketUtil;
import java.util.List;
public class ViaDecodeHandler extends ByteToMessageDecoder {
private final IncomingTransformer incomingTransformer;
private final ByteToMessageDecoder minecraftDecoder;
private final ConnectionInfo info;
public ViaDecodeHandler(ConnectionInfo info, ByteToMessageDecoder minecraftDecoder) {
this.info = info;
this.minecraftDecoder = minecraftDecoder;
this.incomingTransformer = new IncomingTransformer(info);
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> list) throws Exception {
// use transformers
if (bytebuf.readableBytes() > 0) {
if (info.isActive()) {
int id = PacketUtil.readVarInt(bytebuf);
// Transform
ByteBuf newPacket = ctx.alloc().buffer();
try {
incomingTransformer.transform(id, bytebuf, newPacket);
bytebuf = newPacket;
} catch (CancelException e) {
bytebuf.readBytes(bytebuf.readableBytes());
throw e;
}
}
// call minecraft decoder
list.addAll(PacketUtil.callDecode(this.minecraftDecoder, ctx, bytebuf));
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (!(cause.getCause() instanceof CancelException)) {
if (cause instanceof Exception) {
throw (Exception) cause;
}
}
}
}
@@ -0,0 +1,80 @@
package us.myles.ViaVersion.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Constructor;
public class ViaEncodeHandler extends MessageToByteEncoder {
private final ConnectionInfo info;
private final MessageToByteEncoder minecraftEncoder;
private final OutgoingTransformer outgoingTransformer;
public ViaEncodeHandler(ConnectionInfo info, MessageToByteEncoder minecraftEncoder) {
this.info = info;
this.minecraftEncoder = minecraftEncoder;
this.outgoingTransformer = new OutgoingTransformer(info);
}
@Override
protected void encode(ChannelHandlerContext ctx, Object o, ByteBuf bytebuf) throws Exception {
// handle the packet type
if (!(o instanceof ByteBuf)) {
info.setLastPacket(o);
/* This transformer is more for fixing issues which we find hard at packet level :) */
if (o.getClass().getName().endsWith("PacketPlayOutMapChunkBulk") && info.isActive()) {
int[] locX = ReflectionUtil.get(o, "a", int[].class);
int[] locZ = ReflectionUtil.get(o, "b", int[].class);
Object world = ReflectionUtil.get(o, "world", ReflectionUtil.nms("World"));
Class<?> mapChunk = ReflectionUtil.nms("PacketPlayOutMapChunk");
Constructor constructor = mapChunk.getDeclaredConstructor(ReflectionUtil.nms("Chunk"), boolean.class, int.class);
for (int i = 0; i < locX.length; i++) {
int x = locX[i];
int z = locZ[i];
// world invoke function
Object chunk = ReflectionUtil.nms("World").getDeclaredMethod("getChunkAt", int.class, int.class).invoke(world, x, z);
Object packet = constructor.newInstance(chunk, true, 65535);
ctx.pipeline().writeAndFlush(packet);
}
bytebuf.readBytes(bytebuf.readableBytes());
throw new CancelException();
}
// call minecraft encoder
PacketUtil.callEncode(this.minecraftEncoder, ctx, o, bytebuf);
}
if (bytebuf.readableBytes() == 0) {
throw new CancelException();
}
if(info.isActive()) {
int id = PacketUtil.readVarInt(bytebuf);
// Transform
ByteBuf oldPacket = bytebuf.copy();
bytebuf.clear();
try {
outgoingTransformer.transform(id, oldPacket, bytebuf);
} catch (CancelException e) {
bytebuf.readBytes(bytebuf.readableBytes());
throw e;
} finally {
oldPacket.release();
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if(!(cause.getCause() instanceof CancelException)) {
if(cause instanceof Exception){
throw (Exception) cause;
}
}
}
}
@@ -1,53 +0,0 @@
package us.myles.ViaVersion.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.PacketUtil;
import us.myles.ViaVersion.transformers.IncomingTransformer;
@ChannelHandler.Sharable
public class ViaInboundHandler extends ChannelInboundHandlerAdapter {
private final IncomingTransformer incomingTransformer;
private final ViaVersionInitializer init;
public ViaInboundHandler(Channel c, ConnectionInfo info, ViaVersionInitializer init) {
this.init = init;
this.incomingTransformer = new IncomingTransformer(c, info, init);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
boolean compression = ctx.pipeline().get("compress") != null;
if (msg instanceof ByteBuf) {
ByteBuf bytebuf = (ByteBuf) msg;
if (compression) {
// decompress :)
bytebuf = PacketUtil.decompress(ctx, bytebuf);
}
int id = PacketUtil.readVarInt(bytebuf);
// Transform
ByteBuf newPacket = ctx.alloc().buffer();
try {
incomingTransformer.transform(id, bytebuf, newPacket);
} catch (CancelException e) {
return;
} finally {
bytebuf.release();
}
if (compression) {
// recompress :)
newPacket = PacketUtil.compress(ctx, newPacket);
}
msg = newPacket;
}
super.channelRead(ctx, msg);
}
}
@@ -1,53 +0,0 @@
package us.myles.ViaVersion.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.PacketUtil;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
@ChannelHandler.Sharable
public class ViaOutboundHandler extends ChannelOutboundHandlerAdapter {
private final OutgoingTransformer outgoingTransformer;
private final ViaVersionInitializer init;
public ViaOutboundHandler(Channel c, ConnectionInfo info, ViaVersionInitializer init) {
this.init = init;
this.outgoingTransformer = new OutgoingTransformer(c, info, init);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise channelPromise) throws Exception {
try {
if (channelPromise.isDone()) return; // don't break any <3s
boolean compression = ctx.pipeline().get("compress") != null;
if (msg instanceof ByteBuf) {
ByteBuf bytebuf = (ByteBuf) msg;
if (compression) {
// decompress :)
bytebuf = PacketUtil.decompress(ctx, bytebuf);
}
int id = PacketUtil.readVarInt(bytebuf);
// Transform
ByteBuf newPacket = ctx.alloc().buffer();
try {
outgoingTransformer.transform(id, bytebuf, newPacket);
} catch (CancelException e) {
return;
} finally {
bytebuf.release();
}
if (compression) {
// recompress :)
newPacket = PacketUtil.compress(ctx, newPacket);
}
msg = newPacket;
}
super.write(ctx, msg, channelPromise);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,45 +0,0 @@
package us.myles.ViaVersion.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.ReflectionUtil;
import java.lang.reflect.Constructor;
public class ViaOutboundPacketHandler extends ChannelOutboundHandlerAdapter {
private final ConnectionInfo info;
public ViaOutboundPacketHandler(Channel c, ConnectionInfo info) {
this.info = info;
}
@Override
public void write(ChannelHandlerContext channelHandlerContext, Object o, ChannelPromise channelPromise) throws Exception {
if (!(o instanceof ByteBuf)) {
info.setLastPacket(o);
/* This transformer is more for fixing issues which we find hard at byte level :) */
if (o.getClass().getName().endsWith("PacketPlayOutMapChunkBulk")) {
int[] locX = ReflectionUtil.get(o, "a", int[].class);
int[] locZ = ReflectionUtil.get(o, "b", int[].class);
Object world = ReflectionUtil.get(o, "world", ReflectionUtil.nms("World"));
Class<?> mapChunk = ReflectionUtil.nms("PacketPlayOutMapChunk");
Constructor constructor = mapChunk.getDeclaredConstructor(ReflectionUtil.nms("Chunk"), boolean.class, int.class);
for (int i = 0; i < locX.length; i++) {
int x = locX[i];
int z = locZ[i];
// world invoke function
Object chunk = ReflectionUtil.nms("World").getDeclaredMethod("getChunkAt", int.class, int.class).invoke(world, x, z);
Object packet = constructor.newInstance(chunk, true, 65535);
channelHandlerContext.write(packet);
}
return;
}
}
super.write(channelHandlerContext, o, channelPromise);
}
}
@@ -3,6 +3,8 @@ package us.myles.ViaVersion.handlers;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.ConnectionInfo;
import java.lang.reflect.Method;
@@ -10,11 +12,6 @@ import java.lang.reflect.Method;
public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
private final ChannelInitializer<SocketChannel> oldInit;
private Method method;
private ConnectionInfo info;
private ViaInboundHandler inbound;
private ViaOutboundHandler outbound;
private SocketChannel socketChannel;
private ViaOutboundPacketHandler outbound2;
public ViaVersionInitializer(ChannelInitializer<SocketChannel> oldInit) {
this.oldInit = oldInit;
@@ -28,24 +25,14 @@ public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
info = new ConnectionInfo();
ConnectionInfo info = new ConnectionInfo(socketChannel);
// Add originals
this.method.invoke(this.oldInit, socketChannel);
// Add our transformers
this.socketChannel = socketChannel;
this.inbound = new ViaInboundHandler(socketChannel, info, this);
this.outbound = new ViaOutboundHandler(socketChannel, info, this);
this.outbound2 = new ViaOutboundPacketHandler(socketChannel, info);
socketChannel.pipeline().addBefore("decoder", "via_incoming", this.inbound);
socketChannel.pipeline().addBefore("packet_handler", "via_outgoing2", this.outbound2);
socketChannel.pipeline().addBefore("encoder", "via_outgoing", this.outbound);
ViaEncodeHandler encoder = new ViaEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder"));
ViaDecodeHandler decoder = new ViaDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder"));
socketChannel.pipeline().replace("encoder", "encoder", encoder);
socketChannel.pipeline().replace("decoder", "decoder", decoder);
}
public void remove(){
socketChannel.pipeline().remove("via_incoming");
socketChannel.pipeline().remove("via_outgoing");
socketChannel.pipeline().remove("via_outgoing2");
}
}
@@ -1,198 +1,191 @@
package us.myles.ViaVersion.metadata;
import org.bukkit.entity.*;
public enum MetaIndex {
// entity
ENTITY_STATUS(org.bukkit.entity.Entity.class, 0, Type.Byte, NewType.Byte),
ENTITY_AIR(org.bukkit.entity.Entity.class, 1, Type.Short, NewType.VarInt),
ENTITY_SILENT(org.bukkit.entity.Entity.class, 4, Type.Byte, NewType.Boolean),
// living entity
LIVINGENTITY_NAMETAG(LivingEntity.class, 2, Type.String, NewType.String),
LIVINGENTITY_ALWAYS_SHOW_NAMETAG(LivingEntity.class, 3, Type.Byte, NewType.Boolean),
LIVINGENTITY_HEALTH(LivingEntity.class, 6, Type.Float, NewType.Float),
LIVINGENTITY_POTION_EFFECT_COLOR(LivingEntity.class, 7, Type.Int, NewType.VarInt),
LIVINGENTITY_IS_POTION_AMBIENT(LivingEntity.class, 8, Type.Byte, NewType.Boolean),
LIVINGENTITY_NUMBER_OF_ARROWS_IN(LivingEntity.class, 9, Type.Byte, NewType.VarInt),
LIVINGENTITY_NO_AI(LivingEntity.class, 15, Type.Byte, 10, NewType.Byte), // in 1.9 this is combined with Left handed, oh.
// ageable
AGEABLE_AGE(Ageable.class, 12, Type.Byte, 11, NewType.Boolean),
// armour stand
STAND_INFO(ArmorStand.class, 10, Type.Byte, NewType.Byte),
STAND_HEAD_POS(ArmorStand.class, 11, Type.Rotation, NewType.Vector3F),
STAND_BODY_POS(ArmorStand.class, 12, Type.Rotation, NewType.Vector3F),
STAND_LA_POS(ArmorStand.class, 13, Type.Rotation, NewType.Vector3F),
STAND_RA_POS(ArmorStand.class, 14, Type.Rotation, NewType.Vector3F),
STAND_LL_POS(ArmorStand.class, 15, Type.Rotation, NewType.Vector3F),
STAND_RL_POS(ArmorStand.class, 16, Type.Rotation, NewType.Vector3F),
// human, discountined?
PLAYER_SKIN_FLAGS(HumanEntity.class, 10, Type.Byte, NewType.Discontinued), // unsigned on 1.8
PLAYER_HUMAN_BYTE(HumanEntity.class, 16, Type.Byte, NewType.Discontinued), // unused on 1.8
PLAYER_ADDITIONAL_HEARTS(HumanEntity.class, 17, Type.Float, NewType.Discontinued),
PLAYER_SCORE(HumanEntity.class, 18, Type.Int, NewType.Discontinued),
// horse
HORSE_INFO(Horse.class, 16, Type.Int, 12, NewType.Byte),
HORSE_TYPE(Horse.class, 19, Type.Byte, 13, NewType.VarInt),
HORSE_SUBTYPE(Horse.class, 20, Type.Int, 14, NewType.VarInt),
HORSE_OWNER(Horse.class, 21, Type.String, 15, NewType.OptUUID),
HORSE_ARMOR(Horse.class, 22, Type.Int, 16, NewType.VarInt),
// bat
BAT_ISHANGING(Bat.class, 16, Type.Byte, 11, NewType.Byte),
// tameable
TAMING_INFO(Tameable.class, 16, Type.Byte, 12, NewType.Byte),
TAMING_OWNER(Tameable.class, 17, Type.String, 13, NewType.OptUUID),
// ocelot
OCELOT_TYPE(Ocelot.class, 18, Type.Byte, 14, NewType.VarInt),
// wolf
WOLF_HEALTH(Wolf.class, 18, Type.Float, 14, NewType.Float),
WOLF_BEGGING(Wolf.class, 19, Type.Byte, 15, NewType.Boolean),
WOLF_COLLAR(Wolf.class, 20, Type.Byte, 16, NewType.VarInt),
// pig
PIG_SADDLE(Pig.class, 16, Type.Byte, 12, NewType.Boolean),
// rabbit
RABBIT_TYPE(Rabbit.class, 18, Type.Byte, 12, NewType.VarInt),
// sheep
SHEEP_COLOR(Sheep.class, 16, Type.Byte, 12, NewType.Byte),
// villager
VILLAGER_PROFESSION(Villager.class, 16, Type.Int, 12, NewType.VarInt), // TODO write this to wiki.vg
// enderman
ENDERMAN_BLOCK(Enderman.class, 16, Type.Short, 11, NewType.BlockID), // special case
ENDERMAN_BLOCKDATA(Enderman.class, 17, Type.Byte, 11, NewType.BlockID), // special case
ENDERMAN_ISSCREAMING(Enderman.class, 18, Type.Byte, 12, NewType.Boolean),
// zombie
ZOMBIE_ISCHILD(Zombie.class, 12, Type.Byte, 11, NewType.Boolean),
ZOMBIE_ISVILLAGER(Zombie.class, 13, Type.Byte, 12, NewType.VarInt),
ZOMBIE_ISCONVERTING(Zombie.class, 14, Type.Byte, 13, NewType.Boolean),
// ZOMBIE_RISINGHANDS added in 1.9
// blaze
BLAZE_ONFIRE(Blaze.class, 16, Type.Byte, 11, NewType.Byte),
// spider
SPIDER_CIMBING(Spider.class, 16, Type.Byte, 11, NewType.Byte),
// creeper
CREEPER_FUSE(Creeper.class, 16, Type.Byte, 11, NewType.VarInt), // -1 idle, 1 is fuse
CREEPER_ISPOWERED(Creeper.class, 17, Type.Byte, 12, NewType.Boolean),
CREEPER_ISIGNITED(Creeper.class, 18, Type.Byte, 13, NewType.Boolean), // TODO: Write on wiki.vg for current prot
// ghast
GHAST_ISATTACKING(Ghast.class, 16, Type.Byte, 11, NewType.Boolean),
// slime
SLIME_SIZE(Slime.class, 16, Type.Byte, 11, NewType.VarInt),
// skeleton
SKELETON_TYPE(Skeleton.class, 13, Type.Byte, 11, NewType.VarInt),
// witch
WITCH_AGGRO(Witch.class, 21, Type.Byte, 11, NewType.Boolean),
// iron golem
IRON_PLAYERMADE(IronGolem.class, 16, Type.Byte, 11, NewType.Byte),
// wither
WITHER_TARGET1(Wither.class, 17, Type.Int, 11, NewType.VarInt),
WITHER_TARGET2(Wither.class, 18, Type.Int, 12, NewType.VarInt),
WITHER_TARGET3(Wither.class, 19, Type.Int, 13, NewType.VarInt),
WITHER_INVULN_TIME(Wither.class, 20, Type.Int, 14, NewType.VarInt),
// guardian
GUARDIAN_INFO(Guardian.class, 16, Type.Byte, 11, NewType.Byte),
GUARDIAN_TARGET(Guardian.class, 17, Type.Int, 12, NewType.VarInt),
// boat
BOAT_SINCEHIT(Boat.class, 17, Type.Int, 5, NewType.VarInt),
BOAT_FORWARDDIR(Boat.class, 18, Type.Int, 6, NewType.VarInt),
BOAT_DMGTAKEN(Boat.class, 19, Type.Float, 7, NewType.Float),
// BOAT_TYPE in 1.9
// minecart
MINECART_SHAKINGPOWER(Minecart.class, 17, Type.Int, 5, NewType.VarInt),
MINECART_SHAKINGDIRECTION(Minecart.class, 18, Type.Int, 6, NewType.VarInt),
MINECART_DAMAGETAKEN(Minecart.class, 19, Type.Float, 7, NewType.Float), // also shaking modifier :P
MINECART_BLOCK(Minecart.class, 20, Type.Int, 8, NewType.VarInt),
MINECART_BLOCK_Y(Minecart.class, 21, Type.Int, 9, NewType.VarInt),
MINECART_SHOWBLOCK(Minecart.class, 22, Type.Byte, 10, NewType.Boolean),
// furnace cart
FURNACECART_ISPOWERED(org.bukkit.entity.minecart.PoweredMinecart.class, 16, Type.Byte, 11, NewType.Boolean),
// item drop
ITEM_ITEM(Item.class, 10, Type.Slot, 5, NewType.Slot),
// arrow
ARROW_ISCRIT(Arrow.class, 16, Type.Byte, 5, NewType.Byte),
// firework
FIREWORK_INFO(Firework.class, 8, Type.Slot, 5, NewType.Slot),
// item frame
ITEMFRAME_ITEM(ItemFrame.class, 8, Type.Slot, 5, NewType.Slot),
ITEMFRAME_ROTATION(ItemFrame.class, 9, Type.Byte, 5, NewType.VarInt),
// ender crystal
ENDERCRYSTAL_HEALTH(EnderCrystal.class, 8, Type.Int, NewType.Discontinued),;
private Class<?> clazz;
private int newIndex;
private NewType newType;
private Type oldType;
private int index;
MetaIndex(Class<?> type, int index, Type oldType, NewType newType) {
this.clazz = type;
this.index = index;
this.newIndex = index;
this.oldType = oldType;
this.newType = newType;
}
MetaIndex(Class<?> type, int index, Type oldType, int newIndex, NewType newType) {
this.clazz = type;
this.index = index;
this.oldType = oldType;
this.newIndex = newIndex;
this.newType = newType;
}
public int getNewIndex() {
return newIndex;
}
public NewType getNewType() {
return newType;
}
public Type getOldType() {
return oldType;
}
public int getIndex() {
return index;
}
public Class<?> getApplicableClass() {
return this.clazz;
}
public static MetaIndex getIndex(Entity entity, int index) {
EntityType type;
if (entity instanceof Player) {
type = EntityType.PLAYER;
} else {
type = entity.getType();
}
return getIndex(type, index);
}
public static MetaIndex getIndex(EntityType type, int index) {
Class<? extends org.bukkit.entity.Entity> entityClass = type.getEntityClass();
if(entityClass == null){
System.out.println("Could not get entity class for " + type);
return null;
}
for (MetaIndex mi : MetaIndex.values()) {
if (mi.getIndex() == index) {
if (mi.getApplicableClass().isAssignableFrom(entityClass) ||
mi.getApplicableClass().equals(entityClass)) {
return mi;
}
}
}
// fall back to living entity
for (MetaIndex mi : MetaIndex.values()) {
if (mi.getIndex() == index) {
if (mi.getApplicableClass().isAssignableFrom(LivingEntity.class) ||
mi.getApplicableClass().equals(LivingEntity.class)) {
return mi;
}
}
}
return null;
}
}
package us.myles.ViaVersion.metadata;
import org.bukkit.entity.*;
public enum MetaIndex {
// entity
ENTITY_STATUS(org.bukkit.entity.Entity.class, 0, Type.Byte, NewType.Byte),
ENTITY_AIR(org.bukkit.entity.Entity.class, 1, Type.Short, NewType.VarInt),
ENTITY_SILENT(org.bukkit.entity.Entity.class, 4, Type.Byte, NewType.Boolean),
// living entity
LIVINGENTITY_NAMETAG(LivingEntity.class, 2, Type.String, NewType.String),
LIVINGENTITY_ALWAYS_SHOW_NAMETAG(LivingEntity.class, 3, Type.Byte, NewType.Boolean),
LIVINGENTITY_HEALTH(LivingEntity.class, 6, Type.Float, NewType.Float),
LIVINGENTITY_POTION_EFFECT_COLOR(LivingEntity.class, 7, Type.Int, NewType.VarInt),
LIVINGENTITY_IS_POTION_AMBIENT(LivingEntity.class, 8, Type.Byte, NewType.Boolean),
LIVINGENTITY_NUMBER_OF_ARROWS_IN(LivingEntity.class, 9, Type.Byte, NewType.VarInt),
LIVINGENTITY_NO_AI(LivingEntity.class, 15, Type.Byte, 10, NewType.Byte), // in 1.9 this is combined with Left handed, oh.
// ageable
AGEABLE_AGE(Ageable.class, 12, Type.Byte, 11, NewType.Boolean),
// armour stand
STAND_INFO(ArmorStand.class, 10, Type.Byte, NewType.Byte),
STAND_HEAD_POS(ArmorStand.class, 11, Type.Rotation, NewType.Vector3F),
STAND_BODY_POS(ArmorStand.class, 12, Type.Rotation, NewType.Vector3F),
STAND_LA_POS(ArmorStand.class, 13, Type.Rotation, NewType.Vector3F),
STAND_RA_POS(ArmorStand.class, 14, Type.Rotation, NewType.Vector3F),
STAND_LL_POS(ArmorStand.class, 15, Type.Rotation, NewType.Vector3F),
STAND_RL_POS(ArmorStand.class, 16, Type.Rotation, NewType.Vector3F),
// human, discountined?
PLAYER_SKIN_FLAGS(HumanEntity.class, 10, Type.Byte, NewType.Discontinued), // unsigned on 1.8
PLAYER_HUMAN_BYTE(HumanEntity.class, 16, Type.Byte, NewType.Discontinued), // unused on 1.8
PLAYER_ADDITIONAL_HEARTS(HumanEntity.class, 17, Type.Float, NewType.Discontinued),
PLAYER_SCORE(HumanEntity.class, 18, Type.Int, NewType.Discontinued),
// horse
HORSE_INFO(Horse.class, 16, Type.Int, 12, NewType.Byte),
HORSE_TYPE(Horse.class, 19, Type.Byte, 13, NewType.VarInt),
HORSE_SUBTYPE(Horse.class, 20, Type.Int, 14, NewType.VarInt),
HORSE_OWNER(Horse.class, 21, Type.String, 15, NewType.OptUUID),
HORSE_ARMOR(Horse.class, 22, Type.Int, 16, NewType.VarInt),
// bat
BAT_ISHANGING(Bat.class, 16, Type.Byte, 11, NewType.Byte),
// tameable
TAMING_INFO(Tameable.class, 16, Type.Byte, 12, NewType.Byte),
TAMING_OWNER(Tameable.class, 17, Type.String, 13, NewType.OptUUID),
// ocelot
OCELOT_TYPE(Ocelot.class, 18, Type.Byte, 14, NewType.VarInt),
// wolf
WOLF_HEALTH(Wolf.class, 18, Type.Float, 14, NewType.Float),
WOLF_BEGGING(Wolf.class, 19, Type.Byte, 15, NewType.Boolean),
WOLF_COLLAR(Wolf.class, 20, Type.Byte, 16, NewType.VarInt),
// pig
PIG_SADDLE(Pig.class, 16, Type.Byte, 12, NewType.Boolean),
// rabbit
RABBIT_TYPE(Rabbit.class, 18, Type.Byte, 12, NewType.VarInt),
// sheep
SHEEP_COLOR(Sheep.class, 16, Type.Byte, 12, NewType.Byte),
// villager
VILLAGER_PROFESSION(Villager.class, 16, Type.Int, 12, NewType.VarInt), // TODO write this to wiki.vg
// enderman
ENDERMAN_BLOCK(Enderman.class, 16, Type.Short, 11, NewType.BlockID), // special case
ENDERMAN_BLOCKDATA(Enderman.class, 17, Type.Byte, 11, NewType.BlockID), // special case
ENDERMAN_ISSCREAMING(Enderman.class, 18, Type.Byte, 12, NewType.Boolean),
// zombie
ZOMBIE_ISCHILD(Zombie.class, 12, Type.Byte, 11, NewType.Boolean),
ZOMBIE_ISVILLAGER(Zombie.class, 13, Type.Byte, 12, NewType.VarInt),
ZOMBIE_ISCONVERTING(Zombie.class, 14, Type.Byte, 13, NewType.Boolean),
// ZOMBIE_RISINGHANDS added in 1.9
// blaze
BLAZE_ONFIRE(Blaze.class, 16, Type.Byte, 11, NewType.Byte),
// spider
SPIDER_CIMBING(Spider.class, 16, Type.Byte, 11, NewType.Byte),
// creeper
CREEPER_FUSE(Creeper.class, 16, Type.Byte, 11, NewType.VarInt), // -1 idle, 1 is fuse
CREEPER_ISPOWERED(Creeper.class, 17, Type.Byte, 12, NewType.Boolean),
CREEPER_ISIGNITED(Creeper.class, 18, Type.Byte, 13, NewType.Boolean),
// ghast
GHAST_ISATTACKING(Ghast.class, 16, Type.Byte, 11, NewType.Boolean),
// slime
SLIME_SIZE(Slime.class, 16, Type.Byte, 11, NewType.VarInt),
// skeleton
SKELETON_TYPE(Skeleton.class, 13, Type.Byte, 11, NewType.VarInt),
// witch
WITCH_AGGRO(Witch.class, 21, Type.Byte, 11, NewType.Boolean),
// iron golem
IRON_PLAYERMADE(IronGolem.class, 16, Type.Byte, 11, NewType.Byte),
// wither
WITHER_TARGET1(Wither.class, 17, Type.Int, 11, NewType.VarInt),
WITHER_TARGET2(Wither.class, 18, Type.Int, 12, NewType.VarInt),
WITHER_TARGET3(Wither.class, 19, Type.Int, 13, NewType.VarInt),
WITHER_INVULN_TIME(Wither.class, 20, Type.Int, 14, NewType.VarInt),
// guardian
GUARDIAN_INFO(Guardian.class, 16, Type.Int, 11, NewType.Byte),
GUARDIAN_TARGET(Guardian.class, 17, Type.Int, 12, NewType.VarInt),
// boat
BOAT_SINCEHIT(Boat.class, 17, Type.Int, 5, NewType.VarInt),
BOAT_FORWARDDIR(Boat.class, 18, Type.Int, 6, NewType.VarInt),
BOAT_DMGTAKEN(Boat.class, 19, Type.Float, 7, NewType.Float),
// BOAT_TYPE in 1.9
// minecart
MINECART_SHAKINGPOWER(Minecart.class, 17, Type.Int, 5, NewType.VarInt),
MINECART_SHAKINGDIRECTION(Minecart.class, 18, Type.Int, 6, NewType.VarInt),
MINECART_DAMAGETAKEN(Minecart.class, 19, Type.Float, 7, NewType.Float), // also shaking modifier :P
MINECART_BLOCK(Minecart.class, 20, Type.Int, 8, NewType.VarInt),
MINECART_BLOCK_Y(Minecart.class, 21, Type.Int, 9, NewType.VarInt),
MINECART_SHOWBLOCK(Minecart.class, 22, Type.Byte, 10, NewType.Boolean),
// furnace cart
FURNACECART_ISPOWERED(org.bukkit.entity.minecart.PoweredMinecart.class, 16, Type.Byte, 11, NewType.Boolean),
// item drop
ITEM_ITEM(Item.class, 10, Type.Slot, 5, NewType.Slot),
// arrow
ARROW_ISCRIT(Arrow.class, 16, Type.Byte, 5, NewType.Byte),
// firework
FIREWORK_INFO(Firework.class, 8, Type.Slot, 5, NewType.Slot),
// item frame
ITEMFRAME_ITEM(ItemFrame.class, 8, Type.Slot, 5, NewType.Slot),
ITEMFRAME_ROTATION(ItemFrame.class, 9, Type.Byte, 6, NewType.VarInt),
// ender crystal
ENDERCRYSTAL_HEALTH(EnderCrystal.class, 8, Type.Int, NewType.Discontinued),;
private Class<?> clazz;
private int newIndex;
private NewType newType;
private Type oldType;
private int index;
MetaIndex(Class<?> type, int index, Type oldType, NewType newType) {
this.clazz = type;
this.index = index;
this.newIndex = index;
this.oldType = oldType;
this.newType = newType;
}
MetaIndex(Class<?> type, int index, Type oldType, int newIndex, NewType newType) {
this.clazz = type;
this.index = index;
this.oldType = oldType;
this.newIndex = newIndex;
this.newType = newType;
}
public int getNewIndex() {
return newIndex;
}
public NewType getNewType() {
return newType;
}
public Type getOldType() {
return oldType;
}
public int getIndex() {
return index;
}
public Class<?> getApplicableClass() {
return this.clazz;
}
public static MetaIndex getIndex(EntityType type, int index) {
Class<? extends org.bukkit.entity.Entity> entityClass = type.getEntityClass();
if(entityClass == null){
System.out.println("Could not get entity class for " + type);
return null;
}
for (MetaIndex mi : MetaIndex.values()) {
if (mi.getIndex() == index) {
// To fix issue with armour stands colliding with new values
if(mi.getApplicableClass().equals(LivingEntity.class)) continue;
if ((mi.getApplicableClass().isAssignableFrom(entityClass) ||
mi.getApplicableClass().equals(entityClass))) {
return mi;
}
}
}
// fall back to living entity
for (MetaIndex mi : MetaIndex.values()) {
if (mi.getIndex() == index) {
if (mi.getApplicableClass().isAssignableFrom(LivingEntity.class) ||
mi.getApplicableClass().equals(LivingEntity.class)) {
return mi;
}
}
}
return null;
}
}
@@ -20,7 +20,7 @@ public enum PacketType {
/* Play serverbound */
PLAY_TP_CONFIRM(State.PLAY, Direction.INCOMING, -1, 0x00),
PLAY_TAB_COMPLETE_REQUEST(State.PLAY, Direction.INCOMING, 0x14, 0x01),
PLAY_CLICHAT_MESSAGE_CLIENT(State.PLAY, Direction.INCOMING, 0x01, 0x02),
PLAY_CHAT_MESSAGE_CLIENT(State.PLAY, Direction.INCOMING, 0x01, 0x02),
PLAY_CLIENT_STATUS(State.PLAY, Direction.INCOMING, 0x16, 0x03),
PLAY_CLIENT_SETTINGS(State.PLAY, Direction.INCOMING, 0x15, 0x04),
PLAY_CONFIRM_TRANS(State.PLAY, Direction.INCOMING, 0x0F, 0x05),
@@ -167,6 +167,8 @@ public enum PacketType {
}
public static PacketType findNewPacket(State state, Direction direction, int id) {
if(id == -1)
return null;
for (PacketType pt : values()) {
if (pt.getNewPacketID() == id && id != -1
&& pt.getState() == state
@@ -177,6 +179,8 @@ public enum PacketType {
}
public static PacketType findOldPacket(State state, Direction direction, int id) {
if(id == -1)
return null;
for (PacketType pt : values()) {
if (pt.getPacketID() == id && id != -1
&& pt.getState() == state
@@ -0,0 +1,33 @@
package us.myles.ViaVersion.sounds;
public enum SoundCategory {
MASTER("master", 0),
MUSIC("music", 1),
RECORD("record", 2),
WEATHER("weather", 3),
BLOCK("block", 4),
HOSTILE("hostile", 5),
NEUTRAL("neutral", 6),
PLAYER("player", 7),
AMBIENT("ambient", 8),
VOICE("voice", 9);
private String name;
private int id;
SoundCategory(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}
@@ -0,0 +1,283 @@
package us.myles.ViaVersion.sounds;
public enum SoundEffect {
MOB_HORSE_ZOMBIE_IDLE("mob.horse.zombie.idle", "entity.zombie_horse.ambient", SoundCategory.NEUTRAL),
NOTE_SNARE("note.snare", "block.note.snare", SoundCategory.RECORD),
RANDOM_WOOD_CLICK("random.wood_click", "block.wood_button.click_on", SoundCategory.BLOCK),
DIG_GRAVEL("dig.gravel", "block.gravel.place", SoundCategory.BLOCK),
RANDOM_BOWHIT("random.bowhit", "block.tripwire.detach", SoundCategory.NEUTRAL),
DIG_GLASS("dig.glass", "block.glass.break", SoundCategory.BLOCK),
MOB_ZOMBIE_SAY("mob.zombie.say", "entity.zombie_villager.ambient", SoundCategory.HOSTILE),
MOB_PIG_DEATH("mob.pig.death", "entity.pig.death", SoundCategory.NEUTRAL),
MOB_HORSE_DONKEY_HIT("mob.horse.donkey.hit", "entity.donkey.hurt", SoundCategory.NEUTRAL),
GAME_NEUTRAL_SWIM("game.neutral.swim", "entity.player.swim", SoundCategory.NEUTRAL),
GAME_PLAYER_SWIM("game.player.swim", "entity.player.swim", SoundCategory.PLAYER),
MOB_ENDERMEN_IDLE("mob.endermen.idle", "entity.endermen.ambient", SoundCategory.HOSTILE),
PORTAL_PORTAL("portal.portal", "block.portal.ambient", SoundCategory.BLOCK),
RANDOM_FIZZ("random.fizz", "entity.generic.extinguish_fire", SoundCategory.BLOCK),
NOTE_HARP("note.harp", "block.note.harp", SoundCategory.RECORD),
STEP_SNOW("step.snow", "block.snow.step", SoundCategory.NEUTRAL),
RANDOM_SUCCESSFUL_HIT("random.successful_hit", "entity.arrow.hit_player", SoundCategory.PLAYER),
MOB_ZOMBIEPIG_ZPIGHURT("mob.zombiepig.zpighurt", "entity.zombie_pig.hurt", SoundCategory.HOSTILE),
MOB_WOLF_HOWL("mob.wolf.howl", "entity.wolf.howl", SoundCategory.NEUTRAL),
FIREWORKS_LAUNCH("fireworks.launch", "entity.firework.launch", SoundCategory.AMBIENT),
MOB_COW_HURT("mob.cow.hurt", "entity.cow.death", SoundCategory.NEUTRAL),
FIREWORKS_LARGEBLAST("fireworks.largeBlast", "entity.firework.large_blast", SoundCategory.AMBIENT),
MOB_BLAZE_HIT("mob.blaze.hit", "entity.blaze.hurt", SoundCategory.HOSTILE),
MOB_VILLAGER_DEATH("mob.villager.death", "entity.villager.death", SoundCategory.NEUTRAL),
MOB_BLAZE_DEATH("mob.blaze.death", "entity.blaze.death", SoundCategory.HOSTILE),
MOB_HORSE_ZOMBIE_DEATH("mob.horse.zombie.death", "entity.zombie_horse.death", SoundCategory.NEUTRAL),
MOB_SILVERFISH_KILL("mob.silverfish.kill", "entity.endermite.death", SoundCategory.HOSTILE),
MOB_WOLF_PANTING("mob.wolf.panting", "entity.wolf.pant", SoundCategory.NEUTRAL),
NOTE_BASS("note.bass", "null", SoundCategory.RECORD),
DIG_STONE("dig.stone", "block.glass.place", SoundCategory.BLOCK),
MOB_ENDERMEN_STARE("mob.endermen.stare", "entity.endermen.stare", SoundCategory.HOSTILE),
GAME_PLAYER_SWIM_SPLASH("game.player.swim.splash", "entity.generic.splash", SoundCategory.BLOCK),
MOB_SLIME_SMALL("mob.slime.small", "block.slime.hit", SoundCategory.HOSTILE),
MOB_GHAST_DEATH("mob.ghast.death", "entity.ghast.death", SoundCategory.HOSTILE),
MOB_GUARDIAN_ATTACK("mob.guardian.attack", "entity.guardian.attack", SoundCategory.HOSTILE),
RANDOM_CLICK("random.click", "block.wood_pressureplate.click_on", SoundCategory.BLOCK),
MOB_ZOMBIEPIG_ZPIG("mob.zombiepig.zpig", "entity.zombie_pig.ambient", SoundCategory.HOSTILE),
GAME_PLAYER_DIE("game.player.die", "entity.player.death", SoundCategory.PLAYER),
FIREWORKS_TWINKLE_FAR("fireworks.twinkle_far", "entity.firework.twinkle_far", SoundCategory.AMBIENT),
MOB_GUARDIAN_LAND_IDLE("mob.guardian.land.idle", "entity.guardian.ambient_land", SoundCategory.HOSTILE),
DIG_GRASS("dig.grass", "block.grass.place", SoundCategory.BLOCK),
MOB_SKELETON_STEP("mob.skeleton.step", "entity.skeleton.step", SoundCategory.HOSTILE),
MOB_WITHER_DEATH("mob.wither.death", "entity.wither.death", SoundCategory.HOSTILE),
MOB_WOLF_HURT("mob.wolf.hurt", "entity.wolf.hurt", SoundCategory.NEUTRAL),
MOB_HORSE_LEATHER("mob.horse.leather", "entity.horse.saddle", SoundCategory.NEUTRAL),
MOB_BAT_LOOP("mob.bat.loop", "entity.bat.loop", SoundCategory.NEUTRAL),
MOB_GHAST_SCREAM("mob.ghast.scream", "entity.ghast.hurt", SoundCategory.HOSTILE),
GAME_PLAYER_HURT("game.player.hurt", "entity.player.death", SoundCategory.PLAYER),
GAME_NEUTRAL_DIE("game.neutral.die", "entity.player.death", SoundCategory.NEUTRAL),
MOB_CREEPER_DEATH("mob.creeper.death", "entity.creeper.death", SoundCategory.HOSTILE),
MOB_HORSE_GALLOP("mob.horse.gallop", "entity.horse.gallop", SoundCategory.NEUTRAL),
MOB_WITHER_SPAWN("mob.wither.spawn", "entity.wither.spawn", SoundCategory.HOSTILE),
MOB_ENDERMEN_HIT("mob.endermen.hit", "entity.endermen.hurt", SoundCategory.HOSTILE),
MOB_CREEPER_SAY("mob.creeper.say", "entity.creeper.hurt", SoundCategory.HOSTILE),
MOB_HORSE_WOOD("mob.horse.wood", "entity.horse.step_wood", SoundCategory.NEUTRAL),
MOB_ZOMBIE_UNFECT("mob.zombie.unfect", "entity.zombie_villager.converted", SoundCategory.HOSTILE),
RANDOM_ANVIL_USE("random.anvil_use", "block.anvil.use", SoundCategory.BLOCK),
RANDOM_CHESTCLOSED("random.chestclosed", "block.enderchest.close", SoundCategory.BLOCK),
MOB_SHEEP_SHEAR("mob.sheep.shear", "entity.sheep.shear", SoundCategory.NEUTRAL),
RANDOM_POP("random.pop", "entity.item.pickup", SoundCategory.PLAYER),
MOB_BAT_DEATH("mob.bat.death", "entity.bat.death", SoundCategory.NEUTRAL),
DIG_WOOD("dig.wood", "block.ladder.break", SoundCategory.BLOCK),
MOB_HORSE_DONKEY_DEATH("mob.horse.donkey.death", "entity.donkey.death", SoundCategory.NEUTRAL),
FIREWORKS_BLAST("fireworks.blast", "entity.firework.blast", SoundCategory.AMBIENT),
MOB_ZOMBIEPIG_ZPIGANGRY("mob.zombiepig.zpigangry", "entity.zombie_pig.angry", SoundCategory.HOSTILE),
GAME_HOSTILE_SWIM("game.hostile.swim", "entity.player.swim", SoundCategory.HOSTILE),
MOB_GUARDIAN_FLOP("mob.guardian.flop", "entity.guardian.flop", SoundCategory.HOSTILE),
MOB_VILLAGER_YES("mob.villager.yes", "entity.villager.yes", SoundCategory.NEUTRAL),
MOB_GHAST_CHARGE("mob.ghast.charge", "entity.ghast.warn", SoundCategory.HOSTILE),
CREEPER_PRIMED("creeper.primed", "entity.creeper.primed", SoundCategory.HOSTILE),
DIG_SAND("dig.sand", "block.sand.break", SoundCategory.BLOCK),
MOB_CHICKEN_SAY("mob.chicken.say", "entity.chicken.ambient", SoundCategory.NEUTRAL),
RANDOM_DOOR_CLOSE("random.door_close", "null", SoundCategory.BLOCK),
MOB_GUARDIAN_ELDER_DEATH("mob.guardian.elder.death", "entity.elder_guardian.death", SoundCategory.HOSTILE),
FIREWORKS_TWINKLE("fireworks.twinkle", "entity.firework.twinkle", SoundCategory.AMBIENT),
MOB_HORSE_SKELETON_DEATH("mob.horse.skeleton.death", "entity.skeleton_horse.death", SoundCategory.NEUTRAL),
AMBIENT_WEATHER_RAIN("ambient.weather.rain", "weather.rain.above", SoundCategory.WEATHER),
PORTAL_TRIGGER("portal.trigger", "block.portal.trigger", SoundCategory.BLOCK),
RANDOM_CHESTOPEN("random.chestopen", "block.enderchest.open", SoundCategory.BLOCK),
MOB_HORSE_LAND("mob.horse.land", "entity.horse.land", SoundCategory.NEUTRAL),
MOB_SILVERFISH_STEP("mob.silverfish.step", "entity.silverfish.step", SoundCategory.HOSTILE),
MOB_BAT_TAKEOFF("mob.bat.takeoff", "entity.bat.takeoff", SoundCategory.NEUTRAL),
MOB_VILLAGER_NO("mob.villager.no", "entity.villager.no", SoundCategory.NEUTRAL),
GAME_HOSTILE_HURT_FALL_BIG("game.hostile.hurt.fall.big", "entity.hostile.big_fall", SoundCategory.HOSTILE),
MOB_IRONGOLEM_WALK("mob.irongolem.walk", "entity.irongolem.step", SoundCategory.NEUTRAL),
NOTE_HAT("note.hat", "block.note.hat", SoundCategory.RECORD),
MOB_ZOMBIE_METAL("mob.zombie.metal", "entity.zombie.attack_iron_door", SoundCategory.HOSTILE),
MOB_VILLAGER_HAGGLE("mob.villager.haggle", "entity.villager.trading", SoundCategory.NEUTRAL),
MOB_GHAST_FIREBALL("mob.ghast.fireball", "entity.blaze.shoot", SoundCategory.HOSTILE),
MOB_IRONGOLEM_DEATH("mob.irongolem.death", "entity.irongolem.death", SoundCategory.NEUTRAL),
RANDOM_BREAK("random.break", "item.shield.break", SoundCategory.PLAYER),
MOB_ZOMBIE_REMEDY("mob.zombie.remedy", "entity.zombie_villager.cure", SoundCategory.HOSTILE),
RANDOM_BOW("random.bow", "entity.splash_potion.throw", SoundCategory.NEUTRAL),
MOB_VILLAGER_IDLE("mob.villager.idle", "entity.villager.ambient", SoundCategory.NEUTRAL),
STEP_CLOTH("step.cloth", "block.cloth.fall", SoundCategory.NEUTRAL),
MOB_SILVERFISH_HIT("mob.silverfish.hit", "entity.endermite.hurt", SoundCategory.HOSTILE),
LIQUID_LAVA("liquid.lava", "block.lava.ambient", SoundCategory.BLOCK),
GAME_NEUTRAL_HURT_FALL_BIG("game.neutral.hurt.fall.big", "entity.hostile.big_fall", SoundCategory.NEUTRAL),
FIRE_FIRE("fire.fire", "block.fire.ambient", SoundCategory.BLOCK),
MOB_ZOMBIE_WOOD("mob.zombie.wood", "entity.zombie.attack_door_wood", SoundCategory.HOSTILE),
MOB_CHICKEN_STEP("mob.chicken.step", "entity.chicken.step", SoundCategory.NEUTRAL),
MOB_GUARDIAN_LAND_HIT("mob.guardian.land.hit", "entity.guardian.hurt_land", SoundCategory.HOSTILE),
MOB_CHICKEN_PLOP("mob.chicken.plop", "entity.donkey.chest", SoundCategory.NEUTRAL),
MOB_ENDERDRAGON_WINGS("mob.enderdragon.wings", "entity.enderdragon.flap", SoundCategory.HOSTILE),
STEP_GRASS("step.grass", "block.grass.hit", SoundCategory.NEUTRAL),
MOB_HORSE_BREATHE("mob.horse.breathe", "entity.horse.breathe", SoundCategory.NEUTRAL),
GAME_PLAYER_HURT_FALL_BIG("game.player.hurt.fall.big", "entity.hostile.big_fall", SoundCategory.PLAYER),
MOB_HORSE_DONKEY_IDLE("mob.horse.donkey.idle", "entity.donkey.ambient", SoundCategory.NEUTRAL),
MOB_SPIDER_STEP("mob.spider.step", "entity.spider.step", SoundCategory.HOSTILE),
GAME_NEUTRAL_HURT("game.neutral.hurt", "entity.player.death", SoundCategory.NEUTRAL),
MOB_COW_SAY("mob.cow.say", "entity.cow.ambient", SoundCategory.NEUTRAL),
MOB_HORSE_JUMP("mob.horse.jump", "entity.horse.jump", SoundCategory.NEUTRAL),
MOB_HORSE_SOFT("mob.horse.soft", "entity.horse.step", SoundCategory.NEUTRAL),
GAME_NEUTRAL_SWIM_SPLASH("game.neutral.swim.splash", "entity.generic.splash", SoundCategory.NEUTRAL),
MOB_GUARDIAN_HIT("mob.guardian.hit", "entity.guardian.hurt", SoundCategory.HOSTILE),
MOB_ENDERDRAGON_END("mob.enderdragon.end", "entity.enderdragon.death", SoundCategory.HOSTILE),
MOB_ZOMBIE_STEP("mob.zombie.step", "entity.zombie.step", SoundCategory.HOSTILE),
MOB_ENDERDRAGON_GROWL("mob.enderdragon.growl", "entity.enderdragon.growl", SoundCategory.HOSTILE),
MOB_WOLF_SHAKE("mob.wolf.shake", "entity.wolf.shake", SoundCategory.NEUTRAL),
MOB_ENDERMEN_DEATH("mob.endermen.death", "entity.endermen.death", SoundCategory.HOSTILE),
RANDOM_ANVIL_LAND("random.anvil_land", "block.anvil.land", SoundCategory.BLOCK),
GAME_HOSTILE_HURT("game.hostile.hurt", "entity.player.death", SoundCategory.HOSTILE),
MINECART_INSIDE("minecart.inside", "entity.minecart.inside", SoundCategory.PLAYER),
MOB_SLIME_BIG("mob.slime.big", "entity.slime.death", SoundCategory.HOSTILE),
LIQUID_WATER("liquid.water", "block.water.ambient", SoundCategory.BLOCK),
MOB_PIG_SAY("mob.pig.say", "entity.pig.ambient", SoundCategory.NEUTRAL),
MOB_WITHER_SHOOT("mob.wither.shoot", "entity.wither.shoot", SoundCategory.HOSTILE),
ITEM_FIRECHARGE_USE("item.fireCharge.use", "entity.blaze.shoot", SoundCategory.BLOCK),
STEP_SAND("step.sand", "block.sand.fall", SoundCategory.NEUTRAL),
MOB_IRONGOLEM_HIT("mob.irongolem.hit", "entity.irongolem.hurt", SoundCategory.NEUTRAL),
MOB_HORSE_DEATH("mob.horse.death", "entity.horse.death", SoundCategory.NEUTRAL),
MOB_BAT_HURT("mob.bat.hurt", "entity.bat.hurt", SoundCategory.NEUTRAL),
MOB_GHAST_AFFECTIONATE_SCREAM("mob.ghast.affectionate_scream", "entity.ghast.scream", SoundCategory.HOSTILE),
MOB_GUARDIAN_ELDER_IDLE("mob.guardian.elder.idle", "entity.elder_guardian.ambient", SoundCategory.HOSTILE),
MOB_ZOMBIEPIG_ZPIGDEATH("mob.zombiepig.zpigdeath", "entity.zombie_pig.death", SoundCategory.HOSTILE),
AMBIENT_WEATHER_THUNDER("ambient.weather.thunder", "entity.lightning.thunder", SoundCategory.WEATHER),
MINECART_BASE("minecart.base", "entity.minecart.riding", SoundCategory.NEUTRAL),
STEP_LADDER("step.ladder", "block.ladder.hit", SoundCategory.NEUTRAL),
MOB_HORSE_DONKEY_ANGRY("mob.horse.donkey.angry", "entity.donkey.angry", SoundCategory.NEUTRAL),
AMBIENT_CAVE_CAVE("ambient.cave.cave", "ambient.cave", SoundCategory.AMBIENT),
FIREWORKS_BLAST_FAR("fireworks.blast_far", "entity.firework.blast_far", SoundCategory.AMBIENT),
GAME_NEUTRAL_HURT_FALL_SMALL("game.neutral.hurt.fall.small", "entity.generic.small_fall", SoundCategory.NEUTRAL),
GAME_HOSTILE_SWIM_SPLASH("game.hostile.swim.splash", "entity.generic.splash", SoundCategory.HOSTILE),
RANDOM_DRINK("random.drink", "entity.generic.drink", SoundCategory.PLAYER),
GAME_HOSTILE_DIE("game.hostile.die", "entity.player.death", SoundCategory.HOSTILE),
MOB_CAT_HISS("mob.cat.hiss", "entity.cat.hiss", SoundCategory.NEUTRAL),
NOTE_BD("note.bd", "block.note.basedrum", SoundCategory.RECORD),
MOB_SPIDER_SAY("mob.spider.say", "entity.spider.hurt", SoundCategory.HOSTILE),
STEP_STONE("step.stone", "block.anvil.hit", SoundCategory.NEUTRAL),
RANDOM_LEVELUP("random.levelup", "entity.player.levelup", SoundCategory.PLAYER),
LIQUID_LAVAPOP("liquid.lavapop", "block.lava.pop", SoundCategory.BLOCK),
MOB_SHEEP_SAY("mob.sheep.say", "entity.sheep.ambient", SoundCategory.NEUTRAL),
MOB_SKELETON_SAY("mob.skeleton.say", "entity.skeleton.ambient", SoundCategory.HOSTILE),
MOB_BLAZE_BREATHE("mob.blaze.breathe", "entity.blaze.ambient", SoundCategory.HOSTILE),
MOB_BAT_IDLE("mob.bat.idle", "entity.bat.ambient", SoundCategory.NEUTRAL),
MOB_MAGMACUBE_BIG("mob.magmacube.big", "entity.magmacube.squish", SoundCategory.HOSTILE),
MOB_HORSE_IDLE("mob.horse.idle", "entity.horse.ambient", SoundCategory.NEUTRAL),
GAME_HOSTILE_HURT_FALL_SMALL("game.hostile.hurt.fall.small", "entity.generic.small_fall", SoundCategory.HOSTILE),
MOB_HORSE_ZOMBIE_HIT("mob.horse.zombie.hit", "entity.zombie_horse.hurt", SoundCategory.NEUTRAL),
MOB_IRONGOLEM_THROW("mob.irongolem.throw", "entity.irongolem.attack", SoundCategory.NEUTRAL),
DIG_CLOTH("dig.cloth", "block.cloth.place", SoundCategory.BLOCK),
STEP_GRAVEL("step.gravel", "block.gravel.hit", SoundCategory.NEUTRAL),
MOB_SILVERFISH_SAY("mob.silverfish.say", "entity.silverfish.ambient", SoundCategory.HOSTILE),
MOB_CAT_PURR("mob.cat.purr", "entity.cat.purr", SoundCategory.NEUTRAL),
MOB_ZOMBIE_INFECT("mob.zombie.infect", "entity.zombie.infect", SoundCategory.HOSTILE),
RANDOM_EAT("random.eat", "entity.generic.eat", SoundCategory.PLAYER),
MOB_WOLF_BARK("mob.wolf.bark", "entity.wolf.ambient", SoundCategory.NEUTRAL),
GAME_TNT_PRIMED("game.tnt.primed", "entity.creeper.primed", SoundCategory.BLOCK),
MOB_SHEEP_STEP("mob.sheep.step", "entity.sheep.step", SoundCategory.NEUTRAL),
MOB_ZOMBIE_DEATH("mob.zombie.death", "entity.zombie.death", SoundCategory.HOSTILE),
RANDOM_DOOR_OPEN("random.door_open", "null", SoundCategory.BLOCK),
MOB_ENDERMEN_PORTAL("mob.endermen.portal", "entity.endermen.teleport", SoundCategory.HOSTILE),
MOB_HORSE_ANGRY("mob.horse.angry", "entity.horse.angry", SoundCategory.NEUTRAL),
MOB_WOLF_GROWL("mob.wolf.growl", "entity.wolf.growl", SoundCategory.NEUTRAL),
DIG_SNOW("dig.snow", "block.snow.place", SoundCategory.BLOCK),
TILE_PISTON_OUT("tile.piston.out", "block.piston.extend", SoundCategory.BLOCK),
RANDOM_BURP("random.burp", "entity.player.burp", SoundCategory.PLAYER),
MOB_COW_STEP("mob.cow.step", "entity.cow.step", SoundCategory.NEUTRAL),
MOB_WITHER_HURT("mob.wither.hurt", "entity.wither.hurt", SoundCategory.HOSTILE),
MOB_GUARDIAN_LAND_DEATH("mob.guardian.land.death", "entity.elder_guardian.death_land", SoundCategory.HOSTILE),
MOB_CHICKEN_HURT("mob.chicken.hurt", "entity.chicken.death", SoundCategory.NEUTRAL),
MOB_WOLF_STEP("mob.wolf.step", "entity.wolf.step", SoundCategory.NEUTRAL),
MOB_WOLF_DEATH("mob.wolf.death", "entity.wolf.death", SoundCategory.NEUTRAL),
MOB_WOLF_WHINE("mob.wolf.whine", "entity.wolf.whine", SoundCategory.NEUTRAL),
NOTE_PLING("note.pling", "block.note.pling", SoundCategory.RECORD),
GAME_PLAYER_HURT_FALL_SMALL("game.player.hurt.fall.small", "entity.generic.small_fall", SoundCategory.PLAYER),
MOB_CAT_PURREOW("mob.cat.purreow", "entity.cat.purreow", SoundCategory.NEUTRAL),
FIREWORKS_LARGEBLAST_FAR("fireworks.largeBlast_far", "entity.firework.large_blast_far", SoundCategory.AMBIENT),
MOB_SKELETON_HURT("mob.skeleton.hurt", "entity.skeleton.hurt", SoundCategory.HOSTILE),
MOB_SPIDER_DEATH("mob.spider.death", "entity.spider.death", SoundCategory.HOSTILE),
RANDOM_ANVIL_BREAK("random.anvil_break", "block.anvil.destroy", SoundCategory.BLOCK),
MOB_WITHER_IDLE("mob.wither.idle", "entity.wither.ambient", SoundCategory.HOSTILE),
MOB_GUARDIAN_ELDER_HIT("mob.guardian.elder.hit", "entity.elder_guardian.hurt", SoundCategory.HOSTILE),
MOB_ENDERMEN_SCREAM("mob.endermen.scream", "entity.endermen.scream", SoundCategory.HOSTILE),
MOB_CAT_HITT("mob.cat.hitt", "entity.cat.hurt", SoundCategory.NEUTRAL),
MOB_MAGMACUBE_SMALL("mob.magmacube.small", "entity.small_magmacube.squish", SoundCategory.HOSTILE),
FIRE_IGNITE("fire.ignite", "item.flintandsteel.use", SoundCategory.BLOCK),
MOB_ENDERDRAGON_HIT("mob.enderdragon.hit", "entity.enderdragon.hurt", SoundCategory.HOSTILE),
MOB_ZOMBIE_HURT("mob.zombie.hurt", "entity.zombie_villager.hurt", SoundCategory.HOSTILE),
RANDOM_EXPLODE("random.explode", "block.end_gateway.spawn", SoundCategory.BLOCK),
MOB_SLIME_ATTACK("mob.slime.attack", "entity.slime.attack", SoundCategory.HOSTILE),
MOB_MAGMACUBE_JUMP("mob.magmacube.jump", "entity.magmacube.jump", SoundCategory.HOSTILE),
RANDOM_SPLASH("random.splash", "entity.bobber.splash", SoundCategory.PLAYER),
MOB_HORSE_SKELETON_HIT("mob.horse.skeleton.hit", "entity.skeleton_horse.hurt", SoundCategory.NEUTRAL),
MOB_GHAST_MOAN("mob.ghast.moan", "entity.ghast.ambient", SoundCategory.HOSTILE),
MOB_GUARDIAN_CURSE("mob.guardian.curse", "entity.elder_guardian.curse", SoundCategory.HOSTILE),
GAME_POTION_SMASH("game.potion.smash", "block.glass.break", SoundCategory.NEUTRAL),
NOTE_BASSATTACK("note.bassattack", "block.note.bass", SoundCategory.RECORD),
GUI_BUTTON_PRESS("gui.button.press", "block.wood_pressureplate.click_on", SoundCategory.MASTER),
RANDOM_ORB("random.orb", "entity.experience_orb.pickup", SoundCategory.PLAYER),
MOB_ZOMBIE_WOODBREAK("mob.zombie.woodbreak", "entity.zombie.break_door_wood", SoundCategory.HOSTILE),
MOB_HORSE_ARMOR("mob.horse.armor", "entity.horse.armor", SoundCategory.NEUTRAL),
TILE_PISTON_IN("tile.piston.in", "block.piston.contract", SoundCategory.BLOCK),
MOB_CAT_MEOW("mob.cat.meow", "entity.cat.ambient", SoundCategory.NEUTRAL),
MOB_PIG_STEP("mob.pig.step", "entity.pig.step", SoundCategory.NEUTRAL),
STEP_WOOD("step.wood", "block.wood.step", SoundCategory.NEUTRAL),
PORTAL_TRAVEL("portal.travel", "block.portal.travel", SoundCategory.PLAYER),
MOB_GUARDIAN_DEATH("mob.guardian.death", "entity.guardian.death", SoundCategory.HOSTILE),
MOB_SKELETON_DEATH("mob.skeleton.death", "entity.skeleton.death", SoundCategory.HOSTILE),
MOB_HORSE_HIT("mob.horse.hit", "entity.horse.hurt", SoundCategory.NEUTRAL),
MOB_VILLAGER_HIT("mob.villager.hit", "entity.villager.hurt", SoundCategory.NEUTRAL),
MOB_HORSE_SKELETON_IDLE("mob.horse.skeleton.idle", "entity.skeleton_horse.ambient", SoundCategory.NEUTRAL),
RECORDS_CHIRP("records.chirp", "record.chirp", SoundCategory.RECORD),
MOB_RABBIT_HURT("mob.rabbit.hurt", "entity.rabbit.hurt", SoundCategory.NEUTRAL),
RECORDS_STAL("records.stal", "record.stal", SoundCategory.RECORD),
MUSIC_GAME_NETHER("music.game.nether", "music.nether", SoundCategory.MUSIC),
MUSIC_MENU("music.menu", "music.menu", SoundCategory.MUSIC),
RECORDS_MELLOHI("records.mellohi", "record.mellohi", SoundCategory.RECORD),
RECORDS_CAT("records.cat", "record.cat", SoundCategory.RECORD),
RECORDS_FAR("records.far", "record.far", SoundCategory.RECORD),
MUSIC_GAME_END_DRAGON("music.game.end.dragon", "music.dragon", SoundCategory.MUSIC),
MOB_RABBIT_DEATH("mob.rabbit.death", "entity.rabbit.death", SoundCategory.NEUTRAL),
MOB_RABBIT_IDLE("mob.rabbit.idle", "entity.rabbit.ambient", SoundCategory.NEUTRAL),
MUSIC_GAME_END("music.game.end", "music.end", SoundCategory.MUSIC),
MUSIC_GAME("music.game", "music.game", SoundCategory.MUSIC),
MOB_GUARDIAN_IDLE("mob.guardian.idle", "null", SoundCategory.HOSTILE),
RECORDS_WARD("records.ward", "record.ward", SoundCategory.RECORD),
RECORDS_13("records.13", "record.13", SoundCategory.RECORD),
MOB_RABBIT_HOP("mob.rabbit.hop", "entity.rabbit.jump", SoundCategory.NEUTRAL),
RECORDS_STRAD("records.strad", "record.strad", SoundCategory.RECORD),
RECORDS_11("records.11", "record.11", SoundCategory.RECORD),
RECORDS_MALL("records.mall", "record.mall", SoundCategory.RECORD),
RECORDS_BLOCKS("records.blocks", "record.blocks", SoundCategory.RECORD),
RECORDS_WAIT("records.wait", "record.wait", SoundCategory.RECORD),
MUSIC_GAME_END_CREDITS("music.game.end.credits", "music.credits", SoundCategory.MUSIC),
MUSIC_GAME_CREATIVE("music.game.creative", "music.creative", SoundCategory.MUSIC);
private String name;
private String newname;
private SoundCategory cat;
SoundEffect(String name, String newname, SoundCategory cat) {
this.cat = cat;
this.newname = newname;
this.name = name;
}
public static SoundEffect getByName(String name) {
name = name.toLowerCase();
for (SoundEffect e : SoundEffect.values()) {
if (e.getName().equals(name))
return e;
}
return null;
}
public String getNewName() {
return newname;
}
public String getName() {
return name;
}
public SoundCategory getCategory() {
return cat;
}
}
@@ -1,25 +1,23 @@
package us.myles.ViaVersion.transformers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import org.bukkit.inventory.ItemStack;
import us.myles.ViaVersion.*;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.packets.PacketType;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class IncomingTransformer {
private final Channel channel;
private final ConnectionInfo info;
private final ViaVersionInitializer init;
public IncomingTransformer(Channel channel, ConnectionInfo info, ViaVersionInitializer init) {
this.channel = channel;
public IncomingTransformer(ConnectionInfo info) {
this.info = info;
this.init = init;
}
public void transform(int packetID, ByteBuf input, ByteBuf output) throws CancelException {
@@ -36,7 +34,7 @@ public class IncomingTransformer {
// if (packet != PacketType.PLAY_PLAYER_POSITION_LOOK_REQUEST && packet != PacketType.PLAY_KEEP_ALIVE_REQUEST && packet != PacketType.PLAY_PLAYER_POSITION_REQUEST && packet != PacketType.PLAY_PLAYER_LOOK_REQUEST) {
// System.out.println("Packet Type: " + packet + " New ID: " + packetID + " Original: " + original);
// }
if (packet == PacketType.PLAY_TP_CONFIRM) {
if (packet == PacketType.PLAY_TP_CONFIRM || packet == PacketType.PLAY_VEHICLE_MOVE_REQUEST) { //TODO handle client-sided horse riding
throw new CancelException();
}
PacketUtil.writeVarInt(packetID, output);
@@ -46,8 +44,8 @@ public class IncomingTransformer {
PacketUtil.writeVarInt(protVer <= 102 ? protVer : 47, output); // pretend to be older
if (protVer <= 102) {
// Not 1.9 remove pipes
this.init.remove();
// not 1.9, remove pipes
info.setActive(false);
}
String serverAddress = PacketUtil.readString(input);
PacketUtil.writeString(serverAddress, output);
@@ -89,11 +87,8 @@ public class IncomingTransformer {
throw new CancelException();
}
output.writeByte(status);
// read position
Long pos = input.readLong();
output.writeLong(pos);
short face = input.readUnsignedByte();
output.writeByte(face);
// write remaining bytes
output.writeBytes(input);
return;
}
if (packet == PacketType.PLAY_CLICK_WINDOW) {
@@ -108,7 +103,7 @@ public class IncomingTransformer {
try {
Class<?> setSlot = ReflectionUtil.nms("PacketPlayOutSetSlot");
Object setSlotPacket = setSlot.getConstructors()[1].newInstance(windowID, slot, null);
channel.writeAndFlush(setSlotPacket); // slot is empty
info.getChannel().pipeline().writeAndFlush(setSlotPacket); // slot is empty
slot = -999; // we're evil, they'll throw item on the ground
} catch (ClassNotFoundException e) {
e.printStackTrace();
@@ -178,7 +173,7 @@ public class IncomingTransformer {
output.writeByte(face);
int hand = PacketUtil.readVarInt(input);
ItemStack inHand = Core.getHandItem(info);
ItemStack inHand = ViaVersionPlugin.getHandItem(info);
Object item = null;
try {
Method m = ReflectionUtil.obc("inventory.CraftItemStack").getDeclaredMethod("asNMSCopy", ItemStack.class);
@@ -208,9 +203,23 @@ public class IncomingTransformer {
PacketUtil.writeVarInt(PacketType.PLAY_PLAYER_BLOCK_PLACEMENT.getPacketID(), output);
// Simulate using item :)
output.writeLong(-1L);
output.writeByte(-1);
output.writeByte(255);
// write item in hand
output.writeShort(-1);
ItemStack inHand = ViaVersionPlugin.getHandItem(info);
Object item = null;
try {
Method m = ReflectionUtil.obc("inventory.CraftItemStack").getDeclaredMethod("asNMSCopy", ItemStack.class);
item = m.invoke(null, inHand);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
PacketUtil.writeItem(item, output);
output.writeByte(-1);
output.writeByte(-1);
@@ -3,37 +3,39 @@ package us.myles.ViaVersion.transformers;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.spacehq.mc.protocol.data.game.chunk.Column;
import org.spacehq.mc.protocol.util.NetUtil;
import us.myles.ViaVersion.*;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.metadata.MetaIndex;
import us.myles.ViaVersion.metadata.NewType;
import us.myles.ViaVersion.metadata.Type;
import us.myles.ViaVersion.packets.PacketType;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.sounds.SoundEffect;
import us.myles.ViaVersion.util.EntityUtil;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.*;
import static us.myles.ViaVersion.util.PacketUtil.*;
public class OutgoingTransformer {
private static Gson gson = new Gson();
private final Channel channel;
private final ConnectionInfo info;
private final ViaVersionInitializer init;
private final ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
private boolean cancel = false;
private Map<Integer, UUID> uuidMap = new HashMap<Integer, UUID>();
private Map<Integer, EntityType> clientEntityTypes = new HashMap<Integer, EntityType>();
public OutgoingTransformer(Channel channel, ConnectionInfo info, ViaVersionInitializer init) {
this.channel = channel;
public OutgoingTransformer(ConnectionInfo info) {
this.info = info;
this.init = init;
}
public void transform(int packetID, ByteBuf input, ByteBuf output) throws CancelException {
@@ -55,14 +57,53 @@ public class OutgoingTransformer {
// By default no transform
PacketUtil.writeVarInt(packetID, output);
if (packet == PacketType.PLAY_NAMED_SOUND_EFFECT) {
// TODO: Port this over
throw new CancelException();
String name = PacketUtil.readString(input);
SoundEffect effect = SoundEffect.getByName(name);
int catid = 0;
String newname = name;
if (effect != null) {
catid = effect.getCategory().getId();
newname = effect.getNewName();
}
PacketUtil.writeString(newname, output);
PacketUtil.writeVarInt(catid, output);
output.writeBytes(input);
}
if (packet == PacketType.PLAY_ATTACH_ENTITY) {
int id = input.readInt();
output.writeInt(id);
int target = input.readInt();
output.writeInt(target);
int passenger = input.readInt();
int vehicle = input.readInt();
boolean lead = input.readBoolean();
if (!lead) {
output.clear();
writeVarInt(PacketType.PLAY_SET_PASSENGERS.getNewPacketID(), output);
writeVarInt(vehicle, output);
writeVarIntArray(Collections.singletonList(passenger), output);
return;
}
output.writeInt(passenger);
output.writeInt(vehicle);
return;
}
if (packet == PacketType.PLAY_DISCONNECT) {
String reason = readString(input);
writeString(fixJson(reason), output);
return;
}
if (packet == PacketType.PLAY_TITLE) {
int action = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(action, output);
if (action == 0 || action == 1) {
String text = PacketUtil.readString(input);
PacketUtil.writeString(fixJson(text), output);
}
output.writeBytes(input);
return;
}
if (packet == PacketType.PLAY_PLAYER_LIST_HEADER_FOOTER) {
String header = readString(input);
String footer = readString(input);
writeString(fixJson(header), output);
writeString(fixJson(footer), output);
return;
}
if (packet == PacketType.PLAY_ENTITY_TELEPORT) {
@@ -143,7 +184,9 @@ public class OutgoingTransformer {
if (packet == PacketType.LOGIN_SUCCESS) {
String uu = PacketUtil.readString(input);
PacketUtil.writeString(uu, output);
info.setUUID(UUID.fromString(uu));
UUID uniqueId = UUID.fromString(uu);
info.setUUID(uniqueId);
plugin.setPorted(uniqueId, true);
output.writeBytes(input);
return;
}
@@ -158,7 +201,7 @@ public class OutgoingTransformer {
PacketUtil.writeVarInt(id, output);
short slot = input.readShort();
if (slot > 1) {
if (slot > 0) {
slot += 1; // add 1 so it's now 2-5
}
PacketUtil.writeVarInt(slot, output);
@@ -171,13 +214,7 @@ public class OutgoingTransformer {
try {
List dw = ReflectionUtil.get(info.getLastPacket(), "b", List.class);
// get entity via entityID, not preferred but we need it.
Entity entity = Core.getEntity(info.getUUID(), id);
if (entity != null) {
transformMetadata(entity, dw, output);
} else {
// Died before we could get to it. rip
throw new CancelException();
}
transformMetadata(id, dw, output);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
@@ -185,13 +222,42 @@ public class OutgoingTransformer {
}
return;
}
if (packet == PacketType.PLAY_SPAWN_OBJECT) {
if (packet == PacketType.PLAY_SPAWN_GLOBAL_ENTITY) {
int id = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(id, output);
// only used for lightning
byte type = input.readByte();
clientEntityTypes.put(id, EntityType.LIGHTNING);
output.writeByte(type);
double x = input.readInt();
output.writeDouble(x / 32D);
double y = input.readInt();
output.writeDouble(y / 32D);
double z = input.readInt();
output.writeDouble(z / 32D);
return;
}
if (packet == PacketType.PLAY_DESTROY_ENTITIES) {
int count = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(count, output);
int[] toDestroy = PacketUtil.readVarInts(count, input);
for (int entityID : toDestroy) {
clientEntityTypes.remove(entityID);
PacketUtil.writeVarInt(entityID, output);
}
return;
}
if (packet == PacketType.PLAY_SPAWN_OBJECT) {
int id = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(id, output);
PacketUtil.writeUUID(getUUID(id), output);
byte type = input.readByte();
clientEntityTypes.put(id, EntityUtil.getTypeFromID(type, true));
output.writeByte(type);
double x = input.readInt();
@@ -208,19 +274,22 @@ public class OutgoingTransformer {
int data = input.readInt();
output.writeInt(data);
short vX = input.readableBytes() >= 16 ? input.readShort() : 0;
short vX = 0, vY = 0, vZ = 0;
if (data > 0) {
vX = input.readShort();
vY = input.readShort();
vZ = input.readShort();
}
output.writeShort(vX);
short vY = input.readableBytes() >= 16 ? input.readShort() : 0;
output.writeShort(vY);
short vZ = input.readableBytes() >= 16 ? input.readShort() : 0;
output.writeShort(vZ);
return;
}
if (packet == PacketType.PLAY_SPAWN_XP_ORB) { // TODO: Verify
if (packet == PacketType.PLAY_SPAWN_XP_ORB) {
int id = PacketUtil.readVarInt(input);
clientEntityTypes.put(id, EntityType.EXPERIENCE_ORB);
PacketUtil.writeVarInt(id, output);
double x = input.readInt();
output.writeDouble(x / 32D);
double y = input.readInt();
@@ -233,13 +302,43 @@ public class OutgoingTransformer {
return;
}
if (packet == PacketType.PLAY_SPAWN_PAINTING) {
int id = PacketUtil.readVarInt(input);
clientEntityTypes.put(id, EntityType.PAINTING);
PacketUtil.writeVarInt(id, output);
PacketUtil.writeUUID(getUUID(id), output);
String title = PacketUtil.readString(input);
PacketUtil.writeString(title, output);
long[] position = PacketUtil.readBlockPosition(input);
PacketUtil.writeBlockPosition(output, position[0], position[1], position[2]);
byte direction = input.readByte();
output.writeByte(direction);
return;
}
if (packet == PacketType.PLAY_OPEN_WINDOW) {
int windowId = input.readUnsignedByte();
String type = readString(input);
String windowTitle = readString(input);
output.writeByte(windowId);
writeString(type, output);
writeString(fixJson(windowTitle), output);
output.writeBytes(input);
return;
}
if (packet == PacketType.PLAY_SPAWN_MOB) {
int id = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(id, output);
PacketUtil.writeUUID(getUUID(id), output);
short type = input.readUnsignedByte();
clientEntityTypes.put(id, EntityUtil.getTypeFromID(type, false));
output.writeByte(type);
double x = input.readInt();
output.writeDouble(x / 32D);
double y = input.readInt();
@@ -261,7 +360,7 @@ public class OutgoingTransformer {
output.writeShort(vZ);
try {
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "l", ReflectionUtil.nms("DataWatcher"));
transformMetadata(dataWatcher, output);
transformMetadata(id, dataWatcher, output);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
@@ -271,21 +370,33 @@ public class OutgoingTransformer {
}
return;
}
if(packet == PacketType.PLAY_UPDATE_SIGN){
if (packet == PacketType.PLAY_UPDATE_SIGN) {
Long location = input.readLong();
output.writeLong(location);
for(int i = 0;i<4;i++){
for (int i = 0; i < 4; i++) {
String line = PacketUtil.readString(input);
if(line.startsWith("\"")){
line = "{\"text\":" + line + "}";
}
PacketUtil.writeString(line, output);
PacketUtil.writeString(fixJson(line), output);
}
}
if (packet == PacketType.PLAY_CHAT_MESSAGE) {
String chat = PacketUtil.readString(input);
PacketUtil.writeString(fixJson(chat), output);
byte pos = input.readByte();
output.writeByte(pos);
return;
}
if (packet == PacketType.PLAY_JOIN_GAME) {
int id = input.readInt();
clientEntityTypes.put(id, EntityType.PLAYER);
output.writeInt(id);
output.writeBytes(input);
return;
}
if (packet == PacketType.PLAY_SPAWN_PLAYER) {
int id = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(id, output);
clientEntityTypes.put(id, EntityType.PLAYER);
UUID playerUUID = PacketUtil.readUUID(input);
PacketUtil.writeUUID(playerUUID, output);
@@ -302,7 +413,7 @@ public class OutgoingTransformer {
output.writeByte(yaw);
try {
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "i", ReflectionUtil.nms("DataWatcher"));
transformMetadata(dataWatcher, output);
transformMetadata(id, dataWatcher, output);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
@@ -313,7 +424,7 @@ public class OutgoingTransformer {
return;
}
if(packet == PacketType.PLAY_MAP) {
if (packet == PacketType.PLAY_MAP) {
int damage = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(damage, output);
byte scale = input.readByte();
@@ -322,12 +433,12 @@ public class OutgoingTransformer {
output.writeBytes(input);
return;
}
if(packet == PacketType.PLAY_TEAM) {
if (packet == PacketType.PLAY_TEAM) {
String teamName = PacketUtil.readString(input);
PacketUtil.writeString(teamName, output);
byte mode = input.readByte();
output.writeByte(mode);
if(mode == 0 || mode == 2){
if (mode == 0 || mode == 2) {
PacketUtil.writeString(PacketUtil.readString(input), output);
PacketUtil.writeString(PacketUtil.readString(input), output);
PacketUtil.writeString(PacketUtil.readString(input), output);
@@ -391,39 +502,56 @@ public class OutgoingTransformer {
output.writeBytes(input);
}
private void transformMetadata(Object dw, ByteBuf output) {
private String fixJson(String line) {
if (line == null || line.equalsIgnoreCase("null")) {
line = "{\"text\":\"\"}";
} else {
if (!line.startsWith("\"") && !line.startsWith("{"))
line = "\"" + line + "\"";
if (line.startsWith("\""))
line = "{\"text\":" + line + "}";
}
return line;
}
private void transformMetadata(int entityID, Object dw, ByteBuf output) throws CancelException {
// get entity
try {
Class<?> nmsClass = ReflectionUtil.nms("Entity");
Object nmsEntity = ReflectionUtil.get(dw, "a", nmsClass);
Class<?> craftClass = ReflectionUtil.obc("entity.CraftEntity");
Method bukkitMethod = craftClass.getDeclaredMethod("getEntity", ReflectionUtil.obc("CraftServer"), nmsClass);
Object entity = bukkitMethod.invoke(null, Bukkit.getServer(), nmsEntity);
transformMetadata((Entity) entity, (List) ReflectionUtil.invoke(dw, "b"), output);
} catch (NoSuchFieldException e) {
e.printStackTrace();
transformMetadata(entityID, (List) ReflectionUtil.invoke(dw, "b"), output);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private void transformMetadata(Entity entity, List dw, ByteBuf output) {
try {
if (dw != null) {
short id = -1;
int data = -1;
private void transformMetadata(int entityID, List dw, ByteBuf output) throws CancelException {
EntityType type = clientEntityTypes.get(entityID);
if (type == null) {
System.out.println("Unable to get entity for ID: " + entityID);
output.writeByte(255);
return;
}
if (dw != null) {
short id = -1;
int data = -1;
Iterator iterator = dw.iterator();
while (iterator.hasNext()) {
Object watchableObj = iterator.next(); //
MetaIndex metaIndex = MetaIndex.getIndex(entity, (int) ReflectionUtil.invoke(watchableObj, "a"));
Iterator iterator = dw.iterator();
while (iterator.hasNext()) {
Object watchableObj = iterator.next(); //
MetaIndex metaIndex = null;
try {
metaIndex = MetaIndex.getIndex(type, (int) ReflectionUtil.invoke(watchableObj, "a"));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
try {
if (metaIndex.getNewType() != NewType.Discontinued) {
if (metaIndex.getNewType() != NewType.BlockID || id != -1 && data == -1 || id == -1 && data != -1) { // block ID is only written if we have both parts
output.writeByte(metaIndex.getNewIndex());
@@ -451,7 +579,7 @@ public class OutgoingTransformer {
}
output.writeBoolean(toWrite != null);
if (toWrite != null)
PacketUtil.writeUUID((UUID) value, output);
PacketUtil.writeUUID((UUID) toWrite, output);
break;
case BlockID:
// if we have both sources :))
@@ -502,13 +630,20 @@ public class OutgoingTransformer {
output.writeFloat((float) ReflectionUtil.invoke(value, "getY"));
output.writeFloat((float) ReflectionUtil.invoke(value, "getZ"));
}
}
} catch (Exception e) {
if (type != null) {
System.out.println("An error occurred with entity meta data for " + type);
System.out.println("Old ID: " + metaIndex.getIndex() + " New ID: " + metaIndex.getNewIndex());
System.out.println("Old Type: " + metaIndex.getOldType() + " New Type: " + metaIndex.getNewType());
}
e.printStackTrace();
}
}
output.writeByte(255);
}catch(Exception e){
e.printStackTrace();
}
output.writeByte(255);
}
@@ -0,0 +1,91 @@
package us.myles.ViaVersion.util;
import org.bukkit.entity.EntityType;
public class EntityUtil {
public static EntityType getTypeFromID(int typeID, boolean isObject) {
if (isObject) {
return getObjectFromID(typeID);
} else {
return EntityType.fromId(typeID);
}
}
// based on http://wiki.vg/index.php?title=Entities
public static EntityType getObjectFromID(int objectID) {
EntityType type;
switch (objectID) {
case 2:
type = EntityType.DROPPED_ITEM;
break;
case 77:
type = EntityType.LEASH_HITCH;
break;
case 60:
type = EntityType.ARROW;
break;
case 61:
type = EntityType.SNOWBALL;
break;
case 63:
type = EntityType.FIREBALL;
break;
case 64:
type = EntityType.SMALL_FIREBALL;
break;
case 65:
type = EntityType.ENDER_PEARL;
break;
case 72:
type = EntityType.ENDER_SIGNAL;
break;
case 75:
type = EntityType.THROWN_EXP_BOTTLE;
break;
case 71:
type = EntityType.ITEM_FRAME;
break;
case 66:
type = EntityType.WITHER_SKULL;
break;
case 50:
type = EntityType.PRIMED_TNT;
break;
case 70:
type = EntityType.FALLING_BLOCK;
break;
case 76:
type = EntityType.FIREWORK;
break;
case 78:
type = EntityType.ARMOR_STAND;
break;
case 1:
type = EntityType.BOAT;
break;
case 10:
type = EntityType.MINECART;
break;
case 51:
type = EntityType.ENDER_CRYSTAL;
break;
case 73:
type = EntityType.SPLASH_POTION;
break;
case 62:
type = EntityType.EGG;
break;
case 90:
type = EntityType.FISHING_HOOK;
break;
default:
type = EntityType.fromId(objectID);
if (type == null) {
System.out.println("Unable to find entity type for " + objectID);
type = EntityType.UNKNOWN;
}
break;
}
return type;
}
}
@@ -1,4 +1,4 @@
package us.myles.ViaVersion;
package us.myles.ViaVersion.util;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
@@ -42,29 +42,38 @@ public class PacketUtil {
}
}
public static ByteBuf decompress(ChannelHandlerContext ctx, ByteBuf msg) {
ByteToMessageDecoder x = (ByteToMessageDecoder) ctx.pipeline().get("decompress");
public static List<Object> callDecode(ByteToMessageDecoder decoder, ChannelHandlerContext ctx, Object input) {
List<Object> output = new ArrayList<Object>();
try {
PacketUtil.DECODE_METHOD.invoke(x, ctx, msg, output);
PacketUtil.DECODE_METHOD.invoke(decoder, ctx, input, output);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return output;
}
public static void callEncode(MessageToByteEncoder encoder, ChannelHandlerContext ctx, Object msg, ByteBuf output) {
try {
PacketUtil.ENCODE_METHOD.invoke(encoder, ctx, msg, output);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public static ByteBuf decompress(ChannelHandlerContext ctx, ByteBuf msg) {
ByteToMessageDecoder x = (ByteToMessageDecoder) ctx.pipeline().get("decompress");
List<Object> output = callDecode(x, ctx, msg);
return output.size() == 0 ? null : (ByteBuf) output.get(0);
}
public static ByteBuf compress(ChannelHandlerContext ctx, ByteBuf msg) {
MessageToByteEncoder x = (MessageToByteEncoder) ctx.pipeline().get("compress");
ByteBuf output = ctx.alloc().buffer();
try {
PacketUtil.ENCODE_METHOD.invoke(x, ctx, msg, output);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
callEncode(x, ctx, msg, output);
return output;
}
@@ -184,6 +193,13 @@ public class PacketUtil {
}
}
public static void writeVarIntArray(List<Integer> integers, ByteBuf output) {
writeVarInt(integers.size(), output);
for (Integer i : integers) {
writeVarInt(i, output);
}
}
public static int readVarShort(ByteBuf buf) {
int low = buf.readUnsignedShort();
int high = 0;
@@ -356,4 +372,26 @@ public class PacketUtil {
e.printStackTrace();
}
}
public static long[] readBlockPosition(ByteBuf buf) {
long val = buf.readLong();
long x = (val >> 38); // signed
long y = (val >> 26) & 0xfff; // unsigned
// this shifting madness is used to preserve sign
long z = (val << 38) >> 38; // signed
return new long[]{x, y, z};
}
public static void writeBlockPosition(ByteBuf buf, long x, long y, long z) {
buf.writeLong(((x & 0x3ffffff) << 38) | ((y & 0xfff) << 26) | (z & 0x3ffffff));
}
public static int[] readVarInts(int amount, ByteBuf input) {
int data[] = new int[amount];
for (int index = 0; index < amount; index++) {
data[index] = PacketUtil.readVarInt(input);
}
return data;
}
}
@@ -1,4 +1,4 @@
package us.myles.ViaVersion;
package us.myles.ViaVersion.util;
import org.bukkit.Bukkit;
+4 -2
View File
@@ -1,4 +1,6 @@
name: ViaVersion
main: us.myles.ViaVersion.Core
main: us.myles.ViaVersion.ViaVersionPlugin
author: _MylesC
version: 0.3
version: 0.4.2
load: startup
loadbefore: [ProtocolLib, ProxyPipe]