Compare commits

...
43 Commits
Author SHA1 Message Date
Myles dac616d72c Bump snapshot version up 2016-03-06 23:42:27 +00:00
Myles 528b234d5a Add collision options, fixes #95. (By default auto teams players until they're added to a team so you can't push!) 2016-03-06 23:22:45 +00:00
HugoDaBosss e4288383f4 Merge pull request #159 from HugoDaBosss/patch
Change package name from bossbarapi to lowercase.
2016-03-06 23:39:52 +01:00
BuildTools bb17eb01b8 Update 2016-03-06 23:17:51 +01:00
Myles ca6638c740 return null if the item is null :) 2016-03-06 21:40:15 +00:00
Myles d8ce66ce29 Merge pull request #158 from StamBoom/bossbar
Implement 1.9 BossBarAPI for developers
2016-03-06 18:35:55 +00:00
Mats 8460c157a5 Commit API 2016-03-06 19:27:26 +01:00
Mats 0b807569ad Implement 1.9 BossBarAPI for developers 2016-03-06 19:20:39 +01:00
Myles 75d001d09b Merge pull request #157 from rj0495/patch-3
Travis Build Status
2016-03-06 17:37:37 +00:00
Ryan James 2118379cf7 Travis Build Status 2016-03-06 17:35:54 +00:00
Myles cd2441ee52 Update README.md 2016-03-06 17:22:56 +00:00
Myles ffb4fb5c5a Merge pull request #155 from sgdc3/master
Improve POM and fix dead code
2016-03-06 16:48:41 +00:00
Myles c404f2206c Blame a class when the childHandler doesn't inject 2016-03-06 16:16:26 +00:00
Gabriele C aec5aa48da Bump 2016-03-06 16:38:58 +01:00
Gabriele C b63051a796 Improve POM and fix dead code 2016-03-06 16:36:54 +01:00
Myles ea4650000e Bump to 0.5.5 2016-03-06 15:16:36 +00:00
Myles 2d2018b8d0 Disable latest feature due to it breaking signs (no more sync chunks for now) 2016-03-06 15:10:54 +00:00
HugoDaBosss 736a853a85 Merge pull request #153 from HugoDaBosss/patch
Make Metadata Rewriter exception output more clear
2016-03-06 16:00:50 +01:00
HugoDaBosss dfd4c5f93e Formatting 2016-03-06 15:55:53 +01:00
HugoDaBosss 2ac87acc8a Make Metadata Rewriter exception output more clear 2016-03-06 15:52:06 +01:00
Myles 3c5a6a3b7b Fix README, also change a bit of the fixJson so that it can handle quotes on signs. 2016-03-06 14:40:23 +00:00
Myles 6efb5c1b64 Merge pull request #151 from HugoDaBosss/patch
Fix checkforupdates changing from false to true
2016-03-06 14:20:45 +00:00
HugoDaBosss 91de7e5a22 Fix checkforupdates changing from false to true
FIXED:
When starting the server when checkforupdates is false, it won't register the listener.
So when you enable checkforupdates using /viaversion dontbugme it won't send you messages until a restart.
2016-03-06 15:11:36 +01:00
Myles 1c42ae1ee8 Update version to 0.5.4 2016-03-06 13:52:38 +00:00
Myles c5ac3c9b3d Don't freeze current thread when sending chunks 2016-03-06 13:49:33 +00:00
Myles 0ea32b3318 Merge pull request #150 from HugoDaBosss/patch
Fix mob spawners when no EntityId is given
2016-03-06 13:45:56 +00:00
Myles 8afc850ed3 Add new config option "sync-chunks", chunks will now be sent in sync with the MC thread when true, this fixes timings (paper spigot mostly issue) 2016-03-06 13:45:26 +00:00
HugoDaBosss 3c6dcfe5bf Update OutgoingTransformer.java 2016-03-06 14:42:50 +01:00
HugoDaBosss 59d637e0f5 More formatting (stupid eclipse) 2016-03-06 14:42:22 +01:00
HugoDaBosss 923f3088c0 Formatting 2016-03-06 14:40:52 +01:00
HugoDaBosss 4f8aff9c01 Forgot to remove debug message 2016-03-06 14:37:51 +01:00
HugoDaBosss 99ceb9ae79 Fix mob spawners when no EntityId is given 2016-03-06 14:32:57 +01:00
Myles 6e0554f4a4 Fix enchanting tooltips 2016-03-06 13:22:56 +00:00
Myles 36879f8d02 Fix small issue with updater 2016-03-06 13:02:54 +00:00
Myles fe77df1434 Fix brewing #141 2016-03-06 12:25:54 +00:00
Myles 713361f973 Merge pull request #148 from StamBoom/master
Fix commandblock minecarts
2016-03-06 11:20:50 +00:00
Mats a314b86f57 Fix commandblock minecarts 2016-03-06 12:18:18 +01:00
Myles 840c90f871 Don't use GSON >.> 2016-03-06 11:03:41 +00:00
Myles 2a247595c8 Handle invalid version numbers 2016-03-06 10:49:21 +00:00
Myles 4124c3454e Change it so when there is no connection we don't bug them. Also change it to use http instead of https, as https requires certain certificate info by linux. 2016-03-06 10:46:38 +00:00
HugoDaBosss c4185e3056 Merge pull request #147 from fillefilip8/patch-4
Made the config use the default bukkit config methods insteed.
2016-03-06 10:56:07 +01:00
fillefilip8 d6403d495d Opps :) Github likes me :D Removed the new api methods from this branch :D 2016-03-06 10:42:26 +01:00
fillefilip8 d7f54048ff Made the config use the default bukkit config methods insteed. 2016-03-06 10:39:58 +01:00
22 changed files with 1119 additions and 197 deletions

No files matched your search

+115 -2
View File
@@ -1,3 +1,116 @@
target/
.idea/
### Java files ###
*.class
# Package Files
#*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
# Ignore project files
*.iml
# Ignore IDEA directory
.idea/*
# Include the project's code style settings file
!.idea/codeStyleSettings.xml
# Include the project's dictionary
!.idea/dictionaries/
!.idea/dictionaries/*
# File-based project format:
*.ipr
*.iws
### Plugin-specific files: ###
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
.nb-gradle/
### Git ###
# Don't exclude the .gitignore itself
!.gitignore
+12
View File
@@ -0,0 +1,12 @@
sudo: false
language: java
jdk: oraclejdk7
cache:
directories:
- '$HOME/.m2/repository'
script:
- mvn dependency:purge-local-repository -DactTransitively=false -DreResolve=false
- mvn clean install -B -U
+3
View File
@@ -0,0 +1,3 @@
License:
--------
You may modify this work, all rights are still owned by myself excluding any files in the spacebase package as they belong to the respected contributors. Please credit the original author (myself) when forking etc. (or if it helped you understand the new protocol or netty!)
+4 -4
View File
@@ -1,9 +1,10 @@
# ViaVersion 0.5.3
# ViaVersion 0.5.6
[![Build Status](https://travis-ci.org/MylesIsCool/ViaVersion.svg?branch=master)](https://travis-ci.org/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*
###*Don't use late bind*
This took hours of work, so if you enjoy this consider looking into contacting me and supporting my projects.
@@ -37,7 +38,7 @@ Contributors:
**fillefilip8**
**Chat: ** https://gitter.im/MylesIsCool/ViaVersion
**Chat:** https://gitter.im/MylesIsCool/ViaVersion
We use it to collaborate and solve errors, sign in with github.
@@ -49,4 +50,3 @@ You may modify this work, all rights are still owned by myself excluding any fil
Thanks!
+11
View File
@@ -0,0 +1,11 @@
machine:
java:
version: oraclejdk7
general:
artifacts:
- "target/*.jar"
test:
override:
- mvn clean install -B
post:
- cp ./target/*.jar $CIRCLE_ARTIFACTS
+141 -53
View File
@@ -1,20 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>us.myles</groupId>
<artifactId>ViaVersion</artifactId>
<version>0.5.3</version>
<artifactId>viaversion</artifactId>
<version>0.5.7-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ViaVersion</name>
<description>Allow 1.8 clients to join 1.9 bukkit servers!</description>
<inceptionYear>2016</inceptionYear>
<url>https://www.spigotmc.org/resources/viaversion.19254/</url>
<prerequisites>
<maven>3.3.3</maven>
</prerequisites>
<properties>
<!-- Project Properties -->
<projectEncoding>UTF-8</projectEncoding>
<project.build.sourceEncoding>${projectEncoding}</project.build.sourceEncoding>
<project.build.outputEncoding>${projectEncoding}</project.build.outputEncoding>
<jdkVersion>1.7</jdkVersion>
<!-- <testJreVersion>1.7</testJreVersion> -->
<!-- Change Bukkit Version HERE! -->
<bukkitVersion>1.8.8-R0.1-SNAPSHOT</bukkitVersion>
</properties>
<build>
<finalName>ViaVersion-${project.version}</finalName>
<finalName>${project.name}-${project.version}</finalName>
<sourceDirectory>src/main/java</sourceDirectory>
<!-- <testSourceDirectory>src/test/java</testSourceDirectory> -->
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>false</filtering>
<directory>.</directory>
<includes>
<include>LICENSE</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>*</include>
</includes>
</resource>
</resources>
<!--
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
-->
<plugins>
<!-- Maven Java Compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${jdkVersion}</source>
<target>${jdkVersion}</target>
<!--
<testSource>${testJreVersion}</testSource>
<testTarget>${testJreVersion}</testTarget>
-->
</configuration>
</plugin>
<!-- Unit Test Plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>-Dfile.encoding=${projectEncoding} ${argLine}</argLine>
</configuration>
</plugin>
-->
<!-- Libs Shading and Relocation -->
<plugin>
<!--Relocate all lib we use in order to fix class loading errors if we use different versions
than already loaded libs (i.e. by Mojang -> gson)-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<version>2.4.3</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<minimizeJar>false</minimizeJar>
<relocations>
<relocation>
<pattern>org.spacehq.opennbt</pattern>
<shadedPattern>us.myles.viaversion.libs.opennbt</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
@@ -25,62 +112,63 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<version>3.5.1</version>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>org.spacehq</groupId>
<artifactId>opennbt</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.20.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<!-- SpigotMC Repo (Bukkit API) -->
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
</repository>
<!-- SpaceHQ Repo-->
<repository>
<id>spacehq-repo</id>
<url>https://repo.spacehq.org/content/repositories/releases/</url>
</repository>
</repositories>
<dependencies>
<!-- Bukkit API, http://www.spigotmc.org/ or http://bukkit.org/ -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>${bukkitVersion}</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<artifactId>junit</artifactId>
<groupId>junit</groupId>
</exclusion>
<exclusion>
<artifactId>gson</artifactId>
<groupId>com.google.code.gson</groupId>
</exclusion>
<exclusion>
<artifactId>persistence-api</artifactId>
<groupId>javax.persistence</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- NBT Edit Library -->
<dependency>
<groupId>org.spacehq</groupId>
<artifactId>opennbt</artifactId>
<version>1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!-- Netty (Network Library) -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.20.Final</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>
@@ -18,6 +18,7 @@ public class ConnectionInfo {
private int protocol = 0;
private int compression = 0;
private boolean active = true;
private String username;
public ConnectionInfo(SocketChannel socketChannel) {
this.channel = socketChannel;
@@ -100,4 +101,12 @@ public class ConnectionInfo {
public void closeWindow() {
this.openWindow = null;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
}
@@ -7,8 +7,6 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -17,7 +15,11 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.ViaVersionAPI;
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.armor.ArmorListener;
import us.myles.ViaVersion.boss.ViaBossBar;
import us.myles.ViaVersion.commands.ViaVersionCommand;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.listeners.CommandBlockListener;
@@ -25,26 +27,25 @@ import us.myles.ViaVersion.update.UpdateListener;
import us.myles.ViaVersion.update.UpdateUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
private final Map<UUID, ConnectionInfo> portedPlayers = new ConcurrentHashMap<UUID, ConnectionInfo>();
private boolean debug = false;
private FileConfiguration config;
private File configFile;
@Override
public void onEnable() {
ViaVersion.setInstance(this);
saveDefaultConfig();
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.");
@@ -59,21 +60,8 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
getLogger().severe("Unable to inject handlers, are you on 1.8? ");
e.printStackTrace();
}
this.config = getFileConfiguration();
if (!config.contains("checkforupdates")) {
config.set("checkforupdates", true);
try {
config.save(configFile);
} catch (IOException e1) {
this.getLogger().info("Unabled to write config.yml!");
e1.printStackTrace();
}
}
if (config.getBoolean("checkforupdates")) {
Bukkit.getPluginManager().registerEvents(new UpdateListener(this), this);
if (getConfig().getBoolean("checkforupdates"))
UpdateUtil.sendUpdateMessage(this);
}
Bukkit.getPluginManager().registerEvents(new Listener() {
@EventHandler
@@ -84,6 +72,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
Bukkit.getPluginManager().registerEvents(new ArmorListener(this), this);
Bukkit.getPluginManager().registerEvents(new CommandBlockListener(this), this);
Bukkit.getPluginManager().registerEvents(new UpdateListener(this), this);
getCommand("viaversion").setExecutor(new ViaVersionCommand(this));
}
@@ -103,9 +92,15 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
ChannelFuture future = (ChannelFuture) o;
ChannelPipeline pipeline = future.channel().pipeline();
ChannelHandler bootstrapAcceptor = pipeline.first();
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
try {
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
} catch (NoSuchFieldException e) {
// field not found
throw new Exception("Unable to find childHandler, blame " + bootstrapAcceptor.getClass().getName());
}
injected = true;
} else {
break; // not the right list.
@@ -120,7 +115,12 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
@Override
public boolean isPorted(Player player) {
return portedPlayers.containsKey(player.getUniqueId());
return isPorted(player.getUniqueId());
}
@Override
public boolean isPorted(UUID playerUUID) {
return portedPlayers.containsKey(playerUUID);
}
@Override
@@ -129,16 +129,46 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
}
public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException {
if (!isPorted(player)) throw new IllegalArgumentException("This player is not on 1.9");
ConnectionInfo ci = portedPlayers.get(player.getUniqueId());
sendRawPacket(player.getUniqueId(), packet);
}
@Override
public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException {
if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not on 1.9");
ConnectionInfo ci = portedPlayers.get(uuid);
ci.sendRawPacket(packet);
}
@Override
public BossBar createBossBar(String title, BossColor color, BossStyle style) {
return new ViaBossBar(title, 1F, color, style);
}
@Override
public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) {
return new ViaBossBar(title, health, color, style);
}
@Override
public boolean isDebug() {
return this.debug;
}
@Override
public boolean isSyncedChunks() {
return getConfig().getBoolean("sync-chunks", true);
}
public boolean isPreventCollision() {
return getConfig().getBoolean("prevent-collision", true);
}
public boolean isAutoTeam() {
// Collision has to be enabled first
if(!isPreventCollision()) return false;
return getConfig().getBoolean("auto-team", true);
}
public void setDebug(boolean value) {
this.debug = value;
}
@@ -151,20 +181,6 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
portedPlayers.remove(clientID);
}
private FileConfiguration getFileConfiguration() {
if (!this.getDataFolder().exists())
this.getDataFolder().mkdirs();
this.configFile = new File(this.getDataFolder(), "config.yml");
if (!this.configFile.exists())
try {
this.configFile.createNewFile();
} catch (IOException e) {
this.getLogger().info("Unable to create config.yml!");
e.printStackTrace();
}
return YamlConfiguration.loadConfiguration(this.configFile);
}
public static ItemStack getHandItem(final ConnectionInfo info) {
try {
return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<ItemStack>() {
@@ -182,4 +198,22 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
return null;
}
}
}
public void run(final Runnable runnable, boolean wait) {
try {
Future f = Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
runnable.run();
return true;
}
});
if (wait) {
f.get(10, TimeUnit.SECONDS);
}
} catch (Exception e) {
System.out.println("Failed to run task.");
e.printStackTrace();
}
}
}
@@ -2,32 +2,86 @@ package us.myles.ViaVersion.api;
import io.netty.buffer.ByteBuf;
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 java.util.UUID;
public interface ViaVersionAPI {
/**
* Is player using 1.9?
*
* @param player
* @return True if the client is on 1.9
*/
boolean isPorted(Player player);
/**
* Is player using 1.9?
*
* @param playerUUID
* @return True if the client is on 1.9
*/
boolean isPorted(UUID playerUUID);
/**
* Get the version of the plugin
*
* @return Plugin version
*/
String getVersion();
/**
* Send a raw packet to the player (Use new IDs)
*
* @param player The player to send packet
* @param packet The packet, you need a VarInt ID then the packet contents.
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
*/
void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException;
/**
* Send a raw packet to the player (Use new IDs)
*
* @param uuid The uuid from the player to send packet
* @param packet The packet, you need a VarInt ID then the packet contents.
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
*/
void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException;
/**
* Create a new bossbar instance
*
* @param title The title
* @param color The color
* @param style The style
* @return Bossbar instance
*/
BossBar createBossBar(String title, BossColor color, BossStyle style);
/**
* Create a new bossbar instance
*
* @param title The title
* @param health Number between 0 and 1
* @param color The color
* @param style The style
* @return Bossbar instance
*/
BossBar createBossBar(String title, float health, BossColor color, BossStyle style);
/**
* Obtain if global debug is enabled
*
* @return true if debug is enabled
*/
boolean isDebug();
/**
* Obtains if syncing chunks is on
*
* @return true if it is
*/
boolean isSyncedChunks();
}
@@ -0,0 +1,122 @@
package us.myles.ViaVersion.api.boss;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.UUID;
public interface BossBar {
/**
* Change the title
*
* @param title Title can be in either JSON or just text
*/
void setTitle(String title);
/**
* Get the current title
*
* @return the title
*/
String getTitle();
/**
* Change the health
*
* @param health this float has to be between 0F - 1F
*/
void setHealth(float health);
/**
* Get the health
*
* @return float between 0F - 1F
*/
float getHealth();
/**
* Yay colors!
*
* @param color Whatever color you want!
*/
void setColor(BossColor color);
/**
* Get the bossbar color
*
* @return
*/
BossColor getColor();
/**
* Change the bosbar style
*
* @param style BossStyle
*/
void setStyle(BossStyle style);
/**
* Get the bosbar style
*
* @return BossStyle
*/
BossStyle getStyle();
/**
* Show the bossbar to a player.
*
* @param player
*/
void addPlayer(Player player);
/**
* Remove the bossbar from a player
*
* @param player
*/
void removePlayer(Player player);
/**
* Add flags
*
* @param flag
*/
void addFlag(BossFlag flag);
/**
* Remove flags.
*
* @param flag
*/
void removeFlag(BossFlag flag);
/**
* @param flag
* @return
*/
boolean hasFlag(BossFlag flag);
/**
* Get players
*
* @return UUIDS from players (sorry I lied)
*/
Set<UUID> getPlayers();
/**
* Show the bossbar to everyone (In the getPlayer set)
*/
void show();
/**
* Hide the bossbar from everyone (In the getPlayer set)
*/
void hide();
/**
* Is it visible?
*
* @return visibility changable with show() and hide()
*/
boolean isVisible();
}
@@ -0,0 +1,21 @@
package us.myles.ViaVersion.api.boss;
public enum BossColor {
PINK(0),
BLUE(1),
RED(2),
GREEN(3),
YELLOW(4),
PURPLE(5),
WHITE(6);
private final int id;
BossColor(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
@@ -0,0 +1,16 @@
package us.myles.ViaVersion.api.boss;
public enum BossFlag {
DARKEN_SKY(1),
PLAY_BOSS_MUSIC(2);
private final int id;
BossFlag(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
@@ -0,0 +1,19 @@
package us.myles.ViaVersion.api.boss;
public enum BossStyle {
SOLID(0),
SEGMENTED_6(1),
SEGMENTED_10(2),
SEGMENTED_12(3),
SEGMENTED_20(4);
private final int id;
BossStyle(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
@@ -0,0 +1,231 @@
package us.myles.ViaVersion.boss;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossFlag;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.packets.PacketType;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
import us.myles.ViaVersion.util.PacketUtil;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class ViaBossBar implements BossBar {
private UUID uuid;
private String title;
private float health;
private BossColor color;
private BossStyle style;
private Set<UUID> players;
private boolean visible;
private Set<BossFlag> flags;
public ViaBossBar(String title, float health, BossColor color, BossStyle style) {
Validate.notNull(title, "Title cannot be null");
Validate.isTrue((health >= 0 && health <= 1), "Health must be between 0 and 1");
this.uuid = UUID.randomUUID();
this.title = title;
this.health = health;
this.color = color == null ? BossColor.PURPLE : color;
this.style = style == null ? BossStyle.SOLID : style;
this.players = new HashSet<>();
this.flags = new HashSet<>();
visible = true;
}
@Override
public void setTitle(String title) {
Validate.notNull(title, "Title cannot be null");
this.title = title;
sendPacket(UpdateAction.UPDATE_TITLE);
}
@Override
public String getTitle() {
return title;
}
@Override
public void setHealth(float health) {
Validate.isTrue((health >= 0 && health <= 1), "Health must be between 0 and 1");
this.health = health;
sendPacket(UpdateAction.UPDATE_HEALTH);
}
@Override
public float getHealth() {
return health;
}
@Override
public void setColor(BossColor color) {
Validate.notNull(color, "Color cannot be null");
this.color = color;
sendPacket(UpdateAction.UPDATE_STYLE);
}
@Override
public BossColor getColor() {
return color;
}
@Override
public void setStyle(BossStyle style) {
Validate.notNull(style, "Style cannot be null");
this.style = style;
sendPacket(UpdateAction.UPDATE_STYLE);
}
@Override
public BossStyle getStyle() {
return style;
}
@Override
public void addPlayer(Player player) {
if (player != null && !players.contains(player.getUniqueId())) {
players.add(player.getUniqueId());
if (visible)
sendPacket(player.getUniqueId(), getPacket(UpdateAction.ADD));
}
}
@Override
public void removePlayer(Player player) {
if (player != null && players.contains(player.getUniqueId())) {
players.remove(player.getUniqueId());
sendPacket(player.getUniqueId(), getPacket(UpdateAction.REMOVE));
}
}
@Override
public void addFlag(BossFlag flag) {
if (!hasFlag(flag))
flags.add(flag);
sendPacket(UpdateAction.UPDATE_FLAGS);
}
@Override
public void removeFlag(BossFlag flag) {
if (hasFlag(flag))
flags.remove(flag);
sendPacket(UpdateAction.UPDATE_FLAGS);
}
@Override
public boolean hasFlag(BossFlag flag) {
return flags.contains(flag);
}
@Override
public Set<UUID> getPlayers() {
return Collections.unmodifiableSet(players);
}
@Override
public void show() {
setVisible(true);
}
@Override
public void hide() {
setVisible(false);
}
@Override
public boolean isVisible() {
return visible;
}
private void setVisible(boolean value) {
if (visible != value) {
visible = value;
sendPacket(value ? UpdateAction.ADD : UpdateAction.REMOVE);
}
}
private void sendPacket(UpdateAction action) {
ByteBuf buf = getPacket(action);
for (UUID uuid : players)
sendPacket(uuid, buf);
}
private void sendPacket(UUID uuid, ByteBuf buf) {
if (!ViaVersion.getInstance().isPorted(uuid)) {
players.remove(uuid);
return;
}
ViaVersion.getInstance().sendRawPacket(uuid, buf);
}
private ByteBuf getPacket(UpdateAction action) {
ByteBuf buf = Unpooled.buffer();
PacketUtil.writeVarInt(PacketType.PLAY_BOSS_BAR.getNewPacketID(), buf);
PacketUtil.writeUUID(uuid, buf);
PacketUtil.writeVarInt(action.getId(), buf);
switch (action) {
case ADD:
PacketUtil.writeString(fixJson(title), buf);
buf.writeFloat(health);
PacketUtil.writeVarInt(color.getId(), buf);
PacketUtil.writeVarInt(style.getId(), buf);
buf.writeByte(flagToBytes());
break;
case REMOVE:
break;
case UPDATE_HEALTH:
buf.writeFloat(health);
break;
case UPDATE_TITLE:
PacketUtil.writeString(fixJson(title), buf);
break;
case UPDATE_STYLE:
PacketUtil.writeVarInt(color.getId(), buf);
PacketUtil.writeVarInt(style.getId(), buf);
break;
case UPDATE_FLAGS:
buf.writeByte(flagToBytes());
break;
}
return buf;
}
private int flagToBytes() {
int bitmask = 0;
for (BossFlag flag : flags)
bitmask |= flag.getId();
return bitmask;
}
private String fixJson(String text) {
return OutgoingTransformer.fixJson(text);
}
private enum UpdateAction {
ADD(0),
REMOVE(1),
UPDATE_HEALTH(2),
UPDATE_TITLE(3),
UPDATE_STYLE(4),
UPDATE_FLAGS(5);
private final int id;
UpdateAction(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
}
@@ -5,11 +5,14 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ViaEncodeHandler extends MessageToByteEncoder {
private final ConnectionInfo info;
@@ -24,26 +27,51 @@ public class ViaEncodeHandler extends MessageToByteEncoder {
@Override
protected void encode(ChannelHandlerContext ctx, Object o, ByteBuf bytebuf) throws Exception {
protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception {
// handle the packet type
if (!(o instanceof ByteBuf)) {
info.setLastPacket(o);
/* This transformer is more for fixing issues which we find hard at packet level :) */
if (o.getClass().getName().endsWith("PacketPlayOutMapChunkBulk") && info.isActive()) {
int[] locX = ReflectionUtil.get(o, "a", int[].class);
int[] locZ = ReflectionUtil.get(o, "b", int[].class);
final int[] locX = ReflectionUtil.get(o, "a", int[].class);
final int[] locZ = ReflectionUtil.get(o, "b", int[].class);
Object world = ReflectionUtil.get(o, "world", ReflectionUtil.nms("World"));
final Object world = ReflectionUtil.get(o, "world", ReflectionUtil.nms("World"));
Class<?> mapChunk = ReflectionUtil.nms("PacketPlayOutMapChunk");
Constructor constructor = mapChunk.getDeclaredConstructor(ReflectionUtil.nms("Chunk"), boolean.class, int.class);
for (int i = 0; i < locX.length; i++) {
int x = locX[i];
int z = locZ[i];
// world invoke function
Object chunk = ReflectionUtil.nms("World").getDeclaredMethod("getChunkAt", int.class, int.class).invoke(world, x, z);
Object packet = constructor.newInstance(chunk, true, 65535);
ctx.pipeline().writeAndFlush(packet);
}
final Constructor constructor = mapChunk.getDeclaredConstructor(ReflectionUtil.nms("Chunk"), boolean.class, int.class);
Runnable chunks = new Runnable() {
@Override
public void run() {
for (int i = 0; i < locX.length; i++) {
int x = locX[i];
int z = locZ[i];
// world invoke function
try {
Object chunk = ReflectionUtil.nms("World").getDeclaredMethod("getChunkAt", int.class, int.class).invoke(world, x, z);
Object packet = constructor.newInstance(chunk, true, 65535);
ctx.pipeline().writeAndFlush(packet);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
};
// Synced allows timings to work properly.
// if (ViaVersion.getInstance().isSyncedChunks()) {
// ((ViaVersionPlugin) ViaVersion.getInstance()).run(chunks, false);
// } else {
chunks.run();
// }
bytebuf.readBytes(bytebuf.readableBytes());
throw new CancelException();
}
@@ -1,7 +1,6 @@
package us.myles.ViaVersion.metadata;
import org.bukkit.entity.*;
import org.bukkit.entity.minecart.CommandMinecart;
public enum MetaIndex {
@@ -107,8 +106,8 @@ public enum MetaIndex {
MINECART_BLOCK_Y(Minecart.class, 21, Type.Int, 9, NewType.VarInt),
MINECART_SHOWBLOCK(Minecart.class, 22, Type.Byte, 10, NewType.Boolean),
// Command minecart (they are still broken)
MINECART_COMMANDBLOCK_COMMAND(CommandMinecart.class,23,Type.String,11,NewType.String),
MINECART_COMMANDBLOCK_OUTPUT(CommandMinecart.class,24,Type.String,12,NewType.Chat),
MINECART_COMMANDBLOCK_COMMAND(Minecart.class, 23, Type.String, 11, NewType.String),
MINECART_COMMANDBLOCK_OUTPUT(Minecart.class, 24, Type.String, 12, NewType.Chat),
// furnace cart
FURNACECART_ISPOWERED(org.bukkit.entity.minecart.PoweredMinecart.class, 16, Type.Byte, 11, NewType.Boolean),
// item drop
@@ -167,14 +166,14 @@ public enum MetaIndex {
public static MetaIndex getIndex(EntityType type, int index) {
Class<? extends org.bukkit.entity.Entity> entityClass = type.getEntityClass();
if(entityClass == null){
if (entityClass == null) {
System.out.println("Could not get entity class for " + type);
return null;
}
for (MetaIndex mi : MetaIndex.values()) {
if (mi.getIndex() == index) {
// To fix issue with armour stands colliding with new values
if(mi.getApplicableClass().equals(LivingEntity.class)) continue;
if (mi.getApplicableClass().equals(LivingEntity.class)) continue;
if ((mi.getApplicableClass().isAssignableFrom(entityClass) ||
mi.getApplicableClass().equals(entityClass))) {
@@ -1,20 +1,19 @@
package us.myles.ViaVersion.metadata;
import io.netty.buffer.ByteBuf;
import org.bukkit.entity.EntityType;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
import us.myles.ViaVersion.slot.ItemSlotRewriter;
import us.myles.ViaVersion.slot.ItemSlotRewriter.ItemStack;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
import us.myles.ViaVersion.util.PacketUtil;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import org.bukkit.entity.EntityType;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.slot.ItemSlotRewriter;
import us.myles.ViaVersion.slot.ItemSlotRewriter.ItemStack;
import us.myles.ViaVersion.util.PacketUtil;
public class MetadataRewriter {
public static void writeMetadata1_9(EntityType type, List<Entry> list, ByteBuf output) {
@@ -88,7 +87,7 @@ public class MetadataRewriter {
PacketUtil.writeString((String) value, output);
break;
case Boolean:
if(metaIndex == MetaIndex.AGEABLE_AGE)
if (metaIndex == MetaIndex.AGEABLE_AGE)
output.writeBoolean(((Byte) value).byteValue() < 0);
else
output.writeBoolean(((Byte) value).byteValue() != 0);
@@ -110,18 +109,23 @@ public class MetadataRewriter {
output.writeFloat((float) angle.getY());
output.writeFloat((float) angle.getZ());
break;
case Chat:
PacketUtil.writeString(OutgoingTransformer.fixJson((String) value), output);
break;
default:
System.out.println("[Out] Unhandled MetaDataType: " + metaIndex.getNewType());
break;
}
}
} catch (Exception e) {
if (type != null) {
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.oldID);
if (metaIndex != null) {
System.out.println("Old ID: " + metaIndex.getIndex() + " New ID: " + metaIndex.getNewIndex());
System.out.println("Old Type: " + metaIndex.getOldType() + " New Type: " + metaIndex.getNewType());
}
else
System.out.println("An error occurred with entity meta data for UNKOWN_ENTITY OldID: " + entry.oldID);
if (metaIndex != null) {
System.out.println("Old ID: " + metaIndex.getIndex() + " New ID: " + metaIndex.getNewIndex());
System.out.println("Old Type: " + metaIndex.getOldType() + " New Type: " + metaIndex.getNewType());
}
e.printStackTrace();
}
@@ -159,7 +163,7 @@ public class MetadataRewriter {
e.printStackTrace();
}
}
break;
break;
case Position: {
int x = buf.readInt();
int y = buf.readInt();
@@ -178,6 +178,7 @@ public class ItemSlotRewriter {
public CompoundTag tag;
public static ItemStack fromBukkit(org.bukkit.inventory.ItemStack stack) {
if(stack == null) return null;
ItemStack item = new ItemStack();
item.id = (short) stack.getTypeId();
item.amount = (byte) stack.getAmount();
@@ -12,11 +12,8 @@ import us.myles.ViaVersion.packets.PacketType;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.slot.ItemSlotRewriter;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class IncomingTransformer {
private final ConnectionInfo info;
@@ -76,7 +73,7 @@ public class IncomingTransformer {
output.writeLong(location);
for (int i = 0; i < 4; i++) {
String line = PacketUtil.readString(input);
line = "{\"text\":\"" + line + "\"}";
line = OutgoingTransformer.fixJson(line);
PacketUtil.writeString(line, output);
}
return;
@@ -105,28 +102,32 @@ public class IncomingTransformer {
byte button = input.readByte();
short action = input.readShort();
byte mode = input.readByte();
// if the action is on an elytra armour slot
if (slot == 45 && windowID == 0) {
try {
Class<?> setSlot = ReflectionUtil.nms("PacketPlayOutSetSlot");
Constructor setSlotConstruct = setSlot.getDeclaredConstructor(int.class, int.class, ReflectionUtil.nms("ItemStack"));
// properly construct
Object setSlotPacket = setSlotConstruct.newInstance(windowID, slot, null);
info.getChannel().pipeline().writeAndFlush(setSlotPacket); // slot is empty
slot = -999; // we're evil, they'll throw item on the ground
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
int mode = input.readByte();
// if the action is on an elytra armour slot
boolean throwItem = (slot == 45 && windowID == 0);
if (info.getOpenWindow() != null && windowID > 0) {
if (info.getOpenWindow().equals("minecraft:brewing_stand")) {
if (slot == 4) {
// throw
throwItem = true;
}
if (slot > 4)
slot = (short) (slot - 1);
}
}
if (throwItem) {
ByteBuf buf = info.getChannel().alloc().buffer();
PacketUtil.writeVarInt(PacketType.PLAY_SET_SLOT.getNewPacketID(), buf);
buf.writeByte(windowID);
buf.writeShort(slot);
buf.writeShort(-1); // empty
info.sendRawPacket(buf);
// Continue the packet simulating throw
mode = 0;
button = 0;
slot = -999;
}
output.writeByte(windowID);
output.writeShort(slot);
@@ -216,6 +217,11 @@ public class IncomingTransformer {
PacketUtil.writeString(command, output);
output.writeBoolean(flag);
return;
} else if (name.equals("MC|AdvCmd")) {
output.clear();
PacketUtil.writeVarInt(PacketType.PLAY_PLUGIN_MESSAGE_REQUEST.getPacketID(), output);
PacketUtil.writeString("MC|AdvCdm", output);
output.writeBytes(b);
}
output.writeBytes(b);
}
@@ -53,12 +53,12 @@ public class OutgoingTransformer {
PacketType packet = PacketType.getOutgoingPacket(info.getState(), packetID);
int original = packetID;
if (packet.getPacketID() != -1) {
packetID = packet.getNewPacketID();
}
if (packet == null) {
throw new RuntimeException("Outgoing Packet not found? " + packetID + " State: " + info.getState() + " Version: " + info.getProtocol());
}
if (packet.getPacketID() != -1) {
packetID = packet.getNewPacketID();
}
if (ViaVersion.getInstance().isDebug()) {
if (packet != PacketType.PLAY_CHUNK_DATA && packet != PacketType.PLAY_KEEP_ALIVE && packet != PacketType.PLAY_TIME_UPDATE && (!packet.name().toLowerCase().contains("move") && !packet.name().toLowerCase().contains("look"))) {
System.out.println("Direction " + packet.getDirection().name() + " Packet Type: " + packet + " New ID: " + packetID + " Original: " + original + " Size: " + input.readableBytes());
@@ -253,10 +253,6 @@ public class OutgoingTransformer {
return;
}
// If login success
if (packet == PacketType.LOGIN_SUCCESS) {
info.setState(State.PLAY);
}
if (packet == PacketType.LOGIN_SETCOMPRESSION) {
int factor = PacketUtil.readVarInt(input);
info.setCompression(factor);
@@ -277,12 +273,16 @@ public class OutgoingTransformer {
return;
}
if (packet == PacketType.LOGIN_SUCCESS) {
String uu = PacketUtil.readString(input);
PacketUtil.writeString(uu, output);
UUID uniqueId = UUID.fromString(uu);
info.setState(State.PLAY);
String uuid = PacketUtil.readString(input);
PacketUtil.writeString(uuid, output);
UUID uniqueId = UUID.fromString(uuid);
info.setUUID(uniqueId);
plugin.addPortedClient(info);
output.writeBytes(input);
String username = PacketUtil.readString(input);
info.setUsername(username);
PacketUtil.writeString(username, output);
return;
}
@@ -408,6 +408,34 @@ public class OutgoingTransformer {
return;
}
if (packet == PacketType.PLAY_WINDOW_PROPERTY) {
int windowId = input.readUnsignedByte();
output.writeByte(windowId);
short property = input.readShort();
short value = input.readShort();
if (info.getOpenWindow() != null) {
if (info.getOpenWindow().equalsIgnoreCase("minecraft:enchanting_table")) {
if (property > 3 && property < 7) {
short level = (short) (value >> 8);
short enchantID = (short) (value & 0xFF);
// Property 1
ByteBuf buf1 = info.getChannel().alloc().buffer();
PacketUtil.writeVarInt(PacketType.PLAY_WINDOW_PROPERTY.getNewPacketID(), buf1);
buf1.writeByte(windowId);
buf1.writeShort(property);
buf1.writeShort(enchantID);
info.sendRawPacket(buf1);
property = (short) (property + 3);
value = level;
}
}
}
output.writeShort(property);
output.writeShort(value);
}
if (packet == PacketType.PLAY_OPEN_WINDOW) {
int windowId = input.readUnsignedByte();
String type = readString(input);
@@ -418,7 +446,7 @@ public class OutgoingTransformer {
writeString(type, output);
writeString(fixJson(windowTitle), output);
int slots = input.readUnsignedByte();
if(type.equals("minecraft:brewing_stand")){
if (type.equals("minecraft:brewing_stand")) {
slots = slots + 1; // new slot
}
output.writeByte(slots);
@@ -433,6 +461,12 @@ public class OutgoingTransformer {
output.writeByte(windowId);
short slot = input.readShort();
if (info.getOpenWindow() != null) {
if (info.getOpenWindow().equals("minecraft:brewing_stand")) {
if (slot >= 4)
slot = (short) (slot + 1);
}
}
output.writeShort(slot);
ItemSlotRewriter.rewrite1_8To1_9(input, output);
return;
@@ -442,10 +476,22 @@ public class OutgoingTransformer {
output.writeByte(windowId);
short count = input.readShort();
output.writeShort(count);
boolean brewing = false;
if (info.getOpenWindow() != null && windowId > 0) {
if (info.getOpenWindow().equals("minecraft:brewing_stand")) {
brewing = true;
}
}
output.writeShort(brewing ? (count + 1) : count);
for (int i = 0; i < count; i++) {
ItemSlotRewriter.rewrite1_8To1_9(input, output);
// write "fuel" slot
if (brewing && i == 3) {
output.writeShort(-1); // empty slot
}
}
return;
}
@@ -502,6 +548,10 @@ public class OutgoingTransformer {
clientEntityTypes.put(id, EntityType.PLAYER);
output.writeInt(id);
output.writeBytes(input);
// send fake team
if (plugin.isAutoTeam()) {
sendTeamPacket(true);
}
return;
}
if (packet == PacketType.PLAY_SPAWN_PLAYER) {
@@ -566,7 +616,33 @@ public class OutgoingTransformer {
output.writeByte(input.readByte());
PacketUtil.writeString(PacketUtil.readString(input), output);
PacketUtil.writeString("", output); // collission rule :)
PacketUtil.writeString(plugin.isPreventCollision() ? "never" : "", output); // collission rule :)
output.writeByte(input.readByte());
}
if (mode == 0 || mode == 3 || mode == 4) {
// add players
int count = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(count, output);
for (int i = 0; i < count; i++) {
String name = PacketUtil.readString(input);
if (plugin.isAutoTeam() && name.equalsIgnoreCase(info.getUsername())) {
if (mode == 4) {
// since removing add to auto team
plugin.run(new Runnable() {
@Override
public void run() {
sendTeamPacket(true);
}
}, false);
} else {
// since adding remove from auto team
sendTeamPacket(false);
}
}
PacketUtil.writeString(name, output);
}
}
output.writeBytes(input);
return;
@@ -578,14 +654,26 @@ public class OutgoingTransformer {
output.writeByte(action);
if (action == 1) { // update spawner
try {
int index = input.readerIndex();
DataInputStream stream = new DataInputStream(new ByteBufInputStream(input));
CompoundTag tag = (CompoundTag) NBTIO.readTag(stream);
String entity = (String) tag.get("EntityId").getValue();
CompoundTag spawn = new CompoundTag("SpawnData");
spawn.put(new StringTag("id", entity));
tag.put(spawn);
DataOutputStream out = new DataOutputStream(new ByteBufOutputStream(output));
NBTIO.writeTag(out, tag);
if (tag != null && tag.contains("EntityId")) {
String entity = (String) tag.get("EntityId").getValue();
CompoundTag spawn = new CompoundTag("SpawnData");
spawn.put(new StringTag("id", entity));
tag.put(spawn);
DataOutputStream out = new DataOutputStream(new ByteBufOutputStream(output));
NBTIO.writeTag(out, tag);
} else if (tag != null) { // EntityID does not exist
CompoundTag spawn = new CompoundTag("SpawnData");
spawn.put(new StringTag("id", "AreaEffectCloud")); //Make spawners show up as empty when no EntityId is given.
tag.put(spawn);
DataOutputStream out = new DataOutputStream(new ByteBufOutputStream(output));
NBTIO.writeTag(out, tag);
} else { //There doesn't exist any NBT tag
input.readerIndex(index);
output.writeBytes(input, input.readableBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
@@ -660,17 +748,53 @@ public class OutgoingTransformer {
}
output.writeBytes(input);
}
private void sendCreateTeam() {
ByteBuf buf = info.getChannel().alloc().buffer();
PacketUtil.writeVarInt(PacketType.PLAY_TEAM.getNewPacketID(), buf);
PacketUtil.writeString("viaversion", buf);
buf.writeByte(0); // make team
PacketUtil.writeString("viaversion", buf);
PacketUtil.writeString("", buf); // prefix
PacketUtil.writeString("", buf); // suffix
buf.writeByte(0); // friendly fire
PacketUtil.writeString("", buf); // nametags
PacketUtil.writeString("never", buf); // collision rule :)
buf.writeByte(0); // color
PacketUtil.writeVarInt(0, buf); // player count
info.sendRawPacket(buf);
}
private void sendTeamPacket(boolean b) {
ByteBuf buf = info.getChannel().alloc().buffer();
PacketUtil.writeVarInt(PacketType.PLAY_TEAM.getNewPacketID(), buf);
PacketUtil.writeString("viaversion", buf); // Use viaversion as name
if (b) {
// add
buf.writeByte(0); // make team
PacketUtil.writeString("viaversion", buf);
PacketUtil.writeString("", buf); // prefix
PacketUtil.writeString("", buf); // suffix
buf.writeByte(0); // friendly fire
PacketUtil.writeString("", buf); // nametags
PacketUtil.writeString("never", buf); // collision rule :)
buf.writeByte(0); // color
PacketUtil.writeVarInt(1, buf); // player count
PacketUtil.writeString(info.getUsername(), buf); // us
} else {
buf.writeByte(1); // remove team
}
info.sendRawPacket(buf);
}
public static String fixJson(String line) {
if (line == null || line.equalsIgnoreCase("null")) {
line = "{\"text\":\"\"}";
} else {
if (!line.startsWith("\"") && !line.startsWith("{")) {
if ((!line.startsWith("\"") || !line.endsWith("\"")) && (!line.startsWith("{") || !line.endsWith("}"))) {
JSONObject obj = new JSONObject();
obj.put("text", line);
line = obj.toJSONString();
return obj.toJSONString();
}
if (line.startsWith("\"")) {
if (line.startsWith("\"") && line.endsWith("\"")) {
line = "{\"text\":" + line + "}";
}
}
@@ -1,12 +1,13 @@
package us.myles.ViaVersion.update;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import us.myles.ViaVersion.api.ViaVersion;
import java.io.BufferedReader;
@@ -19,7 +20,7 @@ import java.util.UUID;
public class UpdateUtil {
private final static String URL = "https://api.spiget.org/v1/resources/";
private final static String URL = "http://api.spiget.org/v1/resources/";
private final static int PLUGIN = 19254;
public final static String PREFIX = ChatColor.GREEN + "" + ChatColor.BOLD + "[ViaVersion] " + ChatColor.GREEN;
@@ -69,19 +70,30 @@ public class UpdateUtil {
if (ViaVersion.getInstance().getVersion().equals("${project.version}")) {
return "You are using a debug/custom version, consider updating.";
}
Version current = new Version(ViaVersion.getInstance().getVersion());
Version newest = new Version(getNewestVersion());
String newestString = getNewestVersion();
if (newestString == null) {
if (console) {
return "Could not check for updates, check your connection.";
} else {
return null;
}
}
Version current;
try {
current = new Version(ViaVersion.getInstance().getVersion());
} catch (IllegalArgumentException e) {
return "You are using a debug/custom version, consider updating.";
}
Version newest = new Version(newestString);
if (current.compareTo(newest) < 0)
return "There is a newer version available: " + newest.toString();
else if (console) {
else if (console && current.compareTo(newest) != 0) {
return "You are running a newer version than is released!";
}
return null;
}
private static String getNewestVersion() {
String result = "";
try {
URL url = new URL(URL + PLUGIN + "?" + System.currentTimeMillis());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
@@ -95,14 +107,19 @@ public class UpdateUtil {
content = content + input;
}
br.close();
JsonParser parser = new JsonParser();
JsonObject statistics = (JsonObject) parser.parse(content);
result = statistics.get("version").getAsString();
JSONParser parser = new JSONParser();
JSONObject statistics;
try {
statistics = (JSONObject) parser.parse(content);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
return (String) statistics.get("version");
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
return result;
}
}
+10
View File
@@ -0,0 +1,10 @@
# Should ViaVersion check for updates?
checkforupdates: true
# Should we send any bulk chunks, in sync (may be slower but fixes timings)
# Currently broken due to sign updates, possibly will return
sync-chunks: true
# No collide options, these allow you to configure how collision works.
# Do you want us to prevent collision?
prevent-collision: true
# If the above is true, should we automatically team players until you do?
auto-team: true