Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cdfd72700 | ||
|
|
ccd6987f11 | ||
|
|
6c96271925 | ||
|
|
318db73f3c | ||
|
|
b5b0117fa9 | ||
|
|
79e5555d42 | ||
|
|
114a7b6bd6 | ||
|
|
8e6d76296d | ||
|
|
153a68bf06 | ||
|
|
6199e1d8ce | ||
|
|
0db43e612e | ||
|
|
06296ead77 | ||
|
|
dac9bd58e5 | ||
|
|
8e0833ca6b | ||
|
|
88086e00d0 | ||
|
|
9368347b56 | ||
|
|
6828425d72 | ||
|
|
f9da275358 | ||
|
|
1445bd37c3 | ||
|
|
2de176e55c | ||
|
|
b785fe0515 | ||
|
|
984176d53b | ||
|
|
bd46c3f5a0 | ||
|
|
0209c51d10 | ||
|
|
3425ed94e0 | ||
|
|
8ceee31299 | ||
|
|
db9cd296ee | ||
|
|
6b3fb6424c | ||
|
|
e43968c142 | ||
|
|
5c0ba593da | ||
|
|
1f51cf8416 | ||
|
|
442d4de74b | ||
|
|
2a67301642 | ||
|
|
46ec24a686 | ||
|
|
6f25090c01 | ||
|
|
dd36686f1c | ||
|
|
2b980a3cfc | ||
|
|
43aaa728b5 | ||
|
|
45dfe7261b | ||
|
|
7831dc0082 | ||
|
|
ba4e6e5d2f | ||
|
|
68bfaf6d23 | ||
|
|
954dfb74e5 | ||
|
|
f95e7f98b7 | ||
|
|
aabd79e6c7 | ||
|
|
db7daaa6ca | ||
|
|
b66ea090c2 | ||
|
|
ad3317f8d8 | ||
|
|
3b480a61bd | ||
|
|
c0296f04a1 | ||
|
|
6f605e8d6c | ||
|
|
a6cfcac675 | ||
|
|
8e717bb023 | ||
|
|
e885a1cec2 | ||
|
|
e2de17e221 | ||
|
|
5738a992e5 | ||
|
|
122a7e05f6 | ||
|
|
546fdf95d4 | ||
|
|
e6a9cc4776 | ||
|
|
c641f02d7e | ||
|
|
bf11edfaa9 | ||
|
|
3cc6bf4c51 | ||
|
|
156f42318c | ||
|
|
1a1ffe4265 | ||
|
|
3fa4b7a7b2 | ||
|
|
59b270beda | ||
|
|
135942c033 | ||
|
|
0930420844 | ||
|
|
16e546803c | ||
|
|
f6b297fea4 | ||
|
|
3f0b5c8a2b | ||
|
|
dff7d98dd5 |
No files matched your search
@@ -0,0 +1,44 @@
|
||||
# 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*
|
||||
|
||||
**As of this point it doesn't have everything, I need to fix:**
|
||||
|
||||
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.
|
||||
|
||||
|
||||
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/StamBoom**
|
||||
|
||||
**HugoDaBosss**
|
||||
|
||||
**SanderGielisse**
|
||||
|
||||
License:
|
||||
--------
|
||||
|
||||
You may modify this work, all rights are still owned by myself excluding any files in the spacebase package as they belong to the respected contributors. Please credit the original author (myself) when forking etc. (or if it helped you understand the new protocol or netty!)
|
||||
|
||||
|
||||
Thanks!
|
||||
@@ -21,13 +21,34 @@
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<!-- Sorry about this path >:( I promise to fix it when I stop using NMS :) -->
|
||||
<groupId>org.spigot</groupId>
|
||||
<artifactId>spigot1.8</artifactId>
|
||||
<version>1.8</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>E:/spigot_server.jar</systemPath>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.0.20.Final</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
<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;
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package us.myles.ViaVersion;
|
||||
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import net.minecraft.server.v1_8_R3.Entity;
|
||||
import net.minecraft.server.v1_8_R3.MinecraftServer;
|
||||
import net.minecraft.server.v1_8_R3.ServerConnection;
|
||||
import net.minecraft.server.v1_8_R3.WorldServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Core extends JavaPlugin {
|
||||
@Override
|
||||
public void onEnable() {
|
||||
System.out.println("ViaVersion enabled, injecting. (Allows 1.8 to be accessed via 1.9)");
|
||||
/* Obvious message here:
|
||||
If loading this plugin nobody will be on 1.9 cause only 1.8 so we're fine, as for reloading ugh.
|
||||
Clients might crash cause of it being a bum maybe? :P
|
||||
*/
|
||||
try {
|
||||
injectPacketHandler();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("Unable to inject handlers, this version only supports 1.8.");
|
||||
}
|
||||
}
|
||||
|
||||
public void injectPacketHandler() throws NoSuchFieldException, IllegalAccessException {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
ServerConnection connection = server.getServerConnection();
|
||||
|
||||
List<ChannelFuture> futures = getPrivateField(connection, "g", List.class);
|
||||
|
||||
for (ChannelFuture future : futures) {
|
||||
ChannelPipeline pipeline = future.channel().pipeline();
|
||||
ChannelHandler bootstrapAcceptor = pipeline.first();
|
||||
ChannelInitializer<SocketChannel> oldInit = getPrivateField(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
|
||||
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
|
||||
setPrivateField(bootstrapAcceptor, "childHandler", newInit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
WorldServer ws = ((CraftWorld) p.getWorld()).getHandle();
|
||||
for (Entity e : ws.entityList) {
|
||||
if (e.getId() == id) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
System.out.println("Couldn't find in the world!!");
|
||||
return null;
|
||||
}
|
||||
}).get(10, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error fetching entity ");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static <T> T getPrivateField(Object o, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
return (T) field.get(o);
|
||||
}
|
||||
|
||||
public static void setPrivateField(Object o, String f, Object value) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
field.set(o, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
}
|
||||
|
||||
public static ItemStack getHandItem(final ConnectionInfo info) {
|
||||
try {
|
||||
return Bukkit.getScheduler().callSyncMethod(getPlugin(Core.class), new Callable<ItemStack>() {
|
||||
@Override
|
||||
public ItemStack call() throws Exception {
|
||||
if (info.getPlayer() != null) {
|
||||
return info.getPlayer().getItemInHand();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}).get(10, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error fetching hand item ");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package us.myles.ViaVersion;
|
||||
|
||||
import us.myles.ViaVersion.chunks.ByteWriter;
|
||||
|
||||
public class Testing {
|
||||
public static void main(String[] args) {
|
||||
// Map<NewType, Set<Type>> conversions = new HashMap<>();
|
||||
// for (MetaIndex metaIndex : MetaIndex.values()) {
|
||||
// if (!conversions.containsKey(metaIndex.getNewType())) {
|
||||
// conversions.put(metaIndex.getNewType(), new HashSet<Type>());
|
||||
// }
|
||||
// conversions.get(metaIndex.getNewType()).add(metaIndex.getOldType());
|
||||
// }
|
||||
// for (Map.Entry<NewType, Set<Type>> conv : conversions.entrySet()) {
|
||||
// System.out.println("Type: " + conv.getKey().name());
|
||||
// for (Type t : conv.getValue()) {
|
||||
// System.out.println(" -> " + t.name());
|
||||
// }
|
||||
// }
|
||||
ByteWriter bytes = new ByteWriter(2);
|
||||
int id = 255;
|
||||
int data = 4;
|
||||
bytes.writeByte(0, 1);
|
||||
bytes.writeFullByte(id);
|
||||
bytes.writeByte(data, 4);
|
||||
|
||||
System.out.println("output bytes: ");
|
||||
for(byte b:bytes.getOutput()){
|
||||
System.out.println("B: " + b + " I: " + ((int)b & 0xff));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte writeByte(byte a, byte b, int index){
|
||||
int intA = (int) a & 0xff;
|
||||
int intB = (int) b & 0xff;
|
||||
System.out.println("As int: " + (intA | (intB >> index)));
|
||||
return (byte) (intA | (intB >> index));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package us.myles.ViaVersion;
|
||||
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import org.bukkit.Bukkit;
|
||||
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.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 ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
||||
|
||||
private final Set<UUID> portedPlayers = Collections.newSetFromMap(new ConcurrentHashMap<UUID, Boolean>());
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
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) {
|
||||
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 {
|
||||
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
|
||||
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
||||
Object connection = serverClazz.getDeclaredMethod("getServerConnection").invoke(server);
|
||||
|
||||
List<ChannelFuture> futures = ReflectionUtil.get(connection, "g", List.class);
|
||||
if (futures.size() == 0) {
|
||||
throw new Exception("Could not find server to inject (Please ensure late-bind in your spigot.yml is false)");
|
||||
}
|
||||
|
||||
for (ChannelFuture future : futures) {
|
||||
ChannelPipeline pipeline = future.channel().pipeline();
|
||||
ChannelHandler bootstrapAcceptor = pipeline.first();
|
||||
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
|
||||
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
|
||||
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPorted(Player player) {
|
||||
return portedPlayers.contains(player.getUniqueId());
|
||||
}
|
||||
|
||||
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(ViaVersionPlugin.class), new Callable<ItemStack>() {
|
||||
@Override
|
||||
public ItemStack call() throws Exception {
|
||||
if (info.getPlayer() != null) {
|
||||
return info.getPlayer().getItemInHand();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}).get(10, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error fetching hand item ");
|
||||
e.printStackTrace();
|
||||
return 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,51 +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;
|
||||
}
|
||||
if (compression) {
|
||||
// recompress :)
|
||||
newPacket = PacketUtil.compress(ctx, newPacket);
|
||||
}
|
||||
msg = newPacket;
|
||||
}
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,51 +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;
|
||||
}
|
||||
if (compression) {
|
||||
// recompress :)
|
||||
newPacket = PacketUtil.compress(ctx, newPacket);
|
||||
}
|
||||
msg = newPacket;
|
||||
}
|
||||
super.write(ctx, msg, channelPromise);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package us.myles.ViaVersion.handlers;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import net.minecraft.server.v1_8_R3.Packet;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunkBulk;
|
||||
import net.minecraft.server.v1_8_R3.World;
|
||||
import us.myles.ViaVersion.ConnectionInfo;
|
||||
import us.myles.ViaVersion.Core;
|
||||
|
||||
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 Packet){
|
||||
info.setLastPacket(o);
|
||||
/* This transformer is more for fixing issues which we find hard at byte level :) */
|
||||
if(o instanceof PacketPlayOutMapChunkBulk){
|
||||
PacketPlayOutMapChunkBulk bulk = (PacketPlayOutMapChunkBulk) o;
|
||||
int[] locX = Core.getPrivateField(bulk, "a", int[].class);
|
||||
int[] locZ = Core.getPrivateField(bulk, "b", int[].class);
|
||||
|
||||
World world = Core.getPrivateField(bulk, "world", World.class);
|
||||
for(int i = 0;i<locX.length;i++){
|
||||
int x = locX[i];
|
||||
int z = locZ[i];
|
||||
channelHandlerContext.write(new PacketPlayOutMapChunk(world.getChunkAt(x, z), true, 65535)); // magic was 65535
|
||||
}
|
||||
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,199 +1,191 @@
|
||||
package us.myles.ViaVersion.metadata;
|
||||
|
||||
import net.minecraft.server.v1_8_R3.Entity;
|
||||
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_8_R3.EntityTypes;
|
||||
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 EntityPlayer) {
|
||||
type = EntityType.PLAYER;
|
||||
} else {
|
||||
int entityID = EntityTypes.a(entity);
|
||||
type = EntityType.fromId(entityID);
|
||||
}
|
||||
return getIndex(type, index);
|
||||
}
|
||||
|
||||
public static MetaIndex getIndex(EntityType type, int index) {
|
||||
Class<? extends org.bukkit.entity.Entity> entityClass = type.getEntityClass();
|
||||
|
||||
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),
|
||||
@@ -114,7 +114,7 @@ public enum PacketType {
|
||||
PLAY_UPDATE_HEALTH(State.PLAY, Direction.OUTGOING, 0x06, 0x3E),
|
||||
PLAY_SCOREBOARD_OBJ(State.PLAY, Direction.OUTGOING, 0x3B, 0x3F),
|
||||
PLAY_SET_PASSENGERS(State.PLAY, Direction.OUTGOING, -1, 0x40),
|
||||
PLAY_TEAMS(State.PLAY, Direction.OUTGOING, 0x3E, 0x41),
|
||||
PLAY_TEAM(State.PLAY, Direction.OUTGOING, 0x3E, 0x41),
|
||||
PLAY_UPDATE_SCORE(State.PLAY, Direction.OUTGOING, 0x3C, 0x42),
|
||||
PLAY_SPAWN_POSITION(State.PLAY, Direction.OUTGOING, 0x05, 0x43),
|
||||
PLAY_TIME_UPDATE(State.PLAY, Direction.OUTGOING, 0x03, 0x44),
|
||||
@@ -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,28 +1,23 @@
|
||||
package us.myles.ViaVersion.transformers;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import net.minecraft.server.v1_8_R3.PacketDataSerializer;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import us.myles.ViaVersion.CancelException;
|
||||
import us.myles.ViaVersion.ConnectionInfo;
|
||||
import us.myles.ViaVersion.Core;
|
||||
import us.myles.ViaVersion.PacketUtil;
|
||||
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
||||
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 static Gson gson = new Gson();
|
||||
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,24 +31,21 @@ public class IncomingTransformer {
|
||||
if (packet.getPacketID() != -1) {
|
||||
packetID = packet.getPacketID();
|
||||
}
|
||||
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) {
|
||||
System.out.println("Cancelling TP Confirm");
|
||||
// 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 || packet == PacketType.PLAY_VEHICLE_MOVE_REQUEST) { //TODO handle client-sided horse riding
|
||||
throw new CancelException();
|
||||
}
|
||||
PacketUtil.writeVarInt(packetID, output);
|
||||
if (packet == PacketType.HANDSHAKE) {
|
||||
System.out.println("Readable Bytes: " + input.readableBytes());
|
||||
int protVer = PacketUtil.readVarInt(input);
|
||||
info.setProtocol(protVer);
|
||||
PacketUtil.writeVarInt(protVer <= 102 ? protVer : 47, output); // pretend to be older
|
||||
|
||||
System.out.println("Incoming prot ver: " + protVer);
|
||||
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);
|
||||
@@ -72,7 +64,17 @@ public class IncomingTransformer {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(packet == PacketType.PLAY_TAB_COMPLETE_REQUEST){
|
||||
if (packet == PacketType.PLAY_UPDATE_SIGN_REQUEST) {
|
||||
Long location = input.readLong();
|
||||
output.writeLong(location);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
String line = PacketUtil.readString(input);
|
||||
line = "{\"text\":\"" + line + "\"}";
|
||||
PacketUtil.writeString(line, output);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (packet == PacketType.PLAY_TAB_COMPLETE_REQUEST) {
|
||||
String text = PacketUtil.readString(input);
|
||||
PacketUtil.writeString(text, output);
|
||||
input.readBoolean(); // assume command
|
||||
@@ -85,11 +87,41 @@ 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) {
|
||||
// if placed in new slot, reject :)
|
||||
int windowID = input.readUnsignedByte();
|
||||
short slot = input.readShort();
|
||||
|
||||
byte button = input.readByte();
|
||||
short action = input.readShort();
|
||||
byte mode = input.readByte();
|
||||
if (slot == 45 && windowID == 0) {
|
||||
try {
|
||||
Class<?> setSlot = ReflectionUtil.nms("PacketPlayOutSetSlot");
|
||||
Object setSlotPacket = setSlot.getConstructors()[1].newInstance(windowID, slot, null);
|
||||
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();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
output.writeByte(windowID);
|
||||
output.writeShort(slot);
|
||||
output.writeByte(button);
|
||||
output.writeShort(action);
|
||||
output.writeByte(mode);
|
||||
output.writeBytes(input);
|
||||
return;
|
||||
}
|
||||
if (packet == PacketType.PLAY_CLIENT_SETTINGS) {
|
||||
@@ -108,13 +140,11 @@ public class IncomingTransformer {
|
||||
short skinParts = input.readUnsignedByte();
|
||||
output.writeByte(skinParts);
|
||||
|
||||
int mainHand = PacketUtil.readVarInt(input);
|
||||
System.out.println("Main hand: " + mainHand);
|
||||
PacketUtil.readVarInt(input);
|
||||
return;
|
||||
}
|
||||
if (packet == PacketType.PLAY_ANIMATION_REQUEST) {
|
||||
int hand = PacketUtil.readVarInt(input);
|
||||
System.out.println("Animation request " + hand);
|
||||
PacketUtil.readVarInt(input);
|
||||
return;
|
||||
}
|
||||
if (packet == PacketType.PLAY_USE_ENTITY) {
|
||||
@@ -132,7 +162,7 @@ public class IncomingTransformer {
|
||||
output.writeFloat(targetZ);
|
||||
}
|
||||
if (type == 0 || type == 2) {
|
||||
int hand = PacketUtil.readVarInt(input); // lel
|
||||
PacketUtil.readVarInt(input);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -142,9 +172,23 @@ public class IncomingTransformer {
|
||||
int face = PacketUtil.readVarInt(input);
|
||||
output.writeByte(face);
|
||||
int hand = PacketUtil.readVarInt(input);
|
||||
System.out.println("hand: " + hand);
|
||||
// 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);
|
||||
|
||||
short curX = input.readUnsignedByte();
|
||||
output.writeByte(curX);
|
||||
@@ -159,11 +203,23 @@ public class IncomingTransformer {
|
||||
PacketUtil.writeVarInt(PacketType.PLAY_PLAYER_BLOCK_PLACEMENT.getPacketID(), output);
|
||||
// Simulate using item :)
|
||||
output.writeLong(-1L);
|
||||
output.writeByte(-1);
|
||||
int hand = PacketUtil.readVarInt(input);
|
||||
System.out.println("hand: " + hand);
|
||||
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,39 +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 net.minecraft.server.v1_8_R3.*;
|
||||
import net.minecraft.server.v1_8_R3.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.inventory.*;
|
||||
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.CancelException;
|
||||
import us.myles.ViaVersion.ConnectionInfo;
|
||||
import us.myles.ViaVersion.Core;
|
||||
import us.myles.ViaVersion.PacketUtil;
|
||||
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
||||
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.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 {
|
||||
@@ -48,8 +48,8 @@ public class OutgoingTransformer {
|
||||
if (packet == null) {
|
||||
throw new RuntimeException("Outgoing Packet not found? " + packetID + " State: " + info.getState() + " Version: " + info.getProtocol());
|
||||
}
|
||||
if (packet != PacketType.PLAY_CHUNK_DATA && packet != PacketType.PLAY_KEEP_ALIVE && packet != PacketType.PLAY_TIME_UPDATE)
|
||||
System.out.println("Packet Type: " + packet + " Original ID: " + packetID + " State:" + info.getState());
|
||||
// if (packet != PacketType.PLAY_CHUNK_DATA && packet != PacketType.PLAY_KEEP_ALIVE && packet != PacketType.PLAY_TIME_UPDATE && (!packet.name().toLowerCase().contains("move") && !packet.name().contains("look")))
|
||||
// System.out.println("Packet Type: " + packet + " Original ID: " + packetID + " State:" + info.getState());
|
||||
if (packet.getPacketID() != -1) {
|
||||
packetID = packet.getNewPacketID();
|
||||
}
|
||||
@@ -57,15 +57,53 @@ public class OutgoingTransformer {
|
||||
// By default no transform
|
||||
PacketUtil.writeVarInt(packetID, output);
|
||||
if (packet == PacketType.PLAY_NAMED_SOUND_EFFECT) {
|
||||
// TODO: Port this over
|
||||
System.out.println("cancelling");
|
||||
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) {
|
||||
@@ -94,11 +132,11 @@ public class OutgoingTransformer {
|
||||
int id = PacketUtil.readVarInt(input);
|
||||
PacketUtil.writeVarInt(id, output);
|
||||
int x = input.readByte();
|
||||
output.writeShort(x);
|
||||
output.writeShort(x * 128);
|
||||
int y = input.readByte();
|
||||
output.writeShort(y);
|
||||
output.writeShort(y * 128);
|
||||
int z = input.readByte();
|
||||
output.writeShort(z);
|
||||
output.writeShort(z * 128);
|
||||
|
||||
byte yaw = input.readByte();
|
||||
output.writeByte(yaw);
|
||||
@@ -113,12 +151,12 @@ public class OutgoingTransformer {
|
||||
if (packet == PacketType.PLAY_ENTITY_RELATIVE_MOVE) {
|
||||
int id = PacketUtil.readVarInt(input);
|
||||
PacketUtil.writeVarInt(id, output);
|
||||
int x = input.readByte();
|
||||
output.writeShort(x);
|
||||
int y = input.readByte();
|
||||
output.writeShort(y);
|
||||
int z = input.readByte();
|
||||
output.writeShort(z);
|
||||
short x = (short) (input.readByte());
|
||||
output.writeShort(x * 128);
|
||||
short y = (short) (input.readByte());
|
||||
output.writeShort(y * 128);
|
||||
short z = (short) (input.readByte());
|
||||
output.writeShort(z * 128);
|
||||
|
||||
boolean onGround = input.readBoolean();
|
||||
output.writeBoolean(onGround);
|
||||
@@ -146,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;
|
||||
}
|
||||
@@ -161,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);
|
||||
@@ -172,15 +212,9 @@ public class OutgoingTransformer {
|
||||
PacketUtil.writeVarInt(id, output);
|
||||
|
||||
try {
|
||||
List dw = Core.getPrivateField(info.getLastPacket(), "b", List.class);
|
||||
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) {
|
||||
@@ -188,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();
|
||||
@@ -211,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();
|
||||
@@ -236,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();
|
||||
@@ -263,19 +359,44 @@ public class OutgoingTransformer {
|
||||
short vZ = input.readShort();
|
||||
output.writeShort(vZ);
|
||||
try {
|
||||
DataWatcher dw = Core.getPrivateField(info.getLastPacket(), "l", DataWatcher.class);
|
||||
transformMetadata(dw, output);
|
||||
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "l", ReflectionUtil.nms("DataWatcher"));
|
||||
transformMetadata(id, dataWatcher, output);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (packet == PacketType.PLAY_UPDATE_SIGN) {
|
||||
Long location = input.readLong();
|
||||
output.writeLong(location);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
String line = PacketUtil.readString(input);
|
||||
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);
|
||||
|
||||
@@ -290,22 +411,46 @@ public class OutgoingTransformer {
|
||||
output.writeByte(pitch);
|
||||
byte yaw = input.readByte();
|
||||
output.writeByte(yaw);
|
||||
// We don't use currentItem short lel
|
||||
|
||||
// transform entity meta data ugh
|
||||
// get data watcher
|
||||
try {
|
||||
System.out.println("Last Packet Type: " + info.getLastPacket().getClass().getName());
|
||||
DataWatcher dw = Core.getPrivateField(info.getLastPacket(), "i", DataWatcher.class);
|
||||
transformMetadata(dw, output);
|
||||
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "i", ReflectionUtil.nms("DataWatcher"));
|
||||
transformMetadata(id, dataWatcher, output);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (packet == PacketType.PLAY_MAP) {
|
||||
int damage = PacketUtil.readVarInt(input);
|
||||
PacketUtil.writeVarInt(damage, output);
|
||||
byte scale = input.readByte();
|
||||
output.writeByte(scale);
|
||||
output.writeBoolean(true);
|
||||
output.writeBytes(input);
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
PacketUtil.writeString(PacketUtil.readString(input), output);
|
||||
PacketUtil.writeString(PacketUtil.readString(input), output);
|
||||
PacketUtil.writeString(PacketUtil.readString(input), output);
|
||||
|
||||
output.writeByte(input.readByte());
|
||||
PacketUtil.writeString(PacketUtil.readString(input), output);
|
||||
|
||||
PacketUtil.writeString("", output); // collission rule :)
|
||||
}
|
||||
output.writeBytes(input);
|
||||
return;
|
||||
}
|
||||
if (packet == PacketType.PLAY_CHUNK_DATA) {
|
||||
// We need to catch unloading chunk packets as defined by wiki.vg
|
||||
// To unload chunks, send this packet with Ground-Up Continuous=true and no 16^3 chunks (eg. Primary Bit Mask=0)
|
||||
@@ -332,10 +477,9 @@ public class OutgoingTransformer {
|
||||
byte[] data = new byte[size];
|
||||
input.readBytes(data);
|
||||
boolean sk = false;
|
||||
if (info.getLastPacket() instanceof PacketPlayOutMapChunkBulk) {
|
||||
|
||||
if (info.getLastPacket().getClass().getName().endsWith("PacketPlayOutMapChunkBulk")) {
|
||||
try {
|
||||
sk = Core.getPrivateField(info.getLastPacket(), "d", boolean.class);
|
||||
sk = ReflectionUtil.get(info.getLastPacket(), "d", boolean.class);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -358,110 +502,143 @@ public class OutgoingTransformer {
|
||||
output.writeBytes(input);
|
||||
}
|
||||
|
||||
private void transformMetadata(DataWatcher 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 {
|
||||
transformMetadata(Core.getPrivateField(dw, "a", Entity.class), 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();
|
||||
}
|
||||
}
|
||||
|
||||
private void transformMetadata(Entity entity, List<DataWatcher.WatchableObject> dw, ByteBuf output) {
|
||||
PacketDataSerializer packetdataserializer = new PacketDataSerializer(output);
|
||||
|
||||
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<DataWatcher.WatchableObject> iterator = dw.iterator();
|
||||
Iterator iterator = dw.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
DataWatcher.WatchableObject obj = iterator.next();
|
||||
MetaIndex metaIndex = MetaIndex.getIndex(entity, obj.a());
|
||||
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());
|
||||
output.writeByte(metaIndex.getNewType().getTypeID());
|
||||
}
|
||||
switch (metaIndex.getNewType()) {
|
||||
case Byte:
|
||||
// convert from int, byte
|
||||
if (metaIndex.getOldType() == Type.Byte) {
|
||||
packetdataserializer.writeByte(((Byte) obj.b()).byteValue());
|
||||
}
|
||||
if (metaIndex.getOldType() == Type.Int) {
|
||||
packetdataserializer.writeByte(((Integer) obj.b()).byteValue());
|
||||
}
|
||||
break;
|
||||
case OptUUID:
|
||||
String owner = (String) obj.b();
|
||||
UUID toWrite = null;
|
||||
if (owner.length() != 0) {
|
||||
try {
|
||||
toWrite = UUID.fromString(owner);
|
||||
} catch (Exception ignored) {
|
||||
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());
|
||||
output.writeByte(metaIndex.getNewType().getTypeID());
|
||||
}
|
||||
Object value = ReflectionUtil.invoke(watchableObj, "b");
|
||||
switch (metaIndex.getNewType()) {
|
||||
case Byte:
|
||||
// convert from int, byte
|
||||
if (metaIndex.getOldType() == Type.Byte) {
|
||||
output.writeByte(((Byte) value).byteValue());
|
||||
}
|
||||
}
|
||||
packetdataserializer.writeBoolean(toWrite != null);
|
||||
if (toWrite != null)
|
||||
packetdataserializer.a(toWrite);
|
||||
break;
|
||||
case BlockID:
|
||||
// if we have both sources :))
|
||||
if (metaIndex.getOldType() == Type.Byte) {
|
||||
data = ((Byte) obj.b()).byteValue();
|
||||
}
|
||||
if (metaIndex.getOldType() == Type.Short) {
|
||||
id = ((Short) obj.b()).shortValue();
|
||||
}
|
||||
if (id != -1 && data != -1) {
|
||||
int combined = id << 4 | data;
|
||||
data = -1;
|
||||
id = -1;
|
||||
PacketUtil.writeVarInt(combined, output);
|
||||
}
|
||||
break;
|
||||
case VarInt:
|
||||
// convert from int, short, byte
|
||||
if (metaIndex.getOldType() == Type.Byte) {
|
||||
PacketUtil.writeVarInt(((Byte) obj.b()).intValue(), output);
|
||||
}
|
||||
if (metaIndex.getOldType() == Type.Short) {
|
||||
PacketUtil.writeVarInt(((Short) obj.b()).intValue(), output);
|
||||
}
|
||||
if (metaIndex.getOldType() == Type.Int) {
|
||||
PacketUtil.writeVarInt(((Integer) obj.b()).intValue(), output);
|
||||
}
|
||||
break;
|
||||
case Float:
|
||||
packetdataserializer.writeFloat(((Float) obj.b()).floatValue());
|
||||
break;
|
||||
case String:
|
||||
packetdataserializer.a((String) obj.b());
|
||||
break;
|
||||
case Boolean:
|
||||
packetdataserializer.writeBoolean(((Byte) obj.b()).byteValue() != 0);
|
||||
break;
|
||||
case Slot:
|
||||
ItemStack itemstack = (ItemStack) obj.b();
|
||||
packetdataserializer.a(itemstack);
|
||||
break;
|
||||
case Position:
|
||||
BlockPosition blockposition = (BlockPosition) obj.b();
|
||||
if (metaIndex.getOldType() == Type.Int) {
|
||||
output.writeByte(((Integer) value).byteValue());
|
||||
}
|
||||
break;
|
||||
case OptUUID:
|
||||
String owner = (String) value;
|
||||
UUID toWrite = null;
|
||||
if (owner.length() != 0) {
|
||||
try {
|
||||
toWrite = UUID.fromString(owner);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
output.writeBoolean(toWrite != null);
|
||||
if (toWrite != null)
|
||||
PacketUtil.writeUUID((UUID) toWrite, output);
|
||||
break;
|
||||
case BlockID:
|
||||
// if we have both sources :))
|
||||
if (metaIndex.getOldType() == Type.Byte) {
|
||||
data = ((Byte) value).byteValue();
|
||||
}
|
||||
if (metaIndex.getOldType() == Type.Short) {
|
||||
id = ((Short) value).shortValue();
|
||||
}
|
||||
if (id != -1 && data != -1) {
|
||||
int combined = id << 4 | data;
|
||||
data = -1;
|
||||
id = -1;
|
||||
PacketUtil.writeVarInt(combined, output);
|
||||
}
|
||||
break;
|
||||
case VarInt:
|
||||
// convert from int, short, byte
|
||||
if (metaIndex.getOldType() == Type.Byte) {
|
||||
PacketUtil.writeVarInt(((Byte) value).intValue(), output);
|
||||
}
|
||||
if (metaIndex.getOldType() == Type.Short) {
|
||||
PacketUtil.writeVarInt(((Short) value).intValue(), output);
|
||||
}
|
||||
if (metaIndex.getOldType() == Type.Int) {
|
||||
PacketUtil.writeVarInt(((Integer) value).intValue(), output);
|
||||
}
|
||||
break;
|
||||
case Float:
|
||||
output.writeFloat(((Float) value).floatValue());
|
||||
break;
|
||||
case String:
|
||||
PacketUtil.writeString((String) value, output);
|
||||
break;
|
||||
case Boolean:
|
||||
output.writeBoolean(((Byte) value).byteValue() != 0);
|
||||
break;
|
||||
case Slot:
|
||||
PacketUtil.writeItem(value, output);
|
||||
break;
|
||||
case Position:
|
||||
output.writeInt((int) ReflectionUtil.invoke(value, "getX"));
|
||||
output.writeInt((int) ReflectionUtil.invoke(value, "getY"));
|
||||
output.writeInt((int) ReflectionUtil.invoke(value, "getZ"));
|
||||
break;
|
||||
case Vector3F:
|
||||
output.writeFloat((float) ReflectionUtil.invoke(value, "getX"));
|
||||
output.writeFloat((float) ReflectionUtil.invoke(value, "getY"));
|
||||
output.writeFloat((float) ReflectionUtil.invoke(value, "getZ"));
|
||||
}
|
||||
|
||||
packetdataserializer.writeInt(blockposition.getX());
|
||||
packetdataserializer.writeInt(blockposition.getY());
|
||||
packetdataserializer.writeInt(blockposition.getZ());
|
||||
break;
|
||||
case Vector3F:
|
||||
Vector3f vector3f = (Vector3f) obj.b();
|
||||
|
||||
packetdataserializer.writeFloat(vector3f.getX());
|
||||
packetdataserializer.writeFloat(vector3f.getY());
|
||||
packetdataserializer.writeFloat(vector3f.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+67
-11
@@ -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;
|
||||
@@ -338,4 +354,44 @@ public class PacketUtil {
|
||||
return output;
|
||||
}
|
||||
|
||||
public static void writeItem(Object value, ByteBuf output) {
|
||||
try {
|
||||
Class<?> serializer = ReflectionUtil.nms("PacketDataSerializer");
|
||||
Object init = serializer.getDeclaredConstructor(ByteBuf.class).newInstance(output);
|
||||
Method toCall = init.getClass().getDeclaredMethod("a", ReflectionUtil.nms("ItemStack"));
|
||||
toCall.invoke(init, value);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package us.myles.ViaVersion.util;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ReflectionUtil {
|
||||
private static String BASE = Bukkit.getServer().getClass().getPackage().getName();
|
||||
private static String NMS = BASE.replace("org.bukkit.craftbukkit", "net.minecraft.server");
|
||||
|
||||
public static Class<?> nms(String className) throws ClassNotFoundException {
|
||||
return Class.forName(NMS + "." + className);
|
||||
}
|
||||
public static Class<?> obc(String className) throws ClassNotFoundException {
|
||||
return Class.forName(BASE + "." + className);
|
||||
}
|
||||
|
||||
public static Object invokeStatic(Class<?> clazz, String method) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
Method m = clazz.getDeclaredMethod(method);
|
||||
return m.invoke(null);
|
||||
}
|
||||
|
||||
public static Object invoke(Object o, String method) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
Method m = o.getClass().getDeclaredMethod(method);
|
||||
return m.invoke(o);
|
||||
}
|
||||
|
||||
public static <T> T get(Object o, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
return (T) field.get(o);
|
||||
}
|
||||
|
||||
public static void set(Object o, String f, Object value) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
field.set(o, value);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
Howdy Partner:
|
||||
|
||||
[-] Fix arrows going down.
|
||||
[-] Make teleport relative if not 1024 diff.
|
||||
[-] Fix boats / minecarts if possible otherwise tell them nicely they don't work.
|
||||
[-] Cry because how long it took to get this far haha.
|
||||
[-] Clean up so we're not using NMS and more reflection based :)
|
||||
@@ -1,4 +1,6 @@
|
||||
name: ViaVersion
|
||||
main: us.myles.ViaVersion.Core
|
||||
main: us.myles.ViaVersion.ViaVersionPlugin
|
||||
author: _MylesC
|
||||
version: 0.1
|
||||
version: 0.4.2
|
||||
load: startup
|
||||
loadbefore: [ProtocolLib, ProxyPipe]
|
||||
Reference in new issue
Block a user