Compare commits

...
82 Commits
Author SHA1 Message Date
Myles cf20e8ac5f Bump version 2016-04-17 00:53:49 +01:00
Myles 4f8a248c6b Add item-cache as a less expensive way of getting items. (Will rewrite eventually to not depend on Bukkit) 2016-04-17 00:52:35 +01:00
Mats 57d58db35e Fix item showing twice, one in the new slot (#359) 2016-04-15 18:48:28 +01:00
Mats c214ca02e8 Make commandblocks compatible with all 1.8 spigot/craftbukkit versions, fix #355 (#356) 2016-04-14 12:59:23 +01:00
Myles 6b8b0e1771 Bump version to 0.7.6-SNAPSHOT 2016-04-13 19:42:53 +01:00
Myles e6671513f2 Improve an issue to do with block breaking ghosting back, note this is not a fully fix, but improves the issue quite a bit. 2016-04-13 16:54:18 +01:00
Myles 4c7b50d6fb Fix chunk sending order, Fixes #338, #292 (I believe.) 2016-04-13 15:05:50 +01:00
Mats 1c9229a2fc Don't unload the chunks twice (#350) 2016-04-13 12:25:41 +01:00
Mats d11c18c024 Remove MCProtocolLib (#349) 2016-04-12 12:40:12 +01:00
Mats dc4b5b4d35 Possibility to show the new 1.9 death messages (#348) 2016-04-12 12:01:37 +01:00
Mats 517299d673 Show skeletons' bow like 1.8, not down as 1.9 without target (#347) 2016-04-12 11:18:58 +01:00
Mats a8baa7af50 Transform Combat packet (#346) 2016-04-12 11:18:51 +01:00
Myles a1f847c905 Patch respawn packet to reset bulk / loaded cache. 2016-04-11 20:17:48 +01:00
Mats f3ea43b1eb Reformat / optimize imports (#344) 2016-04-10 18:43:08 +01:00
Mats 551b5d0654 Rewrite effect ids (#342)
* Rewrite effect ids

* Remove test line

* Remove Lombok unused thingy

* No need to check.
2016-04-10 14:29:25 +01:00
Mats 9f39662df6 Check if custom name is visible and if custom name is not empty. Fix …
* Check if custom name is visible and if custom name is not empty. Fix #327

* Fix typo
2016-04-06 13:50:09 +01:00
Myles 7ea2156f37 Bump version 2016-04-05 14:31:40 +01:00
Mats 5032e7d07e Only apply the 'Hologram patch' to small entities since it only happens to them.
Only apply the 'Hologram patch' to small entities (Doesn't fix issue but hey)
2016-04-04 15:55:48 +01:00
Myles c7c6ee9fbc Delay registration of protocols until the plugin has loaded to prevent it being done at the wrong time, #323 #316 Fixed 2016-04-03 23:30:10 +01:00
Mats 4431ca63c2 Fix viaversion list command 2016-04-03 11:26:27 +01:00
Myles 1fa7211cf0 Construct List properly, Fix #314 2016-04-03 01:51:38 +01:00
Myles de576795dc Blame @Matsv 2016-04-02 22:59:40 +01:00
Myles f6286bcc25 Bump version 2016-04-02 22:13:30 +01:00
Myles 8276b212e9 Merge pull request #313 from Matsv/master
Stop allowing everyone to change the instance
2016-04-02 21:32:46 +01:00
Matsv aabd9247a6 Stop allowing everyone to change the instance 2016-04-02 21:45:24 +02:00
Myles 997c2ad6a1 Fix Potions: ThrownPotion is now correct, and the particles are too.
Fixes #223
Also changes a tiny bit of javadoc :)
2016-04-02 14:46:30 +01:00
Myles 233a2ba5df Merge pull request #312 from Matsv/dev
Fix custom NBT for potions / spawneggs
2016-04-02 14:09:00 +01:00
Matsv ed0d5a7cfb Fix NBT for potions 2016-04-02 15:06:10 +02:00
Matsv 87f083460c Fix custom named spawneggs 2016-04-02 15:02:41 +02:00
Myles 2d6dedefb8 Add some packet plugins to loadbefore to ensure it works better with them. 2016-04-02 13:50:21 +01:00
Myles 8adbf36a3a Merge pull request #311 from Matsv/dev
Make command sender messages cleaner
2016-04-02 13:30:10 +01:00
Matsv 8c706b665c Don't format if no args are given 2016-04-02 11:58:15 +02:00
Matsv 2e3677a592 Make command sender messages cleaner 2016-04-02 11:51:17 +02:00
Myles 3602c5087b Don't send a meta data packet when list is empty. #288 2016-04-01 18:13:23 +01:00
Myles 5c84b3d8cc Merge pull request #309 from HugoDaBosss/master
Implement subcommand to reload the config
2016-04-01 16:41:03 +01:00
Hugo Kerstens 7defe7129f Implement subcommand to reload the config 2016-04-01 17:31:44 +02:00
Myles 995dc135b8 Merge pull request #308 from Matsv/boss
Cleanup BossBar class & add new bossbar api method, addPlayers()
2016-04-01 15:07:04 +01:00
Matsv 3f64fb7d5f Cleanup BossBar class & add new bossbar api method, addPlayers() 2016-04-01 16:03:56 +02:00
Myles ac8f7a00ae Merge pull request #305 from HugoDaBosss/master
Implement new protocol version registry
2016-03-31 22:45:39 +01:00
Myles 6893f34289 Support reloading to some extent, if you use protocol lib it will kick all your players... (So you probably should just get a PluginManager...)
One day i'll fully patch to work... (If I don't kick the players it ends up that ProtocolLib implodes and nobody can connect.)
2016-03-31 22:45:15 +01:00
Hugo Kerstens 0a69d62cbe Fixed typo (blame Mats) 2016-03-31 23:26:13 +02:00
Myles 5e0096aa2c Merge pull request #307 from Matsv/master
Woops use the same instance
2016-03-31 21:49:42 +01:00
Matsv 7326205495 Woops use the same instance 2016-03-31 22:48:20 +02:00
Myles a8212db7f2 Merge pull request #306 from Matsv/tabcomplete
Tabcomplete
2016-03-31 19:55:11 +01:00
Matsv 2905d77206 Reformatting moved color to the top ;( 2016-03-31 20:53:03 +02:00
Matsv cb8ec2ce20 Add tab-complete possibility and help subcommand 2016-03-31 20:50:22 +02:00
Hugo Kerstens 09f484f956 Implement new protocol version registry 2016-03-31 19:50:04 +02:00
Myles c48922eb3e Merge pull request #304 from Matsv/cmd
Implement new command API
2016-03-31 17:56:08 +01:00
Matsv b701a0ef67 Change debug mode subcmd description 2016-03-31 18:55:05 +02:00
Matsv eb50f4e907 Merge branch 'master' of https://github.com/Matsv/ViaVersion into cmd 2016-03-31 17:53:12 +02:00
Matsv 6480ea34fc Changed javadoc 2016-03-31 17:52:06 +02:00
Matsv 511941462f Add javadoc 2016-03-31 17:51:30 +02:00
Matsv 34cc783cac Fix missing description, add javadocs, make sure subcommand is valid, check permission 2016-03-31 17:48:15 +02:00
Matsv ecc79b4f49 Command API to keep it clean and make it possible for developers to add their own viaversion subcommands if they want to. 2016-03-31 17:22:42 +02:00
Myles 76f10c463f Merge pull request #301 from Matsv/master
Handle discontinued player item in hand, fixes #299
2016-03-31 15:49:24 +01:00
Matsv 41d5144b57 Handle discontinued player item in hand, fixes #299 2016-03-31 16:28:56 +02:00
Myles de196f2e4f Merge pull request #300 from HugoDaBosss/master
Small optimization in join packet
2016-03-31 14:10:52 +01:00
Hugo Kerstens 0acc2f95fb Remove unneeded code 2016-03-31 15:08:19 +02:00
Myles d16eb9b27e Version bump 2016-03-30 17:46:00 +01:00
Myles 8760b53a0a Fix Disconnect Issue (It's not really harmful but still) 2016-03-30 17:45:24 +01:00
Myles a40182186f Fix debug issue with 1.9.2 2016-03-30 17:34:13 +01:00
Myles ef2b173749 Merge pull request #295 from Matsv/master
Rename 1_9_1 PRE to just 1_9_1
2016-03-30 17:33:15 +01:00
Matsv 75c9284cda Rename 1_9_1 PRE to just 1_9_1 2016-03-30 18:23:52 +02:00
Myles 2abecba7bf Bump version 2016-03-30 16:54:49 +01:00
Myles fb6055cbfe 1.9.2 support (no protocol changes from what I've seen) 2016-03-30 16:51:55 +01:00
Myles 639c9ea8c1 Fix 1.8R0.1 not working, ensure flying packets are sent from right place in pipeline, should fix #273 2016-03-30 16:43:01 +01:00
Myles 1872845d2b Add additional information when packets aren't sent correctly. 2016-03-30 15:58:31 +01:00
Myles 93755c6732 Move patch to update health so it works better and is applied upon login. 2016-03-29 18:22:40 +01:00
Myles 68973fd136 Merge pull request #291 from Matsv/gitter
Add Gitter badge to README.md
2016-03-29 16:08:43 +01:00
Matsv 1a0bd37a01 Add gitter badge to ReadMe 2016-03-29 16:43:42 +02:00
Myles 3551779600 Merge pull request #290 from Matsv/master
Add JavaDocs link to README.md
2016-03-29 15:39:40 +01:00
Matsv b8deddcd2c Add JavaDocs link to README.md 2016-03-29 16:36:21 +02:00
Myles c49bf89ead Merge pull request #289 from Matsv/debug
Show all errors on debug
2016-03-29 15:03:36 +01:00
Myles 4ff4fe2ab2 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion 2016-03-29 15:02:04 +01:00
Myles 1b99e2cf57 Move EntityNBT to different file and fix the issue to do with respawn chunks unloading. #287 2016-03-29 15:01:38 +01:00
Matsv 55830b0dfb Show all errors on debug 2016-03-29 16:00:56 +02:00
Myles e61f56b2e0 Merge pull request #283 from Matsv/slpfix
Woops the new api broke ServerListPlus custom outdated message again …
2016-03-28 12:04:06 +01:00
Mats 95ea95be13 Woops the new api broke ServerListPlus custom outdated message again fixes #282 2016-03-28 11:52:29 +02:00
Myles d72b7fc4df Fix shields not being configurable 2016-03-27 23:52:57 +01:00
Myles 0992c74351 Improve block placing a bit 2016-03-27 23:40:32 +01:00
Myles 081c23ad8b Small Javadocs 2016-03-27 22:45:25 +01:00
Myles 258f0fc636 Change the README back ;) 2016-03-27 21:50:49 +01:00
57 changed files with 1284 additions and 261 deletions

No files matched your search

+61 -4
View File
@@ -1,10 +1,67 @@
# ViaVersion API Dev
# ViaVersion 0.7.6
[![Build Status](https://travis-ci.org/MylesIsCool/ViaVersion.svg?branch=master)](https://travis-ci.org/MylesIsCool/ViaVersion)
[![Gitter](https://badges.gitter.im/MylesIsCool/ViaVersion.svg)](https://gitter.im/MylesIsCool/ViaVersion)
**Allows the connection of 1.9 clients to 1.8**
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
This is an experimental branch, but soon to be live.
Sources:
--------
(The only issues would be really really complex protocol pipelines...)
(But I don't see them happening any time soon)
**wiki.vg** (Protocol info, though I did have to find a lot myself)
**OpenNBT** (used for slot rewriting)
Contributors:
--------
**Myself** (harhar)
**Matsv/StamBoom**
**HugoDaBosss**
**SanderGielisse**
**Paulomart**
**gigosaurus**
**fillefilip8**
**lenis0012**
Releases / Dev Builds:
--------
You can find official releases here:
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
**sgdc3's Build Server:** http://ci.xephi.fr/job/ViaVersion/
**sgdc3's Maven:** http://ci.xephi.fr/plugin/repository/everything/
**JavaDocs:** https://jd.matsv.nl/
License:
--------
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>0.7.0</version>
<version>0.7.7-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ViaVersion</name>
@@ -1,10 +1,12 @@
package us.myles.ViaVersion;
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;
@@ -30,8 +32,14 @@ public class ViaIdleThread extends BukkitRunnable {
if (info.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) {
long nextIdleUpdate = info.get(MovementTracker.class).getNextIdlePacket();
if (nextIdleUpdate <= System.currentTimeMillis()) {
info.getChannel().pipeline().fireChannelRead(idlePacket);
info.get(MovementTracker.class).incrementIdlePacket();
ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", info.getChannel().pipeline());
if (info.getChannel().isOpen()) {
if (context != null) {
context.fireChannelRead(idlePacket);
info.get(MovementTracker.class).incrementIdlePacket();
}
}
}
}
}
@@ -9,16 +9,18 @@ import lombok.NonNull;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.ViaVersionAPI;
import us.myles.ViaVersion.api.ViaVersionConfig;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
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.commands.ViaVersionCommand;
import us.myles.ViaVersion.commands.ViaCommandHandler;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.update.UpdateListener;
@@ -30,6 +32,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;
@@ -41,18 +44,36 @@ import java.util.concurrent.TimeUnit;
public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVersionConfig {
private final Map<UUID, UserConnection> portedPlayers = new ConcurrentHashMap<>();
private List<ChannelFuture> injectedFutures = new ArrayList<>();
private List<Pair<Field, Object>> injectedLists = new ArrayList<>();
private ViaCommandHandler commandHandler;
private boolean debug = false;
@Override
public void onEnable() {
public void onLoad() {
ViaVersion.setInstance(this);
generateConfig();
if (System.getProperty("ViaVersion") != null) {
getLogger().severe("ViaVersion is already loaded, we don't support reloads. Please reboot if you wish to update.");
getLogger().severe("Some features may not work.");
return;
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.");
for (Player player : Bukkit.getOnlinePlayers()) {
player.kickPlayer("Server reload, please rejoin!");
}
} else {
getLogger().severe("ViaVersion is already loaded, this should work fine... Otherwise reboot the server!!!");
}
}
getLogger().info("ViaVersion " + getDescription().getVersion() + " is now loaded, injecting.");
injectPacketHandler();
}
@Override
public void onEnable() {
if (isCheckForUpdates())
UpdateUtil.sendUpdateMessage(this);
// Gather version :)
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
@@ -68,17 +89,20 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
}
});
getLogger().info("ViaVersion " + getDescription().getVersion() + " is now enabled, injecting.");
injectPacketHandler();
if (getConfig().getBoolean("simulate-pt", true))
new ViaIdleThread(portedPlayers).runTaskTimerAsynchronously(this, 1L, 1L); // Updates player's idle status
if (isCheckForUpdates())
UpdateUtil.sendUpdateMessage(this);
Bukkit.getPluginManager().registerEvents(new UpdateListener(this), this);
getCommand("viaversion").setExecutor(new ViaVersionCommand(this));
getCommand("viaversion").setExecutor(commandHandler = new ViaCommandHandler());
getCommand("viaversion").setTabCompleter(commandHandler);
// Register Protocol Listeners
ProtocolRegistry.registerListeners();
}
@Override
public void onDisable() {
getLogger().info("ViaVersion is disabling, if this is a reload it may not work.");
uninject();
}
public void gatherProtocolVersion() {
@@ -183,6 +207,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
}
}
};
injectedLists.add(new Pair<>(field, connection));
field.set(connection, wrapper);
// Iterate through current list
synchronized (wrapper) {
@@ -211,6 +236,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
injectedFutures.add(future);
} catch (NoSuchFieldException e) {
// field not found
throw new Exception("Unable to find childHandler, blame " + bootstrapAcceptor.getClass().getName());
@@ -221,6 +247,35 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
}
}
private void uninject() {
// TODO: Uninject from players currently online to prevent protocol lib issues.
for (ChannelFuture future : injectedFutures) {
ChannelHandler bootstrapAcceptor = future.channel().pipeline().first();
try {
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
if (oldInit instanceof ViaVersionInitializer) {
ReflectionUtil.set(bootstrapAcceptor, "childHandler", ((ViaVersionInitializer) oldInit).getOriginal());
}
} catch (Exception e) {
System.out.println("Failed to remove injection... reload won't work with connections sorry");
}
}
injectedFutures.clear();
for (Pair<Field, Object> pair : injectedLists) {
try {
Object o = pair.getKey().get(pair.getValue());
if (o instanceof ListWrapper) {
pair.getKey().set(pair.getValue(), ((ListWrapper) o).getOriginalList());
}
} catch (IllegalAccessException e) {
System.out.println("Failed to remove injection... reload might not work with connections sorry");
}
}
injectedLists.clear();
}
@Override
public boolean isPorted(Player player) {
return isPorted(player.getUniqueId());
@@ -288,6 +343,11 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
this.debug = value;
}
@Override
public ViaVersionCommand getCommandHandler() {
return commandHandler;
}
public boolean isCheckForUpdates() {
return getConfig().getBoolean("checkforupdates", true);
}
@@ -300,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);
}
@@ -328,6 +393,10 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
return getConfig().getDouble("hologram-y", -1D);
}
public boolean isBlockBreakPatch() {
return getConfig().getBoolean("block-break-patch", true);
}
public boolean isAutoTeam() {
// Collision has to be enabled first
return isPreventCollision() && getConfig().getBoolean("auto-team", true);
@@ -359,4 +428,8 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaVe
e.printStackTrace();
}
}
public Map<UUID, UserConnection> getPortedPlayers() {
return portedPlayers;
}
}
@@ -11,6 +11,7 @@ import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
import us.myles.ViaVersion.exception.InformativeException;
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
import us.myles.ViaVersion.util.PipelineUtil;
import java.io.IOException;
import java.util.ArrayList;
@@ -52,7 +53,7 @@ public class PacketWrapper {
}
Exception e = new ArrayIndexOutOfBoundsException("Could not find type " + type.getTypeName() + " at " + index);
throw new InformativeException(e).set("Type", type.getTypeName()).set("Index", index).set("Packet ID", getId());
throw new InformativeException(e).set("Type", type.getTypeName()).set("Index", index).set("Packet ID", getId()).set("Data", packetValues);
}
/**
@@ -92,7 +93,7 @@ public class PacketWrapper {
try {
return type.read(inputBuffer);
} catch (Exception e) {
throw new InformativeException(e).set("Type", type.getTypeName()).set("Packet ID", getId());
throw new InformativeException(e).set("Type", type.getTypeName()).set("Packet ID", getId()).set("Data", packetValues);
}
} else {
Pair<Type, Object> read = readableObjects.poll();
@@ -103,7 +104,7 @@ public class PacketWrapper {
return read(type); // retry
} else {
Exception e = new IOException("Unable to read type " + type.getTypeName() + ", found " + read.getKey().getTypeName());
throw new InformativeException(e).set("Type", type.getTypeName()).set("Packet ID", getId());
throw new InformativeException(e).set("Type", type.getTypeName()).set("Packet ID", getId()).set("Data", packetValues);
}
}
}
@@ -172,7 +173,7 @@ public class PacketWrapper {
}
packetValue.getKey().write(buffer, value);
} catch (Exception e) {
throw new InformativeException(e).set("Index", index).set("Type", packetValue.getKey().getTypeName()).set("Packet ID", getId());
throw new InformativeException(e).set("Index", index).set("Type", packetValue.getKey().getTypeName()).set("Packet ID", getId()).set("Data", packetValues);
}
index++;
}
@@ -197,6 +198,7 @@ public class PacketWrapper {
/**
* Send this packet to the associated user.
* Be careful not to send packets twice.
* (Sends it after current)
*
* @throws Exception if it fails to write
*/
@@ -265,6 +267,12 @@ public class PacketWrapper {
this.packetValues.clear();
}
/**
* Send the current packet to the server.
* (Ensure the ID is suitable for the server version)
*
* @throws Exception If it failed to write
*/
public void sendToServer() throws Exception {
if (!isCancelled()) {
ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer();
@@ -272,15 +280,7 @@ public class PacketWrapper {
writeToBuffer(output);
boolean mark = false;
for (String s : user().getChannel().pipeline().names()) {
if (mark) {
user().getChannel().pipeline().context(user().getChannel().pipeline().get(s)).fireChannelRead(output);
return;
}
if (s.equalsIgnoreCase("decompress"))
mark = true;
}
PipelineUtil.getContextBefore("decompress", user().getChannel().pipeline()).fireChannelRead(output);
}
}
}
@@ -3,12 +3,10 @@ package us.myles.ViaVersion.api;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@EqualsAndHashCode
@ToString
public class Pair<X, Y> {
private X key;
private Y value;
@@ -17,4 +15,9 @@ public class Pair<X, Y> {
this.key = key;
this.value = value;
}
@Override
public String toString() {
return "Pair{" + key + ", " + value + '}';
}
}
@@ -1,6 +1,7 @@
package us.myles.ViaVersion.api;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import us.myles.ViaVersion.ViaVersionPlugin;
public class ViaVersion {
@@ -11,6 +12,7 @@ public class ViaVersion {
private static ViaVersionConfig config;
public static void setInstance(ViaVersionPlugin plugin) {
Validate.isTrue(instance == null, "Instance is already set");
ViaVersion.instance = plugin;
ViaVersion.config = plugin;
}
@@ -5,6 +5,7 @@ import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.api.command.ViaVersionCommand;
import java.util.UUID;
@@ -93,4 +94,11 @@ public interface ViaVersionAPI {
* @return true if debug is enabled
*/
boolean isDebug();
/**
* Get ViaVersions command handler
*
* @return command handler
*/
ViaVersionCommand getCommandHandler();
}
@@ -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,11 @@ 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();
}
@@ -69,6 +69,14 @@ public interface BossBar {
*/
BossBar addPlayer(Player player);
/**
* add multiple players
*
* @param players list of players
* @return the bossbar instance
*/
BossBar addPlayers(Player... players);
/**
* Remove the bossbar from a player
*
@@ -0,0 +1,77 @@
package us.myles.ViaVersion.api.command;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.commands.ViaCommandHandler;
import java.util.Collections;
import java.util.List;
public abstract class ViaSubCommand {
/**
* Subcommand name
*
* @return your input
*/
public abstract String name();
/**
* subcommand description, this'll show in /viaversion list
*
* @return your input
*/
public abstract String description();
/**
* Usage example:
* "playerversion [name]"
*
* @return your input
*/
public String usage() {
return name();
}
/**
* Permission, null for everyone
*
* @return
*/
public String permission() {
return "viaversion.admin";
}
/**
* Gets triggered on execution
*
* @param sender Command sender
* @param args Arguments
* @return command executed succesfully if false, show usage
*/
public abstract boolean execute(CommandSender sender, String[] args);
/**
* Yay, possibility to implement tab-completion
*
* @param sender Command sender
* @param args args
* @return tab complete possibilities
*/
public List<String> onTabComplete(CommandSender sender, String[] args) {
return Collections.emptyList();
}
public String color(String s) {
return ViaCommandHandler.color(s);
}
/**
* Send message formatted / colored
*
* @param sender command sender
* @param message string message
* @param args optional objects
*/
public void sendMessage(CommandSender sender, String message, Object... args) {
ViaCommandHandler.sendMessage(sender, message, args);
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.api.command;
public interface ViaVersionCommand {
/**
* Register your own subcommand inside ViaVersion
*
* @param command Your own SubCommand instance to handle it.
* @throws Exception throws an exception when the subcommand already exists or if it's not valid, example: spacee
*/
void registerSubCommand(ViaSubCommand command) throws Exception;
/**
* Check if a subcommand is registered.
*
* @param name Subcommand name
* @return true if it exists
*/
boolean hasSubCommand(String name);
/**
* Get subcommand instance by name
*
* @param name subcommand name
* @return ViaSubCommand instance
*/
ViaSubCommand getSubCommand(String name);
}
@@ -1,10 +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,9 +2,11 @@ package us.myles.ViaVersion.api.minecraft.chunks;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
@RequiredArgsConstructor
@Getter
@ToString
public class Chunk {
private final int x;
private final int z;
@@ -1,9 +1,6 @@
package us.myles.ViaVersion.api.minecraft.item;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.*;
import org.bukkit.inventory.ItemStack;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
@@ -11,6 +8,7 @@ import org.spacehq.opennbt.tag.builtin.CompoundTag;
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Item {
private short id;
private byte amount;
@@ -13,4 +13,14 @@ public class Metadata {
private int typeID;
private Type type;
private Object value;
@Override
public String toString() {
return "Metadata{" +
"id=" + id +
", typeID=" + typeID +
", type=" + type +
", value=" + value +
'}';
}
}
@@ -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;
@@ -20,7 +20,6 @@ public abstract class Protocol {
public Protocol() {
registerPackets();
registerListeners();
}
/**
@@ -82,11 +82,11 @@ public class ProtocolPipeline extends Protocol {
String packet = "UNKNOWN";
// For 1.8/1.9 server version, eventually we'll probably get an API for this...
if (ProtocolRegistry.SERVER_PROTOCOL >= ProtocolVersion.V1_8 &&
ProtocolRegistry.SERVER_PROTOCOL <= ProtocolVersion.V1_9_1_PRE2) {
if (ProtocolRegistry.SERVER_PROTOCOL >= ProtocolVersion.v1_8.getId() &&
ProtocolRegistry.SERVER_PROTOCOL <= ProtocolVersion.v1_9_2.getId()) {
PacketType type;
if (ProtocolRegistry.SERVER_PROTOCOL == ProtocolVersion.V1_8) {
if (ProtocolRegistry.SERVER_PROTOCOL == ProtocolVersion.v1_8.getId()) {
if (direction == Direction.INCOMING) {
type = PacketType.findNewPacket(state, direction, originalID);
} else {
@@ -1,5 +1,6 @@
package us.myles.ViaVersion.api.protocol;
import org.bukkit.Bukkit;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.protocols.protocol1_9_1to1_9.Protocol1_9_1TO1_9;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
@@ -11,11 +12,12 @@ public class ProtocolRegistry {
// 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<>();
static {
// Register built in protocols
registerProtocol(new Protocol1_9TO1_8(), Collections.singletonList(ProtocolVersion.V1_9), ProtocolVersion.V1_8);
registerProtocol(new Protocol1_9_1TO1_9(), Collections.singletonList(ProtocolVersion.V1_9_1_PRE2), ProtocolVersion.V1_9);
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());
}
/**
@@ -37,6 +39,12 @@ public class ProtocolRegistry {
registryMap.get(version).put(output, protocol);
}
if (Bukkit.getPluginManager().getPlugin("ViaVersion").isEnabled()) {
protocol.registerListeners();
} else {
registerList.add(protocol);
}
}
/**
@@ -51,6 +59,16 @@ public class ProtocolRegistry {
return false; // No destination for protocol
}
/**
* Called when the server is enabled, to register any non registered listeners.
*/
public static void registerListeners() {
for (Protocol protocol : registerList) {
protocol.registerListeners();
}
registerList.clear();
}
/**
* Calculate a path to get from an input protocol to the servers protocol.
*
@@ -1,12 +1,46 @@
package us.myles.ViaVersion.api.protocol;
import lombok.Data;
import lombok.NonNull;
import java.util.*;
@Data
public class ProtocolVersion {
/* Defined protocol constants */
public static final int V1_7_1 = 4;
public static final int V1_7_6 = 5;
private static final Map<Integer, ProtocolVersion> versions = new HashMap<>();
public static final int V1_8 = 47;
public static final ProtocolVersion v1_7_1;
public static final ProtocolVersion v1_7_6;
public static final ProtocolVersion v1_8;
public static final ProtocolVersion v1_9;
public static final ProtocolVersion v1_9_1;
public static final ProtocolVersion v1_9_2;
public static final int V1_9 = 107;
public static final int V1_9_1_PRE2 = 108;
private final int id;
private final String name;
static {
register(v1_7_1 = new ProtocolVersion(4, "1.7-1.7.5"));
register(v1_7_6 = new ProtocolVersion(5, "1.7.6-1.7.10"));
register(v1_8 = new ProtocolVersion(47, "1.8.x"));
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"));
}
public static void register(@NonNull ProtocolVersion protocol) {
versions.put(protocol.getId(), protocol);
}
public static boolean isRegistered(int id) {
return versions.containsKey(id);
}
public static ProtocolVersion getProtocol(int id) {
return versions.get(id);
}
public static List<ProtocolVersion> getProtocols() {
return Collections.unmodifiableList(new ArrayList<ProtocolVersion>(versions.values()));
}
}
@@ -77,4 +77,9 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
this.outputClass = outputClass;
this.typeName = typeName;
}
@Override
public String toString() {
return "Type|" + getTypeName();
}
}
@@ -3,6 +3,7 @@ package us.myles.ViaVersion.boss;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
@@ -42,8 +43,7 @@ public class ViaBossBar implements BossBar {
}
@Override
public BossBar setTitle(String title) {
Validate.notNull(title, "Title cannot be null");
public BossBar setTitle(@NonNull String title) {
this.title = title;
sendPacket(UpdateAction.UPDATE_TITLE);
return this;
@@ -63,24 +63,22 @@ public class ViaBossBar implements BossBar {
}
@Override
public BossBar setColor(BossColor color) {
Validate.notNull(color, "Color cannot be null");
public BossBar setColor(@NonNull BossColor color) {
this.color = color;
sendPacket(UpdateAction.UPDATE_STYLE);
return this;
}
@Override
public BossBar setStyle(BossStyle style) {
Validate.notNull(style, "Style cannot be null");
public BossBar setStyle(@NonNull BossStyle style) {
this.style = style;
sendPacket(UpdateAction.UPDATE_STYLE);
return this;
}
@Override
public BossBar addPlayer(Player player) {
if (player != null && !players.contains(player.getUniqueId())) {
public BossBar addPlayer(@NonNull Player player) {
if (!players.contains(player.getUniqueId())) {
players.add(player.getUniqueId());
if (visible)
sendPacket(player.getUniqueId(), getPacket(UpdateAction.ADD));
@@ -89,8 +87,8 @@ public class ViaBossBar implements BossBar {
}
@Override
public BossBar removePlayer(Player player) {
if (player != null && players.contains(player.getUniqueId())) {
public BossBar removePlayer(@NonNull Player player) {
if (players.contains(player.getUniqueId())) {
players.remove(player.getUniqueId());
sendPacket(player.getUniqueId(), getPacket(UpdateAction.REMOVE));
}
@@ -98,7 +96,14 @@ public class ViaBossBar implements BossBar {
}
@Override
public BossBar addFlag(BossFlag flag) {
public BossBar addPlayers(@NonNull Player... players) {
for (Player p : players)
addPlayer(p);
return this;
}
@Override
public BossBar addFlag(@NonNull BossFlag flag) {
if (!hasFlag(flag))
flags.add(flag);
sendPacket(UpdateAction.UPDATE_FLAGS);
@@ -106,7 +111,7 @@ public class ViaBossBar implements BossBar {
}
@Override
public BossBar removeFlag(BossFlag flag) {
public BossBar removeFlag(@NonNull BossFlag flag) {
if (hasFlag(flag))
flags.remove(flag);
sendPacket(UpdateAction.UPDATE_FLAGS);
@@ -114,7 +119,7 @@ public class ViaBossBar implements BossBar {
}
@Override
public boolean hasFlag(BossFlag flag) {
public boolean hasFlag(@NonNull BossFlag flag) {
return flags.contains(flag);
}
@@ -154,7 +159,7 @@ public class ViaBossBar implements BossBar {
}
private void sendPacket(UUID uuid, ByteBuf buf) {
if (!ViaVersion.getInstance().isPorted(uuid) || !(ViaVersion.getInstance().getPlayerVersion(uuid) >= ProtocolVersion.V1_9)) {
if (!ViaVersion.getInstance().isPorted(uuid) || !(ViaVersion.getInstance().getPlayerVersion(uuid) >= ProtocolVersion.v1_9.getId())) {
players.remove(uuid);
return;
}
@@ -0,0 +1,152 @@
package us.myles.ViaVersion.commands;
import lombok.NonNull;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
import us.myles.ViaVersion.api.command.ViaVersionCommand;
import us.myles.ViaVersion.commands.defaultsubs.*;
import java.util.*;
public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, TabCompleter {
private Map<String, ViaSubCommand> commandMap;
public ViaCommandHandler() {
commandMap = new HashMap<>();
try {
registerDefaults();
} catch (Exception e) {
//ignore never throws exception because it doesn't exists
}
}
@Override
public void registerSubCommand(@NonNull ViaSubCommand command) throws Exception {
Validate.isTrue(command.name().matches("^[a-z0-9_-]{3,15}$"), command.name() + " is not a valid subcommand name");
if (hasSubCommand(command.name()))
throw new Exception("ViaSubCommand " + command.name() + " does already exists!"); //Maybe another exception later.
commandMap.put(command.name().toLowerCase(), command);
}
@Override
public boolean hasSubCommand(String name) {
return commandMap.containsKey(name.toLowerCase());
}
@Override
public ViaSubCommand getSubCommand(String name) {
return commandMap.get(name.toLowerCase());
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String arg, String[] args) {
if (args.length == 0) {
showHelp(sender);
return false;
}
if (!hasSubCommand(args[0])) {
sender.sendMessage(color("&cThis command is not found"));
showHelp(sender);
return false;
}
ViaSubCommand handler = getSubCommand(args[0]);
if (!hasPermission(sender, handler.permission())) {
sender.sendMessage(color("&cYou are not allowed to use this command!"));
return false;
}
String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
boolean result = handler.execute(sender, subArgs);
if (!result)
sender.sendMessage("Usage: /viaversion " + handler.usage());
return result;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String arg, String[] args) {
Set<ViaSubCommand> allowed = calculateAllowedCommands(sender);
List<String> output = new ArrayList<>();
//SubCommands tabcomplete
if (args.length == 1) {
if (!args[0].equals("")) {
for (ViaSubCommand sub : allowed)
if (sub.name().toLowerCase().startsWith(args[0].toLowerCase()))
output.add(sub.name());
} else {
for (ViaSubCommand sub : allowed)
output.add(sub.name());
}
}
//Let the SubCommand handle it
else if (args.length >= 2) {
if (getSubCommand(args[0]) != null) {
ViaSubCommand sub = getSubCommand(args[0]);
if (!allowed.contains(sub))
return output;
String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
List<String> tab = sub.onTabComplete(sender, subArgs);
Collections.sort(tab);
return tab;
}
}
return output;
}
public void showHelp(CommandSender sender) {
Set<ViaSubCommand> allowed = calculateAllowedCommands(sender);
if (allowed.size() == 0) {
sender.sendMessage(color("&cYou are not allowed to use this command!"));
return;
}
sender.sendMessage(color("&aViaVersion &c" + ViaVersion.getInstance().getVersion()));
sender.sendMessage(color("&6Commands:"));
for (ViaSubCommand cmd : allowed)
sender.sendMessage(color(String.format("&2/viaversion %s &7- &6%s", cmd.usage(), cmd.description())));
allowed.clear();
}
private Set<ViaSubCommand> calculateAllowedCommands(CommandSender sender) {
Set<ViaSubCommand> cmds = new HashSet<>();
for (ViaSubCommand sub : commandMap.values())
if (hasPermission(sender, sub.permission()))
cmds.add(sub);
return cmds;
}
private boolean hasPermission(CommandSender sender, String permission) {
return permission == null || sender.hasPermission(permission);
}
private void registerDefaults() throws Exception {
registerSubCommand(new ListSubCmd());
registerSubCommand(new DebugSubCmd());
registerSubCommand(new DisplayLeaksSubCmd());
registerSubCommand(new DontBugMeSubCmd());
registerSubCommand(new AutoTeamSubCmd());
registerSubCommand(new HelpSubCmd());
registerSubCommand(new ReloadSubCmd());
}
public static String color(String string) {
try {
string = ChatColor.translateAlternateColorCodes('&', string); //Dont replace all & with $ like we did before.
} catch (Exception ignored) {
}
return string;
}
public static void sendMessage(@NonNull CommandSender sender, String message, Object... args) {
sender.sendMessage(color(args == null ? message : String.format(message, args)));
}
}
@@ -1,82 +0,0 @@
package us.myles.ViaVersion.commands;
import io.netty.util.ResourceLeakDetector;
import lombok.RequiredArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import java.util.ArrayList;
import java.util.List;
@RequiredArgsConstructor
public class ViaVersionCommand implements CommandExecutor {
private final ViaVersionPlugin plugin;
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.hasPermission("viaversion.admin")) {
if (args.length == 0) {
sendHelp(sender);
} else if (args.length == 1) {
if (args[0].equalsIgnoreCase("list")) {
List<String> portedPlayers = new ArrayList<>();
List<String> normalPlayers = new ArrayList<>();
for (Player p : Bukkit.getOnlinePlayers()) {
if (ViaVersion.getInstance().isPorted(p)) {
portedPlayers.add(p.getName());
} else {
normalPlayers.add(p.getName());
}
}
sender.sendMessage(color("&8[&61.9&8]: &b" + portedPlayers.toString()));
sender.sendMessage(color("&8[&61.8&8]: &b" + normalPlayers.toString()));
} else if (args[0].equalsIgnoreCase("debug")) {
plugin.setDebug(!plugin.isDebug());
sender.sendMessage(color("&6Debug mode is now " + (plugin.isDebug() ? "&aenabled" : "&cdisabled")));
} else if (args[0].equalsIgnoreCase("displayleaks")) {
if (ResourceLeakDetector.getLevel() != ResourceLeakDetector.Level.ADVANCED) {
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
} else {
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
}
sender.sendMessage(color("&6Leak detector is now " + (ResourceLeakDetector.getLevel() == ResourceLeakDetector.Level.ADVANCED ? "&aenabled" : "&cdisabled")));
} else if (args[0].equalsIgnoreCase("dontbugme")) {
boolean newValue = !plugin.isCheckForUpdates();
plugin.getConfig().set("checkforupdates", newValue);
plugin.saveConfig();
sender.sendMessage(color("&6We will " + (newValue ? "&anotify you about updates." : "&cnot tell you about updates.")));
} else if (args[0].equalsIgnoreCase("autoteam")) {
boolean newValue = !plugin.isAutoTeam();
plugin.getConfig().set("auto-team", newValue);
plugin.saveConfig();
sender.sendMessage(color("&6We will " + (newValue ? "&aautomatically team players" : "&cno longer auto team players")));
sender.sendMessage(color("&6All players will need to re-login for the change to take place."));
} else {
sendHelp(sender);
}
}
}
return false;
}
public void sendHelp(CommandSender sender) {
sender.sendMessage(color("&aViaVersion &c" + ViaVersion.getInstance().getVersion()));
sender.sendMessage(color("&6Commands:"));
sender.sendMessage(color("&2/viaversion list &7- &6Shows lists of all 1.9 clients and 1.8 clients."));
sender.sendMessage(color("&2/viaversion debug &7- &6Toggle debug mode"));
sender.sendMessage(color("&2/viaversion autoteam &7- &6Toggle automatically teaming to prevent colliding."));
sender.sendMessage(color("&2/viaversion dontbugme &7- &6Toggle checking for updates."));
}
public String color(String string) {
return string.replace("&", "§");
}
}
@@ -0,0 +1,31 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
public class AutoTeamSubCmd extends ViaSubCommand {
@Override
public String name() {
return "autoteam";
}
@Override
public String description() {
return "Toggle automatically teaming to prevent colliding.";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
boolean newValue = !plugin.isAutoTeam();
plugin.getConfig().set("auto-team", newValue);
plugin.saveConfig();
sendMessage(sender, "&6We will %s", (newValue ? "&aautomatically team players" : "&cno longer auto team players"));
sendMessage(sender, "&6All players will need to re-login for the change to take place.");
return true;
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
public class DebugSubCmd extends ViaSubCommand {
@Override
public String name() {
return "debug";
}
@Override
public String description() {
return "Toggle debug mode";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
plugin.setDebug(!plugin.isDebug());
sendMessage(sender, "&6Debug mode is now %s", (plugin.isDebug() ? "&aenabled" : "&cdisabled"));
return true;
}
}
@@ -0,0 +1,28 @@
package us.myles.ViaVersion.commands.defaultsubs;
import io.netty.util.ResourceLeakDetector;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.api.command.ViaSubCommand;
public class DisplayLeaksSubCmd extends ViaSubCommand {
@Override
public String name() {
return "displayleaks";
}
@Override
public String description() {
return "Try to hunt memory leaks!";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
if (ResourceLeakDetector.getLevel() != ResourceLeakDetector.Level.ADVANCED)
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
else
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
sendMessage(sender, "&6Leak detector is now %s", (ResourceLeakDetector.getLevel() == ResourceLeakDetector.Level.ADVANCED ? "&aenabled" : "&cdisabled"));
return true;
}
}
@@ -0,0 +1,30 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
public class DontBugMeSubCmd extends ViaSubCommand {
@Override
public String name() {
return "dontbugme";
}
@Override
public String description() {
return "Toggle checking for updates";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
boolean newValue = !plugin.isCheckForUpdates();
plugin.getConfig().set("checkforupdates", newValue);
plugin.saveConfig();
sendMessage(sender, "&6We will %snotify you about updates.", (newValue ? "&a" : "&cnot "));
return true;
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
import us.myles.ViaVersion.commands.ViaCommandHandler;
public class HelpSubCmd extends ViaSubCommand {
@Override
public String name() {
return "help";
}
@Override
public String description() {
return "You are looking at it right now!";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
((ViaCommandHandler) plugin.getCommandHandler()).showHelp(sender);
return true;
}
}
@@ -0,0 +1,45 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import java.util.*;
public class ListSubCmd extends ViaSubCommand {
@Override
public String name() {
return "list";
}
@Override
public String description() {
return "Shows lists of the versions from logged in players";
}
@Override
public String usage() {
return "list";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
Map<Integer, Set<String>> playerVersions = new HashMap<>();
for (Player p : Bukkit.getOnlinePlayers()) {
int playerVersion = ViaVersion.getInstance().getPlayerVersion(p);
if (!playerVersions.containsKey(playerVersion))
playerVersions.put(playerVersion, new HashSet<String>());
playerVersions.get(playerVersion).add(p.getName());
}
Map<Integer, Set<String>> sorted = new TreeMap<>(playerVersions);
for (Map.Entry<Integer, Set<String>> entry : sorted.entrySet())
sendMessage(sender, "&8[&6%s&8]: &b%s", ProtocolVersion.getProtocol(entry.getKey()).getName(), entry.getValue());
sorted.clear();
return true;
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
public class ReloadSubCmd extends ViaSubCommand {
@Override
public String name() {
return "reload";
}
@Override
public String description() {
return "Reload the config from the disk";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
plugin.generateConfig();
sendMessage(sender, "&6Configuration successfully reloaded! Some features may need a restart.");
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();
}
}
@@ -56,6 +56,7 @@ public class ViaDecodeHandler extends ByteToMessageDecoder {
throw e;
}
}
// call minecraft decoder
try {
list.addAll(PipelineUtil.callDecode(this.minecraftDecoder, ctx, bytebuf));
@@ -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;
@@ -12,11 +12,11 @@ import java.lang.reflect.Method;
public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
private final ChannelInitializer<SocketChannel> oldInit;
private final ChannelInitializer<SocketChannel> original;
private Method method;
public ViaVersionInitializer(ChannelInitializer<SocketChannel> oldInit) {
this.oldInit = oldInit;
this.original = oldInit;
try {
this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
this.method.setAccessible(true);
@@ -25,13 +25,17 @@ public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
}
}
public ChannelInitializer<SocketChannel> getOriginal() {
return original;
}
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
UserConnection info = new UserConnection(socketChannel);
// init protocol
new ProtocolPipeline(info);
// Add originals
this.method.invoke(this.oldInit, socketChannel);
this.method.invoke(this.original, socketChannel);
// Add our transformers
ViaEncodeHandler encoder = new ViaEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder"));
ViaDecodeHandler decoder = new ViaDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder"));
@@ -40,14 +40,14 @@ public class BaseProtocol extends Protocol {
try {
JSONObject json = (JSONObject) new JSONParser().parse(originalStatus);
JSONObject version = (JSONObject) json.get("version");
if (ProtocolRegistry.SERVER_PROTOCOL == -1) {
Long original = (Long) version.get("protocol");
ProtocolRegistry.SERVER_PROTOCOL = original.intValue();
}
List<Pair<Integer, Protocol>> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), ProtocolRegistry.SERVER_PROTOCOL);
if (protocols != null) {
version.put("protocol", info.getProtocolVersion());
if ((long) version.get("protocol") != 9999) //Fix serverlistplus
version.put("protocol", info.getProtocolVersion());
} else {
// not compatible :(, *plays very sad violin*
wrapper.user().setActive(false);
@@ -18,6 +18,8 @@ public class ItemRewriter {
private static final Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
private static final Map<Integer, String> POTION_ID_TO_NAME = new HashMap<>();
private static final Map<Integer, Integer> POTION_INDEX = new HashMap<>();
static {
/* Entities */
registerEntity(1, "Item");
@@ -84,6 +86,7 @@ public class ItemRewriter {
registerEntity(200, "EnderCrystal");
/* Potions */
registerPotion(-1, "empty");
registerPotion(0, "water");
registerPotion(64, "mundane");
registerPotion(32, "thick");
@@ -147,8 +150,9 @@ public class ItemRewriter {
if (ENTTIY_NAME_TO_ID.containsKey(id.getValue()))
data = ENTTIY_NAME_TO_ID.get(id.getValue());
}
tag.remove("EntityTag");
}
item.setTag(null);
item.setTag(tag);
item.setData((short) data);
}
if (item.getId() == Material.POTION.getId()) {
@@ -160,10 +164,12 @@ public class ItemRewriter {
if (POTION_NAME_TO_ID.containsKey(potionName)) {
data = POTION_NAME_TO_ID.get(potionName);
}
tag.remove("Potion");
}
item.setTag(null);
item.setTag(tag);
item.setData((short) data);
}
//Splash potion
if (item.getId() == 438) {
CompoundTag tag = item.getTag();
int data = 0;
@@ -174,8 +180,9 @@ public class ItemRewriter {
if (POTION_NAME_TO_ID.containsKey(potionName)) {
data = POTION_NAME_TO_ID.get(potionName) + 8192;
}
tag.remove("Potion");
}
item.setTag(null);
item.setTag(tag);
item.setData((short) data);
}
}
@@ -238,12 +245,20 @@ public class ItemRewriter {
}
}
public static int getNewEffectID(int oldID) {
if (oldID >= 16384) {
oldID -= 8192;
}
return POTION_INDEX.containsKey(oldID) ? POTION_INDEX.get(oldID) : 0;
}
private static void registerEntity(Integer id, String name) {
ENTTIY_ID_TO_NAME.put(id, name);
ENTTIY_NAME_TO_ID.put(name, id);
}
private static void registerPotion(Integer id, String name) {
POTION_INDEX.put(id, POTION_ID_TO_NAME.size());
POTION_ID_TO_NAME.put(id, name);
POTION_NAME_TO_ID.put(name, id);
}
@@ -5,19 +5,18 @@ 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;
@@ -64,23 +63,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;
}
}
}
@@ -98,11 +101,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
if (plugin.getConfig().getBoolean("item-cache", true)) {
new HandItemCache().runTaskTimerAsynchronously(plugin, 2L, 2L); // Updates player's items :)
HandItemCache.CACHE = true;
}
}
@Override
@@ -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();
@@ -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);
@@ -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("showDeathMessage"));
} 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();
}
}
});
}
}
@@ -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);
}
}
}
@@ -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() <= 1.1D && diff.getY() >= 0D){
if (relative == BlockFace.UP) {
if (diff.getY() < 1D && diff.getY() >= 0D) {
e.setCancelled(true);
}
}
@@ -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;
@@ -141,7 +140,7 @@ public class MetadataRewriter {
}
} catch (Exception e) {
list.remove(entry);
if (!((ViaVersionPlugin) ViaVersion.getInstance()).isSuppressMetadataErrors()) {
if (!ViaVersion.getConfig().isSuppressMetadataErrors() || ViaVersion.getInstance().isDebug()) {
System.out.println("INCLUDE THIS IN YOUR ERROR LOG!");
if (type != null)
System.out.println("An error occurred with entity meta data for " + type + " OldID: " + entry.getId());
@@ -157,7 +157,7 @@ public class EntityPackets {
Item stack = wrapper.get(Type.ITEM, 0);
if (stack != null) {
if(Material.getMaterial(stack.getId()) != null) {
if (Material.getMaterial(stack.getId()) != null) {
if (Material.getMaterial(stack.getId()).name().endsWith("SWORD")) {
entityTracker.getValidBlocking().add(entityID);
return;
@@ -184,7 +184,7 @@ public class EntityPackets {
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (tracker.getClientEntityTypes().containsKey(entityID)) {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityID), metadataList);
} else if (!ViaVersion.getConfig().isUnknownEntitiesSuppressed()) {
} else if (!ViaVersion.getConfig().isUnknownEntitiesSuppressed() || ViaVersion.getInstance().isDebug()) {
System.out.println("Unable to find entity for metadata, entity ID: " + entityID);
metadataList.clear();
}
@@ -201,6 +201,16 @@ public class EntityPackets {
tracker.handleMetadata(entityID, metadataList);
}
});
// Cancel packet if list empty
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
List<Metadata> metadataList = wrapper.get(Protocol1_9TO1_8.METADATA_LIST, 0);
if (metadataList.size() == 0)
wrapper.cancel();
}
});
}
});
@@ -225,14 +235,50 @@ public class EntityPackets {
}
});
// Update Entity NBT
protocol.registerOutgoing(State.PLAY, 0x49, 0x49, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
// int id = wrapper.read(Type.VAR_INT);
// CompoundTag tag = wrapper.read(Type.NBT);
// System.out.println(id + " - " + tag);
wrapper.cancel();
}
});
}
});
// 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 */
protocol.registerOutgoing(State.PLAY, 0x20, 0x4B); // Entity Properties Packet
protocol.registerOutgoing(State.PLAY, 0x1A, 0x1B); // Entity Status Packet
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
@@ -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];
}
}
@@ -15,6 +15,7 @@ import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
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.storage.ClientChunks;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
public class PlayerPackets {
@@ -145,10 +146,11 @@ public class PlayerPackets {
// Parse this info
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception{
public void handle(PacketWrapper wrapper) throws Exception {
int entityID = wrapper.get(Type.INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
tracker.getClientEntityTypes().put(entityID, EntityType.PLAYER);
tracker.setEntityID(entityID);
}
});
map(Type.UNSIGNED_BYTE); // 1 - Player Gamemode
@@ -157,15 +159,6 @@ 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 {
int myID = wrapper.get(Type.INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
tracker.setEntityID(myID);
}
});
}
});
@@ -221,6 +214,7 @@ public class PlayerPackets {
});
}
});
// Packet Plugin Message Outgoing
protocol.registerOutgoing(State.PLAY, 0x3F, 0x18, new PacketRemapper() {
@Override
@@ -239,23 +233,46 @@ public class PlayerPackets {
}
});
/* Removed packets */
// Map Bulk
protocol.registerOutgoing(State.PLAY, 0x26, 0x26, new PacketRemapper() {
// Update Health Packet
protocol.registerOutgoing(State.PLAY, 0x06, 0x3E, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.FLOAT); // 0 - Health
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
float health = wrapper.get(Type.FLOAT, 0);
if (health <= 0) {
// Client unloads chunks on respawn, take note
ClientChunks cc = wrapper.user().get(ClientChunks.class);
cc.getBulkChunks().clear();
cc.getLoadedChunks().clear();
}
}
});
}
});
// Update Entity NBT
protocol.registerOutgoing(State.PLAY, 0x49, 0x49, new PacketRemapper() {
// Respawn Packet
protocol.registerOutgoing(State.PLAY, 0x07, 0x33, new PacketRemapper() {
@Override
public void registerMap() {
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();
}
});
}
});
/* Removed packets */
// Map Bulk
protocol.registerOutgoing(State.PLAY, 0x26, 0x26, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@@ -289,7 +306,6 @@ 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
@@ -299,7 +315,6 @@ public class PlayerPackets {
protocol.registerOutgoing(State.PLAY, 0x05, 0x43); // Spawn Position Packet
protocol.registerOutgoing(State.PLAY, 0x1F, 0x3D); // Set XP Packet
protocol.registerOutgoing(State.PLAY, 0x06, 0x3E); // Update Health Packet
protocol.registerOutgoing(State.PLAY, 0x0D, 0x49); // Collect Item Packet
/* Incoming Packets */
@@ -1,7 +1,9 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.packets;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import us.myles.ViaVersion.api.PacketWrapper;
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.PacketHandler;
@@ -10,11 +12,14 @@ import us.myles.ViaVersion.api.remapper.ValueCreator;
import us.myles.ViaVersion.api.remapper.ValueTransformer;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.ItemRewriter;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.MetadataRewriter;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
import us.myles.ViaVersion.util.EntityUtil;
import java.util.ArrayList;
import java.util.List;
public class SpawnPackets {
@@ -80,6 +85,34 @@ public class SpawnPackets {
wrapper.write(Type.SHORT, vZ);
}
});
// Handle potions
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
final int entityID = wrapper.get(Type.VAR_INT, 0);
final int data = wrapper.get(Type.INT, 0); // Data
int typeID = wrapper.get(Type.BYTE, 0);
if (EntityUtil.getTypeFromID(typeID, true) == EntityType.SPLASH_POTION) {
// Convert this to meta data, woo!
PacketWrapper metaPacket = wrapper.create(0x39, new ValueCreator() {
@Override
public void write(PacketWrapper wrapper) throws Exception {
wrapper.write(Type.VAR_INT, entityID);
List<Metadata> meta = new ArrayList<>();
Item item = new Item((short) Material.POTION.getId(), (byte) 1, (short) data, null);
ItemRewriter.toClient(item); // Rewrite so that it gets the right nbt
Metadata potion = new Metadata(5, NewType.Slot.getTypeID(), Type.ITEM, item);
meta.add(potion);
wrapper.write(Protocol1_9TO1_8.METADATA_LIST, meta);
}
});
metaPacket.send();
}
}
});
}
});
@@ -253,7 +286,24 @@ public class SpawnPackets {
map(Type.BYTE); // 5 - Yaw
map(Type.BYTE); // 6 - Pitch
map(Type.SHORT, Type.NOTHING); // Current Item is discontinued
handler(new PacketHandler() { //Handle discontinued player hand item
@Override
public void handle(PacketWrapper wrapper) throws Exception {
short item = wrapper.read(Type.SHORT);
// System.out.println(item);
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.ITEM, new Item(item, (byte) 1, (short) 0, null));
try {
packet.send();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
map(Protocol1_9TO1_8.METADATA_LIST);
@@ -6,7 +6,6 @@ import org.spacehq.opennbt.tag.builtin.StringTag;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.minecraft.Position;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.api.remapper.PacketHandler;
@@ -15,7 +14,9 @@ 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;
@@ -40,21 +41,31 @@ public class WorldPackets {
@Override
public void registerMap() {
map(Type.INT); // 0 - Effect ID
// Everything else get's written through
map(Type.POSITION); // 1 - Position
map(Type.INT); // 2 - Data
map(Type.BOOLEAN); // 3 - Disable relative volume
handler(new PacketHandler() {
@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);
}
});
// Rewrite potion effect as it changed to use a dynamic registry
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int id = wrapper.get(Type.INT, 0);
if (id == 2002) {
int data = wrapper.get(Type.INT, 1);
int newData = ItemRewriter.getNewEffectID(data);
wrapper.set(Type.INT, 1, newData);
}
}
});
}
});
@@ -103,14 +114,9 @@ public class WorldPackets {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ClientChunks clientChunks = wrapper.user().get(ClientChunks.class);
Chunk chunk = wrapper.passthrough(new ChunkType(clientChunks));
if (chunk.isUnloadPacket()) {
PacketWrapper unload = wrapper.create(0x1D);
unload.write(Type.INT, chunk.getX());
unload.write(Type.INT, chunk.getZ());
unload.send();
wrapper.cancel();
}
wrapper.passthrough(new ChunkType(clientChunks));
// eat any other data (Usually happens with unload packets)
wrapper.read(Type.REMAINING_BYTES);
}
});
}
@@ -167,11 +173,34 @@ 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);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Position pos = wrapper.user().get(EntityTracker.class).getCurrentlyDigging();
if (pos != null) {
if (wrapper.get(Type.POSITION, 0).equals(pos)) {
// cancel this one
if (wrapper.get(Type.VAR_INT, 0) != 0) {
wrapper.cancel();
wrapper.user().get(EntityTracker.class).setCurrentlyDigging(null);
}
}
}
}
});
}
});
/* 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
@@ -221,6 +250,26 @@ public class WorldPackets {
}
}
});
// Digging patch (prevents it glitching)
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if(!ViaVersion.getConfig().isBlockBreakPatch()) return;
EntityTracker entityTracker = wrapper.user().get(EntityTracker.class);
final Position block = wrapper.get(Type.POSITION, 0);
int status = wrapper.get(Type.UNSIGNED_BYTE, 0);
if (status == 0) {
entityTracker.setCurrentlyDigging(null);
}
if (status == 1) {
entityTracker.setCurrentlyDigging(null);
}
if (status == 2) {
entityTracker.setCurrentlyDigging(block);
}
}
});
}
});
@@ -239,19 +288,21 @@ 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 (item != null) {
if (Material.getMaterial(item.getId()) != null) {
if (Material.getMaterial(item.getId()).name().endsWith("SWORD")) {
if (hand == 0) {
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (!tracker.isBlocking()) {
tracker.setBlocking(true);
Item shield = new Item((short) 442, (byte) 1, (short) 0, null);
tracker.setSecondHand(shield);
if (ViaVersion.getConfig().isShieldBlocking()) {
if (item != null) {
if (Material.getMaterial(item.getId()) != null) {
if (Material.getMaterial(item.getId()).name().endsWith("SWORD")) {
if (hand == 0) {
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if (!tracker.isBlocking()) {
tracker.setBlocking(true);
Item shield = new Item((short) 442, (byte) 1, (short) 0, null);
tracker.setSecondHand(shield);
}
wrapper.cancel();
}
wrapper.cancel();
}
}
}
@@ -317,7 +368,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
}
});
@@ -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);
}
}
@@ -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;
}
@@ -22,6 +22,7 @@ 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.metadata.NewType;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -43,6 +44,8 @@ public class EntityTracker extends StoredObject {
private Long lastPlaceBlock = -1L;
@Setter
private int entityID;
@Setter
private Position currentlyDigging = null;
private boolean teamExists = false;
public EntityTracker(UserConnection user) {
@@ -89,21 +92,21 @@ public class EntityTracker extends StoredObject {
}
public boolean interactedBlockRecently(int x, int y, int z) {
if(blockInteractions.size() == 0)
if (blockInteractions.size() == 0)
return false;
Iterator<Position> it = blockInteractions.asMap().keySet().iterator();
while(it.hasNext()) {
while (it.hasNext()) {
Position p = it.next();
if(p.getX() == x)
if(p.getY() == y)
if(p.getZ() == z)
if (p.getX() == x)
if (p.getY() == y)
if (p.getZ() == z)
return true;
}
return false;
}
public void addBlockInteraction(Position p) {
blockInteractions.put(p,Material.AIR);
blockInteractions.put(p, Material.AIR);
}
public void handleMetadata(int entityID, List<Metadata> metadataList) {
@@ -126,6 +129,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
@@ -143,9 +152,12 @@ public class EntityTracker extends StoredObject {
}
}
if (type == EntityType.ARMOR_STAND && ((ViaVersionPlugin) ViaVersion.getInstance()).isHologramPatch()) {
if (metadata.getId() == 0) {
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) {
// 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 {
@@ -200,6 +212,13 @@ public class EntityTracker extends StoredObject {
}
}
public Metadata getMetaByIndex(List<Metadata> list, int index) {
for (Metadata meta : list)
if (index == meta.getId())
return meta;
return null;
}
public void sendTeamPacket(boolean b) {
PacketWrapper wrapper = new PacketWrapper(0x41, null, getUser());
wrapper.write(Type.STRING, "viaversion"); // Use viaversion as name
@@ -14,6 +14,10 @@ public abstract class ListWrapper implements List {
public abstract void handleAdd(Object o);
public List getOriginalList() {
return list;
}
@Override
public synchronized int size() {
return this.list.size();
@@ -2,6 +2,7 @@ package us.myles.ViaVersion.util;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
@@ -57,4 +58,16 @@ public class PipelineUtil {
}
return false;
}
public static ChannelHandlerContext getContextBefore(String name, ChannelPipeline pipeline) {
boolean mark = false;
for (String s : pipeline.names()) {
if (mark) {
return pipeline.context(pipeline.get(s));
}
if (s.equalsIgnoreCase(name))
mark = true;
}
return null;
}
}
@@ -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);
+7 -1
View File
@@ -22,6 +22,12 @@ bossbar-patch: true
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
+1 -2
View File
@@ -3,9 +3,8 @@ main: us.myles.ViaVersion.ViaVersionPlugin
author: _MylesC
version: ${project.version}
load: startup
loadbefore: [ProtocolLib, ProxyPipe]
loadbefore: [ProtocolLib, ProxyPipe, SpigotLib, PacketListenerApi]
commands:
viaversion:
description: Shows ViaVersion Version and more.
permission: viaversion.admin
aliases: [viaver]