Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d89362a271 | ||
|
|
0a407069fa | ||
|
|
661fdb1127 | ||
|
|
9e6c0f72a8 | ||
|
|
70ad2613f1 | ||
|
|
9052946c45 | ||
|
|
3ddc43bf7b | ||
|
|
cdb757eae5 | ||
|
|
50a3e03649 | ||
|
|
957284930e | ||
|
|
198a24371c | ||
|
|
bcc994b0dd | ||
|
|
f870bd5a32 | ||
|
|
a14abd6f4f | ||
|
|
2456c3cf17 | ||
|
|
9828e4ae1d | ||
|
|
030aa887c7 | ||
|
|
ba624a2b48 | ||
|
|
e7582cb1ec | ||
|
|
82bf11fcbc | ||
|
|
ac6e8b1709 | ||
|
|
00cc545795 | ||
|
|
c7ee816aba | ||
|
|
e7f85e67f6 | ||
|
|
d239d2f967 | ||
|
|
63970c6d82 | ||
|
|
4cffdd4f64 | ||
|
|
cb3f0291b7 | ||
|
|
edaffad045 | ||
|
|
172f89940a | ||
|
|
fb4bc397c6 | ||
|
|
e595344941 | ||
|
|
05dbc53fd0 | ||
|
|
0374da573b | ||
|
|
8e64fb8c21 | ||
|
|
0f55402171 | ||
|
|
acb7372eb7 | ||
|
|
057ab050ea | ||
|
|
a01997fe53 | ||
|
|
e4adbf4a1a | ||
|
|
261d68c58e |
No files matched your search
@@ -1,3 +1,24 @@
|
||||
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!)
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,4 +1,4 @@
|
||||
# ViaVersion 0.7.8
|
||||
# ViaVersion 0.8.3
|
||||
[](https://travis-ci.org/MylesIsCool/ViaVersion)
|
||||
[](https://gitter.im/MylesIsCool/ViaVersion)
|
||||
|
||||
@@ -8,8 +8,6 @@ This plugin modifies netty to allow connection of 1.9 clients to 1.8,
|
||||
|
||||
###*Don't use late bind*
|
||||
|
||||
This uses our new API, we currently don't have javadocs yet but look at one of our protocols on how to get started then use ProtocolRegistry.registerProtocol()
|
||||
|
||||
This took 100s hours of work, so if you enjoy this consider looking into contacting me and supporting my projects.
|
||||
|
||||
**Contributor Chat:** https://gitter.im/MylesIsCool/ViaVersion
|
||||
@@ -20,6 +18,8 @@ Sources:
|
||||
|
||||
**wiki.vg** (Protocol info, though I did have to find a lot myself)
|
||||
|
||||
**Burger** We use this tool to get protocol and other useful information for new / undocumented Minecraft versions
|
||||
|
||||
**OpenNBT** (used for slot rewriting)
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ https://www.spigotmc.org/resources/viaversion.19254/history
|
||||
|
||||
You can find unofficial dev builds here:
|
||||
|
||||
**fillefilip8's Build Server:** http://build.fillecraft.com:8080/job/ViaVersion
|
||||
**Terrobility's Build Server:** https://ci.terrocidepvp.net/job/ViaVersion/
|
||||
|
||||
**sgdc3's Build Server:** http://ci.xephi.fr/job/ViaVersion/
|
||||
**sgdc3's Maven:** http://ci.xephi.fr/plugin/repository/everything/
|
||||
@@ -66,8 +66,7 @@ You can find unofficial dev builds here:
|
||||
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!)
|
||||
|
||||
MIT License, see LICENSE for more details.
|
||||
|
||||
Thanks!
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion</artifactId>
|
||||
<version>0.7.9-SNAPSHOT</version>
|
||||
<version>0.8.4-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ViaVersion</name>
|
||||
@@ -33,6 +33,7 @@
|
||||
<build>
|
||||
<finalName>${project.name}-${project.version}</finalName>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<defaultGoal>clean install</defaultGoal>
|
||||
<!-- <testSourceDirectory>src/test/java</testSourceDirectory> -->
|
||||
|
||||
<resources>
|
||||
@@ -105,6 +106,10 @@
|
||||
<pattern>com.google.gson</pattern>
|
||||
<shadedPattern>us.myles.viaversion.libs.gson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.javassist</pattern>
|
||||
<shadedPattern>us.myles.viaversion.libs.javassist</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
<executions>
|
||||
@@ -157,6 +162,15 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Javassist (Bytecode Library) -->
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<version>3.20.0-GA</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- NBT Edit Library -->
|
||||
<dependency>
|
||||
<groupId>org.spacehq</groupId>
|
||||
|
||||
@@ -20,6 +20,7 @@ import us.myles.ViaVersion.api.command.ViaVersionCommand;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
import us.myles.ViaVersion.boss.ViaBossBar;
|
||||
import us.myles.ViaVersion.classgenerator.ClassGenerator;
|
||||
import us.myles.ViaVersion.commands.ViaCommandHandler;
|
||||
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
@@ -32,10 +33,7 @@ import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
@@ -48,11 +46,15 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
|
||||
private List<Pair<Field, Object>> injectedLists = new ArrayList<>();
|
||||
private ViaCommandHandler commandHandler;
|
||||
private boolean debug = false;
|
||||
private boolean compatSpigotBuild = false;
|
||||
private boolean spigot = true;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
ViaVersion.setInstance(this);
|
||||
// Config magic
|
||||
generateConfig();
|
||||
// Handle reloads
|
||||
if (System.getProperty("ViaVersion") != null) {
|
||||
if (Bukkit.getPluginManager().getPlugin("ProtocolLib") != null) {
|
||||
getLogger().severe("ViaVersion is already loaded, we're going to kick all the players... because otherwise we'll crash because of ProtocolLib.");
|
||||
@@ -65,8 +67,22 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
|
||||
|
||||
}
|
||||
}
|
||||
// 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)
|
||||
ClassGenerator.generate();
|
||||
|
||||
getLogger().info("ViaVersion " + getDescription().getVersion() + " is now loaded, injecting.");
|
||||
getLogger().info("ViaVersion " + getDescription().getVersion() + (compatSpigotBuild ? "compat" : "") + " is now loaded, injecting.");
|
||||
injectPacketHandler();
|
||||
}
|
||||
|
||||
@@ -86,6 +102,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
|
||||
getLogger().warning("ViaVersion will not function on the current protocol.");
|
||||
}
|
||||
}
|
||||
ProtocolRegistry.refreshVersions();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -97,6 +114,11 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
|
||||
|
||||
// Register Protocol Listeners
|
||||
ProtocolRegistry.registerListeners();
|
||||
|
||||
// Warn them if they have anti-xray on and they aren't using spigot
|
||||
if(isAntiXRay() && !spigot){
|
||||
getLogger().info("You have anti-xray on in your config, since you're not using spigot it won't fix xray!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -348,6 +370,21 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
|
||||
return commandHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompatSpigotBuild() {
|
||||
return compatSpigotBuild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortedSet<Integer> getSupportedVersions() {
|
||||
return ProtocolRegistry.getSupportedVersions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpigot() {
|
||||
return this.spigot;
|
||||
}
|
||||
|
||||
public boolean isCheckForUpdates() {
|
||||
return getConfig().getBoolean("checkforupdates", true);
|
||||
}
|
||||
@@ -427,6 +464,16 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
|
||||
return getConfig().getString("tracking-max-kick-msg", "You are sending too many packets, :(");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAntiXRay() {
|
||||
return getConfig().getBoolean("anti-xray-patch", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSendSupportedVersions() {
|
||||
return getConfig().getBoolean("send-supported-versions", false);
|
||||
}
|
||||
|
||||
public boolean isAutoTeam() {
|
||||
// Collision has to be enabled first
|
||||
return isPreventCollision() && getConfig().getBoolean("auto-team", true);
|
||||
|
||||
@@ -117,7 +117,7 @@ public class PacketWrapper {
|
||||
}
|
||||
} else {
|
||||
Pair<Type, Object> read = readableObjects.poll();
|
||||
if (read.getKey().equals(type)) {
|
||||
if (read.getKey().equals(type) || (type.getBaseClass().equals(read.getKey().getBaseClass()) && type.getOutputClass().equals(read.getKey().getOutputClass()))) {
|
||||
return (T) read.getValue();
|
||||
} else {
|
||||
if (type == Type.NOTHING) {
|
||||
@@ -163,6 +163,21 @@ public class PacketWrapper {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take all the inputs and write them to the output.
|
||||
*
|
||||
* @throws Exception If it failed to read or write
|
||||
*/
|
||||
public void passthroughAll() throws Exception {
|
||||
// Copy previous objects
|
||||
packetValues.addAll(readableObjects);
|
||||
readableObjects.clear();
|
||||
// If the buffer has readable bytes, copy them.
|
||||
if (inputBuffer.readableBytes() > 0) {
|
||||
passthrough(Type.REMAINING_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the current output to a buffer.
|
||||
*
|
||||
@@ -209,6 +224,14 @@ public class PacketWrapper {
|
||||
readableObjects.clear(); // :(
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the packet, used if you have to change the packet completely
|
||||
*/
|
||||
public void clearPacket() {
|
||||
clearInputBuffer();
|
||||
packetValues.clear();
|
||||
}
|
||||
|
||||
private void writeRemaining(ByteBuf output) {
|
||||
if (inputBuffer != null) {
|
||||
output.writeBytes(inputBuffer);
|
||||
@@ -303,4 +326,13 @@ public class PacketWrapper {
|
||||
PipelineUtil.getContextBefore("decompress", user().getChannel().pipeline()).fireChannelRead(output);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PacketWrapper{" +
|
||||
"packetValues=" + packetValues +
|
||||
", readableObjects=" + readableObjects +
|
||||
", id=" + id +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import us.myles.ViaVersion.api.boss.BossColor;
|
||||
import us.myles.ViaVersion.api.boss.BossStyle;
|
||||
import us.myles.ViaVersion.api.command.ViaVersionCommand;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ViaVersionAPI {
|
||||
@@ -101,4 +102,27 @@ public interface ViaVersionAPI {
|
||||
* @return command handler
|
||||
*/
|
||||
ViaVersionCommand getCommandHandler();
|
||||
|
||||
/**
|
||||
* Get if this version is a compatibility build for spigot.
|
||||
* Eg. 1.9.1 / 1.9.2 allow certain versions to connect
|
||||
*
|
||||
* @return True if it is
|
||||
*/
|
||||
boolean isCompatSpigotBuild();
|
||||
|
||||
/**
|
||||
* Get the supported protocol versions
|
||||
*
|
||||
* @return a list of protocol versions
|
||||
*/
|
||||
SortedSet<Integer> getSupportedVersions();
|
||||
|
||||
/**
|
||||
* Gets if the server uses spigot
|
||||
*
|
||||
* Note: Will only work after ViaVersion load
|
||||
* @return True if spigot
|
||||
*/
|
||||
boolean isSpigot();
|
||||
}
|
||||
@@ -142,4 +142,18 @@ public interface ViaVersionConfig {
|
||||
* @return Kick message, with colour codes using '&'
|
||||
*/
|
||||
String getMaxWarningsKickMessage();
|
||||
|
||||
/**
|
||||
* Is anti-xray enabled?
|
||||
*
|
||||
* @return A boolean
|
||||
*/
|
||||
boolean isAntiXRay();
|
||||
|
||||
/**
|
||||
* Send supported versions in the status response packet
|
||||
*
|
||||
* @return If true, enabled
|
||||
*/
|
||||
boolean isSendSupportedVersions();
|
||||
}
|
||||
@@ -69,6 +69,14 @@ public interface BossBar {
|
||||
*/
|
||||
BossBar addPlayer(Player player);
|
||||
|
||||
/**
|
||||
* Show the bossbar to a player (uuid)
|
||||
*
|
||||
* @param player uuid of the player
|
||||
* @return the BossBar instance
|
||||
*/
|
||||
BossBar addPlayer(UUID player);
|
||||
|
||||
/**
|
||||
* add multiple players
|
||||
*
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package us.myles.ViaVersion.api.data;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -7,17 +7,16 @@ import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.packets.PacketType;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
import us.myles.ViaVersion.protocols.base.BaseProtocol;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class ProtocolPipeline extends Protocol {
|
||||
LinkedList<Protocol> protocolList;
|
||||
List<Protocol> protocolList;
|
||||
private UserConnection userConnection;
|
||||
|
||||
public ProtocolPipeline(UserConnection userConnection) {
|
||||
@@ -27,9 +26,9 @@ public class ProtocolPipeline extends Protocol {
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocolList = new LinkedList<>();
|
||||
protocolList = new CopyOnWriteArrayList<>();
|
||||
// This is a pipeline so we register basic pipes
|
||||
protocolList.addLast(new BaseProtocol());
|
||||
protocolList.add(ProtocolRegistry.BASE_PROTOCOL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,7 +54,7 @@ public class ProtocolPipeline extends Protocol {
|
||||
*/
|
||||
public void add(Protocol protocol) {
|
||||
if (protocolList != null) {
|
||||
protocolList.addLast(protocol);
|
||||
protocolList.add(protocol);
|
||||
protocol.init(userConnection);
|
||||
} else {
|
||||
throw new NullPointerException("Tried to add protocol to early");
|
||||
@@ -83,21 +82,17 @@ public class ProtocolPipeline extends Protocol {
|
||||
|
||||
// For 1.8/1.9 server version, eventually we'll probably get an API for this...
|
||||
if (ProtocolRegistry.SERVER_PROTOCOL >= ProtocolVersion.v1_8.getId() &&
|
||||
ProtocolRegistry.SERVER_PROTOCOL <= ProtocolVersion.v1_9_2.getId()) {
|
||||
ProtocolRegistry.SERVER_PROTOCOL <= ProtocolVersion.v1_9_3.getId()) {
|
||||
|
||||
PacketType type;
|
||||
if (ProtocolRegistry.SERVER_PROTOCOL == ProtocolVersion.v1_8.getId()) {
|
||||
if (ProtocolRegistry.SERVER_PROTOCOL <= ProtocolVersion.v1_8.getId()) {
|
||||
if (direction == Direction.INCOMING) {
|
||||
type = PacketType.findNewPacket(state, direction, originalID);
|
||||
} else {
|
||||
type = PacketType.findOldPacket(state, direction, originalID);
|
||||
}
|
||||
} else {
|
||||
if (direction == Direction.INCOMING) {
|
||||
type = PacketType.findOldPacket(state, direction, originalID);
|
||||
} else {
|
||||
type = PacketType.findNewPacket(state, direction, originalID);
|
||||
}
|
||||
type = PacketType.findNewPacket(state, direction, originalID);
|
||||
}
|
||||
|
||||
// Filter :) This would be not hard coded too, sorry :(
|
||||
@@ -116,13 +111,19 @@ public class ProtocolPipeline extends Protocol {
|
||||
}
|
||||
String name = packet + "[" + userConnection.get(ProtocolInfo.class).getProtocolVersion() + "]";
|
||||
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
|
||||
plugin.getLogger().log(Level.INFO, "{0}: {1} {2} -> {3} [{4}]",
|
||||
|
||||
String actualUsername = packetWrapper.user().get(ProtocolInfo.class).getUsername();
|
||||
String username = actualUsername != null ? actualUsername + " " : "";
|
||||
|
||||
plugin.getLogger().log(Level.INFO, "{0}{1}: {2} {3} -> {4} [{5}] Value: {6}",
|
||||
new Object[]{
|
||||
username,
|
||||
direction,
|
||||
state,
|
||||
originalID,
|
||||
packetWrapper.getId(),
|
||||
name
|
||||
name,
|
||||
packetWrapper
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -158,4 +159,8 @@ public class ProtocolPipeline extends Protocol {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<Protocol> pipes() {
|
||||
return protocolList;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,41 @@
|
||||
package us.myles.ViaVersion.api.protocol;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.bukkit.Bukkit;
|
||||
import us.myles.ViaVersion.api.Pair;
|
||||
import us.myles.ViaVersion.protocols.base.BaseProtocol;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3.Protocol1_9_1_2TO1_9_3;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9_1to1_9.Protocol1_9_1TO1_9;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.Protocol1_9_3TO1_9_1_2;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_9_1.Protocol1_9TO1_9_1;
|
||||
import us.myles.ViaVersion.protocols.protocolsnapshotto1_9_3.ProtocolSnapshotTo1_9_3;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ProtocolRegistry {
|
||||
public static final Protocol BASE_PROTOCOL = new BaseProtocol();
|
||||
public static int SERVER_PROTOCOL = -1;
|
||||
// Input Version -> Output Version & Protocol (Allows fast lookup)
|
||||
private static Map<Integer, Map<Integer, Protocol>> registryMap = new HashMap<>();
|
||||
private static Map<Pair<Integer, Integer>, List<Pair<Integer, Protocol>>> pathCache = new HashMap<>();
|
||||
private static List<Protocol> registerList = new ArrayList<>();
|
||||
private static Map<Integer, Map<Integer, Protocol>> registryMap = new ConcurrentHashMap<>();
|
||||
private static Map<Pair<Integer, Integer>, List<Pair<Integer, Protocol>>> pathCache = new ConcurrentHashMap<>();
|
||||
private static List<Protocol> registerList = Lists.newCopyOnWriteArrayList();
|
||||
private static Set<Integer> supportedVersions = Sets.newConcurrentHashSet();
|
||||
|
||||
static {
|
||||
// Base Protocol
|
||||
registerProtocol(BASE_PROTOCOL, Arrays.<Integer>asList(), -1);
|
||||
// Register built in protocols
|
||||
registerProtocol(new Protocol1_9TO1_8(), Collections.singletonList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_8.getId());
|
||||
registerProtocol(new Protocol1_9_1TO1_9(), Arrays.asList(ProtocolVersion.v1_9_1.getId(), ProtocolVersion.v1_9_2.getId()), ProtocolVersion.v1_9.getId());
|
||||
registerProtocol(new Protocol1_9_3TO1_9_1_2(), Arrays.asList(ProtocolVersion.v1_9_3.getId()), ProtocolVersion.v1_9_2.getId());
|
||||
// Only supported for 1.9.4 server to 1.9 (nothing else)
|
||||
registerProtocol(new Protocol1_9TO1_9_1(), Arrays.asList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_9_2.getId());
|
||||
registerProtocol(new Protocol1_9_1_2TO1_9_3(), Arrays.asList(ProtocolVersion.v1_9_1.getId(), ProtocolVersion.v1_9_2.getId()), ProtocolVersion.v1_9_3.getId());
|
||||
registerProtocol(new ProtocolSnapshotTo1_9_3(), Collections.singletonList(ProtocolVersion.SNAPSHOT.getId()), ProtocolVersion.v1_9_3.getId());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,11 +60,29 @@ public class ProtocolRegistry {
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("ViaVersion").isEnabled()) {
|
||||
protocol.registerListeners();
|
||||
refreshVersions();
|
||||
} else {
|
||||
registerList.add(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshVersions() {
|
||||
supportedVersions.clear();
|
||||
|
||||
supportedVersions.add(ProtocolRegistry.SERVER_PROTOCOL);
|
||||
for (ProtocolVersion versions : ProtocolVersion.getProtocols()) {
|
||||
List<Pair<Integer, Protocol>> paths = getProtocolPath(versions.getId(), ProtocolRegistry.SERVER_PROTOCOL);
|
||||
if (paths == null) continue;
|
||||
supportedVersions.add(versions.getId());
|
||||
for (Pair<Integer, Protocol> path : paths)
|
||||
supportedVersions.add(path.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
public static SortedSet<Integer> getSupportedVersions() {
|
||||
return Collections.unmodifiableSortedSet(new TreeSet<>(supportedVersions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this plugin is useful to the server.
|
||||
*
|
||||
@@ -78,6 +114,7 @@ public class ProtocolRegistry {
|
||||
* @return The path which has been generated, null if failed.
|
||||
*/
|
||||
private static List<Pair<Integer, Protocol>> getProtocolPath(List<Pair<Integer, Protocol>> current, int clientVersion, int serverVersion) {
|
||||
if (clientVersion == serverVersion) return null; // We're already there
|
||||
if (current.size() > 50) return null; // Fail safe, protocol too complicated.
|
||||
|
||||
// First check if there is any protocols for this
|
||||
@@ -91,6 +128,8 @@ public class ProtocolRegistry {
|
||||
return current; // Easy solution
|
||||
}
|
||||
// There might be a more advanced solution... So we'll see if any of the others can get us there
|
||||
List<Pair<Integer, Protocol>> shortest = null;
|
||||
|
||||
for (Map.Entry<Integer, Protocol> entry : inputMap.entrySet()) {
|
||||
// Ensure it wasn't caught by the other loop
|
||||
if (!entry.getKey().equals(serverVersion)) {
|
||||
@@ -103,13 +142,16 @@ public class ProtocolRegistry {
|
||||
// Calculate the rest of the protocol using the current
|
||||
newCurrent = getProtocolPath(newCurrent, entry.getKey(), serverVersion);
|
||||
if (newCurrent != null) {
|
||||
return newCurrent;
|
||||
// If it's shorter then choose it
|
||||
if (shortest == null || shortest.size() > newCurrent.size()) {
|
||||
shortest = newCurrent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return shortest; // null if none found
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,8 @@ public class ProtocolVersion {
|
||||
public static final ProtocolVersion v1_9;
|
||||
public static final ProtocolVersion v1_9_1;
|
||||
public static final ProtocolVersion v1_9_2;
|
||||
public static final ProtocolVersion v1_9_3;
|
||||
public static final ProtocolVersion SNAPSHOT;
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
@@ -26,6 +28,9 @@ public class ProtocolVersion {
|
||||
register(v1_9 = new ProtocolVersion(107, "1.9"));
|
||||
register(v1_9_1 = new ProtocolVersion(108, "1.9.1"));
|
||||
register(v1_9_2 = new ProtocolVersion(109, "1.9.2"));
|
||||
register(v1_9_3 = new ProtocolVersion(110, "1.9.3/4"));
|
||||
register(v1_9_3 = new ProtocolVersion(110, "1.9.3"));
|
||||
register(SNAPSHOT = new ProtocolVersion(201, "16w20a"));
|
||||
}
|
||||
|
||||
public static void register(@NonNull ProtocolVersion protocol) {
|
||||
@@ -37,7 +42,11 @@ public class ProtocolVersion {
|
||||
}
|
||||
|
||||
public static ProtocolVersion getProtocol(int id) {
|
||||
return versions.get(id);
|
||||
if (versions.containsKey(id)) {
|
||||
return versions.get(id);
|
||||
} else {
|
||||
return new ProtocolVersion(id, "Unknown (" + id + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ProtocolVersion> getProtocols() {
|
||||
|
||||
@@ -10,6 +10,8 @@ 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.UUID;
|
||||
|
||||
@Getter
|
||||
@@ -61,12 +63,14 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
|
||||
public static final Type<CompoundTag> NBT = new NBTType();
|
||||
|
||||
public static final Type<UUID> OPTIONAL_UUID = new OptUUIDType();
|
||||
public static final Type<Position> OPTIONAL_POSITION = new OptPositionType();
|
||||
|
||||
public static final Type<Item> ITEM = new ItemType();
|
||||
public static final Type<Item[]> ITEM_ARRAY = new ItemArrayType();
|
||||
/* 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) {
|
||||
@@ -76,6 +80,11 @@ 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() {
|
||||
return this.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package us.myles.ViaVersion.api.type.types.minecraft;
|
||||
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class MetaListTypeTemplate extends Type<List<Metadata>> {
|
||||
public MetaListTypeTemplate() {
|
||||
super("MetaData List", List.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Type> getBaseClass() {
|
||||
return MetaListTypeTemplate.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package us.myles.ViaVersion.api.type.types.minecraft;
|
||||
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
public abstract class MetaTypeTemplate extends Type<Metadata> {
|
||||
public MetaTypeTemplate() {
|
||||
super("Metadata type", Metadata.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Type> getBaseClass() {
|
||||
return MetaTypeTemplate.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package us.myles.ViaVersion.api.type.types.minecraft;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import us.myles.ViaVersion.api.minecraft.Position;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
public class OptPositionType extends Type<Position> {
|
||||
public OptPositionType() {
|
||||
super(Position.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position read(ByteBuf buffer) throws Exception {
|
||||
boolean present = buffer.readBoolean();
|
||||
if (!present) return null;
|
||||
return Type.POSITION.read(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Position object) throws Exception {
|
||||
buffer.writeBoolean(object != null);
|
||||
if (object != null)
|
||||
Type.POSITION.write(buffer, object);
|
||||
}
|
||||
}
|
||||
@@ -78,10 +78,15 @@ public class ViaBossBar implements BossBar {
|
||||
|
||||
@Override
|
||||
public BossBar addPlayer(@NonNull Player player) {
|
||||
if (!players.contains(player.getUniqueId())) {
|
||||
players.add(player.getUniqueId());
|
||||
return addPlayer(player.getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar addPlayer(UUID player) {
|
||||
if (!players.contains(player)) {
|
||||
players.add(player);
|
||||
if (visible)
|
||||
sendPacket(player.getUniqueId(), getPacket(UpdateAction.ADD));
|
||||
sendPacket(player, getPacket(UpdateAction.ADD));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package us.myles.ViaVersion.classgenerator;
|
||||
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
|
||||
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
|
||||
|
||||
public class BasicHandlerConstructor implements HandlerConstructor {
|
||||
@Override
|
||||
public ViaEncodeHandler newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
|
||||
return new ViaEncodeHandler(info, minecraftEncoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViaDecodeHandler newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
|
||||
return new ViaDecodeHandler(info, minecraftDecoder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package us.myles.ViaVersion.classgenerator;
|
||||
|
||||
import javassist.*;
|
||||
import javassist.expr.ConstructorCall;
|
||||
import javassist.expr.ExprEditor;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
|
||||
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
public class ClassGenerator {
|
||||
private static HandlerConstructor constructor = new BasicHandlerConstructor();
|
||||
|
||||
public static HandlerConstructor getConstructor() {
|
||||
return constructor;
|
||||
}
|
||||
|
||||
public static void generate() {
|
||||
if(!ViaVersion.getInstance().isCompatSpigotBuild()) return; // Use Basic Handler as not needed.
|
||||
|
||||
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"));
|
||||
|
||||
// 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));
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
return generated.toClass(HandlerConstructor.class.getClassLoader());
|
||||
} catch (NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CannotCompileException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package us.myles.ViaVersion.classgenerator;
|
||||
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
|
||||
public interface HandlerConstructor {
|
||||
public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder);
|
||||
public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder);
|
||||
}
|
||||
@@ -35,6 +35,8 @@ public class PPSSubCmd extends ViaSubCommand {
|
||||
long max = 0;
|
||||
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
if (!ViaVersion.getInstance().isPorted(p))
|
||||
continue;
|
||||
int playerVersion = ViaVersion.getInstance().getPlayerVersion(p);
|
||||
if (!playerVersions.containsKey(playerVersion))
|
||||
playerVersions.put(playerVersion, new HashSet<String>());
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
@@ -11,6 +12,7 @@ import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.util.PipelineUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class ViaEncodeHandler extends MessageToByteEncoder {
|
||||
@@ -25,6 +27,11 @@ public class ViaEncodeHandler extends MessageToByteEncoder {
|
||||
|
||||
@Override
|
||||
protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception {
|
||||
if (ViaVersion.getInstance().isCompatSpigotBuild()) {
|
||||
Field ver = minecraftEncoder.getClass().getDeclaredField("version");
|
||||
ver.setAccessible(true);
|
||||
ver.set(minecraftEncoder, ver.get(this));
|
||||
}
|
||||
// handle the packet type
|
||||
if (!(o instanceof ByteBuf)) {
|
||||
// call minecraft encoder
|
||||
|
||||
@@ -7,6 +7,8 @@ import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
|
||||
import us.myles.ViaVersion.classgenerator.ClassGenerator;
|
||||
import us.myles.ViaVersion.classgenerator.HandlerConstructor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -36,9 +38,11 @@ public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
|
||||
new ProtocolPipeline(info);
|
||||
// Add originals
|
||||
this.method.invoke(this.original, socketChannel);
|
||||
|
||||
HandlerConstructor constructor = ClassGenerator.getConstructor();
|
||||
// Add our transformers
|
||||
ViaEncodeHandler encoder = new ViaEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder"));
|
||||
ViaDecodeHandler decoder = new ViaDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder"));
|
||||
MessageToByteEncoder encoder = constructor.newEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder"));
|
||||
ByteToMessageDecoder decoder = constructor.newDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder"));
|
||||
ViaPacketHandler chunkHandler = new ViaPacketHandler(info);
|
||||
|
||||
socketChannel.pipeline().replace("encoder", "encoder", encoder);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package us.myles.ViaVersion.protocols.base;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
@@ -22,6 +23,7 @@ import us.myles.ViaVersion.packets.State;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class BaseProtocol extends Protocol {
|
||||
|
||||
@@ -40,6 +42,8 @@ public class BaseProtocol extends Protocol {
|
||||
try {
|
||||
JSONObject json = (JSONObject) new JSONParser().parse(originalStatus);
|
||||
JSONObject version = (JSONObject) json.get("version");
|
||||
if (ViaVersion.getConfig().isSendSupportedVersions())
|
||||
version.put("supportedVersions", ViaVersion.getInstance().getSupportedVersions());
|
||||
if (ProtocolRegistry.SERVER_PROTOCOL == -1) {
|
||||
Long original = (Long) version.get("protocol");
|
||||
ProtocolRegistry.SERVER_PROTOCOL = original.intValue();
|
||||
@@ -83,6 +87,15 @@ public class BaseProtocol extends Protocol {
|
||||
info.setUsername(wrapper.get(Type.STRING, 1));
|
||||
// Add to ported clients
|
||||
((ViaVersionPlugin) ViaVersion.getInstance()).addPortedClient(wrapper.user());
|
||||
if (ViaVersion.getInstance().isDebug()) {
|
||||
// Print out the route to console
|
||||
((ViaVersionPlugin) ViaVersion.getInstance()).getLogger().log(Level.INFO, "{0} logged in with protocol {1}, Route: {2}",
|
||||
new Object[]{
|
||||
wrapper.get(Type.STRING, 1),
|
||||
info.getProtocolVersion(),
|
||||
StringUtils.join(info.getPipeline().pipes(), ", ")
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
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;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class BlockEntity {
|
||||
@Getter
|
||||
private static final Map<String, Integer> types = new ConcurrentHashMap<>();
|
||||
|
||||
static {
|
||||
types.put("MobSpawner", 1);
|
||||
types.put("Control", 2);
|
||||
types.put("Beacon", 3);
|
||||
types.put("Skull", 4);
|
||||
types.put("FlowerPot", 5);
|
||||
types.put("Banner", 6);
|
||||
types.put("UNKNOWN", 7);
|
||||
types.put("EndGateway", 8);
|
||||
types.put("Sign", 9);
|
||||
|
||||
//I didn't see anything that didn't work about chests
|
||||
// types.put("Chest", -1);
|
||||
}
|
||||
|
||||
public static void handle(List<CompoundTag> tags, UserConnection connection) {
|
||||
for (CompoundTag tag : tags) {
|
||||
try {
|
||||
if (!tag.contains("id"))
|
||||
throw new Exception("NBT tag not handled because the id key is missing");
|
||||
|
||||
String id = (String) tag.get("id").getValue();
|
||||
if (!types.containsKey(id))
|
||||
throw new Exception("Not handled id: " + id);
|
||||
|
||||
int newId = types.get(id);
|
||||
if (newId == -1)
|
||||
continue;
|
||||
|
||||
|
||||
int x = (int) tag.get("x").getValue();
|
||||
int y = (int) tag.get("y").getValue();
|
||||
int z = (int) tag.get("z").getValue();
|
||||
|
||||
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 {
|
||||
String[] lines = new String[4];
|
||||
for (int i = 1; i < 5; i++)
|
||||
lines[i - 1] = (String) tag.get("Text" + i).getValue();
|
||||
updateSign(pos, lines, connection);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if(ViaVersion.getInstance().isDebug()) {
|
||||
System.out.println("Block Entity: " + e.getMessage() + ": " + tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateBlockEntity(Position pos, short id, CompoundTag tag, UserConnection connection) throws Exception {
|
||||
PacketWrapper wrapper = new PacketWrapper(0x09, null, connection);
|
||||
wrapper.write(Type.POSITION, pos);
|
||||
wrapper.write(Type.UNSIGNED_BYTE, id);
|
||||
wrapper.write(Type.NBT, tag);
|
||||
wrapper.send();
|
||||
}
|
||||
|
||||
private static void updateSign(Position pos, String[] lines, UserConnection connection) throws Exception {
|
||||
PacketWrapper wrapper = new PacketWrapper(0x46, null, connection);
|
||||
wrapper.write(Type.POSITION, pos);
|
||||
for (String s : lines)
|
||||
wrapper.write(Type.STRING, s);
|
||||
wrapper.send();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class Chunk1_9_3 {
|
||||
private int x;
|
||||
private int z;
|
||||
private boolean groundUp;
|
||||
private int bitmask;
|
||||
private byte[] sections;
|
||||
List<CompoundTag> blockEntities;
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Chunk1_9_3Type extends Type<Chunk1_9_3> {
|
||||
public Chunk1_9_3Type() {
|
||||
super("1.9.3 Chunk", Chunk1_9_3.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk1_9_3 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);
|
||||
|
||||
byte[] sections = new byte[size];
|
||||
input.readBytes(sections);
|
||||
|
||||
int blockEntities = Type.VAR_INT.read(input);
|
||||
List<CompoundTag> nbtData = new ArrayList<>();
|
||||
for (int i = 0; i < blockEntities; i++) {
|
||||
nbtData.add(Type.NBT.read(input));
|
||||
}
|
||||
return new Chunk1_9_3(chunkX, chunkZ, groundUp, primaryBitmask, sections, nbtData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Chunk1_9_3 chunk) throws Exception {
|
||||
buffer.writeInt(chunk.getX());
|
||||
buffer.writeInt(chunk.getZ());
|
||||
|
||||
buffer.writeBoolean(chunk.isGroundUp());
|
||||
Type.VAR_INT.write(buffer, chunk.getBitmask());
|
||||
|
||||
Type.VAR_INT.write(buffer, chunk.getSections().length);
|
||||
buffer.writeBytes(chunk.getSections());
|
||||
|
||||
// no block entities as it's earlier
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3;
|
||||
|
||||
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.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;
|
||||
|
||||
public class Protocol1_9_1_2TO1_9_3 extends Protocol {
|
||||
public static Type<Chunk1_9_3> CHUNK = new Chunk1_9_3Type();
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
|
||||
//Unchanged packet structure
|
||||
registerOutgoing(State.PLAY, 0x46, 0x47); //Sound effect
|
||||
registerOutgoing(State.PLAY, 0x47, 0x48); //Player list header and footer
|
||||
registerOutgoing(State.PLAY, 0x48, 0x49); //Collect item
|
||||
registerOutgoing(State.PLAY, 0x49, 0x4A); //Entity teleport
|
||||
registerOutgoing(State.PLAY, 0x4A, 0x4B); //Entity properties
|
||||
registerOutgoing(State.PLAY, 0x4B, 0x4C); //Entity effect
|
||||
|
||||
//Update block entity
|
||||
registerOutgoing(State.PLAY, 0x09, 0x09, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.POSITION); //Position
|
||||
map(Type.UNSIGNED_BYTE); //Type
|
||||
map(Type.NBT); //NBT
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 9) {
|
||||
Position position = wrapper.get(Type.POSITION, 0);
|
||||
CompoundTag tag = wrapper.get(Type.NBT, 0);
|
||||
|
||||
wrapper.clearPacket(); //Clear the packet
|
||||
|
||||
wrapper.setId(0x46); //Update sign packet
|
||||
wrapper.write(Type.POSITION, position); // Position
|
||||
for (int i = 1; i < 5; i++)
|
||||
wrapper.write(Type.STRING, (String) tag.get("Text" + i).getValue()); // Sign line
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
registerOutgoing(State.PLAY, 0x20, 0x20, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
Chunk1_9_3 chunk = wrapper.passthrough(CHUNK);
|
||||
BlockEntity.handle(chunk.getBlockEntities(), wrapper.user());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@ import us.myles.ViaVersion.packets.State;
|
||||
public class Protocol1_9_1TO1_9 extends Protocol {
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
// Currently supports 1.9.1 PRE 2
|
||||
// Currently supports 1.9.1 and 1.9.2
|
||||
// Join Game Packet
|
||||
registerOutgoing(State.PLAY, 0x23, 0x23, new PacketRemapper() {
|
||||
@Override
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2;
|
||||
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
import org.spacehq.opennbt.tag.builtin.IntTag;
|
||||
import org.spacehq.opennbt.tag.builtin.StringTag;
|
||||
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.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;
|
||||
|
||||
public class Protocol1_9_3TO1_9_1_2 extends Protocol {
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
|
||||
//Unchanged packet structure
|
||||
registerOutgoing(State.PLAY, 0x47, 0x46); //Sound effect
|
||||
registerOutgoing(State.PLAY, 0x48, 0x47); //Player list header and footer
|
||||
registerOutgoing(State.PLAY, 0x49, 0x48); //Collect item
|
||||
registerOutgoing(State.PLAY, 0x4A, 0x49); //Entity teleport
|
||||
registerOutgoing(State.PLAY, 0x4B, 0x4A); //Entity properties
|
||||
registerOutgoing(State.PLAY, 0x4C, 0x4B); //Entity effect
|
||||
|
||||
//Sign update
|
||||
registerOutgoing(State.PLAY, 0x46, -1, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
//read data
|
||||
Position position = wrapper.read(Type.POSITION);
|
||||
String[] lines = new String[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
lines[i] = wrapper.read(Type.STRING);
|
||||
|
||||
wrapper.clearInputBuffer();
|
||||
|
||||
//write data
|
||||
wrapper.setId(0x09); //Update block entity
|
||||
wrapper.write(Type.POSITION, position); //Block location
|
||||
wrapper.write(Type.UNSIGNED_BYTE, (short) 9); //Action type (9 update sign)
|
||||
|
||||
//Create nbt
|
||||
CompoundTag tag = new CompoundTag("");
|
||||
tag.put(new StringTag("id", "Sign"));
|
||||
tag.put(new IntTag("x", position.getX().intValue()));
|
||||
tag.put(new IntTag("y", position.getY().intValue()));
|
||||
tag.put(new IntTag("z", position.getZ().intValue()));
|
||||
for (int i = 0; i < lines.length; i++)
|
||||
tag.put(new StringTag("Text" + (i + 1), lines[i]));
|
||||
|
||||
wrapper.write(Type.NBT, tag);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,7 @@ import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners.*;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.packets.*;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.InventoryTracker;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.*;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.types.MetadataListType;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.types.MetadataType;
|
||||
|
||||
@@ -62,9 +59,9 @@ public class Protocol1_9TO1_8 extends Protocol {
|
||||
}
|
||||
|
||||
public static Item getHandItem(final UserConnection info) {
|
||||
if(HandItemCache.CACHE){
|
||||
if (HandItemCache.CACHE) {
|
||||
return HandItemCache.getHandItem(info.get(ProtocolInfo.class).getUuid());
|
||||
}else {
|
||||
} else {
|
||||
try {
|
||||
return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<Item>() {
|
||||
@Override
|
||||
@@ -133,5 +130,7 @@ public class Protocol1_9TO1_8 extends Protocol {
|
||||
userConnection.put(new MovementTracker(userConnection));
|
||||
// Inventory tracker
|
||||
userConnection.put(new InventoryTracker(userConnection));
|
||||
// Place block tracker
|
||||
userConnection.put(new PlaceBlockTracker(userConnection));
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class ViaIdleThread extends BukkitRunnable {
|
||||
} catch (NoSuchFieldException | InstantiationException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException("Couldn't make player idle packet, help!", e);
|
||||
}
|
||||
if(USE_NMS) {
|
||||
if (USE_NMS) {
|
||||
try {
|
||||
getHandle = ReflectionUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
@@ -70,6 +70,7 @@ public class ViaIdleThread extends BukkitRunnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (UserConnection info : portedPlayers.values()) {
|
||||
@@ -79,15 +80,19 @@ public class ViaIdleThread extends BukkitRunnable {
|
||||
if (info.getChannel().isOpen()) {
|
||||
if (USE_NMS) {
|
||||
Player player = Bukkit.getPlayer(info.get(ProtocolInfo.class).getUuid());
|
||||
try {
|
||||
// Tick player
|
||||
Object entityPlayer = getHandle.invoke(player);
|
||||
Object pc = connection.get(entityPlayer);
|
||||
handleFlying.invoke(pc, (info.get(MovementTracker.class).isGround() ? idlePacket2 : idlePacket));
|
||||
// Tick world
|
||||
info.get(MovementTracker.class).incrementIdlePacket();
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
if (player != null) {
|
||||
try {
|
||||
// Tick player
|
||||
Object entityPlayer = getHandle.invoke(player);
|
||||
Object pc = connection.get(entityPlayer);
|
||||
if (pc != null) {
|
||||
handleFlying.invoke(pc, (info.get(MovementTracker.class).isGround() ? idlePacket2 : idlePacket));
|
||||
// Tick world
|
||||
info.get(MovementTracker.class).incrementIdlePacket();
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Old method using packets.
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.chat;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
|
||||
|
||||
public class ChatRewriter {
|
||||
public static void toClient(JsonObject obj, UserConnection user) {
|
||||
//Check gamemode change
|
||||
if (obj.get("translate") != null && obj.get("translate").getAsString().equals("gameMode.changed")) {
|
||||
String gameMode = user.get(EntityTracker.class).getGameMode().getText();
|
||||
|
||||
JsonObject gameModeObject = new JsonObject();
|
||||
gameModeObject.addProperty("text", gameMode);
|
||||
gameModeObject.addProperty("color", "gray");
|
||||
gameModeObject.addProperty("italic", true);
|
||||
|
||||
JsonArray array = new JsonArray();
|
||||
array.add(gameModeObject);
|
||||
|
||||
obj.add("with", array);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.chat;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum GameMode {
|
||||
SURVIVAL(0, "Survival Mode"),
|
||||
CREATIVE(1, "Creative Mode"),
|
||||
ADVENTURE(2, "Adventure Mode"),
|
||||
SPECTATOR(3, "Spectator Mode");
|
||||
|
||||
private final int id;
|
||||
private final String text;
|
||||
|
||||
public static GameMode getById(int id) {
|
||||
for (GameMode gm : GameMode.values())
|
||||
if (gm.getId() == id)
|
||||
return gm;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+7
-2
@@ -19,6 +19,7 @@ import org.bukkit.inventory.CraftingInventory;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
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;
|
||||
@@ -39,9 +40,12 @@ 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();
|
||||
try {
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
Type.VAR_INT.write(buf, 0x4B); // Entity Properties
|
||||
|
||||
//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");
|
||||
@@ -53,6 +57,7 @@ public class ArmorListener implements Listener {
|
||||
|
||||
ViaVersion.getInstance().sendRawPacket(player, buf);
|
||||
} catch (Exception ignored) {
|
||||
buf.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class DeathListener implements Listener {
|
||||
|
||||
public boolean checkGamerule(World w) {
|
||||
try {
|
||||
return Boolean.parseBoolean(w.getGameRuleValue("showDeathMessage"));
|
||||
return Boolean.parseBoolean(w.getGameRuleValue("showDeathMessages"));
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -157,7 +157,7 @@ public enum MetaIndex {
|
||||
}
|
||||
|
||||
public static MetaIndex getIndex(EntityType type, int index) {
|
||||
Class<? extends org.bukkit.entity.Entity> entityClass = type.getEntityClass();
|
||||
Class<? extends org.bukkit.entity.Entity> entityClass = type == null ? LivingEntity.class : type.getEntityClass();
|
||||
if (entityClass == null) {
|
||||
System.out.println("Could not get entity class for " + type);
|
||||
return null;
|
||||
|
||||
+20
-14
@@ -2,25 +2,31 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum NewType {
|
||||
Byte(0),
|
||||
VarInt(1),
|
||||
Float(2),
|
||||
String(3),
|
||||
Chat(4),
|
||||
Slot(5),
|
||||
Boolean(6),
|
||||
Vector3F(7),
|
||||
Position(8),
|
||||
OptPosition(9),
|
||||
Direction(10),
|
||||
OptUUID(11),
|
||||
BlockID(12),
|
||||
Discontinued(99);
|
||||
Byte(0, Type.BYTE),
|
||||
VarInt(1, Type.VAR_INT),
|
||||
Float(2, Type.FLOAT),
|
||||
String(3, Type.STRING),
|
||||
Chat(4, Type.STRING),
|
||||
Slot(5, Type.ITEM),
|
||||
Boolean(6, Type.BOOLEAN),
|
||||
Vector3F(7, Type.ROTATION),
|
||||
Position(8, Type.POSITION),
|
||||
OptPosition(9, Type.OPTIONAL_POSITION),
|
||||
Direction(10, Type.VAR_INT),
|
||||
OptUUID(11, Type.OPTIONAL_UUID),
|
||||
BlockID(12, Type.VAR_INT),
|
||||
Discontinued(99, null);
|
||||
|
||||
private final int typeID;
|
||||
private final Type type;
|
||||
|
||||
public static NewType byId(int id) {
|
||||
return values()[id];
|
||||
}
|
||||
|
||||
}
|
||||
+78
-1
@@ -1,5 +1,7 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.packets;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
@@ -13,8 +15,11 @@ import us.myles.ViaVersion.api.remapper.ValueCreator;
|
||||
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_9to1_8.ItemRewriter;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.PlayerMovementMapper;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.chat.ChatRewriter;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.chat.GameMode;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
|
||||
|
||||
@@ -26,6 +31,19 @@ public class PlayerPackets {
|
||||
public void registerMap() {
|
||||
map(Type.STRING, Protocol1_9TO1_8.FIX_JSON); // 0 - Chat Message (json)
|
||||
map(Type.BYTE); // 1 - Chat Positon
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
try {
|
||||
JsonObject obj = (JsonObject) new JsonParser().parse(wrapper.get(Type.STRING, 0));
|
||||
ChatRewriter.toClient(obj, wrapper.user());
|
||||
wrapper.set(Type.STRING, 0, obj.toString());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -159,6 +177,14 @@ public class PlayerPackets {
|
||||
map(Type.UNSIGNED_BYTE); // 4 - Max Players (Tab)
|
||||
map(Type.STRING); // 5 - Level Type
|
||||
map(Type.BOOLEAN); // 6 - Reduced Debug info
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
|
||||
tracker.setGameMode(GameMode.getById(wrapper.get(Type.UNSIGNED_BYTE, 0))); //Set player gamemode
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -228,6 +254,31 @@ public class PlayerPackets {
|
||||
wrapper.passthrough(Type.REMAINING_BYTES); // This is so ugly, :(
|
||||
wrapper.write(Type.VAR_INT, 0);
|
||||
}
|
||||
if (name.equalsIgnoreCase("MC|TrList")) {
|
||||
wrapper.passthrough(Type.INT); // ID
|
||||
|
||||
Short size = wrapper.passthrough(Type.UNSIGNED_BYTE);
|
||||
|
||||
for (int i = 0; i < size; ++i) {
|
||||
Item item1 = wrapper.passthrough(Type.ITEM);
|
||||
ItemRewriter.toClient(item1);
|
||||
|
||||
Item item2 = wrapper.passthrough(Type.ITEM);
|
||||
ItemRewriter.toClient(item2);
|
||||
|
||||
boolean present = wrapper.passthrough(Type.BOOLEAN);
|
||||
|
||||
if (present) {
|
||||
Item item3 = wrapper.passthrough(Type.ITEM);
|
||||
ItemRewriter.toClient(item3);
|
||||
}
|
||||
|
||||
wrapper.passthrough(Type.BOOLEAN);
|
||||
|
||||
wrapper.passthrough(Type.INT);
|
||||
wrapper.passthrough(Type.INT);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -257,6 +308,11 @@ public class PlayerPackets {
|
||||
protocol.registerOutgoing(State.PLAY, 0x07, 0x33, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.INT); // 0 - Dimension
|
||||
map(Type.UNSIGNED_BYTE); // 1 - Difficulty
|
||||
map(Type.UNSIGNED_BYTE); // 2 - GameMode
|
||||
map(Type.STRING); // 3 - Level Type
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
@@ -264,6 +320,28 @@ public class PlayerPackets {
|
||||
ClientChunks cc = wrapper.user().get(ClientChunks.class);
|
||||
cc.getBulkChunks().clear();
|
||||
cc.getLoadedChunks().clear();
|
||||
|
||||
int gamemode = wrapper.get(Type.UNSIGNED_BYTE, 0);
|
||||
wrapper.user().get(EntityTracker.class).setGameMode(GameMode.getById(gamemode));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Change Game State Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x2B, 0x1E, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.UNSIGNED_BYTE); //0 - Reason
|
||||
map(Type.FLOAT); //1 - Value
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 3) { //Change gamemode
|
||||
int gamemode = wrapper.get(Type.FLOAT, 0).intValue();
|
||||
wrapper.user().get(EntityTracker.class).setGameMode(GameMode.getById(gamemode));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -307,7 +385,6 @@ public class PlayerPackets {
|
||||
protocol.registerOutgoing(State.PLAY, 0x00, 0x1F); // Keep Alive Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x48, 0x32); // Resource Pack Send Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x43, 0x36); // Camera Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x2B, 0x1E); // Change Game State Packet
|
||||
|
||||
protocol.registerOutgoing(State.PLAY, 0x3D, 0x38); // Display Scoreboard Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x3B, 0x3F); // Scoreboard Objective Packet
|
||||
|
||||
+13
-29
@@ -6,6 +6,7 @@ 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;
|
||||
@@ -13,13 +14,13 @@ import us.myles.ViaVersion.api.remapper.PacketRemapper;
|
||||
import us.myles.ViaVersion.api.remapper.ValueCreator;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.ArmorType;
|
||||
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.sounds.Effect;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.sounds.SoundEffect;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.PlaceBlockTracker;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.types.ChunkType;
|
||||
|
||||
public class WorldPackets {
|
||||
@@ -114,7 +115,10 @@ public class WorldPackets {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
ClientChunks clientChunks = wrapper.user().get(ClientChunks.class);
|
||||
wrapper.passthrough(new ChunkType(clientChunks));
|
||||
Chunk chunk = wrapper.passthrough(new ChunkType(clientChunks));
|
||||
if (chunk.isUnloadPacket())
|
||||
wrapper.setId(0x1D);
|
||||
|
||||
// eat any other data (Usually happens with unload packets)
|
||||
wrapper.read(Type.REMAINING_BYTES);
|
||||
}
|
||||
@@ -226,7 +230,7 @@ public class WorldPackets {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
int status = wrapper.get(Type.UNSIGNED_BYTE, 0);
|
||||
if (status == 4) {
|
||||
if (status == 5 || status == 4 || status == 3) {
|
||||
EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
|
||||
if (entityTracker.isBlocking()) {
|
||||
entityTracker.setBlocking(false);
|
||||
@@ -345,32 +349,12 @@ public class WorldPackets {
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
Item item = wrapper.get(Type.ITEM, 0);
|
||||
if (item != null) {
|
||||
Material m = Material.getMaterial(item.getId());
|
||||
if (m != null) {
|
||||
// Prevent special items from sending certain info
|
||||
// Books
|
||||
boolean special = m == Material.WRITTEN_BOOK;
|
||||
// Buckets
|
||||
special = special || m == Material.WATER_BUCKET || m == Material.LAVA_BUCKET || m == Material.BUCKET;
|
||||
// Food
|
||||
special = special || m.isEdible();
|
||||
// Potions
|
||||
special = special || m == Material.POTION || m == Material.GLASS_BOTTLE;
|
||||
// Projectiles
|
||||
special = special || m == Material.BOW;
|
||||
special = special || m == Material.SNOW_BALL || m == Material.EGG || m == Material.EXP_BOTTLE || m == Material.ENDER_PEARL || m == Material.EYE_OF_ENDER;
|
||||
// Armour
|
||||
special = special || ArmorType.isArmor(m);
|
||||
// Don't send data if special
|
||||
if (special && m != Material.AIR) {
|
||||
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
|
||||
tracker.setLastPlaceBlock(wrapper.user().getReceivedPackets());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Position position = wrapper.get(Type.POSITION, 0);
|
||||
PlaceBlockTracker tracker = wrapper.user().get(PlaceBlockTracker.class);
|
||||
if (tracker.getLastPlacedPosition() != null && tracker.getLastPlacedPosition().equals(position) && !tracker.isExpired(50))
|
||||
wrapper.cancel();
|
||||
tracker.updateTime();
|
||||
tracker.setLastPlacedPosition(position);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+24
@@ -4,10 +4,12 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.StoredObject;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
@@ -17,11 +19,15 @@ public class ClientChunks extends StoredObject {
|
||||
// Reflection
|
||||
private static ReflectionUtil.ClassReflection mapChunkBulkRef;
|
||||
private static ReflectionUtil.ClassReflection mapChunkRef;
|
||||
private static Method obfuscateRef;
|
||||
private static Class<?> worldRef;
|
||||
|
||||
static {
|
||||
try {
|
||||
mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk"));
|
||||
mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk"));
|
||||
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);
|
||||
}
|
||||
@@ -44,6 +50,24 @@ public class ClientChunks extends StoredObject {
|
||||
int[] xcoords = mapChunkBulkRef.getFieldValue("a", packet, int[].class);
|
||||
int[] zcoords = mapChunkBulkRef.getFieldValue("b", packet, int[].class);
|
||||
Object[] chunkMaps = mapChunkBulkRef.getFieldValue("c", packet, Object[].class);
|
||||
|
||||
if (ViaVersion.getConfig().isAntiXRay() && ViaVersion.getInstance().isSpigot()) { //Spigot anti-xray patch
|
||||
try {
|
||||
Object world = mapChunkBulkRef.getFieldValue("world", packet, Object.class);
|
||||
|
||||
for (int i = 0; i < xcoords.length; ++i) {
|
||||
Object spigotConfig = ReflectionUtil.getPublic(world, "spigotConfig", Object.class);
|
||||
Object antiXrayInstance = ReflectionUtil.getPublic(spigotConfig, "antiXrayInstance", Object.class);
|
||||
|
||||
Object b = ReflectionUtil.get(chunkMaps[i], "b", Object.class);
|
||||
Object a = ReflectionUtil.get(chunkMaps[i], "a", Object.class);
|
||||
|
||||
obfuscateRef.invoke(antiXrayInstance, xcoords[i], zcoords[i], b, a, world);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// not spigot, or it failed.
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < chunkMaps.length; i++) {
|
||||
int x = xcoords[i];
|
||||
int z = zcoords[i];
|
||||
|
||||
+14
-11
@@ -2,13 +2,12 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.storage;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.collect.Sets;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
@@ -22,19 +21,21 @@ import us.myles.ViaVersion.api.minecraft.item.Item;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.chat.GameMode;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Getter
|
||||
public class EntityTracker extends StoredObject {
|
||||
private final Map<Integer, UUID> uuidMap = new HashMap<>();
|
||||
private final Map<Integer, EntityType> clientEntityTypes = new HashMap<>();
|
||||
private final Map<Integer, Integer> vehicleMap = new HashMap<>();
|
||||
private final Map<Integer, BossBar> bossBarMap = new HashMap<>();
|
||||
private final Set<Integer> validBlocking = new HashSet<>();
|
||||
private final Set<Integer> knownHolograms = new HashSet<>();
|
||||
private final Map<Integer, UUID> uuidMap = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, EntityType> clientEntityTypes = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, Integer> vehicleMap = new ConcurrentHashMap<>();
|
||||
private final Map<Integer, BossBar> bossBarMap = new ConcurrentHashMap<>();
|
||||
private final Set<Integer> validBlocking = Sets.newConcurrentHashSet();
|
||||
private final Set<Integer> knownHolograms = Sets.newConcurrentHashSet();
|
||||
private final Cache<Position, Material> blockInteractions = CacheBuilder.newBuilder().maximumSize(10).expireAfterAccess(250, TimeUnit.MILLISECONDS).build();
|
||||
@Setter
|
||||
private boolean blocking = false;
|
||||
@@ -47,6 +48,8 @@ public class EntityTracker extends StoredObject {
|
||||
@Setter
|
||||
private Position currentlyDigging = null;
|
||||
private boolean teamExists = false;
|
||||
@Setter
|
||||
private GameMode gameMode;
|
||||
|
||||
public EntityTracker(UserConnection user) {
|
||||
super(user);
|
||||
@@ -176,7 +179,7 @@ public class EntityTracker extends StoredObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
Player player = Bukkit.getPlayer(getUser().get(ProtocolInfo.class).getUuid());
|
||||
UUID uuid = getUser().get(ProtocolInfo.class).getUuid();
|
||||
// Boss bar
|
||||
if (((ViaVersionPlugin) ViaVersion.getInstance()).isBossbarPatch()) {
|
||||
if (type == EntityType.ENDER_DRAGON || type == EntityType.WITHER) {
|
||||
@@ -187,7 +190,7 @@ public class EntityTracker extends StoredObject {
|
||||
if (bar == null) {
|
||||
bar = ViaVersion.getInstance().createBossBar(title, BossColor.PINK, BossStyle.SOLID);
|
||||
bossBarMap.put(entityID, bar);
|
||||
bar.addPlayer(player);
|
||||
bar.addPlayer(uuid);
|
||||
bar.show();
|
||||
} else {
|
||||
bar.setTitle(title);
|
||||
@@ -201,7 +204,7 @@ public class EntityTracker extends StoredObject {
|
||||
String title = type == EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither";
|
||||
bar = ViaVersion.getInstance().createBossBar(title, health, BossColor.PINK, BossStyle.SOLID);
|
||||
bossBarMap.put(entityID, bar);
|
||||
bar.addPlayer(player);
|
||||
bar.addPlayer(uuid);
|
||||
bar.show();
|
||||
} else {
|
||||
bar.setHealth(health);
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.storage;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import us.myles.ViaVersion.api.data.StoredObject;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.minecraft.Position;
|
||||
|
||||
@Getter
|
||||
public class PlaceBlockTracker extends StoredObject {
|
||||
private long lastPlaceTimestamp = System.currentTimeMillis();
|
||||
@Setter
|
||||
private Position lastPlacedPosition = null;
|
||||
|
||||
public PlaceBlockTracker(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
public boolean isExpired(int ms) {
|
||||
return System.currentTimeMillis() > (lastPlaceTimestamp + ms);
|
||||
}
|
||||
|
||||
public void updateTime() {
|
||||
lastPlaceTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
@@ -128,11 +128,6 @@ public class ChunkType extends PartialType<Chunk, ClientChunks> {
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf output, ClientChunks param, Chunk chunk) throws Exception {
|
||||
if (chunk.isUnloadPacket()) {
|
||||
output.clear();
|
||||
Type.VAR_INT.write(output, 0x1D); // Unload packet ID
|
||||
}
|
||||
|
||||
// Write primary info
|
||||
output.writeInt(chunk.getX());
|
||||
output.writeInt(chunk.getZ());
|
||||
|
||||
+2
-5
@@ -2,16 +2,13 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.types;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.api.type.types.minecraft.MetaListTypeTemplate;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MetadataListType extends Type<List<Metadata>> {
|
||||
public MetadataListType() {
|
||||
super("Metadata List", List.class);
|
||||
}
|
||||
public class MetadataListType extends MetaListTypeTemplate {
|
||||
|
||||
@Override
|
||||
public List<Metadata> read(ByteBuf buffer) throws Exception {
|
||||
|
||||
+2
-6
@@ -3,14 +3,10 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.types;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.api.type.types.minecraft.MetaTypeTemplate;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.MetadataTypes;
|
||||
|
||||
public class MetadataType extends Type<Metadata> {
|
||||
|
||||
public MetadataType() {
|
||||
super(Metadata.class);
|
||||
}
|
||||
public class MetadataType extends MetaTypeTemplate {
|
||||
|
||||
@Override
|
||||
public Metadata read(ByteBuf buffer) throws Exception {
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_9_1;
|
||||
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
import us.myles.ViaVersion.api.remapper.PacketRemapper;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
|
||||
public class Protocol1_9TO1_9_1 extends Protocol {
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
// Currently supports 1.9.1 and 1.9.2
|
||||
// Join Game Packet
|
||||
registerOutgoing(State.PLAY, 0x23, 0x23, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.INT); // 0 - Player ID
|
||||
map(Type.UNSIGNED_BYTE); // 1 - Player Gamemode
|
||||
// 1.9.1 PRE 2 Changed this
|
||||
map(Type.INT, Type.BYTE); // 2 - Player Dimension
|
||||
map(Type.UNSIGNED_BYTE); // 3 - World Difficulty
|
||||
map(Type.UNSIGNED_BYTE); // 4 - Max Players (Tab)
|
||||
map(Type.STRING); // 5 - Level Type
|
||||
map(Type.BOOLEAN); // 6 - Reduced Debug info
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package us.myles.ViaVersion.protocols.protocolsnapshotto1_9_3;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.api.type.types.minecraft.MetaListTypeTemplate;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MetaListSnapshotType extends MetaListTypeTemplate {
|
||||
|
||||
@Override
|
||||
public List<Metadata> read(ByteBuf buffer) throws Exception {
|
||||
List<Metadata> list = new ArrayList<>();
|
||||
Metadata meta;
|
||||
do {
|
||||
meta = ProtocolSnapshotTo1_9_3.METADATA.read(buffer);
|
||||
if (meta != null)
|
||||
list.add(meta);
|
||||
} while (meta != null);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, List<Metadata> object) throws Exception {
|
||||
for (Metadata m : object) {
|
||||
if (m.getId() >= 5)
|
||||
m.setId(m.getId() + 1);
|
||||
if (m.getId() == 4)
|
||||
ProtocolSnapshotTo1_9_3.METADATA.write(buffer, new Metadata(5, NewType.Boolean.getTypeID(), Type.BOOLEAN, false)); // No gravity metadata
|
||||
ProtocolSnapshotTo1_9_3.METADATA.write(buffer, m);
|
||||
}
|
||||
|
||||
// Write end of list
|
||||
ProtocolSnapshotTo1_9_3.METADATA.write(buffer, null);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package us.myles.ViaVersion.protocols.protocolsnapshotto1_9_3;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
import us.myles.ViaVersion.api.type.types.minecraft.MetaTypeTemplate;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType;
|
||||
|
||||
public class MetaSnapshotType extends MetaTypeTemplate {
|
||||
|
||||
@Override
|
||||
public Metadata read(ByteBuf buffer) throws Exception {
|
||||
short index = buffer.readUnsignedByte();
|
||||
|
||||
if (index == 0xff) return null; //End of metadata
|
||||
NewType type = NewType.byId(buffer.readByte());
|
||||
|
||||
return new Metadata(index, type.getTypeID(), type.getType(), type.getType().read(buffer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Metadata object) throws Exception {
|
||||
if (object == null) {
|
||||
buffer.writeByte(255);
|
||||
} else {
|
||||
buffer.writeByte(object.getId());
|
||||
buffer.writeByte(object.getTypeID());
|
||||
object.getType().write(buffer, object.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
package us.myles.ViaVersion.protocols.protocolsnapshotto1_9_3;
|
||||
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
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.remapper.ValueTransformer;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ProtocolSnapshotTo1_9_3 extends Protocol {
|
||||
public static final Type<List<Metadata>> METADATA_LIST = new MetaListSnapshotType();
|
||||
public static final Type<Metadata> METADATA = new MetaSnapshotType();
|
||||
public static ValueTransformer<Short, Float> toNewPitch = new ValueTransformer<Short, Float>(Type.FLOAT) {
|
||||
@Override
|
||||
public Float transform(PacketWrapper wrapper, Short inputValue) throws Exception {
|
||||
return inputValue / 63.5F;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
// Named sound effect
|
||||
registerOutgoing(State.PLAY, 0x19, 0x19, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.STRING); // 0 - Sound name
|
||||
map(Type.VAR_INT); // 1 - Sound Category
|
||||
map(Type.INT); // 2 - x
|
||||
map(Type.INT); // 3 - y
|
||||
map(Type.INT); // 4 - z
|
||||
map(Type.FLOAT); // 5 - Volume
|
||||
map(Type.UNSIGNED_BYTE, toNewPitch); // 6 - Pitch
|
||||
}
|
||||
});
|
||||
|
||||
// Sound effect
|
||||
registerOutgoing(State.PLAY, 0x46, 0x46, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.VAR_INT); // 0 - Sound name
|
||||
map(Type.VAR_INT); // 1 - Sound Category
|
||||
map(Type.INT); // 2 - x
|
||||
map(Type.INT); // 3 - y
|
||||
map(Type.INT); // 4 - z
|
||||
map(Type.FLOAT); // 5 - Volume
|
||||
map(Type.UNSIGNED_BYTE, toNewPitch); // 6 - Pitch
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
int id = wrapper.get(Type.VAR_INT, 0);
|
||||
wrapper.set(Type.VAR_INT, 0, getNewSoundId(id));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Metadata packet
|
||||
registerOutgoing(State.PLAY, 0x39, 0x39, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.VAR_INT); // 0 - Entity ID
|
||||
map(METADATA_LIST); // 1 - Metadata list
|
||||
}
|
||||
});
|
||||
|
||||
// Spawn Mob
|
||||
registerOutgoing(State.PLAY, 0x03, 0x03, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.VAR_INT); // 0 - Entity id
|
||||
map(Type.UUID); // 1 - UUID
|
||||
map(Type.UNSIGNED_BYTE); // 2 - Entity Type
|
||||
map(Type.DOUBLE); // 3 - X
|
||||
map(Type.DOUBLE); // 4 - Y
|
||||
map(Type.DOUBLE); // 5 - Z
|
||||
map(Type.BYTE); // 6 - Yaw
|
||||
map(Type.BYTE); // 7 - Pitch
|
||||
map(Type.BYTE); // 8 - Head Pitch
|
||||
map(Type.SHORT); // 9 - Velocity X
|
||||
map(Type.SHORT); // 10 - Velocity Y
|
||||
map(Type.SHORT); // 11 - Velocity Z
|
||||
map(METADATA_LIST); // 12 - Metadata
|
||||
}
|
||||
});
|
||||
|
||||
// Spawn Player
|
||||
registerOutgoing(State.PLAY, 0x05, 0x05, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.VAR_INT); // 0 - Entity ID
|
||||
map(Type.UUID); // 1 - Player UUID
|
||||
map(Type.DOUBLE); // 2 - X
|
||||
map(Type.DOUBLE); // 3 - Y
|
||||
map(Type.DOUBLE); // 4 - Z
|
||||
map(Type.BYTE); // 5 - Yaw
|
||||
map(Type.BYTE); // 6 - Pitch
|
||||
map(METADATA_LIST); // 7 - Metadata list
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public int getNewSoundId(int id) { //TODO organize things later
|
||||
if (id >= 24 && id <= 295) //One EnchantTable sound makes everything move between 24 and 295, blame the enchant table.
|
||||
return ++id;
|
||||
else if (id >= 296 && id < 443) //Blame the polar bear
|
||||
return id + 7;
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,13 @@ public class ReflectionUtil {
|
||||
return (T) field.get(o);
|
||||
}
|
||||
|
||||
public static <T> T getPublic(Object o, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getField(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);
|
||||
|
||||
@@ -1,5 +1,46 @@
|
||||
# Thanks for downloading ViaVersion
|
||||
# Ensure you look through all these options
|
||||
# If you need help:
|
||||
# viaversion.com - Discussion tab
|
||||
# IRC - https://elmer.spi.gt/iris/?nick=&channels=viaversion #viaversion on irc.spi.gt
|
||||
#
|
||||
#----------------------------------------------------------#
|
||||
# GLOBAL OPTIONS #
|
||||
#----------------------------------------------------------#
|
||||
#
|
||||
# Should ViaVersion check for updates?
|
||||
checkforupdates: true
|
||||
# Send the supported versions with the Status (Ping) response packet
|
||||
send-supported-versions: false
|
||||
#
|
||||
#----------------------------------------------------------#
|
||||
# GLOBAL PACKET LIMITER #
|
||||
#----------------------------------------------------------#
|
||||
#
|
||||
# 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
|
||||
# Use -1 to disable.
|
||||
max-pps: 400
|
||||
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.
|
||||
|
||||
# Period to track (in seconds)
|
||||
# Use -1 to disable.
|
||||
tracking-period: 6
|
||||
# How many packets per second counts as a warning
|
||||
tracking-warning-pps: 120
|
||||
# How many warnings over the interval can we have
|
||||
# This can never be higher than "tracking-interval"
|
||||
tracking-max-warnings: 4
|
||||
tracking-max-kick-msg: "You are sending too many packets, :("
|
||||
#
|
||||
#----------------------------------------------------------#
|
||||
# 1.9 CLIENTS ON 1.8 SERVERS OPTIONS #
|
||||
#----------------------------------------------------------#
|
||||
#
|
||||
# No collide options, these allow you to configure how collision works.
|
||||
# Do you want us to prevent collision?
|
||||
prevent-collision: true
|
||||
@@ -33,22 +74,5 @@ suppress-entityid-errors: false
|
||||
block-break-patch: true
|
||||
# Should we cache our items, this will prevent server from being lagged out, however the cost is a constant task caching items
|
||||
item-cache: true
|
||||
# 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
|
||||
# Use -1 to disable.
|
||||
max-pps: 400
|
||||
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.
|
||||
|
||||
# Period to track (in seconds)
|
||||
# Use -1 to disable.
|
||||
tracking-period: 6
|
||||
# How many packets per second counts as a warning
|
||||
tracking-warning-pps: 120
|
||||
# How many warnings over the interval can we have
|
||||
# This can never be higher than "tracking-interval"
|
||||
tracking-max-warnings: 4
|
||||
tracking-max-kick-msg: "You are sending too many packets, :("
|
||||
# Patch the Anti xray to work on 1.9 (If your server is 1.8) This can cost more performance, so disable it if you don't use it.
|
||||
anti-xray-patch: true
|
||||
Reference in new issue
Block a user