Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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,4 +1,4 @@
|
||||
# ViaVersion 0.7.4
|
||||
# ViaVersion 0.8.0
|
||||
[](https://travis-ci.org/MylesIsCool/ViaVersion)
|
||||
[](https://gitter.im/MylesIsCool/ViaVersion)
|
||||
|
||||
@@ -20,8 +20,6 @@ Sources:
|
||||
|
||||
**wiki.vg** (Protocol info, though I did have to find a lot myself)
|
||||
|
||||
**MCProtocolLib** (used for chunk reading & some of writing.)
|
||||
|
||||
**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/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion</artifactId>
|
||||
<version>0.7.5-SNAPSHOT</version>
|
||||
<version>0.8.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ViaVersion</name>
|
||||
@@ -105,6 +105,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 +161,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,6 +360,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 +393,40 @@ 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, :(");
|
||||
}
|
||||
|
||||
public boolean isAutoTeam() {
|
||||
// Collision has to be enabled first
|
||||
return isPreventCollision() && getConfig().getBoolean("auto-team", true);
|
||||
@@ -423,4 +462,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
|
||||
*
|
||||
@@ -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){
|
||||
read(Type.REMAINING_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the current output to a buffer.
|
||||
*
|
||||
|
||||
@@ -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,53 @@ 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();
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public interface BossBar {
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,37 @@
|
||||
package us.myles.ViaVersion.api.data;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
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 +106,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,7 +7,6 @@ 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;
|
||||
@@ -29,7 +28,7 @@ public class ProtocolPipeline extends Protocol {
|
||||
protected void registerPackets() {
|
||||
protocolList = new LinkedList<>();
|
||||
// This is a pipeline so we register basic pipes
|
||||
protocolList.addLast(new BaseProtocol());
|
||||
protocolList.addLast(ProtocolRegistry.BASE_PROTOCOL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,7 +82,7 @@ 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()) {
|
||||
|
||||
@@ -2,7 +2,9 @@ package us.myles.ViaVersion.api.protocol;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import us.myles.ViaVersion.api.Pair;
|
||||
import us.myles.ViaVersion.protocols.base.BaseProtocol;
|
||||
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 java.util.*;
|
||||
@@ -13,11 +15,15 @@ public class ProtocolRegistry {
|
||||
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<>();
|
||||
public static final Protocol BASE_PROTOCOL = new BaseProtocol();
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,7 @@ 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;
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
@@ -26,6 +27,7 @@ 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"));
|
||||
}
|
||||
|
||||
public static void register(@NonNull ProtocolVersion protocol) {
|
||||
@@ -37,7 +39,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() {
|
||||
|
||||
@@ -153,14 +153,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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -39,9 +39,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 +49,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;
|
||||
|
||||
+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;
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
+15
-1
@@ -22,6 +22,8 @@ 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.TimeUnit;
|
||||
@@ -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 {
|
||||
|
||||
+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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -16,12 +16,39 @@ 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
|
||||
# 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, :("
|
||||
Reference in new issue
Block a user