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 | ||
|
|
38617d1f61 | ||
|
|
cc5bcb8a64 | ||
|
|
b6794f5597 | ||
|
|
18f77308f5 | ||
|
|
6bb473ea8d | ||
|
|
7984f6400c | ||
|
|
3498d093b0 | ||
|
|
a3db32758c | ||
|
|
45952d3759 | ||
|
|
c552b12696 | ||
|
|
0ae9d9dbbf | ||
|
|
8852e3b3a3 | ||
|
|
a496b2d3a8 | ||
|
|
6198dbfe70 | ||
|
|
a81d52a54f | ||
|
|
cf20e8ac5f | ||
|
|
4f8a248c6b | ||
|
|
57d58db35e | ||
|
|
c214ca02e8 | ||
|
|
6b8b0e1771 | ||
|
|
e6671513f2 | ||
|
|
4c7b50d6fb | ||
|
|
1c9229a2fc | ||
|
|
d11c18c024 | ||
|
|
dc4b5b4d35 | ||
|
|
517299d673 | ||
|
|
a8baa7af50 | ||
|
|
a1f847c905 | ||
|
|
f3ea43b1eb | ||
|
|
551b5d0654 | ||
|
|
9f39662df6 |
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.4
|
||||
# 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,7 +18,7 @@ Sources:
|
||||
|
||||
**wiki.vg** (Protocol info, though I did have to find a lot myself)
|
||||
|
||||
**MCProtocolLib** (used for chunk reading & some of writing.)
|
||||
**Burger** We use this tool to get protocol and other useful information for new / undocumented Minecraft versions
|
||||
|
||||
**OpenNBT** (used for slot rewriting)
|
||||
|
||||
@@ -58,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/
|
||||
@@ -68,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.5-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>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package us.myles.ViaVersion;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
|
||||
import us.myles.ViaVersion.util.PipelineUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ViaIdleThread extends BukkitRunnable {
|
||||
private final Map<UUID, UserConnection> portedPlayers;
|
||||
private final Object idlePacket;
|
||||
|
||||
public ViaIdleThread(Map<UUID, UserConnection> portedPlayers) {
|
||||
this.portedPlayers = portedPlayers;
|
||||
try {
|
||||
Class<?> idlePacketClass = ReflectionUtil.nms("PacketPlayInFlying");
|
||||
idlePacket = idlePacketClass.newInstance();
|
||||
} catch (InstantiationException | IllegalArgumentException | IllegalAccessException | ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find/make player idle packet, help!", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (UserConnection info : portedPlayers.values()) {
|
||||
if (info.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) {
|
||||
long nextIdleUpdate = info.get(MovementTracker.class).getNextIdlePacket();
|
||||
if (nextIdleUpdate <= System.currentTimeMillis()) {
|
||||
ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", info.getChannel().pipeline());
|
||||
if(info.getChannel().isOpen()) {
|
||||
if (context != null) {
|
||||
context.fireChannelRead(idlePacket);
|
||||
|
||||
info.get(MovementTracker.class).incrementIdlePacket();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -360,6 +397,11 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
|
||||
return getConfig().getBoolean("use-new-effect-indicator", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowNewDeathMessages() {
|
||||
return getConfig().getBoolean("use-new-deathmessages", false);
|
||||
}
|
||||
|
||||
public boolean isSuppressMetadataErrors() {
|
||||
return getConfig().getBoolean("suppress-metadata-errors", false);
|
||||
}
|
||||
@@ -388,6 +430,50 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
|
||||
return getConfig().getDouble("hologram-y", -1D);
|
||||
}
|
||||
|
||||
public boolean isBlockBreakPatch() {
|
||||
return getConfig().getBoolean("block-break-patch", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxPPS() {
|
||||
return getConfig().getInt("max-pps", 140);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMaxPPSKickMessage() {
|
||||
return getConfig().getString("max-pps-kick-msg", "Sending packets too fast? lag?");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTrackingPeriod() {
|
||||
return getConfig().getInt("tracking-period", 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWarningPPS() {
|
||||
return getConfig().getInt("tracking-warning-pps", 120);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxWarnings() {
|
||||
return getConfig().getInt("tracking-max-warnings", 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMaxWarningsKickMessage() {
|
||||
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);
|
||||
@@ -423,4 +509,34 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
|
||||
public Map<UUID, UserConnection> getPortedPlayers() {
|
||||
return portedPlayers;
|
||||
}
|
||||
|
||||
public boolean handlePPS(UserConnection info) {
|
||||
// Max PPS Checker
|
||||
if (getMaxPPS() > 0) {
|
||||
if (info.getPacketsPerSecond() >= getMaxPPS()) {
|
||||
info.disconnect(getMaxPPSKickMessage());
|
||||
return true; // don't send current packet
|
||||
}
|
||||
}
|
||||
|
||||
// Tracking PPS Checker
|
||||
if (getMaxWarnings() > 0 && getTrackingPeriod() > 0) {
|
||||
if (info.getSecondsObserved() > getTrackingPeriod()) {
|
||||
// Reset
|
||||
info.setWarnings(0);
|
||||
info.setSecondsObserved(1);
|
||||
} else {
|
||||
info.setSecondsObserved(info.getSecondsObserved() + 1);
|
||||
if (info.getPacketsPerSecond() >= getWarningPPS()) {
|
||||
info.setWarnings(info.getWarnings() + 1);
|
||||
}
|
||||
|
||||
if (info.getWarnings() >= getMaxWarnings()) {
|
||||
info.disconnect(getMaxWarningsKickMessage());
|
||||
return true; // don't send current packet
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,26 @@ public class PacketWrapper {
|
||||
throw new InformativeException(e).set("Type", type.getTypeName()).set("Index", index).set("Packet ID", getId()).set("Data", packetValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 is(Type type, int index) {
|
||||
int currentIndex = 0;
|
||||
for (Pair<Type, Object> packetValue : packetValues) {
|
||||
if (packetValue.getKey() == type) { // Ref check
|
||||
if (currentIndex == index) {
|
||||
return true;
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a currently existing part in the output
|
||||
*
|
||||
@@ -97,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) {
|
||||
@@ -143,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.
|
||||
*
|
||||
@@ -189,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);
|
||||
@@ -283,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();
|
||||
}
|
||||
@@ -30,6 +30,13 @@ public interface ViaVersionConfig {
|
||||
*/
|
||||
boolean isNewEffectIndicator();
|
||||
|
||||
/**
|
||||
* Get if 1.9 clients are shown the new death message on the death screen
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean isShowNewDeathMessages();
|
||||
|
||||
/**
|
||||
* Get if metadata errors will be suppressed
|
||||
*
|
||||
@@ -86,4 +93,67 @@ public interface ViaVersionConfig {
|
||||
* @return true if automatic teaming is enabled
|
||||
*/
|
||||
boolean isAutoTeam();
|
||||
|
||||
/**
|
||||
* Get if our block break patch is enabled to prevent weird ghost glitches.
|
||||
*
|
||||
* @return true if it is enabled.
|
||||
*/
|
||||
boolean isBlockBreakPatch();
|
||||
|
||||
/**
|
||||
* Get the maximum number of packets a client can send per second.
|
||||
*
|
||||
* @return The number of packets a client can send per second.
|
||||
*/
|
||||
int getMaxPPS();
|
||||
|
||||
/**
|
||||
* Get the kick message sent if the user hits the max packets per second.
|
||||
*
|
||||
* @return Kick message, with colour codes using '&'
|
||||
*/
|
||||
String getMaxPPSKickMessage();
|
||||
|
||||
/**
|
||||
* The time in seconds that should be tracked for warnings
|
||||
*
|
||||
* @return Time in seconds that should be tracked for warnings
|
||||
*/
|
||||
int getTrackingPeriod();
|
||||
|
||||
/**
|
||||
* The number of packets per second to count as a warning
|
||||
*
|
||||
* @return The number of packets per second to count as a warning.
|
||||
*/
|
||||
int getWarningPPS();
|
||||
|
||||
/**
|
||||
* Get the maximum number of warnings the client can have in the interval
|
||||
*
|
||||
* @return The number of packets a client can send per second.
|
||||
*/
|
||||
int getMaxWarnings();
|
||||
|
||||
/**
|
||||
* Get the kick message sent if the user goes over the warnings in the interval
|
||||
*
|
||||
* @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,13 +69,21 @@ 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
|
||||
*
|
||||
* @param players list of players
|
||||
* @return the bossbar instance
|
||||
*/
|
||||
BossBar addPlayers(Player...players);
|
||||
BossBar addPlayers(Player... players);
|
||||
|
||||
/**
|
||||
* Remove the bossbar from a player
|
||||
|
||||
@@ -67,11 +67,11 @@ public abstract class ViaSubCommand {
|
||||
/**
|
||||
* Send message formatted / colored
|
||||
*
|
||||
* @param sender command sender
|
||||
* @param sender command sender
|
||||
* @param message string message
|
||||
* @param args optional objects
|
||||
* @param args optional objects
|
||||
*/
|
||||
public void sendMessage(CommandSender sender, String message, Object... args){
|
||||
public void sendMessage(CommandSender sender, String message, Object... args) {
|
||||
ViaCommandHandler.sendMessage(sender, message, args);
|
||||
}
|
||||
}
|
||||
@@ -3,26 +3,32 @@ package us.myles.ViaVersion.api.data;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Data
|
||||
public class UserConnection {
|
||||
@Getter
|
||||
private final SocketChannel channel;
|
||||
Map<Class, StoredObject> storedObjects = new ConcurrentHashMap<>();
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean active = true;
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean pendingDisconnect = false;
|
||||
private Object lastPacket;
|
||||
@Getter
|
||||
private long sentPackets = 0L;
|
||||
@Getter
|
||||
private long receivedPackets = 0L;
|
||||
// Used for tracking pps
|
||||
private long startTime = 0L;
|
||||
private long intervalPackets = 0L;
|
||||
private long packetsPerSecond = -1L;
|
||||
// Used for handling warnings (over time)
|
||||
private int secondsObserved = 0;
|
||||
private int warnings = 0;
|
||||
|
||||
|
||||
public UserConnection(SocketChannel socketChannel) {
|
||||
@@ -97,7 +103,45 @@ public class UserConnection {
|
||||
/**
|
||||
* Used for incrementing the number of packets received from the client
|
||||
*/
|
||||
public void incrementReceived() {
|
||||
public boolean incrementReceived() {
|
||||
// handle stats
|
||||
Long diff = System.currentTimeMillis() - startTime;
|
||||
if (diff >= 1000) {
|
||||
packetsPerSecond = intervalPackets;
|
||||
startTime = System.currentTimeMillis();
|
||||
intervalPackets = 1;
|
||||
return true;
|
||||
} else {
|
||||
intervalPackets++;
|
||||
}
|
||||
// increase total
|
||||
this.receivedPackets++;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect a connection
|
||||
*
|
||||
* @param reason The reason to use, not used if player is not active.
|
||||
*/
|
||||
public void disconnect(final String reason) {
|
||||
if(!getChannel().isOpen()) return;
|
||||
if(pendingDisconnect) return;
|
||||
pendingDisconnect = true;
|
||||
if (get(ProtocolInfo.class).getUuid() != null) {
|
||||
final UUID uuid = get(ProtocolInfo.class).getUuid();
|
||||
if (Bukkit.getPlayer(uuid) != null) {
|
||||
Bukkit.getScheduler().runTask(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
player.kickPlayer(ChatColor.translateAlternateColorCodes('&', reason));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
getChannel().close(); // =)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package us.myles.ViaVersion.api.minecraft;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
public class Position {
|
||||
private Long x;
|
||||
private Long y;
|
||||
|
||||
@@ -2,11 +2,11 @@ package us.myles.ViaVersion.api.protocol;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.Pair;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.remapper.PacketRemapper;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -153,14 +158,16 @@ public class ViaBossBar implements BossBar {
|
||||
}
|
||||
|
||||
private void sendPacket(UpdateAction action) {
|
||||
ByteBuf buf = getPacket(action);
|
||||
for (UUID uuid : new ArrayList<>(players))
|
||||
for (UUID uuid : new ArrayList<>(players)) {
|
||||
ByteBuf buf = getPacket(action);
|
||||
sendPacket(uuid, buf);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(UUID uuid, ByteBuf buf) {
|
||||
if (!ViaVersion.getInstance().isPorted(uuid) || !(ViaVersion.getInstance().getPlayerVersion(uuid) >= ProtocolVersion.v1_9.getId())) {
|
||||
players.remove(uuid);
|
||||
buf.release();
|
||||
return;
|
||||
}
|
||||
ViaVersion.getInstance().sendRawPacket(uuid, buf);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -130,6 +130,7 @@ public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, Ta
|
||||
|
||||
private void registerDefaults() throws Exception {
|
||||
registerSubCommand(new ListSubCmd());
|
||||
registerSubCommand(new PPSSubCmd());
|
||||
registerSubCommand(new DebugSubCmd());
|
||||
registerSubCommand(new DisplayLeaksSubCmd());
|
||||
registerSubCommand(new DontBugMeSubCmd());
|
||||
|
||||
@@ -21,7 +21,7 @@ public class DebugSubCmd extends ViaSubCommand {
|
||||
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
|
||||
|
||||
plugin.setDebug(!plugin.isDebug());
|
||||
sendMessage(sender, "&6Debug mode is now %s" , (plugin.isDebug() ? "&aenabled" : "&cdisabled"));
|
||||
sendMessage(sender, "&6Debug mode is now %s", (plugin.isDebug() ? "&aenabled" : "&cdisabled"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package us.myles.ViaVersion.commands.defaultsubs;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.command.ViaSubCommand;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PPSSubCmd extends ViaSubCommand {
|
||||
@Override
|
||||
public String name() {
|
||||
return "pps";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Shows the packets per second of online players";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String usage() {
|
||||
return "pps";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String[] args) {
|
||||
Map<Integer, Set<String>> playerVersions = new HashMap<>();
|
||||
int totalPackets = 0;
|
||||
int clients = 0;
|
||||
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>());
|
||||
UserConnection uc = ((ViaVersionPlugin) ViaVersion.getInstance()).getConnection(p);
|
||||
if (uc.getPacketsPerSecond() > -1) {
|
||||
playerVersions.get(playerVersion).add(p.getName() + " (" + uc.getPacketsPerSecond() + " PPS)");
|
||||
totalPackets += uc.getPacketsPerSecond();
|
||||
if (uc.getPacketsPerSecond() > max) {
|
||||
max = uc.getPacketsPerSecond();
|
||||
}
|
||||
clients++;
|
||||
}
|
||||
}
|
||||
Map<Integer, Set<String>> sorted = new TreeMap<>(playerVersions);
|
||||
sendMessage(sender, "&4Live Packets Per Second");
|
||||
if (clients > 1) {
|
||||
sendMessage(sender, "&cAverage: &f" + (totalPackets / clients));
|
||||
sendMessage(sender, "&cHighest: &f" + max);
|
||||
}
|
||||
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();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,9 @@ public class InformativeException extends Exception {
|
||||
}
|
||||
|
||||
private String getSource(Class<?> sourceClazz) {
|
||||
if(sourceClazz.isAnonymousClass()){
|
||||
if (sourceClazz.isAnonymousClass()) {
|
||||
return sourceClazz.getName() + " (Anonymous)";
|
||||
}else{
|
||||
} else {
|
||||
return sourceClazz.getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ package us.myles.ViaVersion.handlers;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import us.myles.ViaVersion.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.type.Type;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
@@ -29,9 +31,19 @@ public class ViaDecodeHandler extends ByteToMessageDecoder {
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> list) throws Exception {
|
||||
// use transformers
|
||||
if (bytebuf.readableBytes() > 0) {
|
||||
// Ignore if pending disconnect
|
||||
if (info.isPendingDisconnect()) {
|
||||
return;
|
||||
}
|
||||
// Increment received
|
||||
boolean second = info.incrementReceived();
|
||||
// Check PPS
|
||||
if(second) {
|
||||
if (((ViaVersionPlugin) ViaVersion.getConfig()).handlePPS(info))
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.isActive()) {
|
||||
// Increment received
|
||||
info.incrementReceived();
|
||||
// Handle ID
|
||||
int id = Type.VAR_INT.read(bytebuf);
|
||||
// Transform
|
||||
|
||||
@@ -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
|
||||
@@ -39,9 +46,9 @@ public class ViaEncodeHandler extends MessageToByteEncoder {
|
||||
if (bytebuf.readableBytes() == 0) {
|
||||
throw new CancelException();
|
||||
}
|
||||
// Increment sent
|
||||
info.incrementSent();
|
||||
if (info.isActive()) {
|
||||
// Increment sent
|
||||
info.incrementSent();
|
||||
// Handle ID
|
||||
int id = Type.VAR_INT.read(bytebuf);
|
||||
// Transform
|
||||
@@ -49,10 +56,10 @@ public class ViaEncodeHandler extends MessageToByteEncoder {
|
||||
bytebuf.clear();
|
||||
|
||||
try {
|
||||
PacketWrapper wrapper = new PacketWrapper(id, oldPacket, info);
|
||||
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
|
||||
protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper);
|
||||
wrapper.writeToBuffer(bytebuf);
|
||||
PacketWrapper wrapper = new PacketWrapper(id, oldPacket, info);
|
||||
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
|
||||
protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper);
|
||||
wrapper.writeToBuffer(bytebuf);
|
||||
} catch (Exception e) {
|
||||
bytebuf.clear();
|
||||
throw e;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -2,17 +2,17 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8;
|
||||
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
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.protocols.protocol1_9to1_8.storage.MovementTracker;
|
||||
|
||||
public class PlayerMovementMapper extends PacketRemapper {
|
||||
public class PlayerMovementMapper extends PacketHandler {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
wrapper.user().get(MovementTracker.class).incrementIdlePacket();
|
||||
}
|
||||
});
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
MovementTracker tracker = wrapper.user().get(MovementTracker.class);
|
||||
tracker.incrementIdlePacket();
|
||||
// If packet has the ground data
|
||||
if (wrapper.is(Type.BOOLEAN, 0)) {
|
||||
tracker.setGround(wrapper.get(Type.BOOLEAN, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
-28
@@ -4,26 +4,19 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import us.myles.ViaVersion.ViaIdleThread;
|
||||
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.item.Item;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
import us.myles.ViaVersion.api.remapper.ValueTransformer;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners.ArmorListener;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners.BlockListener;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners.CommandBlockListener;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners.PaperPatch;
|
||||
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;
|
||||
|
||||
@@ -65,23 +58,27 @@ public class Protocol1_9TO1_8 extends Protocol {
|
||||
return line;
|
||||
}
|
||||
|
||||
public static ItemStack getHandItem(final UserConnection info) {
|
||||
try {
|
||||
return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<ItemStack>() {
|
||||
@Override
|
||||
public ItemStack call() throws Exception {
|
||||
UUID playerUUID = info.get(ProtocolInfo.class).getUuid();
|
||||
if (Bukkit.getPlayer(playerUUID) != null) {
|
||||
return Bukkit.getPlayer(playerUUID).getItemInHand();
|
||||
public static Item getHandItem(final UserConnection info) {
|
||||
if (HandItemCache.CACHE) {
|
||||
return HandItemCache.getHandItem(info.get(ProtocolInfo.class).getUuid());
|
||||
} else {
|
||||
try {
|
||||
return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<Item>() {
|
||||
@Override
|
||||
public Item call() throws Exception {
|
||||
UUID playerUUID = info.get(ProtocolInfo.class).getUuid();
|
||||
if (Bukkit.getPlayer(playerUUID) != null) {
|
||||
return Item.getItem(Bukkit.getPlayer(playerUUID).getItemInHand());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}).get(10, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error fetching hand item: " + e.getClass().getName());
|
||||
if (ViaVersion.getInstance().isDebug())
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}).get(10, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error fetching hand item: " + e.getClass().getName());
|
||||
if (ViaVersion.getInstance().isDebug())
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,13 +96,18 @@ public class Protocol1_9TO1_8 extends Protocol {
|
||||
ViaVersionPlugin plugin = (ViaVersionPlugin) Bukkit.getPluginManager().getPlugin("ViaVersion");
|
||||
Bukkit.getPluginManager().registerEvents(new ArmorListener(plugin), plugin);
|
||||
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")){
|
||||
if (Bukkit.getVersion().toLowerCase().contains("paper")) {
|
||||
plugin.getLogger().info("Enabling PaperSpigot patch: Fixes block placement.");
|
||||
Bukkit.getPluginManager().registerEvents(new PaperPatch(), plugin);
|
||||
}
|
||||
if (plugin.getConfig().getBoolean("simulate-pt", true))
|
||||
new ViaIdleThread(plugin.getPortedPlayers()).runTaskTimerAsynchronously(plugin, 1L, 1L); // Updates player's idle status
|
||||
new ViaIdleThread(plugin.getPortedPlayers()).runTaskTimer(plugin, 1L, 1L); // Updates player's idle status
|
||||
if (plugin.getConfig().getBoolean("item-cache", true)) {
|
||||
new HandItemCache().runTaskTimerAsynchronously(plugin, 2L, 2L); // Updates player's items :)
|
||||
HandItemCache.CACHE = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
|
||||
import us.myles.ViaVersion.util.PipelineUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ViaIdleThread extends BukkitRunnable {
|
||||
private static boolean USE_NMS = true;
|
||||
private final Map<UUID, UserConnection> portedPlayers;
|
||||
// Used for packet mode
|
||||
private Object idlePacket;
|
||||
private Object idlePacket2;
|
||||
// Use for nms
|
||||
private Method getHandle;
|
||||
private Field connection;
|
||||
private Method handleFlying;
|
||||
|
||||
public ViaIdleThread(Map<UUID, UserConnection> portedPlayers) {
|
||||
USE_NMS = ((ViaVersionPlugin) ViaVersion.getInstance()).getConfig().getBoolean("nms-player-ticking", true);
|
||||
|
||||
this.portedPlayers = portedPlayers;
|
||||
Class<?> idlePacketClass;
|
||||
try {
|
||||
idlePacketClass = ReflectionUtil.nms("PacketPlayInFlying");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find idle packet, help!", e);
|
||||
}
|
||||
try {
|
||||
idlePacket = idlePacketClass.newInstance();
|
||||
idlePacket2 = idlePacketClass.newInstance();
|
||||
|
||||
Field flying = idlePacketClass.getDeclaredField("f");
|
||||
flying.setAccessible(true);
|
||||
|
||||
flying.set(idlePacket2, true);
|
||||
} catch (NoSuchFieldException | InstantiationException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException("Couldn't make player idle packet, help!", e);
|
||||
}
|
||||
if (USE_NMS) {
|
||||
try {
|
||||
getHandle = ReflectionUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
||||
}
|
||||
|
||||
try {
|
||||
connection = ReflectionUtil.nms("EntityPlayer").getDeclaredField("playerConnection");
|
||||
} catch (NoSuchFieldException | ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find Player Connection", e);
|
||||
}
|
||||
|
||||
try {
|
||||
handleFlying = ReflectionUtil.nms("PlayerConnection").getDeclaredMethod("a", idlePacketClass);
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (UserConnection info : portedPlayers.values()) {
|
||||
if (info.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) {
|
||||
long nextIdleUpdate = info.get(MovementTracker.class).getNextIdlePacket();
|
||||
if (nextIdleUpdate <= System.currentTimeMillis()) {
|
||||
if (info.getChannel().isOpen()) {
|
||||
if (USE_NMS) {
|
||||
Player player = Bukkit.getPlayer(info.get(ProtocolInfo.class).getUuid());
|
||||
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.
|
||||
ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", info.getChannel().pipeline());
|
||||
if (context != null) {
|
||||
if (info.get(MovementTracker.class).isGround()) {
|
||||
context.fireChannelRead(idlePacket2);
|
||||
} else {
|
||||
context.fireChannelRead(idlePacket);
|
||||
}
|
||||
info.get(MovementTracker.class).incrementIdlePacket();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -20,7 +20,7 @@ public class BlockListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void placeBlock(BlockPlaceEvent e) {
|
||||
if(plugin.isPorted(e.getPlayer())) {
|
||||
if (plugin.isPorted(e.getPlayer())) {
|
||||
UserConnection c = plugin.getConnection(e.getPlayer());
|
||||
if (!c.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) return;
|
||||
Block b = e.getBlockPlaced();
|
||||
|
||||
+6
-2
@@ -122,11 +122,15 @@ public class CommandBlockListener implements Listener {
|
||||
private long[] getPosition(Object obj) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||
return new long[]{
|
||||
(long) ReflectionUtil.getSuper(obj, "a", int.class), //X
|
||||
(long) ReflectionUtil.getSuper(obj, "c", int.class), //Y
|
||||
(long) ReflectionUtil.getSuper(obj, "d", int.class) //Z
|
||||
(long) ReflectionUtil.getSuper(obj, isR1() ? "b" : "c", int.class), //Y
|
||||
(long) ReflectionUtil.getSuper(obj, isR1() ? "c" : "d", int.class) //Z
|
||||
};
|
||||
}
|
||||
|
||||
private boolean isR1() {
|
||||
return ReflectionUtil.getVersion().equals("v1_8_R1");
|
||||
}
|
||||
|
||||
private CompoundTag getNBT(Object obj) throws Exception {
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
Method m = ReflectionUtil.nms("NBTCompressedStreamTools").getMethod("a", ReflectionUtil.nms("NBTTagCompound"), DataOutput.class);
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class DeathListener implements Listener {
|
||||
private final ViaVersionPlugin plugin;
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player p = e.getEntity();
|
||||
if (plugin.isShowNewDeathMessages() && checkGamerule(p.getWorld()) && e.getDeathMessage() != null && checkPipeline(p)) {
|
||||
sendPacket(p, e.getDeathMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkPipeline(Player p) {
|
||||
UserConnection userConnection = plugin.getConnection(p);
|
||||
return userConnection != null && userConnection.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class);
|
||||
}
|
||||
|
||||
private UserConnection getUserConnection(Player p) {
|
||||
return plugin.getConnection(p);
|
||||
}
|
||||
|
||||
public boolean checkGamerule(World w) {
|
||||
try {
|
||||
return Boolean.parseBoolean(w.getGameRuleValue("showDeathMessages"));
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(final Player p, final String msg) {
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PacketWrapper wrapper = new PacketWrapper(0x2C, null, getUserConnection(p));
|
||||
try {
|
||||
wrapper.write(Type.VAR_INT, 2);
|
||||
wrapper.write(Type.VAR_INT, p.getEntityId());
|
||||
wrapper.write(Type.INT, p.getEntityId());
|
||||
Protocol1_9TO1_8.FIX_JSON.write(wrapper, msg);
|
||||
wrapper.send();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
wrapper.clearInputBuffer();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import us.myles.ViaVersion.api.minecraft.item.Item;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class HandItemCache extends BukkitRunnable {
|
||||
public static boolean CACHE = false;
|
||||
private static ConcurrentHashMap<UUID, Item> handCache = new ConcurrentHashMap<>();
|
||||
|
||||
public static Item getHandItem(UUID player) {
|
||||
if (!handCache.containsKey(player))
|
||||
return null;
|
||||
return handCache.get(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<UUID> players = new ArrayList<>(handCache.keySet());
|
||||
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
handCache.put(p.getUniqueId(), Item.getItem(p.getItemInHand()));
|
||||
players.remove(p.getUniqueId());
|
||||
}
|
||||
// Remove offline players
|
||||
for (UUID uuid : players) {
|
||||
handCache.remove(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -32,18 +32,18 @@ public class PaperPatch implements Listener {
|
||||
} else {
|
||||
if (e.getPlayer().getLocation().getBlock().getRelative(BlockFace.UP).equals(e.getBlock())) {
|
||||
e.setCancelled(true);
|
||||
}else{
|
||||
} else {
|
||||
// Within radius of block
|
||||
if(Math.abs(diff.getX()) <= 0.8 && Math.abs(diff.getZ()) <= 0.8D){
|
||||
if (Math.abs(diff.getX()) <= 0.8 && Math.abs(diff.getZ()) <= 0.8D) {
|
||||
// Are they on the edge / shifting ish
|
||||
if(diff.getY() <= 0.1D && diff.getY() >= -0.1D){
|
||||
if (diff.getY() <= 0.1D && diff.getY() >= -0.1D) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
BlockFace relative = e.getBlockAgainst().getFace(e.getBlock());
|
||||
// Are they towering up, (handles some latency)
|
||||
if(relative == BlockFace.UP){
|
||||
if(diff.getY() < 1D && diff.getY() >= 0D){
|
||||
if (relative == BlockFace.UP) {
|
||||
if (diff.getY() < 1D && diff.getY() >= 0D) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
+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;
|
||||
|
||||
-1
@@ -3,7 +3,6 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.util.EulerAngle;
|
||||
import org.bukkit.util.Vector;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.minecraft.item.Item;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
|
||||
+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];
|
||||
}
|
||||
|
||||
}
|
||||
+19
-2
@@ -207,7 +207,7 @@ public class EntityPackets {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
List<Metadata> metadataList = wrapper.get(Protocol1_9TO1_8.METADATA_LIST, 0);
|
||||
if(metadataList.size() == 0)
|
||||
if (metadataList.size() == 0)
|
||||
wrapper.cancel();
|
||||
}
|
||||
});
|
||||
@@ -252,6 +252,24 @@ public class EntityPackets {
|
||||
}
|
||||
});
|
||||
|
||||
// Combat Event Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x42, 0x2C, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.VAR_INT); //Event id
|
||||
|
||||
handler(new PacketHandler() {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
if (wrapper.get(Type.VAR_INT, 0) == 2) { // entity dead
|
||||
wrapper.passthrough(Type.VAR_INT); //Player id
|
||||
wrapper.passthrough(Type.INT); //Entity id
|
||||
Protocol1_9TO1_8.FIX_JSON.write(wrapper, wrapper.read(Type.STRING));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/* Packets which do not have any field remapping or handlers */
|
||||
|
||||
@@ -261,7 +279,6 @@ public class EntityPackets {
|
||||
protocol.registerOutgoing(State.PLAY, 0x16, 0x27); // Entity Look Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x14, 0x28); // Entity Packet
|
||||
|
||||
protocol.registerOutgoing(State.PLAY, 0x42, 0x2C); // Combat Event Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x0A, 0x2F); // Use Bed Packet
|
||||
|
||||
protocol.registerOutgoing(State.PLAY, 0x1E, 0x31); // Remove Entity Effect Packet
|
||||
|
||||
+2
-2
@@ -146,10 +146,10 @@ public class InventoryPackets {
|
||||
Item[] oldStack = wrapper.get(Type.ITEM_ARRAY, 0);
|
||||
Item[] newStack = new Item[oldStack.length + 1];
|
||||
for (int i = 0; i < newStack.length; i++) {
|
||||
if (i > 3) {
|
||||
if (i > 4) {
|
||||
newStack[i] = oldStack[i - 1];
|
||||
} else {
|
||||
if (i != 3) { // Leave index 3 blank
|
||||
if (i != 4) { // Leave index 3 blank
|
||||
newStack[i] = oldStack[i];
|
||||
}
|
||||
}
|
||||
|
||||
+141
-6
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -253,6 +304,49 @@ public class PlayerPackets {
|
||||
}
|
||||
});
|
||||
|
||||
// Respawn Packet
|
||||
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 {
|
||||
// Client unloads chunks on respawn, take note
|
||||
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));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/* Removed packets */
|
||||
|
||||
// Map Bulk
|
||||
@@ -290,9 +384,7 @@ public class PlayerPackets {
|
||||
protocol.registerOutgoing(State.PLAY, 0x39, 0x2B); // Player Abilities Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x00, 0x1F); // Keep Alive Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x48, 0x32); // Resource Pack Send Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x07, 0x33); // Respawn 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
|
||||
@@ -428,6 +520,52 @@ public class PlayerPackets {
|
||||
}
|
||||
});
|
||||
|
||||
// Player Position Packet
|
||||
protocol.registerIncoming(State.PLAY, 0x04, 0x0C, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.DOUBLE); // 0 - X
|
||||
map(Type.DOUBLE); // 1 - Y
|
||||
map(Type.DOUBLE); // 2 - Z
|
||||
map(Type.BOOLEAN); // 3 - Ground
|
||||
handler(new PlayerMovementMapper());
|
||||
}
|
||||
});
|
||||
|
||||
// Player Move & Look Packet
|
||||
protocol.registerIncoming(State.PLAY, 0x06, 0x0D, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.DOUBLE); // 0 - X
|
||||
map(Type.DOUBLE); // 1 - Y
|
||||
map(Type.DOUBLE); // 2 - Z
|
||||
map(Type.FLOAT); // 3 - Yaw
|
||||
map(Type.FLOAT); // 4 - Pitch
|
||||
map(Type.BOOLEAN); // 5 - Ground
|
||||
handler(new PlayerMovementMapper());
|
||||
}
|
||||
});
|
||||
|
||||
// Player Look Packet
|
||||
protocol.registerIncoming(State.PLAY, 0x05, 0x0E, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.FLOAT); // 0 - Yaw
|
||||
map(Type.FLOAT); // 1 - Pitch
|
||||
map(Type.BOOLEAN); // 2 - Ground
|
||||
handler(new PlayerMovementMapper());
|
||||
}
|
||||
});
|
||||
|
||||
// Player Packet
|
||||
protocol.registerIncoming(State.PLAY, 0x03, 0x0F, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.BOOLEAN); // 0 - Ground
|
||||
handler(new PlayerMovementMapper());
|
||||
}
|
||||
});
|
||||
|
||||
/* Packets which do not have any field remapping or handlers */
|
||||
|
||||
protocol.registerIncoming(State.PLAY, 0x01, 0x02); // Chat Message Packet
|
||||
@@ -436,9 +574,6 @@ public class PlayerPackets {
|
||||
|
||||
protocol.registerIncoming(State.PLAY, 0x00, 0x0B); // Keep Alive Request Packet
|
||||
|
||||
protocol.registerIncoming(State.PLAY, 0x04, 0x0C, new PlayerMovementMapper()); // Player Position Packet
|
||||
protocol.registerIncoming(State.PLAY, 0x06, 0x0D, new PlayerMovementMapper()); // Player Move & Look Packet
|
||||
protocol.registerIncoming(State.PLAY, 0x05, 0x0E, new PlayerMovementMapper()); // Player Look Packet
|
||||
protocol.registerIncoming(State.PLAY, 0x03, 0x0F, new PlayerMovementMapper()); // Player Packet
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -294,7 +294,7 @@ public class SpawnPackets {
|
||||
if (item != 0) {
|
||||
PacketWrapper packet = new PacketWrapper(0x3C, null, wrapper.user());
|
||||
packet.write(Type.VAR_INT, wrapper.get(Type.VAR_INT, 0));
|
||||
packet.write(Type.VAR_INT, 1);
|
||||
packet.write(Type.VAR_INT, 0);
|
||||
packet.write(Type.ITEM, new Item(item, (byte) 1, (short) 0, null));
|
||||
try {
|
||||
packet.send();
|
||||
|
||||
+27
-44
@@ -14,12 +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 {
|
||||
@@ -49,12 +50,8 @@ public class WorldPackets {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
int id = wrapper.get(Type.INT, 0);
|
||||
if (id >= 1000 && id < 2000 && id != 1005) { // Sound Effect
|
||||
wrapper.cancel();
|
||||
}
|
||||
if (id == 1005) { // Fix jukebox
|
||||
id = 1010;
|
||||
}
|
||||
|
||||
id = Effect.getNewId(id);
|
||||
wrapper.set(Type.INT, 0, id);
|
||||
}
|
||||
});
|
||||
@@ -119,13 +116,11 @@ public class WorldPackets {
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
ClientChunks clientChunks = wrapper.user().get(ClientChunks.class);
|
||||
Chunk chunk = wrapper.passthrough(new ChunkType(clientChunks));
|
||||
if (chunk.isUnloadPacket()) {
|
||||
PacketWrapper unload = wrapper.create(0x1D);
|
||||
unload.write(Type.INT, chunk.getX());
|
||||
unload.write(Type.INT, chunk.getZ());
|
||||
unload.send();
|
||||
wrapper.cancel();
|
||||
}
|
||||
if (chunk.isUnloadPacket())
|
||||
wrapper.setId(0x1D);
|
||||
|
||||
// eat any other data (Usually happens with unload packets)
|
||||
wrapper.read(Type.REMAINING_BYTES);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -182,11 +177,19 @@ public class WorldPackets {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Block Change Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x23, 0x0B, new PacketRemapper() {
|
||||
@Override
|
||||
public void registerMap() {
|
||||
map(Type.POSITION);
|
||||
map(Type.VAR_INT);
|
||||
}
|
||||
});
|
||||
/* Packets which do not have any field remapping or handlers */
|
||||
|
||||
protocol.registerOutgoing(State.PLAY, 0x25, 0x08); // Block Break Animation Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x24, 0x0A); // Block Action Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x23, 0x0B); // Block Change Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x22, 0x10); // Multi Block Change Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x27, 0x1C); // Explosion Packet
|
||||
protocol.registerOutgoing(State.PLAY, 0x2A, 0x22); // Particle Packet
|
||||
@@ -227,7 +230,7 @@ public class WorldPackets {
|
||||
@Override
|
||||
public void handle(PacketWrapper wrapper) throws Exception {
|
||||
int status = wrapper.get(Type.UNSIGNED_BYTE, 0);
|
||||
if (status == 5) {
|
||||
if (status == 5 || status == 4 || status == 3) {
|
||||
EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
|
||||
if (entityTracker.isBlocking()) {
|
||||
entityTracker.setBlocking(false);
|
||||
@@ -254,7 +257,7 @@ public class WorldPackets {
|
||||
wrapper.write(Type.LONG, -1L);
|
||||
wrapper.write(Type.BYTE, (byte) 255);
|
||||
// Write item in hand
|
||||
Item item = Item.getItem(Protocol1_9TO1_8.getHandItem(wrapper.user()));
|
||||
Item item = Protocol1_9TO1_8.getHandItem(wrapper.user());
|
||||
// Blocking patch
|
||||
if (ViaVersion.getConfig().isShieldBlocking()) {
|
||||
if (item != null) {
|
||||
@@ -334,7 +337,7 @@ public class WorldPackets {
|
||||
create(new ValueCreator() {
|
||||
@Override
|
||||
public void write(PacketWrapper wrapper) throws Exception {
|
||||
Item item = Item.getItem(Protocol1_9TO1_8.getHandItem(wrapper.user()));
|
||||
Item item = Protocol1_9TO1_8.getHandItem(wrapper.user());
|
||||
wrapper.write(Type.ITEM, item); // 3 - Item
|
||||
}
|
||||
});
|
||||
@@ -346,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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.sounds;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Effect {
|
||||
|
||||
private static HashMap<Integer, Integer> effects;
|
||||
|
||||
static {
|
||||
effects = new HashMap<>();
|
||||
addRewrite(1005, 1010); //Play music disc
|
||||
addRewrite(1003, 1005); //Iron door open
|
||||
addRewrite(1006, 1011); //Iron door close
|
||||
addRewrite(1004, 1009); //Fizz / Fire extinguished
|
||||
addRewrite(1007, 1015); //Ghast charge / warns
|
||||
addRewrite(1008, 1016); //Ghast shoot
|
||||
addRewrite(1009, 1016); //Ghast shoot (Lower volume according to wiki.vg)
|
||||
addRewrite(1010, 1019); //Zombie attacks wood door
|
||||
addRewrite(1011, 1020); //Zombie attacks metal door
|
||||
addRewrite(1012, 1021); //Zombie breaks wood door
|
||||
addRewrite(1014, 1024); //Wither shoot
|
||||
addRewrite(1015, 1025); //Bat takeoff / aka herobrine
|
||||
addRewrite(1016, 1026); //Zombie inject
|
||||
addRewrite(1017, 1027); //Zombie villager converted
|
||||
addRewrite(1020, 1029); //Anvil break
|
||||
addRewrite(1021, 1030); //Anvil use
|
||||
addRewrite(1022, 1031); //Anvil land
|
||||
|
||||
}
|
||||
|
||||
public static int getNewId(int id) {
|
||||
if (!contains(id))
|
||||
return id;
|
||||
return effects.get(id);
|
||||
}
|
||||
|
||||
public static boolean contains(int oldId) {
|
||||
return effects.containsKey(oldId);
|
||||
}
|
||||
|
||||
private static void addRewrite(int oldId, int newId) {
|
||||
effects.put(oldId, newId);
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -260,9 +260,10 @@ public enum SoundEffect {
|
||||
private final boolean breaksound;
|
||||
|
||||
private static HashMap<String, SoundEffect> effects;
|
||||
|
||||
static {
|
||||
effects = new HashMap<String, SoundEffect>();
|
||||
for(SoundEffect e : SoundEffect.values()) {
|
||||
effects = new HashMap<>();
|
||||
for (SoundEffect e : SoundEffect.values()) {
|
||||
effects.put(e.getName(), e);
|
||||
}
|
||||
}
|
||||
@@ -283,7 +284,7 @@ public enum SoundEffect {
|
||||
|
||||
public static SoundEffect getByName(String name) {
|
||||
name = name.toLowerCase();
|
||||
if(effects.containsKey(name))
|
||||
if (effects.containsKey(name))
|
||||
return effects.get(name);
|
||||
return null;
|
||||
}
|
||||
|
||||
+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];
|
||||
|
||||
+26
-12
@@ -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,18 +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;
|
||||
@@ -43,7 +45,11 @@ public class EntityTracker extends StoredObject {
|
||||
private Long lastPlaceBlock = -1L;
|
||||
@Setter
|
||||
private int entityID;
|
||||
@Setter
|
||||
private Position currentlyDigging = null;
|
||||
private boolean teamExists = false;
|
||||
@Setter
|
||||
private GameMode gameMode;
|
||||
|
||||
public EntityTracker(UserConnection user) {
|
||||
super(user);
|
||||
@@ -126,6 +132,12 @@ public class EntityTracker extends StoredObject {
|
||||
}
|
||||
}
|
||||
|
||||
if (type == EntityType.SKELETON) {
|
||||
if ((getMetaByIndex(metadataList, 12)) == null) {
|
||||
metadataList.add(new Metadata(12, NewType.Boolean.getTypeID(), Type.BOOLEAN, true));
|
||||
}
|
||||
}
|
||||
|
||||
if (type == EntityType.PLAYER) {
|
||||
if (metadata.getId() == 0) {
|
||||
// Byte
|
||||
@@ -146,7 +158,9 @@ public class EntityTracker extends StoredObject {
|
||||
if (metadata.getId() == 0 && getMetaByIndex(metadataList, 10) != null) {
|
||||
Metadata meta = getMetaByIndex(metadataList, 10); //Only happens if the armorstand is small
|
||||
byte data = (byte) metadata.getValue();
|
||||
if ((data & 0x20) == 0x20 && ((byte) meta.getValue() & 0x01) == 0x01) {
|
||||
// Check invisible | Check small | Check if custom name is empty | Check if custom name visible is true
|
||||
if ((data & 0x20) == 0x20 && ((byte) meta.getValue() & 0x01) == 0x01
|
||||
&& ((String) getMetaByIndex(metadataList, 2).getValue()).length() != 0 && (boolean) getMetaByIndex(metadataList, 3).getValue()) {
|
||||
if (!knownHolograms.contains(entityID)) {
|
||||
knownHolograms.add(entityID);
|
||||
try {
|
||||
@@ -165,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) {
|
||||
@@ -176,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);
|
||||
@@ -190,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);
|
||||
|
||||
+4
@@ -1,6 +1,7 @@
|
||||
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;
|
||||
|
||||
@@ -9,6 +10,9 @@ public class MovementTracker extends StoredObject {
|
||||
private static final long IDLE_PACKET_LIMIT = 20; // Max 20 ticks behind
|
||||
@Getter
|
||||
private long nextIdlePacket = 0L;
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean ground = true;
|
||||
|
||||
public MovementTracker(UserConnection user) {
|
||||
super(user);
|
||||
|
||||
+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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package us.myles.ViaVersion.util;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
|
||||
@@ -22,6 +22,10 @@ public class ReflectionUtil {
|
||||
return Class.forName(BASE + "." + className);
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return BASE.substring(BASE.lastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
public static Object invokeStatic(Class<?> clazz, String method) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
Method m = clazz.getDeclaredMethod(method);
|
||||
return m.invoke(null);
|
||||
@@ -56,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
|
||||
@@ -16,12 +57,22 @@ hologram-patch: false
|
||||
hologram-y: -1
|
||||
# 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)
|
||||
nms-player-ticking: true
|
||||
# Should we patch boss bars so they work? (Default: true, disable if you're having issues)
|
||||
bossbar-patch: true
|
||||
# If your boss bar flickers on 1.9, set this to 'true'. It will keep all boss bars on 100% (not recommended)
|
||||
bossbar-anti-flicker: false
|
||||
# This will show the new effect indicator in the top-right corner for 1.9 players.
|
||||
use-new-effect-indicator: true
|
||||
# Show the new death messages for 1.9 on the death screen
|
||||
use-new-deathmessages: false
|
||||
# This will suppress the following error: 'Unable to get entity for ID: xxxx'
|
||||
# This error message means one of you plugins is sending bad packets!
|
||||
suppress-entityid-errors: false
|
||||
suppress-entityid-errors: false
|
||||
# Our patch for block breaking issue, if you have issues with block updates then disable this.
|
||||
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
|
||||
# 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