Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f91fcb4ea8 | ||
|
|
b3060e0dc8 | ||
|
|
808a9a7d82 | ||
|
|
32c43e6023 | ||
|
|
4c9c50f939 | ||
|
|
ac1b35379e | ||
|
|
b743589d77 | ||
|
|
9dad0a0d5e | ||
|
|
f5b49bc9ce | ||
|
|
b3612a68b0 | ||
|
|
7385db02c2 | ||
|
|
501d2ec3a2 | ||
|
|
1217a9b7e2 | ||
|
|
6740c5c6dc | ||
|
|
44e8056fb3 | ||
|
|
d1da412cf7 | ||
|
|
6534a5414e | ||
|
|
91344a0b50 | ||
|
|
cdd9ff4469 | ||
|
|
d88b76db85 | ||
|
|
27d6c12556 | ||
|
|
a76dd1ba49 | ||
|
|
1a4388b3e7 | ||
|
|
f1b81f77d6 | ||
|
|
094f4c6d58 |
No files matched your search
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion</artifactId>
|
||||
<version>0.9.3</version>
|
||||
<version>0.9.4</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ViaVersion</name>
|
||||
|
||||
@@ -87,7 +87,7 @@ public class ViaConfig implements ViaVersionConfig {
|
||||
|
||||
@Override
|
||||
public double getHologramYOffset() {
|
||||
return plugin.getConfig().getDouble("hologram-y", -1D);
|
||||
return plugin.getConfig().getDouble("hologram-y", -0.96D);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,6 +28,7 @@ import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.update.UpdateListener;
|
||||
import us.myles.ViaVersion.update.UpdateUtil;
|
||||
import us.myles.ViaVersion.util.ListWrapper;
|
||||
import us.myles.ViaVersion.util.ProtocolSupportUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@@ -48,6 +49,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
||||
private boolean compatSpigotBuild = false;
|
||||
private boolean spigot = true;
|
||||
private boolean lateBind = false;
|
||||
private boolean protocolSupport = false;
|
||||
@Getter
|
||||
private ViaConfig conf;
|
||||
|
||||
@@ -56,6 +58,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
||||
// Config magic
|
||||
conf = new ViaConfig(this);
|
||||
ViaVersion.setInstance(this);
|
||||
|
||||
// Handle reloads
|
||||
if (System.getProperty("ViaVersion") != null) {
|
||||
if (Bukkit.getPluginManager().getPlugin("ProtocolLib") != null) {
|
||||
@@ -69,19 +72,25 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Spigot detector
|
||||
try {
|
||||
Class.forName("org.spigotmc.SpigotConfig");
|
||||
} catch (ClassNotFoundException e) {
|
||||
spigot = false;
|
||||
}
|
||||
|
||||
// Check if it's a spigot build with a protocol mod
|
||||
try {
|
||||
compatSpigotBuild = ReflectionUtil.nms("PacketEncoder").getDeclaredField("version") != null;
|
||||
} catch (Exception e) {
|
||||
compatSpigotBuild = false;
|
||||
}
|
||||
// Generate classes needed (only works if it's compat)
|
||||
|
||||
// Check if we're using protocol support too
|
||||
protocolSupport = Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null;
|
||||
|
||||
// Generate classes needed (only works if it's compat or ps)
|
||||
ClassGenerator.generate();
|
||||
lateBind = !isBinded();
|
||||
|
||||
@@ -329,17 +338,25 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
||||
@Override
|
||||
public int getPlayerVersion(@NonNull Player player) {
|
||||
if (!isPorted(player))
|
||||
return ProtocolRegistry.SERVER_PROTOCOL;
|
||||
return getExternalVersion(player);
|
||||
return portedPlayers.get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerVersion(@NonNull UUID uuid) {
|
||||
if (!isPorted(uuid))
|
||||
return ProtocolRegistry.SERVER_PROTOCOL;
|
||||
return getExternalVersion(Bukkit.getPlayer(uuid));
|
||||
return portedPlayers.get(uuid).get(ProtocolInfo.class).getProtocolVersion();
|
||||
}
|
||||
|
||||
private int getExternalVersion(Player player) {
|
||||
if (!isProtocolSupport()) {
|
||||
return ProtocolRegistry.SERVER_PROTOCOL;
|
||||
} else {
|
||||
return ProtocolSupportUtil.getProtocolVersion(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPorted(UUID playerUUID) {
|
||||
return portedPlayers.containsKey(playerUUID);
|
||||
@@ -435,6 +452,10 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isProtocolSupport() {
|
||||
return protocolSupport;
|
||||
}
|
||||
|
||||
public Map<UUID, UserConnection> getPortedPlayers() {
|
||||
return portedPlayers;
|
||||
}
|
||||
@@ -443,7 +464,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
||||
// Max PPS Checker
|
||||
if (conf.getMaxPPS() > 0) {
|
||||
if (info.getPacketsPerSecond() >= conf.getMaxPPS()) {
|
||||
info.disconnect(conf.getMaxPPSKickMessage());
|
||||
info.disconnect(conf.getMaxPPSKickMessage().replace("%pps", ((Long) info.getPacketsPerSecond()).intValue() + ""));
|
||||
return true; // don't send current packet
|
||||
}
|
||||
}
|
||||
@@ -461,7 +482,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
||||
}
|
||||
|
||||
if (info.getWarnings() >= conf.getMaxWarnings()) {
|
||||
info.disconnect(conf.getMaxWarningsKickMessage());
|
||||
info.disconnect(conf.getMaxWarningsKickMessage().replace("%pps", ((Long) info.getPacketsPerSecond()).intValue() + ""));
|
||||
return true; // don't send current packet
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package us.myles.ViaVersion.api;
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
@@ -84,6 +83,27 @@ public class PacketWrapper {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a type is at an index
|
||||
*
|
||||
* @param type The type of the part you wish to get.
|
||||
* @param index The index of the part (relative to the type)
|
||||
* @return True if the type is at the index
|
||||
*/
|
||||
public boolean isReadable(Type type, int index) {
|
||||
int currentIndex = 0;
|
||||
for (Pair<Type, Object> packetValue : readableObjects) {
|
||||
if (packetValue.getKey().getBaseClass() == type.getBaseClass()) { // Ref check
|
||||
if (currentIndex == index) {
|
||||
return true;
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a currently existing part in the output
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@ public interface ViaVersionAPI {
|
||||
|
||||
/**
|
||||
* Get protocol number from a player
|
||||
* Will also retrieve version from ProtocolSupport if it's being used.
|
||||
*
|
||||
* @param player Bukkit player object
|
||||
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
|
||||
@@ -120,9 +121,17 @@ public interface ViaVersionAPI {
|
||||
|
||||
/**
|
||||
* Gets if the server uses spigot
|
||||
*
|
||||
* <p>
|
||||
* Note: Will only work after ViaVersion load
|
||||
*
|
||||
* @return True if spigot
|
||||
*/
|
||||
boolean isSpigot();
|
||||
|
||||
/**
|
||||
* Gets if protocol support is also being used.
|
||||
*
|
||||
* @return True if it is being used.
|
||||
*/
|
||||
boolean isProtocolSupport();
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public abstract class ViaSubCommand {
|
||||
public List<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
public String color(String s) {
|
||||
return ViaCommandHandler.color(s);
|
||||
}
|
||||
|
||||
@@ -1,38 +1,4 @@
|
||||
package us.myles.ViaVersion.api.minecraft.chunks;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
public class Chunk {
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final boolean groundUp;
|
||||
private final int primaryBitmask;
|
||||
private final ChunkSection[] sections;
|
||||
private final byte[] biomeData;
|
||||
private boolean unloadPacket = false;
|
||||
|
||||
/**
|
||||
* Chunk unload.
|
||||
*
|
||||
* @param x coord
|
||||
* @param z coord
|
||||
*/
|
||||
public Chunk(int x, int z) {
|
||||
this(x, z, true, 0, new ChunkSection[16], null);
|
||||
this.unloadPacket = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this chunk have biome data
|
||||
*
|
||||
* @return True if the chunk has biome data
|
||||
*/
|
||||
public boolean hasBiomeData() {
|
||||
return biomeData != null && groundUp;
|
||||
}
|
||||
public interface Chunk {
|
||||
}
|
||||
@@ -92,20 +92,21 @@ public class ProtocolPipeline extends Protocol {
|
||||
} else {
|
||||
type = PacketType.findNewPacket(state, direction, originalID);
|
||||
}
|
||||
if (type != null) {
|
||||
// Filter :) This would be not hard coded too, sorry :(
|
||||
if (type == PacketType.PLAY_CHUNK_DATA) return;
|
||||
if (type == PacketType.PLAY_TIME_UPDATE) return;
|
||||
if (type == PacketType.PLAY_KEEP_ALIVE) return;
|
||||
if (type == PacketType.PLAY_KEEP_ALIVE_REQUEST) return;
|
||||
if (type == PacketType.PLAY_ENTITY_LOOK_MOVE) return;
|
||||
if (type == PacketType.PLAY_ENTITY_LOOK) return;
|
||||
if (type == PacketType.PLAY_ENTITY_RELATIVE_MOVE) return;
|
||||
if (type == PacketType.PLAY_PLAYER_POSITION_LOOK_REQUEST) return;
|
||||
if (type == PacketType.PLAY_PLAYER_LOOK_REQUEST) return;
|
||||
if (type == PacketType.PLAY_PLAYER_POSITION_REQUEST) return;
|
||||
|
||||
// Filter :) This would be not hard coded too, sorry :(
|
||||
if (type == PacketType.PLAY_CHUNK_DATA) return;
|
||||
if (type == PacketType.PLAY_TIME_UPDATE) return;
|
||||
if (type == PacketType.PLAY_KEEP_ALIVE) return;
|
||||
if (type == PacketType.PLAY_KEEP_ALIVE_REQUEST) return;
|
||||
if (type == PacketType.PLAY_ENTITY_LOOK_MOVE) return;
|
||||
if (type == PacketType.PLAY_ENTITY_LOOK) return;
|
||||
if (type == PacketType.PLAY_ENTITY_RELATIVE_MOVE) return;
|
||||
if (type == PacketType.PLAY_PLAYER_POSITION_LOOK_REQUEST) return;
|
||||
if (type == PacketType.PLAY_PLAYER_LOOK_REQUEST) return;
|
||||
if (type == PacketType.PLAY_PLAYER_POSITION_REQUEST) return;
|
||||
|
||||
packet = type.name();
|
||||
packet = type.name();
|
||||
}
|
||||
}
|
||||
String name = packet + "[" + userConnection.get(ProtocolInfo.class).getProtocolVersion() + "]";
|
||||
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
package us.myles.ViaVersion.api.protocol;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class ProtocolVersion {
|
||||
private static final Map<Integer, ProtocolVersion> versions = new HashMap<>();
|
||||
private static final List<ProtocolVersion> versionList = new ArrayList<>();
|
||||
|
||||
public static final ProtocolVersion v1_4_6;
|
||||
public static final ProtocolVersion v1_5_1;
|
||||
public static final ProtocolVersion v1_5_2;
|
||||
public static final ProtocolVersion v_1_6_1;
|
||||
public static final ProtocolVersion v_1_6_2;
|
||||
public static final ProtocolVersion v_1_6_3;
|
||||
public static final ProtocolVersion v_1_6_4;
|
||||
public static final ProtocolVersion v1_7_1;
|
||||
public static final ProtocolVersion v1_7_6;
|
||||
public static final ProtocolVersion v1_8;
|
||||
@@ -17,11 +27,21 @@ public class ProtocolVersion {
|
||||
public static final ProtocolVersion v1_9_2;
|
||||
public static final ProtocolVersion v1_9_3;
|
||||
public static final ProtocolVersion v1_10;
|
||||
public static final ProtocolVersion unknown;
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
|
||||
static {
|
||||
// Before netty rewrite
|
||||
register(v1_4_6 = new ProtocolVersion(51, "1.4.6"));
|
||||
register(v1_5_1 = new ProtocolVersion(60, "1.5.1"));
|
||||
register(v1_5_2 = new ProtocolVersion(61, "1.5.2"));
|
||||
register(v_1_6_1 = new ProtocolVersion(73, "1.6.1"));
|
||||
register(v_1_6_2 = new ProtocolVersion(74, "1.6.2"));
|
||||
register(v_1_6_3 = new ProtocolVersion(77, "1.6.3"));
|
||||
register(v_1_6_4 = new ProtocolVersion(78, "1.6.4"));
|
||||
// After netty rewrite
|
||||
register(v1_7_1 = new ProtocolVersion(4, "1.7-1.7.5"));
|
||||
register(v1_7_6 = new ProtocolVersion(5, "1.7.6-1.7.10"));
|
||||
register(v1_8 = new ProtocolVersion(47, "1.8.x"));
|
||||
@@ -30,10 +50,12 @@ public class ProtocolVersion {
|
||||
register(v1_9_2 = new ProtocolVersion(109, "1.9.2"));
|
||||
register(v1_9_3 = new ProtocolVersion(110, "1.9.3/4"));
|
||||
register(v1_10 = new ProtocolVersion(210, "1.10"));
|
||||
register(unknown = new ProtocolVersion(-1, "UNKNOWN"));
|
||||
}
|
||||
|
||||
public static void register(@NonNull ProtocolVersion protocol) {
|
||||
versions.put(protocol.getId(), protocol);
|
||||
versionList.add(protocol);
|
||||
}
|
||||
|
||||
public static boolean isRegistered(int id) {
|
||||
@@ -48,7 +70,25 @@ public class ProtocolVersion {
|
||||
}
|
||||
}
|
||||
|
||||
public static int getIndex(ProtocolVersion version) {
|
||||
return versionList.indexOf(version);
|
||||
}
|
||||
|
||||
public static List<ProtocolVersion> getProtocols() {
|
||||
return Collections.unmodifiableList(new ArrayList<>(versions.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ProtocolVersion that = (ProtocolVersion) o;
|
||||
return id == that.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,7 @@ import us.myles.ViaVersion.api.minecraft.item.Item;
|
||||
import us.myles.ViaVersion.api.type.types.*;
|
||||
import us.myles.ViaVersion.api.type.types.minecraft.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@@ -61,6 +60,7 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
|
||||
public static final Type<EulerAngle> ROTATION = new EulerAngleType();
|
||||
public static final Type<Vector> VECTOR = new VectorType();
|
||||
public static final Type<CompoundTag> NBT = new NBTType();
|
||||
public static final Type<CompoundTag[]> NBT_ARRAY = new ArrayType<>(Type.NBT);
|
||||
|
||||
public static final Type<UUID> OPTIONAL_UUID = new OptUUIDType();
|
||||
public static final Type<Position> OPTIONAL_POSITION = new OptPositionType();
|
||||
@@ -70,7 +70,6 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
|
||||
/* Actual Class */
|
||||
|
||||
private final Class<? super T> outputClass;
|
||||
private final Set<Class<? extends Type>> compatibilities;
|
||||
private final String typeName;
|
||||
|
||||
public Type(Class<? super T> outputClass) {
|
||||
@@ -80,7 +79,6 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
|
||||
public Type(String typeName, Class<? super T> outputClass) {
|
||||
this.outputClass = outputClass;
|
||||
this.typeName = typeName;
|
||||
this.compatibilities = new HashSet<>();
|
||||
}
|
||||
|
||||
public Class<? extends Type> getBaseClass() {
|
||||
|
||||
@@ -13,38 +13,9 @@ public class ArrayType<T> extends Type<T[]> {
|
||||
this.elementType = type;
|
||||
}
|
||||
|
||||
/* Taken from http://stackoverflow.com/questions/4901128/obtaining-the-array-class-of-a-component-type */
|
||||
public static Class<?> getArrayClass(Class<?> componentType) {
|
||||
ClassLoader classLoader = componentType.getClassLoader();
|
||||
String name;
|
||||
if (componentType.isArray()) {
|
||||
// just add a leading "["
|
||||
name = "[" + componentType.getName();
|
||||
} else if (componentType == boolean.class) {
|
||||
name = "[Z";
|
||||
} else if (componentType == byte.class) {
|
||||
name = "[B";
|
||||
} else if (componentType == char.class) {
|
||||
name = "[C";
|
||||
} else if (componentType == double.class) {
|
||||
name = "[D";
|
||||
} else if (componentType == float.class) {
|
||||
name = "[F";
|
||||
} else if (componentType == int.class) {
|
||||
name = "[I";
|
||||
} else if (componentType == long.class) {
|
||||
name = "[J";
|
||||
} else if (componentType == short.class) {
|
||||
name = "[S";
|
||||
} else {
|
||||
// must be an object non-array class
|
||||
name = "[L" + componentType.getName() + ";";
|
||||
}
|
||||
try {
|
||||
return classLoader != null ? classLoader.loadClass(name) : Class.forName(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null; // oh
|
||||
}
|
||||
// Should only happen once per class init.
|
||||
return Array.newInstance(componentType, 0).getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package us.myles.ViaVersion.api.type.types.minecraft;
|
||||
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
public abstract class BaseChunkType extends Type<Chunk> {
|
||||
public BaseChunkType() {
|
||||
super(Chunk.class);
|
||||
}
|
||||
|
||||
public BaseChunkType(String typeName) {
|
||||
super(typeName, Chunk.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Type> getBaseClass() {
|
||||
return BaseChunkType.class;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package us.myles.ViaVersion.classgenerator;
|
||||
import javassist.*;
|
||||
import javassist.expr.ConstructorCall;
|
||||
import javassist.expr.ExprEditor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
|
||||
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
|
||||
@@ -10,72 +12,93 @@ import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
public class ClassGenerator {
|
||||
private static HandlerConstructor constructor = new BasicHandlerConstructor();
|
||||
private static String psPackage = null;
|
||||
|
||||
public static HandlerConstructor getConstructor() {
|
||||
return constructor;
|
||||
}
|
||||
|
||||
public static void generate() {
|
||||
if(!ViaVersion.getInstance().isCompatSpigotBuild()) return; // Use Basic Handler as not needed.
|
||||
if (ViaVersion.getInstance().isCompatSpigotBuild() || ViaVersion.getInstance().isProtocolSupport()) {
|
||||
try {
|
||||
ClassPool pool = ClassPool.getDefault();
|
||||
for (Plugin p : Bukkit.getPluginManager().getPlugins()) {
|
||||
pool.insertClassPath(new LoaderClassPath(p.getClass().getClassLoader()));
|
||||
}
|
||||
|
||||
try {
|
||||
ClassPool pool = ClassPool.getDefault();
|
||||
pool.insertClassPath(new LoaderClassPath(ClassGenerator.class.getClassLoader()));
|
||||
// Generate the classes
|
||||
transformSuperclass(pool, ViaDecodeHandler.class, ReflectionUtil.nms("PacketDecoder"));
|
||||
transformSuperclass(pool, ViaEncodeHandler.class, ReflectionUtil.nms("PacketEncoder"));
|
||||
if (ViaVersion.getInstance().isCompatSpigotBuild()) {
|
||||
Class decodeSuper = ReflectionUtil.nms("PacketDecoder");
|
||||
Class encodeSuper = ReflectionUtil.nms("PacketEncoder");
|
||||
// Generate the classes
|
||||
addSpigotCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
|
||||
addSpigotCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
|
||||
} else {
|
||||
Class decodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedDecoder");
|
||||
Class encodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedEncoder");
|
||||
// Generate the classes
|
||||
addPSCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
|
||||
addPSCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
|
||||
}
|
||||
|
||||
// Implement Constructor
|
||||
CtClass generated = pool.makeClass("us.myles.ViaVersion.classgenerator.generated.GeneratedConstructor");
|
||||
CtClass handlerInterface = pool.get(HandlerConstructor.class.getName());
|
||||
|
||||
generated.setInterfaces(new CtClass[]{handlerInterface});
|
||||
// Import required classes
|
||||
pool.importPackage("us.myles.ViaVersion.classgenerator.generated");
|
||||
pool.importPackage("us.myles.ViaVersion.classgenerator");
|
||||
pool.importPackage("us.myles.ViaVersion.api.data");
|
||||
pool.importPackage("io.netty.handler.codec");
|
||||
// Implement Methods
|
||||
generated.addMethod(CtMethod.make("public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {\n" +
|
||||
" return new ViaEncodeHandler(info, minecraftEncoder);\n" +
|
||||
" }", generated));
|
||||
generated.addMethod(CtMethod.make("public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {\n" +
|
||||
" return new ViaDecodeHandler(info, minecraftDecoder);\n" +
|
||||
" }", generated));
|
||||
// Implement Constructor
|
||||
CtClass generated = pool.makeClass("us.myles.ViaVersion.classgenerator.generated.GeneratedConstructor");
|
||||
CtClass handlerInterface = pool.get(HandlerConstructor.class.getName());
|
||||
|
||||
constructor = (HandlerConstructor) generated.toClass(HandlerConstructor.class.getClassLoader()).newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CannotCompileException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
generated.setInterfaces(new CtClass[]{handlerInterface});
|
||||
// Import required classes
|
||||
pool.importPackage("us.myles.ViaVersion.classgenerator.generated");
|
||||
pool.importPackage("us.myles.ViaVersion.classgenerator");
|
||||
pool.importPackage("us.myles.ViaVersion.api.data");
|
||||
pool.importPackage("io.netty.handler.codec");
|
||||
// Implement Methods
|
||||
generated.addMethod(CtMethod.make("public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {\n" +
|
||||
" return new ViaEncodeHandler(info, minecraftEncoder);\n" +
|
||||
" }", generated));
|
||||
generated.addMethod(CtMethod.make("public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {\n" +
|
||||
" return new ViaDecodeHandler(info, minecraftDecoder);\n" +
|
||||
" }", generated));
|
||||
|
||||
constructor = (HandlerConstructor) generated.toClass(HandlerConstructor.class.getClassLoader()).newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CannotCompileException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Class transformSuperclass(ClassPool pool, Class input, Class superclass) {
|
||||
private static Class addSpigotCompatibility(ClassPool pool, Class input, Class superclass) {
|
||||
String newName = "us.myles.ViaVersion.classgenerator.generated." + input.getSimpleName();
|
||||
|
||||
try {
|
||||
CtClass toExtend = pool.get(superclass.getName());
|
||||
CtClass generated = pool.getAndRename(input.getName(), newName);
|
||||
generated.setSuperclass(toExtend);
|
||||
// Modify constructor to call super
|
||||
if(generated.getConstructors().length != 0) {
|
||||
generated.getConstructors()[0].instrument(new ExprEditor() {
|
||||
@Override
|
||||
public void edit(ConstructorCall c) throws CannotCompileException {
|
||||
if (c.isSuper()) {
|
||||
// Constructor for both has a stats thing.
|
||||
c.replace("super(null);");
|
||||
}
|
||||
super.edit(c);
|
||||
if (superclass != null) {
|
||||
CtClass toExtend = pool.get(superclass.getName());
|
||||
generated.setSuperclass(toExtend);
|
||||
|
||||
// If it's NMS satisfy constructor.
|
||||
if (superclass.getName().startsWith("net.minecraft")) {
|
||||
// Modify constructor to call super
|
||||
if (generated.getConstructors().length != 0) {
|
||||
generated.getConstructors()[0].instrument(new ExprEditor() {
|
||||
@Override
|
||||
public void edit(ConstructorCall c) throws CannotCompileException {
|
||||
if (c.isSuper()) {
|
||||
// Constructor for both has a stats thing.
|
||||
c.replace("super(null);");
|
||||
}
|
||||
super.edit(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return generated.toClass(HandlerConstructor.class.getClassLoader());
|
||||
} catch (NotFoundException e) {
|
||||
@@ -85,4 +108,58 @@ public class ClassGenerator {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Class addPSCompatibility(ClassPool pool, Class input, Class superclass) {
|
||||
String newName = "us.myles.ViaVersion.classgenerator.generated." + input.getSimpleName();
|
||||
|
||||
try {
|
||||
CtClass generated = pool.getAndRename(input.getName(), newName);
|
||||
if (superclass != null) {
|
||||
CtClass toExtend = pool.get(superclass.getName());
|
||||
generated.setSuperclass(toExtend);
|
||||
|
||||
// Override setRealEncoder / setRealDecoder
|
||||
pool.importPackage(getPSPackage());
|
||||
pool.importPackage(getPSPackage() + ".wrapped");
|
||||
if (superclass.getName().endsWith("Decoder")) {
|
||||
// Decoder
|
||||
generated.addMethod(CtMethod.make("public void setRealDecoder(IPacketDecoder dec) {\n" +
|
||||
" WrappedDecoder decoder = new WrappedDecoder();" +
|
||||
" decoder.setRealDecoder(dec);\n" +
|
||||
" this.minecraftDecoder = decoder;\n" +
|
||||
" }", generated));
|
||||
} else {
|
||||
// Encoder
|
||||
generated.addMethod(CtMethod.make("public void setRealEncoder(IPacketEncoder enc) {\n" +
|
||||
" WrappedEncoder encoder = new WrappedEncoder();" +
|
||||
" encoder.setRealEncoder(enc);\n" +
|
||||
" this.minecraftEncoder = encoder;\n" +
|
||||
" }", generated));
|
||||
}
|
||||
}
|
||||
return generated.toClass(HandlerConstructor.class.getClassLoader());
|
||||
} catch (NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CannotCompileException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getPSPackage() {
|
||||
if (psPackage == null) {
|
||||
try {
|
||||
Class.forName("protocolsupport.protocol.core.IPacketDecoder");
|
||||
psPackage = "protocolsupport.protocol.core";
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
Class.forName("protocolsupport.protocol.pipeline.IPacketDecoder");
|
||||
psPackage = "protocolsupport.protocol.pipeline";
|
||||
} catch (ClassNotFoundException e1) {
|
||||
psPackage = "unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
return psPackage;
|
||||
}
|
||||
}
|
||||
@@ -6,5 +6,6 @@ import us.myles.ViaVersion.api.data.UserConnection;
|
||||
|
||||
public interface HandlerConstructor {
|
||||
public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder);
|
||||
|
||||
public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder);
|
||||
}
|
||||
@@ -27,19 +27,25 @@ public class ListSubCmd extends ViaSubCommand {
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String[] args) {
|
||||
Map<Integer, Set<String>> playerVersions = new HashMap<>();
|
||||
Map<ProtocolVersion, Set<String>> playerVersions = new TreeMap<>(new Comparator<ProtocolVersion>() {
|
||||
@Override
|
||||
public int compare(ProtocolVersion o1, ProtocolVersion o2) {
|
||||
return ProtocolVersion.getIndex(o2) - ProtocolVersion.getIndex(o1);
|
||||
}
|
||||
});
|
||||
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
int playerVersion = ViaVersion.getInstance().getPlayerVersion(p);
|
||||
if (!playerVersions.containsKey(playerVersion))
|
||||
playerVersions.put(playerVersion, new HashSet<String>());
|
||||
playerVersions.get(playerVersion).add(p.getName());
|
||||
ProtocolVersion key = ProtocolVersion.getProtocol(playerVersion);
|
||||
if (!playerVersions.containsKey(key))
|
||||
playerVersions.put(key, new HashSet<String>());
|
||||
playerVersions.get(key).add(p.getName());
|
||||
}
|
||||
Map<Integer, Set<String>> sorted = new TreeMap<>(playerVersions);
|
||||
|
||||
for (Map.Entry<Integer, Set<String>> entry : sorted.entrySet())
|
||||
sendMessage(sender, "&8[&6%s&8]: &b%s", ProtocolVersion.getProtocol(entry.getKey()).getName(), entry.getValue());
|
||||
for (Map.Entry<ProtocolVersion, Set<String>> entry : playerVersions.entrySet())
|
||||
sendMessage(sender, "&8[&6%s&8]: &b%s", entry.getKey().getName(), entry.getValue());
|
||||
|
||||
sorted.clear();
|
||||
playerVersions.clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,9 @@ public class PPSSubCmd extends ViaSubCommand {
|
||||
sendMessage(sender, "&cAverage: &f" + (totalPackets / clients));
|
||||
sendMessage(sender, "&cHighest: &f" + max);
|
||||
}
|
||||
if (clients == 0) {
|
||||
sendMessage(sender, "&cNo clients to display.");
|
||||
}
|
||||
for (Map.Entry<Integer, Set<String>> entry : sorted.entrySet())
|
||||
sendMessage(sender, "&8[&6%s&8]: &b%s", ProtocolVersion.getProtocol(entry.getKey()).getName(), entry.getValue());
|
||||
sorted.clear();
|
||||
|
||||
@@ -38,7 +38,7 @@ public class ViaDecodeHandler extends ByteToMessageDecoder {
|
||||
// Increment received
|
||||
boolean second = info.incrementReceived();
|
||||
// Check PPS
|
||||
if(second) {
|
||||
if (second) {
|
||||
if (((ViaVersionPlugin) ViaVersion.getInstance()).handlePPS(info))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ public class ViaPacketHandler extends MessageToMessageEncoder {
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, Object o, List list) throws Exception {
|
||||
// Split chunk bulk packet up in to single chunk packets before it reached the encoder.
|
||||
// This will prevent issues with several plugins and other protocol handlers due to the chunk being sent twice.
|
||||
// It also sends the chunk in the right order possible resolving some issues with added chunk/block/entity data.
|
||||
// Split chunks bulk packet up in to single chunks packets before it reached the encoder.
|
||||
// This will prevent issues with several plugins and other protocol handlers due to the chunks being sent twice.
|
||||
// It also sends the chunks in the right order possible resolving some issues with added chunks/block/entity data.
|
||||
if (!(o instanceof ByteBuf)) {
|
||||
info.setLastPacket(o);
|
||||
/* This transformer is more for fixing issues which we find hard at packet level :) */
|
||||
|
||||
@@ -19,6 +19,7 @@ import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
import us.myles.ViaVersion.api.remapper.PacketHandler;
|
||||
import us.myles.ViaVersion.api.remapper.PacketRemapper;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
|
||||
import java.util.List;
|
||||
@@ -170,4 +171,15 @@ public class BaseProtocol extends Protocol {
|
||||
}
|
||||
}, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
|
||||
super.transform(direction, state, packetWrapper);
|
||||
if (direction == Direction.INCOMING && state == State.HANDSHAKE) {
|
||||
// Disable if it isn't a handshake packet.
|
||||
if (packetWrapper.getId() > 0) {
|
||||
packetWrapper.user().setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,8 +10,8 @@ import us.myles.ViaVersion.api.remapper.ValueTransformer;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.storage.ResourcePackTracker;
|
||||
import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.types.MetaList1_10Type;
|
||||
import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.types.Meta1_10Type;
|
||||
import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.types.MetaList1_10Type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
+1
-3
@@ -52,8 +52,6 @@ public class BlockEntity {
|
||||
|
||||
Position pos = new Position((long) x, (long) y, (long) z);
|
||||
|
||||
//Sorry, the PacketWrapper class wil handle this in the future
|
||||
//TODO let the packetwrapper class handle it
|
||||
if (newId != 9) {
|
||||
updateBlockEntity(pos, (short) newId, tag, connection);
|
||||
} else {
|
||||
@@ -63,7 +61,7 @@ public class BlockEntity {
|
||||
updateSign(pos, lines, connection);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if(ViaVersion.getInstance().isDebug()) {
|
||||
if (ViaVersion.getInstance().isDebug()) {
|
||||
System.out.println("Block Entity: " + e.getMessage() + ": " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -3,12 +3,13 @@ package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class Chunk1_9_3_4 {
|
||||
public class Chunk1_9_3_4 implements Chunk {
|
||||
private int x;
|
||||
private int z;
|
||||
private boolean groundUp;
|
||||
|
||||
+10
-4
@@ -2,18 +2,20 @@ package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.api.type.types.minecraft.BaseChunkType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Chunk1_9_3_4Type extends Type<Chunk1_9_3_4> {
|
||||
public class Chunk1_9_3_4Type extends BaseChunkType {
|
||||
public Chunk1_9_3_4Type() {
|
||||
super("1.9.3 Chunk", Chunk1_9_3_4.class);
|
||||
super("1.9.3 Chunk");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk1_9_3_4 read(ByteBuf input) throws Exception {
|
||||
public Chunk read(ByteBuf input) throws Exception {
|
||||
int chunkX = input.readInt();
|
||||
int chunkZ = input.readInt();
|
||||
|
||||
@@ -33,7 +35,11 @@ public class Chunk1_9_3_4Type extends Type<Chunk1_9_3_4> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Chunk1_9_3_4 chunk) throws Exception {
|
||||
public void write(ByteBuf buffer, Chunk input) throws Exception {
|
||||
if (!(input instanceof Chunk1_9_3_4))
|
||||
throw new Exception("Tried to send the wrong chunk type from 1.9.3-4 chunk: " + input.getClass());
|
||||
Chunk1_9_3_4 chunk = (Chunk1_9_3_4) input;
|
||||
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
|
||||
|
||||
+4
-3
@@ -4,6 +4,7 @@ import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.minecraft.Position;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
import us.myles.ViaVersion.api.remapper.PacketHandler;
|
||||
import us.myles.ViaVersion.api.remapper.PacketRemapper;
|
||||
@@ -11,7 +12,7 @@ import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
|
||||
public class Protocol1_9_1_2TO1_9_3_4 extends Protocol {
|
||||
public static Type<Chunk1_9_3_4> CHUNK = new Chunk1_9_3_4Type();
|
||||
public static Type<Chunk> CHUNK = new Chunk1_9_3_4Type();
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
@@ -56,8 +57,8 @@ public class Protocol1_9_1_2TO1_9_3_4 extends Protocol {
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
Chunk1_9_3_4 chunk = wrapper.passthrough(CHUNK);
|
||||
BlockEntity.handle(chunk.getBlockEntities(), wrapper.user());
|
||||
Chunk chunk = wrapper.passthrough(CHUNK);
|
||||
BlockEntity.handle(((Chunk1_9_3_4) chunk).getBlockEntities(), wrapper.user());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+20
@@ -1,7 +1,9 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_1to1_9;
|
||||
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
import us.myles.ViaVersion.api.remapper.PacketHandler;
|
||||
import us.myles.ViaVersion.api.remapper.PacketRemapper;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
@@ -24,6 +26,24 @@ public class Protocol1_9_1TO1_9 extends Protocol {
|
||||
map(Type.BOOLEAN); // 6 - Reduced Debug info
|
||||
}
|
||||
});
|
||||
|
||||
// Sound Effect Packet
|
||||
registerOutgoing(State.PLAY, 0x47, 0x47, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.VAR_INT); // 0 - Sound ID
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
int sound = wrapper.get(Type.VAR_INT, 0);
|
||||
|
||||
if (sound >= 415) // Add 1 to every sound id since there is no Elytra sound on a 1.9 server
|
||||
wrapper.set(Type.VAR_INT, 0, sound + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class Chunk1_9_1_2 implements Chunk {
|
||||
private int x;
|
||||
private int z;
|
||||
private boolean groundUp;
|
||||
private int bitmask;
|
||||
private final ChunkSection1_9_1_2[] sections;
|
||||
private byte[] biomeData;
|
||||
List<CompoundTag> blockEntities;
|
||||
|
||||
public boolean isBiomeData() {
|
||||
return biomeData != null;
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.api.type.types.minecraft.BaseChunkType;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks.ChunkSection1_9to1_8;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
|
||||
public class Chunk1_9_1_2Type extends BaseChunkType {
|
||||
public Chunk1_9_1_2Type() {
|
||||
super("1.9.1/2 Chunk");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk read(ByteBuf input) throws Exception {
|
||||
int chunkX = input.readInt();
|
||||
int chunkZ = input.readInt();
|
||||
|
||||
boolean groundUp = input.readBoolean();
|
||||
int primaryBitmask = Type.VAR_INT.read(input);
|
||||
int size = Type.VAR_INT.read(input);
|
||||
|
||||
BitSet usedSections = new BitSet(16);
|
||||
ChunkSection1_9_1_2[] sections = new ChunkSection1_9_1_2[16];
|
||||
// Calculate section count from bitmask
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((primaryBitmask & (1 << i)) != 0) {
|
||||
usedSections.set(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Read sections
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (!usedSections.get(i)) continue; // Section not set
|
||||
ChunkSection1_9_1_2 section = new ChunkSection1_9_1_2();
|
||||
sections[i] = section;
|
||||
// WIP.
|
||||
// section.readBlocks(input);
|
||||
// section.readBlockLight(input);
|
||||
// section.readSkyLight(input);
|
||||
/*
|
||||
BlockStorage blocks = new BlockStorage(in);
|
||||
NibbleArray3d blocklight = new NibbleArray3d(in, 2048); (1024 bytes)
|
||||
NibbleArray3d skylight = hasSkylight ? new NibbleArray3d(in, 2048) : null; (1024 bytes)
|
||||
chunks[index] = new Chunk(blocks, blocklight, skylight);
|
||||
*/
|
||||
}
|
||||
byte[] biomeData = groundUp ? new byte[256] : null;
|
||||
if (groundUp)
|
||||
input.readBytes(biomeData);
|
||||
|
||||
return new Chunk1_9_1_2(chunkX, chunkZ, groundUp, primaryBitmask, sections, biomeData, new ArrayList<CompoundTag>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf output, Chunk input) throws Exception {
|
||||
if (!(input instanceof Chunk1_9_1_2))
|
||||
throw new Exception("Tried to send the wrong chunk type from 1.9.3-4 chunk: " + input.getClass());
|
||||
Chunk1_9_1_2 chunk = (Chunk1_9_1_2) input;
|
||||
|
||||
output.writeInt(chunk.getX());
|
||||
output.writeInt(chunk.getZ());
|
||||
|
||||
output.writeBoolean(chunk.isGroundUp());
|
||||
Type.VAR_INT.write(output, chunk.getBitmask());
|
||||
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
ChunkSection1_9_1_2 section = chunk.getSections()[i];
|
||||
if (section == null) continue; // Section not set
|
||||
section.writeBlocks(buf);
|
||||
section.writeBlockLight(buf);
|
||||
|
||||
if (!section.hasSkyLight()) continue; // No sky light, we're done here.
|
||||
section.writeSkyLight(buf);
|
||||
|
||||
}
|
||||
buf.readerIndex(0);
|
||||
Type.VAR_INT.write(output, buf.readableBytes() + (chunk.isBiomeData() ? 256 : 0));
|
||||
output.writeBytes(buf);
|
||||
buf.release(); // release buffer
|
||||
|
||||
// Write biome data
|
||||
if (chunk.isBiomeData()) {
|
||||
output.writeBytes(chunk.getBiomeData());
|
||||
}
|
||||
|
||||
// Type.NBT_ARRAY.write(output, tags.toArray(new CompoundTag[0])); Written by the handler
|
||||
}
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.NibbleArray;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ChunkSection1_9_1_2 {
|
||||
/**
|
||||
* Size (dimensions) of blocks in a chunks section.
|
||||
*/
|
||||
public static final int SIZE = 16 * 16 * 16; // width * depth * height
|
||||
/**
|
||||
* Length of the sky and block light nibble arrays.
|
||||
*/
|
||||
public static final int LIGHT_LENGTH = 16 * 16 * 16 / 2; // size * size * size / 2 (nibble bit count)
|
||||
/**
|
||||
* Length of the block data array.
|
||||
*/
|
||||
|
||||
private final List<Integer> palette = Lists.newArrayList();
|
||||
private final int[] blocks;
|
||||
private final NibbleArray blockLight;
|
||||
private NibbleArray skyLight;
|
||||
|
||||
public ChunkSection1_9_1_2() {
|
||||
this.blocks = new int[SIZE];
|
||||
this.blockLight = new NibbleArray(SIZE);
|
||||
palette.add(0); // AIR
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a block in the chunks
|
||||
*
|
||||
* @param x Block X
|
||||
* @param y Block Y
|
||||
* @param z Block Z
|
||||
* @param type The type of the block
|
||||
* @param data The data value of the block
|
||||
*/
|
||||
public void setBlock(int x, int y, int z, int type, int data) {
|
||||
setBlock(index(x, y, z), type, data);
|
||||
}
|
||||
|
||||
public int getBlockId(int x, int y, int z){
|
||||
int index = blocks[index(x, y, z)];
|
||||
return palette.indexOf(index) >> 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a block in the chunks based on the index
|
||||
*
|
||||
* @param idx Index
|
||||
* @param type The type of the block
|
||||
* @param data The data value of the block
|
||||
*/
|
||||
public void setBlock(int idx, int type, int data) {
|
||||
int hash = type << 4 | (data & 0xF);
|
||||
int index = palette.indexOf(hash);
|
||||
if (index == -1) {
|
||||
index = palette.size();
|
||||
palette.add(hash);
|
||||
}
|
||||
|
||||
blocks[idx] = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block light array
|
||||
*
|
||||
* @param data The value to set the block light to
|
||||
*/
|
||||
public void setBlockLight(byte[] data) {
|
||||
blockLight.setHandle(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sky light array
|
||||
*
|
||||
* @param data The value to set the sky light to
|
||||
*/
|
||||
public void setSkyLight(byte[] data) {
|
||||
if (data.length != LIGHT_LENGTH) throw new IllegalArgumentException("Data length != " + LIGHT_LENGTH);
|
||||
this.skyLight = new NibbleArray(data);
|
||||
}
|
||||
|
||||
private int index(int x, int y, int z) {
|
||||
return z << 8 | y << 4 | x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the blocks to a buffer.
|
||||
*
|
||||
* @param output The buffer to write to.
|
||||
* @throws Exception Throws if it failed to write.
|
||||
*/
|
||||
public void writeBlocks(ByteBuf output) throws Exception {
|
||||
// Write bits per block
|
||||
int bitsPerBlock = 4;
|
||||
while (palette.size() > 1 << bitsPerBlock) {
|
||||
bitsPerBlock += 1;
|
||||
}
|
||||
long maxEntryValue = (1L << bitsPerBlock) - 1;
|
||||
output.writeByte(bitsPerBlock);
|
||||
|
||||
// Write pallet (or not)
|
||||
Type.VAR_INT.write(output, palette.size());
|
||||
for (int mappedId : palette) {
|
||||
Type.VAR_INT.write(output, mappedId);
|
||||
}
|
||||
|
||||
int length = (int) Math.ceil(SIZE * bitsPerBlock / 64.0);
|
||||
Type.VAR_INT.write(output, length);
|
||||
long[] data = new long[length];
|
||||
for (int index = 0; index < blocks.length; index++) {
|
||||
int value = blocks[index];
|
||||
int bitIndex = index * bitsPerBlock;
|
||||
int startIndex = bitIndex / 64;
|
||||
int endIndex = ((index + 1) * bitsPerBlock - 1) / 64;
|
||||
int startBitSubIndex = bitIndex % 64;
|
||||
data[startIndex] = data[startIndex] & ~(maxEntryValue << startBitSubIndex) | ((long) value & maxEntryValue) << startBitSubIndex;
|
||||
if (startIndex != endIndex) {
|
||||
int endBitSubIndex = 64 - startBitSubIndex;
|
||||
data[endIndex] = data[endIndex] >>> endBitSubIndex << endBitSubIndex | ((long) value & maxEntryValue) >> endBitSubIndex;
|
||||
}
|
||||
}
|
||||
for (long l : data) {
|
||||
Type.LONG.write(output, l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the block light to a buffer
|
||||
*
|
||||
* @param output The buffer to write to
|
||||
*/
|
||||
public void writeBlockLight(ByteBuf output) {
|
||||
output.writeBytes(blockLight.getHandle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the sky light to a buffer
|
||||
*
|
||||
* @param output The buffer to write to
|
||||
*/
|
||||
public void writeSkyLight(ByteBuf output) {
|
||||
output.writeBytes(skyLight.getHandle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if sky light is present
|
||||
*
|
||||
* @return True if skylight is present
|
||||
*/
|
||||
public boolean hasSkyLight() {
|
||||
return skyLight != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get expected size of this chunks section.
|
||||
*
|
||||
* @return Amount of bytes sent by this section
|
||||
* @throws Exception If it failed to calculate bits properly
|
||||
*/
|
||||
public int getExpectedSize() throws Exception {
|
||||
int bitsPerBlock = palette.size() > 255 ? 16 : 8;
|
||||
int bytes = 1; // bits per block
|
||||
bytes += paletteBytes(); // palette
|
||||
bytes += countBytes(bitsPerBlock == 16 ? SIZE * 2 : SIZE); // block data length
|
||||
bytes += (palette.size() > 255 ? 2 : 1) * SIZE; // block data
|
||||
bytes += LIGHT_LENGTH; // block light
|
||||
bytes += hasSkyLight() ? LIGHT_LENGTH : 0; // sky light
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private int paletteBytes() throws Exception {
|
||||
// Count bytes used by pallet
|
||||
int bytes = countBytes(palette.size());
|
||||
for (int mappedId : palette) {
|
||||
bytes += countBytes(mappedId);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private int countBytes(int value) throws Exception {
|
||||
// Count amount of bytes that would be sent if the value were sent as a VarInt
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
Type.VAR_INT.write(buf, value);
|
||||
buf.readerIndex(0);
|
||||
int bitCount = buf.readableBytes();
|
||||
buf.release();
|
||||
return bitCount;
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
import org.spacehq.opennbt.tag.builtin.IntTag;
|
||||
import org.spacehq.opennbt.tag.builtin.StringTag;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Mojang changed the way how tile entities inside chunk packets work in 1.10.1
|
||||
* It requires now to have all tile entity data included in the chunk packet, otherwise it'll crash.
|
||||
*/
|
||||
public class FakeTileEntity {
|
||||
private static Map<Integer, CompoundTag> tileEntities = new ConcurrentHashMap<>();
|
||||
|
||||
static {
|
||||
register(Material.FURNACE, "Furnace");
|
||||
register(Arrays.asList(Material.CHEST, Material.TRAPPED_CHEST), "Chest");
|
||||
register(Material.ENDER_CHEST, "EnderChest");
|
||||
register(Material.JUKEBOX, "RecordPlayer");
|
||||
register(Material.DISPENSER, "Trap");
|
||||
register(Material.DROPPER, "Dropper");
|
||||
register(Arrays.asList(Material.SIGN_POST, Material.WALL_SIGN), "Sign");
|
||||
register(Material.MOB_SPAWNER, "MobSpawner");
|
||||
register(Material.NOTE_BLOCK, "Music");
|
||||
register(Material.PISTON_BASE, "Piston");
|
||||
register(Arrays.asList(Material.BREWING_STAND, Material.CAULDRON), "Cauldron");
|
||||
register(Material.ENCHANTMENT_TABLE, "EnchantTable");
|
||||
register(Arrays.asList(Material.ENDER_PORTAL, Material.ENDER_PORTAL_FRAME), "Airportal");
|
||||
register(Material.BEACON, "Beacon");
|
||||
register(Arrays.asList(Material.SKULL, Material.SKULL_ITEM), "Skull");
|
||||
register(Arrays.asList(Material.DAYLIGHT_DETECTOR, Material.DAYLIGHT_DETECTOR_INVERTED), "DLDetector");
|
||||
register(Material.HOPPER, "Hopper");
|
||||
register(Arrays.asList(Material.REDSTONE_COMPARATOR, Material.REDSTONE_COMPARATOR_OFF, Material.REDSTONE_COMPARATOR_ON), "Comparator");
|
||||
register(Material.FLOWER_POT, "FlowerPot");
|
||||
register(Arrays.asList(Material.STANDING_BANNER, Material.WALL_BANNER, Material.BANNER), "Banner");
|
||||
register(209, "EndGateway"); // todo test
|
||||
register(Material.COMMAND.getId(), "Control");
|
||||
}
|
||||
|
||||
private static void register(Integer material, String name) {
|
||||
CompoundTag comp = new CompoundTag("");
|
||||
comp.put(new StringTag(name));
|
||||
tileEntities.put(material, comp);
|
||||
}
|
||||
|
||||
private static void register(Material material, String name) {
|
||||
register(material.getId(), name);
|
||||
}
|
||||
|
||||
private static void register(List<Material> materials, String name) {
|
||||
for (Material m : materials)
|
||||
register(m.getId(), name);
|
||||
}
|
||||
|
||||
public static boolean hasBlock(int block) {
|
||||
return tileEntities.containsKey(block);
|
||||
}
|
||||
|
||||
public static CompoundTag getFromBlock(int x, int y, int z, int block) {
|
||||
if (tileEntities.containsKey(block)) {
|
||||
CompoundTag tag = tileEntities.get(block).clone();
|
||||
tag.put(new IntTag("x", x));
|
||||
tag.put(new IntTag("y", y));
|
||||
tag.put(new IntTag("z", z));
|
||||
return tag;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+38
-3
@@ -11,6 +11,13 @@ import us.myles.ViaVersion.api.remapper.PacketHandler;
|
||||
import us.myles.ViaVersion.api.remapper.PacketRemapper;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks.Chunk1_9to1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks.ChunkSection1_9to1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.types.ChunkType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Protocol1_9_3TO1_9_1_2 extends Protocol {
|
||||
@Override
|
||||
@@ -24,7 +31,7 @@ public class Protocol1_9_3TO1_9_1_2 extends Protocol {
|
||||
registerOutgoing(State.PLAY, 0x4B, 0x4A); //Entity properties
|
||||
registerOutgoing(State.PLAY, 0x4C, 0x4B); //Entity effect
|
||||
|
||||
//Sign update
|
||||
// Sign update packet
|
||||
registerOutgoing(State.PLAY, 0x46, -1, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
@@ -60,14 +67,42 @@ public class Protocol1_9_3TO1_9_1_2 extends Protocol {
|
||||
}
|
||||
});
|
||||
|
||||
// Chunk packet
|
||||
registerOutgoing(State.PLAY, 0x20, 0x20, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
wrapper.passthroughAll();
|
||||
wrapper.write(Type.VAR_INT, 0);
|
||||
ClientChunks clientChunks = wrapper.user().get(ClientChunks.class);
|
||||
|
||||
ChunkType type = new ChunkType(clientChunks);
|
||||
if (wrapper.isReadable(type, 0)) {
|
||||
Chunk1_9to1_8 chunk = (Chunk1_9to1_8) wrapper.read(type);
|
||||
|
||||
List<CompoundTag> tags = new ArrayList<>();
|
||||
for (int i = 0; i < chunk.getSections().length; i++) {
|
||||
ChunkSection1_9to1_8 section = chunk.getSections()[i];
|
||||
if (section == null)
|
||||
continue;
|
||||
|
||||
for (int x = 0; x < 16; x++)
|
||||
for (int y = 0; y < 16; y++)
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int block = section.getBlockId(x, y, z);
|
||||
if (FakeTileEntity.hasBlock(block)) {
|
||||
// NOT SURE WHY Y AND Z WORK THIS WAY, TODO: WORK OUT WHY THIS IS OR FIX W/E BROKE IT
|
||||
tags.add(FakeTileEntity.getFromBlock(x + (chunk.getX() << 4), z + (i << 4), y + (chunk.getZ() << 4), block));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrapper.write(type, chunk);
|
||||
wrapper.write(Type.NBT_ARRAY, tags.toArray(new CompoundTag[0]));
|
||||
} else {
|
||||
wrapper.passthroughAll();
|
||||
wrapper.write(Type.VAR_INT, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ public class Protocol1_9TO1_8 extends Protocol {
|
||||
Bukkit.getPluginManager().registerEvents(new CommandBlockListener(plugin), plugin);
|
||||
Bukkit.getPluginManager().registerEvents(new DeathListener(plugin), plugin);
|
||||
Bukkit.getPluginManager().registerEvents(new BlockListener(plugin), plugin);
|
||||
if (Bukkit.getVersion().toLowerCase().contains("paper")) {
|
||||
plugin.getLogger().info("Enabling PaperSpigot patch: Fixes block placement.");
|
||||
if (Bukkit.getVersion().toLowerCase().contains("paper") || Bukkit.getVersion().toLowerCase().contains("taco")) {
|
||||
plugin.getLogger().info("Enabling PaperSpigot/TacoSpigot patch: Fixes block placement.");
|
||||
Bukkit.getPluginManager().registerEvents(new PaperPatch(), plugin);
|
||||
}
|
||||
if (plugin.getConf().isStimulatePlayerTick())
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
public class Chunk1_9to1_8 implements Chunk {
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final boolean groundUp;
|
||||
private final int primaryBitmask;
|
||||
private final ChunkSection1_9to1_8[] sections;
|
||||
private final byte[] biomeData;
|
||||
private boolean unloadPacket = false;
|
||||
|
||||
/**
|
||||
* Chunk unload.
|
||||
*
|
||||
* @param x coord
|
||||
* @param z coord
|
||||
*/
|
||||
public Chunk1_9to1_8(int x, int z) {
|
||||
this(x, z, true, 0, new ChunkSection1_9to1_8[16], null);
|
||||
this.unloadPacket = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this chunks have biome data
|
||||
*
|
||||
* @return True if the chunks has biome data
|
||||
*/
|
||||
public boolean hasBiomeData() {
|
||||
return biomeData != null && groundUp;
|
||||
}
|
||||
}
|
||||
+13
-7
@@ -1,15 +1,16 @@
|
||||
package us.myles.ViaVersion.api.minecraft.chunks;
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.NibbleArray;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ChunkSection {
|
||||
public class ChunkSection1_9to1_8 {
|
||||
/**
|
||||
* Size (dimensions) of blocks in a chunk section.
|
||||
* Size (dimensions) of blocks in a chunks section.
|
||||
*/
|
||||
public static final int SIZE = 16 * 16 * 16; // width * depth * height
|
||||
/**
|
||||
@@ -25,14 +26,14 @@ public class ChunkSection {
|
||||
private final NibbleArray blockLight;
|
||||
private NibbleArray skyLight;
|
||||
|
||||
public ChunkSection() {
|
||||
public ChunkSection1_9to1_8() {
|
||||
this.blocks = new int[SIZE];
|
||||
this.blockLight = new NibbleArray(SIZE);
|
||||
palette.add(0); // AIR
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a block in the chunk
|
||||
* Set a block in the chunks
|
||||
*
|
||||
* @param x Block X
|
||||
* @param y Block Y
|
||||
@@ -44,8 +45,13 @@ public class ChunkSection {
|
||||
setBlock(index(x, y, z), type, data);
|
||||
}
|
||||
|
||||
public int getBlockId(int x, int y, int z){
|
||||
int index = blocks[index(x, y, z)];
|
||||
return palette.get(index) >> 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a block in the chunk based on the index
|
||||
* Set a block in the chunks based on the index
|
||||
*
|
||||
* @param idx Index
|
||||
* @param type The type of the block
|
||||
@@ -154,7 +160,7 @@ public class ChunkSection {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get expected size of this chunk section.
|
||||
* Get expected size of this chunks section.
|
||||
*
|
||||
* @return Amount of bytes sent by this section
|
||||
* @throws Exception If it failed to calculate bits properly
|
||||
+14
-19
@@ -1,7 +1,5 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
@@ -17,9 +15,9 @@ import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.inventory.CraftingInventory;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.ArmorType;
|
||||
@@ -40,24 +38,21 @@ public class ArmorListener implements Listener {
|
||||
if (!userConnection.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) return;
|
||||
|
||||
int armor = ArmorType.calculateArmorPoints(player.getInventory().getArmorContents());
|
||||
int protocol = userConnection.get(ProtocolInfo.class).getProtocolVersion();
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
|
||||
PacketWrapper wrapper = new PacketWrapper(0x4B, null, userConnection);
|
||||
try {
|
||||
wrapper.write(Type.VAR_INT, player.getEntityId()); // Player ID
|
||||
wrapper.write(Type.INT, 1); // only 1 property
|
||||
wrapper.write(Type.STRING, "generic.armor");
|
||||
wrapper.write(Type.DOUBLE, 0D); //default 0 armor
|
||||
wrapper.write(Type.VAR_INT, 1); // 1 modifier
|
||||
wrapper.write(Type.UUID, ARMOR_ATTRIBUTE); // armor modifier uuid
|
||||
wrapper.write(Type.DOUBLE, (double) armor); // the modifier value
|
||||
wrapper.write(Type.BYTE, (byte) 0);// the modifier operation, 0 is add number
|
||||
|
||||
//TODO possibility to send packets by Protocol version, to let the transformer do the work
|
||||
Type.VAR_INT.write(buf, (protocol >= ProtocolVersion.v1_9_3.getId()) ? 0x4A : 0x4B); // Entity Properties
|
||||
Type.VAR_INT.write(buf, player.getEntityId());
|
||||
buf.writeInt(1); // only 1 property
|
||||
Type.STRING.write(buf, "generic.armor");
|
||||
buf.writeDouble(0); //default 0 armor
|
||||
Type.VAR_INT.write(buf, 1); // 1 modifier
|
||||
Type.UUID.write(buf, ARMOR_ATTRIBUTE); // armor modifier uuid
|
||||
buf.writeDouble((double) armor); // the modifier value
|
||||
buf.writeByte(0); // the modifier operation, 0 is add number
|
||||
|
||||
ViaVersion.getInstance().sendRawPacket(player, buf);
|
||||
} catch (Exception ignored) {
|
||||
buf.release();
|
||||
wrapper.send(Protocol1_9TO1_8.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-17
@@ -19,6 +19,7 @@ import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.spacehq.opennbt.tag.builtin.ByteTag;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.minecraft.Position;
|
||||
@@ -80,12 +81,12 @@ public class CommandBlockListener implements Listener {
|
||||
if (!userConnection.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) return;
|
||||
|
||||
try {
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
Type.VAR_INT.write(buf, 0x1B); // Entity Status
|
||||
buf.writeInt(p.getEntityId());
|
||||
buf.writeByte(26);
|
||||
plugin.sendRawPacket(p, buf);
|
||||
} catch (Exception ignored) {
|
||||
PacketWrapper wrapper = new PacketWrapper(0x1B, null, userConnection); // Entity status
|
||||
wrapper.write(Type.INT, p.getEntityId());
|
||||
wrapper.write(Type.BYTE, (byte) 26); //Hardcoded op permission level
|
||||
wrapper.send(Protocol1_9TO1_8.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,26 +98,32 @@ public class CommandBlockListener implements Listener {
|
||||
|
||||
Object tileEntityCommand = ReflectionUtil.get(cmd, "commandBlock", ReflectionUtil.nms("TileEntityCommand"));
|
||||
Object updatePacket = ReflectionUtil.invoke(tileEntityCommand, "getUpdatePacket");
|
||||
ByteBuf buf = packetToByteBuf(updatePacket);
|
||||
plugin.sendRawPacket(player, buf);
|
||||
|
||||
UserConnection userConnection = ((ViaVersionPlugin) ViaVersion.getInstance()).getConnection(player);
|
||||
|
||||
PacketWrapper wrapper = generatePacket(updatePacket, userConnection);
|
||||
wrapper.send(Protocol1_9TO1_8.class);
|
||||
}
|
||||
|
||||
private ByteBuf packetToByteBuf(Object updatePacket) throws Exception {
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
Type.VAR_INT.write(buf, 0x09); //Block Entity Packet ID
|
||||
private PacketWrapper generatePacket(Object updatePacket, UserConnection usr) throws Exception {
|
||||
PacketWrapper wrapper = new PacketWrapper(0x09, null, usr); // Update block entity
|
||||
|
||||
long[] pos = getPosition(ReflectionUtil.get(updatePacket, "a", ReflectionUtil.nms("BlockPosition")));
|
||||
Type.POSITION.write(buf, new Position(pos[0], pos[1], pos[2])); //Block position
|
||||
buf.writeByte(2); //Action id always 2
|
||||
|
||||
wrapper.write(Type.POSITION, new Position(pos[0], pos[1], pos[2])); //Block position
|
||||
wrapper.write(Type.BYTE, (byte) 2); // Action id always 2
|
||||
|
||||
CompoundTag nbt = getNBT(ReflectionUtil.get(updatePacket, "c", ReflectionUtil.nms("NBTTagCompound")));
|
||||
if (nbt == null) {
|
||||
buf.writeByte(0); //If nbt is null. Use 0 as nbt
|
||||
return buf;
|
||||
wrapper.write(Type.BYTE, (byte) 0); //If nbt is null. Use 0 as nbt
|
||||
return wrapper;
|
||||
}
|
||||
nbt.put(new ByteTag("powered", (byte) 0));
|
||||
nbt.put(new ByteTag("auto", (byte) 0));
|
||||
nbt.put(new ByteTag("conditionMet", (byte) 0));
|
||||
Type.NBT.write(buf, nbt); //NBT tag
|
||||
return buf;
|
||||
|
||||
wrapper.write(Type.NBT, nbt); // NBT TAG
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
private long[] getPosition(Object obj) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||
|
||||
@@ -12,8 +12,6 @@ import us.myles.ViaVersion.api.remapper.ValueCreator;
|
||||
import us.myles.ViaVersion.api.remapper.ValueTransformer;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.Protocol1_10To1_9_3_4;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.ItemRewriter;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.MetadataRewriter;
|
||||
|
||||
+2
-42
@@ -6,7 +6,6 @@ import org.spacehq.opennbt.tag.builtin.StringTag;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.minecraft.Position;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||
import us.myles.ViaVersion.api.minecraft.item.Item;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
import us.myles.ViaVersion.api.remapper.PacketHandler;
|
||||
@@ -16,6 +15,7 @@ import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.ItemRewriter;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks.Chunk1_9to1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.sounds.Effect;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.sounds.SoundEffect;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
@@ -115,7 +115,7 @@ public class WorldPackets {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
ClientChunks clientChunks = wrapper.user().get(ClientChunks.class);
|
||||
Chunk chunk = wrapper.passthrough(new ChunkType(clientChunks));
|
||||
Chunk1_9to1_8 chunk = (Chunk1_9to1_8) wrapper.passthrough(new ChunkType(clientChunks));
|
||||
if (chunk.isUnloadPacket())
|
||||
wrapper.setId(0x1D);
|
||||
|
||||
@@ -283,46 +283,6 @@ public class WorldPackets {
|
||||
wrapper.write(Type.BYTE, (byte) 0);
|
||||
}
|
||||
});
|
||||
/*
|
||||
|
||||
The thing i've discovered is when using an item in air, it needs to send 2 packets.
|
||||
I believe the issue is that this needs to be flipped with the packet above while still
|
||||
sending block info.
|
||||
|
||||
Otherwise no idea, the disadvantage: Interact does not get fired if you right click
|
||||
special items. (there's quite a few...)
|
||||
|
||||
*/
|
||||
// handler(new PacketHandler() {
|
||||
// @Override
|
||||
// public void handle(PacketWrapper wrapper) throws Exception {
|
||||
// if(wrapper.isCancelled()) return;
|
||||
// EntityTracker tracker = wrapper.user().get(EntityTracker.class);
|
||||
// if(tracker.isBlocking()) return;
|
||||
//
|
||||
// Long last = tracker.getLastPlaceBlock();
|
||||
// if (last != -1) {
|
||||
// if ((wrapper.user().getReceivedPackets() - last) < 3) {
|
||||
// tracker.setLastPlaceBlock(-1L);
|
||||
// return;
|
||||
// }
|
||||
// tracker.setLastPlaceBlock(-1L);
|
||||
// }
|
||||
// final Item item = wrapper.get(Type.ITEM, 0);
|
||||
// wrapper.create(0x08, new ValueCreator() {
|
||||
// @Override
|
||||
// public void write(PacketWrapper wrapper) throws Exception {
|
||||
// wrapper.write(Type.POSITION, new Position(1L, 1L, 1L));
|
||||
// wrapper.write(Type.BYTE, (byte) 2);
|
||||
// wrapper.write(Type.ITEM, item); // hand
|
||||
//
|
||||
// wrapper.write(Type.UNSIGNED_BYTE, (short) 1);
|
||||
// wrapper.write(Type.UNSIGNED_BYTE, (short) 1);
|
||||
// wrapper.write(Type.UNSIGNED_BYTE, (short) 1);
|
||||
// }
|
||||
// }).sendToServer();
|
||||
// }
|
||||
// });
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ public class ClientChunks extends StoredObject {
|
||||
obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, ReflectionUtil.nms("World"));
|
||||
worldRef = ReflectionUtil.nms("World");
|
||||
} catch (Exception e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to initialise chunk reflection", e);
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class ClientChunks extends StoredObject {
|
||||
list.add(chunkPacket);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to transform chunk bulk", e);
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
-2
@@ -44,8 +44,6 @@ public class EntityTracker extends StoredObject {
|
||||
@Setter
|
||||
private boolean autoTeam = false;
|
||||
@Setter
|
||||
private Long lastPlaceBlock = -1L;
|
||||
@Setter
|
||||
private int entityID;
|
||||
@Setter
|
||||
private Position currentlyDigging = null;
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import us.myles.ViaVersion.api.minecraft.Position;
|
||||
|
||||
@Getter
|
||||
public class PlaceBlockTracker extends StoredObject {
|
||||
private long lastPlaceTimestamp = System.currentTimeMillis();
|
||||
private long lastPlaceTimestamp = 0;
|
||||
@Setter
|
||||
private Position lastPlacedPosition = null;
|
||||
|
||||
|
||||
@@ -4,9 +4,11 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.bukkit.Bukkit;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
|
||||
import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection;
|
||||
import us.myles.ViaVersion.api.type.PartialType;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.api.type.types.minecraft.BaseChunkType;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks.Chunk1_9to1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks.ChunkSection1_9to1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -17,11 +19,11 @@ import java.util.logging.Level;
|
||||
|
||||
public class ChunkType extends PartialType<Chunk, ClientChunks> {
|
||||
/**
|
||||
* Amount of sections in a chunk.
|
||||
* Amount of sections in a chunks.
|
||||
*/
|
||||
private static final int SECTION_COUNT = 16;
|
||||
public static final int SECTION_COUNT = 16;
|
||||
/**
|
||||
* size of each chunk section (16x16x16).
|
||||
* size of each chunks section (16x16x16).
|
||||
*/
|
||||
private static final int SECTION_SIZE = 16;
|
||||
/**
|
||||
@@ -37,6 +39,11 @@ public class ChunkType extends PartialType<Chunk, ClientChunks> {
|
||||
return ((long) msw << 32) + lsw - -2147483648L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Type> getBaseClass() {
|
||||
return BaseChunkType.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk read(ByteBuf input, ClientChunks param) throws Exception {
|
||||
int chunkX = input.readInt();
|
||||
@@ -48,7 +55,7 @@ public class ChunkType extends PartialType<Chunk, ClientChunks> {
|
||||
|
||||
// Data to be read
|
||||
BitSet usedSections = new BitSet(16);
|
||||
ChunkSection[] sections = new ChunkSection[16];
|
||||
ChunkSection1_9to1_8[] sections = new ChunkSection1_9to1_8[16];
|
||||
byte[] biomeData = null;
|
||||
|
||||
// Calculate section count from bitmask
|
||||
@@ -59,33 +66,34 @@ public class ChunkType extends PartialType<Chunk, ClientChunks> {
|
||||
}
|
||||
int sectionCount = usedSections.cardinality(); // the amount of sections set
|
||||
|
||||
// If the chunk is from a chunk bulk, it is never an unload packet
|
||||
// If the chunks is from a chunks bulk, it is never an unload packet
|
||||
// Other wise, if it has no data, it is :)
|
||||
boolean isBulkPacket = param.getBulkChunks().remove(chunkHash);
|
||||
if (sectionCount == 0 && groundUp && !isBulkPacket && param.getLoadedChunks().contains(chunkHash)) {
|
||||
// This is a chunk unload packet
|
||||
// This is a chunks unload packet
|
||||
param.getLoadedChunks().remove(chunkHash);
|
||||
return new Chunk(chunkX, chunkZ);
|
||||
return new Chunk1_9to1_8(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
int startIndex = input.readerIndex();
|
||||
param.getLoadedChunks().add(chunkHash); // mark chunk as loaded
|
||||
param.getLoadedChunks().add(chunkHash); // mark chunks as loaded
|
||||
|
||||
// Read blocks
|
||||
for (int i = 0; i < SECTION_COUNT; i++) {
|
||||
if (!usedSections.get(i)) continue; // Section not set
|
||||
ChunkSection section = new ChunkSection();
|
||||
ChunkSection1_9to1_8 section = new ChunkSection1_9to1_8();
|
||||
sections[i] = section;
|
||||
|
||||
// Read block data and convert to short buffer
|
||||
byte[] blockData = new byte[ChunkSection.SIZE * 2];
|
||||
byte[] blockData = new byte[ChunkSection1_9to1_8.SIZE * 2];
|
||||
input.readBytes(blockData);
|
||||
ShortBuffer blockBuf = ByteBuffer.wrap(blockData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
|
||||
|
||||
for (int j = 0; j < ChunkSection.SIZE; j++) {
|
||||
for (int j = 0; j < ChunkSection1_9to1_8.SIZE; j++) {
|
||||
int mask = blockBuf.get();
|
||||
int type = mask >> 4;
|
||||
int data = mask & 0xF;
|
||||
|
||||
section.setBlock(j, type, data);
|
||||
}
|
||||
}
|
||||
@@ -93,20 +101,20 @@ public class ChunkType extends PartialType<Chunk, ClientChunks> {
|
||||
// Read block light
|
||||
for (int i = 0; i < SECTION_COUNT; i++) {
|
||||
if (!usedSections.get(i)) continue; // Section not set, has no light
|
||||
byte[] blockLightArray = new byte[ChunkSection.LIGHT_LENGTH];
|
||||
byte[] blockLightArray = new byte[ChunkSection1_9to1_8.LIGHT_LENGTH];
|
||||
input.readBytes(blockLightArray);
|
||||
sections[i].setBlockLight(blockLightArray);
|
||||
}
|
||||
|
||||
// Read sky light
|
||||
int bytesLeft = dataLength - (input.readerIndex() - startIndex);
|
||||
if (bytesLeft >= ChunkSection.LIGHT_LENGTH) {
|
||||
if (bytesLeft >= ChunkSection1_9to1_8.LIGHT_LENGTH) {
|
||||
for (int i = 0; i < SECTION_COUNT; i++) {
|
||||
if (!usedSections.get(i)) continue; // Section not set, has no light
|
||||
byte[] skyLightArray = new byte[ChunkSection.LIGHT_LENGTH];
|
||||
byte[] skyLightArray = new byte[ChunkSection1_9to1_8.LIGHT_LENGTH];
|
||||
input.readBytes(skyLightArray);
|
||||
sections[i].setSkyLight(skyLightArray);
|
||||
bytesLeft -= ChunkSection.LIGHT_LENGTH;
|
||||
bytesLeft -= ChunkSection1_9to1_8.LIGHT_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,15 +127,18 @@ public class ChunkType extends PartialType<Chunk, ClientChunks> {
|
||||
|
||||
// Check remaining bytes
|
||||
if (bytesLeft > 0) {
|
||||
Bukkit.getLogger().log(Level.WARNING, bytesLeft + " Bytes left after reading chunk! (" + groundUp + ")");
|
||||
Bukkit.getLogger().log(Level.WARNING, bytesLeft + " Bytes left after reading chunks! (" + groundUp + ")");
|
||||
}
|
||||
|
||||
// Return chunk
|
||||
return new Chunk(chunkX, chunkZ, groundUp, bitmask, sections, biomeData);
|
||||
// Return chunks
|
||||
return new Chunk1_9to1_8(chunkX, chunkZ, groundUp, bitmask, sections, biomeData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf output, ClientChunks param, Chunk chunk) throws Exception {
|
||||
public void write(ByteBuf output, ClientChunks param, Chunk input) throws Exception {
|
||||
if (!(input instanceof Chunk1_9to1_8)) throw new Exception("Incompatible chunk, " + input.getClass());
|
||||
|
||||
Chunk1_9to1_8 chunk = (Chunk1_9to1_8) input;
|
||||
// Write primary info
|
||||
output.writeInt(chunk.getX());
|
||||
output.writeInt(chunk.getZ());
|
||||
@@ -137,12 +148,14 @@ public class ChunkType extends PartialType<Chunk, ClientChunks> {
|
||||
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
for (int i = 0; i < SECTION_COUNT; i++) {
|
||||
ChunkSection section = chunk.getSections()[i];
|
||||
ChunkSection1_9to1_8 section = chunk.getSections()[i];
|
||||
if (section == null) continue; // Section not set
|
||||
section.writeBlocks(buf);
|
||||
section.writeBlockLight(buf);
|
||||
|
||||
if (!section.hasSkyLight()) continue; // No sky light, we're done here.
|
||||
section.writeSkyLight(buf);
|
||||
|
||||
}
|
||||
buf.readerIndex(0);
|
||||
Type.VAR_INT.write(output, buf.readableBytes() + (chunk.hasBiomeData() ? 256 : 0));
|
||||
@@ -153,5 +166,9 @@ public class ChunkType extends PartialType<Chunk, ClientChunks> {
|
||||
if (chunk.hasBiomeData()) {
|
||||
output.writeBytes(chunk.getBiomeData());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+22
@@ -1,7 +1,9 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_9_1;
|
||||
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
import us.myles.ViaVersion.api.remapper.PacketHandler;
|
||||
import us.myles.ViaVersion.api.remapper.PacketRemapper;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
@@ -24,6 +26,26 @@ public class Protocol1_9TO1_9_1 extends Protocol {
|
||||
map(Type.BOOLEAN); // 6 - Reduced Debug info
|
||||
}
|
||||
});
|
||||
|
||||
// Sound Effect Packet
|
||||
registerOutgoing(State.PLAY, 0x47, 0x47, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.VAR_INT); // 0 - Sound ID
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
int sound = wrapper.get(Type.VAR_INT, 0);
|
||||
|
||||
if (sound == 415) // Stop the Elytra sound for 1.9 (It's introduced in 1.9.2)
|
||||
wrapper.cancel();
|
||||
else if (sound >= 416) // Act like the Elytra sound never existed
|
||||
wrapper.set(Type.VAR_INT, 0, sound - 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package us.myles.ViaVersion.util;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ProtocolSupportUtil {
|
||||
private static Method protocolVersionMethod = null;
|
||||
private static Method getIdMethod = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
protocolVersionMethod = Class.forName("protocolsupport.api.ProtocolSupportAPI").getMethod("getProtocolVersion", Player.class);
|
||||
getIdMethod = Class.forName("protocolsupport.api.ProtocolVersion").getMethod("getId");
|
||||
} catch (Exception e) {
|
||||
// ProtocolSupport not installed.
|
||||
}
|
||||
}
|
||||
|
||||
public static int getProtocolVersion(Player player) {
|
||||
if (protocolVersionMethod == null) return -1;
|
||||
try {
|
||||
Object version = protocolVersionMethod.invoke(null, player);
|
||||
return (int) getIdMethod.invoke(version);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,9 @@ send-supported-versions: false
|
||||
# Anti-Cheat, Packets Per Second (PPS) limiter
|
||||
# Clients by default send around 20-90 packets per second.
|
||||
|
||||
# What is the maximum per second a client can send
|
||||
# What is the maximum per second a client can send (Use %pps to display their pps)
|
||||
# Use -1 to disable.
|
||||
max-pps: 400
|
||||
max-pps: 600
|
||||
max-pps-kick-msg: "You are sending too many packets!"
|
||||
|
||||
# We can also kick them if over a period they send over a threshold a certain amount of times.
|
||||
@@ -54,7 +54,7 @@ shield-blocking: true
|
||||
# If they're in the wrong place enable this
|
||||
hologram-patch: false
|
||||
# This is the offset, should work as default when enabled.
|
||||
hologram-y: -1
|
||||
hologram-y: -0.96
|
||||
# Enable player tick simulation, this fixes eating, drinking, nether portals.
|
||||
simulate-pt: true
|
||||
# Should we use nms player to simulate packets, (may fix anti-cheat issues)
|
||||
|
||||
@@ -4,6 +4,7 @@ author: _MylesC
|
||||
version: ${project.version}
|
||||
load: postworld
|
||||
loadbefore: [ProtocolLib, ProxyPipe, SpigotLib, PacketListenerApi, SkinRestorer]
|
||||
softdepend: [ProtocolSupport]
|
||||
commands:
|
||||
viaversion:
|
||||
description: Shows ViaVersion Version and more.
|
||||
|
||||
Reference in new issue
Block a user