Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adb3c5392c | ||
|
|
cd2f56d7c7 | ||
|
|
7c9bbc3f6c | ||
|
|
52e396b25d | ||
|
|
aeb2cfb65e | ||
|
|
7f5ea6e493 | ||
|
|
1be94aad78 | ||
|
|
6bb169ac01 | ||
|
|
ea7900d64f | ||
|
|
123abdff30 | ||
|
|
11247f1c01 | ||
|
|
f093c9196d | ||
|
|
81daa62071 | ||
|
|
f99b977888 | ||
|
|
b00ae2ff15 | ||
|
|
b4f9c501b3 | ||
|
|
1738c6f243 | ||
|
|
abea7441a4 | ||
|
|
3887ba27d2 | ||
|
|
76a3af84a1 | ||
|
|
be5d42ee19 | ||
|
|
790711c16e | ||
|
|
8c3127dee1 | ||
|
|
5ec87c9d76 | ||
|
|
2205ce639e | ||
|
|
2844d75607 | ||
|
|
a6810ea874 | ||
|
|
aaf1af8e41 | ||
|
|
b8dd43aeed | ||
|
|
e959efc5af | ||
|
|
73ce01bbde | ||
|
|
b30628f6db | ||
|
|
9289825d87 | ||
|
|
57cfbc4f81 | ||
|
|
3ab2026d62 | ||
|
|
e439c778a6 | ||
|
|
98413c917e | ||
|
|
540a5e53c4 | ||
|
|
27047f83a5 | ||
|
|
222b535c15 | ||
|
|
3f31af6b70 | ||
|
|
b6a054b766 | ||
|
|
3b7b692e80 | ||
|
|
c6788addeb | ||
|
|
5b38bc7f38 | ||
|
|
33bb12713d | ||
|
|
d175a7655e | ||
|
|
4afb38aae1 | ||
|
|
36b5670b3d | ||
|
|
7b61796506 | ||
|
|
684b687e42 | ||
|
|
7a9b9afe2e | ||
|
|
7d382279ad | ||
|
|
b4f5f18283 | ||
|
|
17e150393a | ||
|
|
b5ecfb9c5f | ||
|
|
31a0c9b10c | ||
|
|
e4d95e09cf | ||
|
|
d173be0db5 | ||
|
|
051989a396 | ||
|
|
795c77e943 | ||
|
|
1de6bbc9dc | ||
|
|
474c74b1f9 | ||
|
|
caaa57c915 | ||
|
|
588f736348 | ||
|
|
828302150a | ||
|
|
144723af18 | ||
|
|
087913ab3a | ||
|
|
64942cbb5e | ||
|
|
97430a8e42 | ||
|
|
1bdd200794 | ||
|
|
679035c3bf | ||
|
|
bd4352f041 | ||
|
|
05ffeb8e7f | ||
|
|
6c982a83f0 | ||
|
|
9860fbaec6 | ||
|
|
26c29d9c85 | ||
|
|
242b25eb1e | ||
|
|
c13b8d4fc6 | ||
|
|
12e9c08a1a | ||
|
|
98a0528806 | ||
|
|
015a6067fd | ||
|
|
e34105e754 | ||
|
|
a995866d5b | ||
|
|
a88347dfe6 | ||
|
|
4f404a41c6 | ||
|
|
88444dcf74 | ||
|
|
4f5ab9eb8c | ||
|
|
f51427b63c | ||
|
|
cdcb6a6007 | ||
|
|
ac7e17d0a6 | ||
|
|
402390866a | ||
|
|
cc362a1b7f | ||
|
|
1ca7973b77 | ||
|
|
9ecbea68ca | ||
|
|
e5bc602af3 | ||
|
|
a9aa406d29 | ||
|
|
c1ae6f14fc | ||
|
|
411b7a2446 | ||
|
|
869b457810 | ||
|
|
4330bae47f | ||
|
|
1c36c41050 | ||
|
|
bea4356aca | ||
|
|
32f51c612a | ||
|
|
355d00d951 | ||
|
|
bf56f3919f | ||
|
|
d876580ddf | ||
|
|
90f36198d2 | ||
|
|
e542f3c9d3 | ||
|
|
87c56d0248 | ||
|
|
8c928cb237 | ||
|
|
6030992af4 | ||
|
|
688da1a1bb | ||
|
|
ceecd51982 | ||
|
|
c77a700442 | ||
|
|
10ded26d60 | ||
|
|
74adaba8ac | ||
|
|
19c57b0e5e | ||
|
|
f561057311 | ||
|
|
0e6a7a39a0 | ||
|
|
13b905e762 | ||
|
|
b4c0cc5a27 | ||
|
|
a042c8bb3c | ||
|
|
286a642739 | ||
|
|
513a83c4b0 | ||
|
|
9b2c8826b1 | ||
|
|
413a3c27a4 | ||
|
|
c9328d98d7 | ||
|
|
f6c0751ce3 | ||
|
|
16c7ebef73 | ||
|
|
ec38ac7292 | ||
|
|
b8497a91a6 | ||
|
|
5115bcaf98 | ||
|
|
7077037bb7 | ||
|
|
11ba322b5f | ||
|
|
a39a37ec51 | ||
|
|
ec8fa0d1fe | ||
|
|
5efc4ffee3 | ||
|
|
c2d028df4f | ||
|
|
9b838df17d | ||
|
|
a20ff4645d | ||
|
|
850e3431da | ||
|
|
072a60516e | ||
|
|
9b3feb995a | ||
|
|
d359f7455f | ||
|
|
4987cd188a | ||
|
|
019e45572d | ||
|
|
d87e877a27 | ||
|
|
05c7da17b9 | ||
|
|
8c21f75e6d | ||
|
|
615a4e6e37 | ||
|
|
11ca1bf51e | ||
|
|
7fabfad65d | ||
|
|
ce4779f49d | ||
|
|
a88b919e60 | ||
|
|
cc4d035b63 | ||
|
|
12b78eb1d7 | ||
|
|
8a5267ab76 | ||
|
|
a189947617 | ||
|
|
f01b3999ff |
No files matched your search
@@ -0,0 +1,38 @@
|
||||
Contributing to ProtocolLib
|
||||
===========================
|
||||
This page will detail specific things that must be done if you intend to contribute to this project.
|
||||
|
||||
## Updating ProtocolLib to a New Protocol Version
|
||||
#### Before we get started:
|
||||
1. **When do we need to update the protocol version?**
|
||||
_A Minecraft protocol version is a number for each specification of the Minecraft protocol.
|
||||
This means it is incremented when there is a change to the [Protocol Specification](http://wiki.vg/Protocol),
|
||||
but not necessarily for each Minecraft version update. If the latest Minecraft version contains a protocol change,
|
||||
that means ProtocolLib needs to be updated._
|
||||
2. **When do we need to update other parts of ProtocolLib?**
|
||||
_When the package version guard changes. The package version guard is the version string inserted
|
||||
into the package identifier for CraftBukkit and net.minecraft.server (e.g. v1_9_R2). It is incremented
|
||||
by Spigot if there is a major breaking change in the internal server code. This is to encourage plugins
|
||||
that interact directly with CraftBukkit/nms code to update more specifically. However, since most of
|
||||
ProtocolLib uses reflection, and the structure of packet classes is generally static, one will have
|
||||
to go through the code and change imports from nms/CraftBukkit._
|
||||
|
||||
#### Ready? Let's get started!
|
||||
1. Read the [Protocol Changes](http://wiki.vg/Protocol_History). Always make sure the list is both
|
||||
complete and correct. If you're unsure, don't hesitate to ask in #mcdevs (the people who maintain wiki.vg) on [freenode.net](http://freenode.net)
|
||||
or #spigot on [irc.spi.gt](http://irc.spi.gt) ([webchat](https://irc.spi.gt/iris/?channels=spigot)).
|
||||
2. Search for usages of the now-defunct NMS package guard and change them.
|
||||
3. The class `com.comphenix.protocol.PacketType` contains a list of all the packets. If any packets were added or removed
|
||||
(or had their ID changed), make sure to update this list. If a packet was removed
|
||||
in favor of usage of another packet, instead of removing it, move it to the bottom of the list
|
||||
in its section, add a deprecation warning to it, and redirect it to the packet that replaced it.
|
||||
4. `mvn` in the root directory to build the project.
|
||||
5. If tests fail in the maven build, go through the tests to make sure you removed references to any removed packets
|
||||
and changed the NMS version guards.
|
||||
6. Increment the package version in `com.comphenix.protocol.utility.Constants`.
|
||||
7. `com.comphenix.protocol.ProtocolLibrary` contains several constants that must be updated, including the Minecraft version
|
||||
and the release date.
|
||||
8. `com.comphenix.protocol.utility.MinecraftProtocolVersion` contains a map of all the protocol version integers.
|
||||
If the protocol version has been incremented, add a new line to the map.
|
||||
9. `mvn` in root directory again. If it builds successfully, test on the appropriate version of a Spigot server. If
|
||||
the build fails, debug!
|
||||
@@ -0,0 +1,10 @@
|
||||
_Follow this template except for feature requests. Use pastebin when providing /protocol dump and any relevant errors._
|
||||
|
||||
Make sure you've done the following:
|
||||
- [ ] You're using the latest build for your server version
|
||||
- [ ] This isn't an issue caused by another plugin
|
||||
- [ ] You've checked for duplicate issues
|
||||
|
||||
Debug paste link:
|
||||
|
||||
Description and relevant errors:
|
||||
@@ -7,6 +7,10 @@
|
||||
.classpath
|
||||
.settings/
|
||||
bin/
|
||||
.idea/
|
||||
*.iml
|
||||
.ipr
|
||||
.iws
|
||||
|
||||
*.pydevproject
|
||||
.metadata
|
||||
|
||||
+2
-3
@@ -1,9 +1,8 @@
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- oraclejdk7
|
||||
script: mvn clean test -U
|
||||
before_install: cd ProtocolLib
|
||||
script: mvn clean test
|
||||
#before_install: cd ProtocolLib
|
||||
install: true
|
||||
notifications:
|
||||
email:
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
#################
|
||||
## Eclipse
|
||||
#################
|
||||
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
target/
|
||||
.gitignore
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.vspscc
|
||||
.builds
|
||||
*.dotCover
|
||||
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment this
|
||||
#packages/
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish
|
||||
|
||||
# Others
|
||||
[Bb]in
|
||||
[Oo]bj
|
||||
sql
|
||||
TestResults
|
||||
*.Cache
|
||||
ClientBin
|
||||
stylecop.*
|
||||
~$*
|
||||
*.dbmdl
|
||||
Generated_Code #added for RIA/Silverlight projects
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
|
||||
|
||||
|
||||
############
|
||||
## Windows
|
||||
############
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
|
||||
#############
|
||||
## Python
|
||||
#############
|
||||
|
||||
*.py[co]
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
develop-eggs
|
||||
.installed.cfg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
|
||||
#Translations
|
||||
*.mo
|
||||
|
||||
#Mr Developer
|
||||
.mr.developer.cfg
|
||||
|
||||
# Mac crap
|
||||
.DS_Store
|
||||
/target
|
||||
/target
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2012 Kristian S. Stangeland
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* Ignore this class.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
public class Application {
|
||||
private static Thread mainThread;
|
||||
private static boolean primaryMethod = true;
|
||||
|
||||
public static void main(String[] args) {
|
||||
// For now, though we might consider making a proper application
|
||||
System.out.println("This is a Bukkit library. Place it in the plugin-folder and restart the server!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we are running on the main thread.
|
||||
* @return TRUE if we are, FALSE otherwise.
|
||||
*/
|
||||
public static boolean isPrimaryThread() {
|
||||
if (primaryMethod) {
|
||||
try {
|
||||
return Bukkit.isPrimaryThread();
|
||||
} catch (LinkageError e) {
|
||||
primaryMethod = false;
|
||||
}
|
||||
}
|
||||
// Fallback method
|
||||
return Thread.currentThread().equals(mainThread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the calling thread as the primary thread.
|
||||
*/
|
||||
static void registerPrimaryThread() {
|
||||
mainThread = Thread.currentThread();
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.guava;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class Guava {
|
||||
private static GuavaCompat compat;
|
||||
|
||||
static {
|
||||
try {
|
||||
Range.closed(1, 2);
|
||||
compat = new Guava17();
|
||||
} catch (Throwable ex) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName("com.comphenix.protocol.compat.guava.Guava10");
|
||||
compat = (GuavaCompat) clazz.newInstance();
|
||||
} catch (Throwable ex1) {
|
||||
ProtocolLibrary.log(Level.SEVERE, "Failed to create Guava 10 compat:", ex1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static GuavaCompat getCompat() {
|
||||
return compat;
|
||||
}
|
||||
|
||||
public static <C extends Comparable<C>> Range<C> closedRange(C lower, C upper) {
|
||||
return getCompat().closedRange(lower, upper);
|
||||
}
|
||||
|
||||
public static <C extends Comparable<C>> Range<C> singleton(C singleton) {
|
||||
return getCompat().singletonRange(singleton);
|
||||
}
|
||||
|
||||
public static Set<Integer> toSet(Range<Integer> range) {
|
||||
return getCompat().toSet(range);
|
||||
}
|
||||
|
||||
public static DataInputStream addHeader(DataInputStream input, PacketType type) {
|
||||
return getCompat().addHeader(input, type);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.guava;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.google.common.collect.ContiguousSet;
|
||||
import com.google.common.collect.DiscreteDomain;
|
||||
import com.google.common.collect.Range;
|
||||
import com.google.common.io.ByteSource;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class Guava17 implements GuavaCompat {
|
||||
|
||||
@Override
|
||||
public <C extends Comparable<C>> Range<C> closedRange(C lower, C upper) {
|
||||
return Range.closed(lower, upper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C extends Comparable<C>> Range<C> singletonRange(C singleton) {
|
||||
return Range.singleton(singleton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Integer> toSet(Range<Integer> range) {
|
||||
return ContiguousSet.create(range, DiscreteDomain.integers());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataInputStream addHeader(final DataInputStream input, final PacketType type) {
|
||||
ByteSource header = new ByteSource() {
|
||||
@Override
|
||||
public InputStream openStream() throws IOException {
|
||||
byte[] data = new byte[] { (byte) type.getLegacyId() };
|
||||
return new ByteArrayInputStream(data);
|
||||
}
|
||||
};
|
||||
|
||||
ByteSource data = new ByteSource() {
|
||||
@Override
|
||||
public InputStream openStream() throws IOException {
|
||||
return input;
|
||||
}
|
||||
};
|
||||
|
||||
// Combine them into a single stream
|
||||
try {
|
||||
return new DataInputStream(ByteSource.concat(header, data).openStream());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Cannot add header.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.guava;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public interface GuavaCompat {
|
||||
|
||||
<C extends Comparable<C>> Range<C> closedRange(C lower, C upper);
|
||||
|
||||
<C extends Comparable<C>> Range<C> singletonRange(C singleton);
|
||||
|
||||
Set<Integer> toSet(Range<Integer> range);
|
||||
|
||||
DataInputStream addHeader(DataInputStream input, PacketType type);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty;
|
||||
|
||||
import com.comphenix.protocol.injector.netty.Injector;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public interface ChannelInjector extends Injector {
|
||||
|
||||
WrappedChannel getChannel();
|
||||
}
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.PacketType.Protocol;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.injector.netty.ProtocolRegistry;
|
||||
import com.comphenix.protocol.injector.packet.MapContainer;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class LegacyProtocolRegistry extends ProtocolRegistry {
|
||||
|
||||
public LegacyProtocolRegistry() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
final Object[] protocols = enumProtocol.getEnumConstants();
|
||||
List<Map<Integer, Class<?>>> serverMaps = Lists.newArrayList();
|
||||
List<Map<Integer, Class<?>>> clientMaps = Lists.newArrayList();
|
||||
StructureModifier<Object> modifier = null;
|
||||
|
||||
// Result
|
||||
Register result = new Register();
|
||||
|
||||
for (Object protocol : protocols) {
|
||||
if (modifier == null)
|
||||
modifier = new StructureModifier<Object>(protocol.getClass().getSuperclass(), false);
|
||||
StructureModifier<Map<Integer, Class<?>>> maps = modifier.withTarget(protocol).withType(Map.class);
|
||||
|
||||
serverMaps.add(maps.read(0));
|
||||
clientMaps.add(maps.read(1));
|
||||
}
|
||||
// Maps we have to occationally check have changed
|
||||
for (Map<Integer, Class<?>> map : Iterables.concat(serverMaps, clientMaps)) {
|
||||
result.containers.add(new MapContainer(map));
|
||||
}
|
||||
|
||||
// Heuristic - there are more server packets than client packets
|
||||
if (sum(clientMaps) > sum(serverMaps)) {
|
||||
// Swap if this is violated
|
||||
List<Map<Integer, Class<?>>> temp = serverMaps;
|
||||
serverMaps = clientMaps;
|
||||
clientMaps = temp;
|
||||
}
|
||||
|
||||
for (int i = 0; i < protocols.length; i++) {
|
||||
Enum<?> enumProtocol = (Enum<?>) protocols[i];
|
||||
Protocol equivalent = Protocol.fromVanilla(enumProtocol);
|
||||
|
||||
// Associate known types
|
||||
associatePackets(result, serverMaps.get(i), equivalent, Sender.SERVER);
|
||||
associatePackets(result, clientMaps.get(i), equivalent, Sender.CLIENT);
|
||||
}
|
||||
|
||||
// Exchange (thread safe, as we have only one writer)
|
||||
this.register = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void associatePackets(Register register, Map<Integer, Class<?>> lookup, Protocol protocol, Sender sender) {
|
||||
for (Entry<Integer, Class<?>> entry : lookup.entrySet()) {
|
||||
PacketType type = PacketType.fromID(protocol, sender, entry.getKey(), entry.getValue());
|
||||
|
||||
try {
|
||||
register.typeToClass.put(type, entry.getValue());
|
||||
|
||||
if (sender == Sender.SERVER)
|
||||
register.serverPackets.add(type);
|
||||
if (sender == Sender.CLIENT)
|
||||
register.clientPackets.add(type);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Sometimes this happens with fake packets, just ignore it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.compat.netty.independent.IndependentNetty;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.injector.PacketFilterManager;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing.CompressedImage;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class Netty {
|
||||
private static NettyCompat compat;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class.forName("io.netty.buffer.ByteBuf");
|
||||
compat = new IndependentNetty();
|
||||
} catch (ClassNotFoundException ex) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName("com.comphenix.protocol.compat.netty.shaded.ShadedNetty");
|
||||
compat = (NettyCompat) clazz.newInstance();
|
||||
} catch (Exception ex1) {
|
||||
ProtocolLibrary.log(Level.SEVERE, "Failed to create legacy netty compat:", ex1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static NettyCompat getCompat() {
|
||||
return compat;
|
||||
}
|
||||
|
||||
public static boolean isIndependent() {
|
||||
return compat instanceof IndependentNetty;
|
||||
}
|
||||
|
||||
public static WrappedByteBuf createPacketBuffer() {
|
||||
return getCompat().createPacketBuffer();
|
||||
}
|
||||
|
||||
public static Class<?> getGenericFutureListenerArray() {
|
||||
return getCompat().getGenericFutureListenerArray();
|
||||
}
|
||||
|
||||
public static Class<?> getChannelHandlerContext() {
|
||||
return getCompat().getChannelHandlerContext();
|
||||
}
|
||||
|
||||
public static String toEncodedText(CompressedImage image) {
|
||||
return getCompat().toEncodedText(image);
|
||||
}
|
||||
|
||||
public static WrappedByteBuf decode(byte[] encoded) {
|
||||
return getCompat().decode(encoded);
|
||||
}
|
||||
|
||||
public static ProtocolInjector getProtocolInjector(Plugin library, PacketFilterManager packetFilterManager, ErrorReporter reporter) {
|
||||
return getCompat().getProtocolInjector(library, packetFilterManager, reporter);
|
||||
}
|
||||
|
||||
public static WrappedByteBuf packetReader(DataInputStream input) {
|
||||
return getCompat().packetReader(input);
|
||||
}
|
||||
|
||||
public static WrappedByteBuf packetWriter(DataOutputStream output) {
|
||||
return getCompat().packetWriter(output);
|
||||
}
|
||||
|
||||
public static WrappedByteBuf copiedBuffer(byte[] array) {
|
||||
return getCompat().copiedBuffer(array);
|
||||
}
|
||||
|
||||
public static WrappedByteBuf buffer() {
|
||||
return getCompat().buffer();
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.injector.ListenerInvoker;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing.CompressedImage;
|
||||
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
// TODO: Sort out packet readers/writers
|
||||
public interface NettyCompat {
|
||||
|
||||
WrappedByteBuf createPacketBuffer();
|
||||
|
||||
WrappedByteBuf copiedBuffer(byte[] array);
|
||||
|
||||
WrappedByteBuf buffer();
|
||||
|
||||
Class<?> getGenericFutureListenerArray();
|
||||
|
||||
Class<?> getChannelHandlerContext();
|
||||
|
||||
String toEncodedText(CompressedImage image);
|
||||
|
||||
WrappedByteBuf decode(byte[] encoded);
|
||||
|
||||
ProtocolInjector getProtocolInjector(Plugin plugin, ListenerInvoker invoker, ErrorReporter reporter);
|
||||
|
||||
WrappedByteBuf packetReader(DataInputStream input);
|
||||
|
||||
WrappedByteBuf packetWriter(DataOutputStream output);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty;
|
||||
|
||||
import com.comphenix.protocol.injector.netty.ChannelListener;
|
||||
import com.comphenix.protocol.injector.packet.PacketInjector;
|
||||
import com.comphenix.protocol.injector.player.PlayerInjectionHandler;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public interface ProtocolInjector extends ChannelListener {
|
||||
|
||||
PlayerInjectionHandler getPlayerInjector();
|
||||
|
||||
PacketInjector getPacketInjector();
|
||||
|
||||
void setDebug(boolean debug);
|
||||
|
||||
void inject();
|
||||
|
||||
void close();
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public interface WrappedByteBuf {
|
||||
|
||||
void writeBytes(ObjectInputStream input, int id) throws IOException;
|
||||
|
||||
Object getHandle();
|
||||
|
||||
int readableBytes();
|
||||
|
||||
void readBytes(ObjectOutputStream output, int readableBytes) throws IOException;
|
||||
|
||||
void readBytes(byte[] data);
|
||||
|
||||
void writeByte(byte b);
|
||||
|
||||
void writeByte(int i);
|
||||
|
||||
void writeBytes(byte[] bytes);
|
||||
|
||||
byte[] array();
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public interface WrappedChannel {
|
||||
|
||||
void writeAndFlush(Object packet);
|
||||
}
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty.independent;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.base64.Base64;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.compat.netty.NettyCompat;
|
||||
import com.comphenix.protocol.compat.netty.ProtocolInjector;
|
||||
import com.comphenix.protocol.compat.netty.WrappedByteBuf;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.injector.ListenerInvoker;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing.CompressedImage;
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class IndependentNetty implements NettyCompat {
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf createPacketBuffer() {
|
||||
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
|
||||
Class<?> packetSerializer = MinecraftReflection.getPacketDataSerializerClass();
|
||||
|
||||
try {
|
||||
return new NettyByteBuf((ByteBuf) packetSerializer.getConstructor(ByteBuf.class).newInstance(buffer));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot construct packet serializer.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getGenericFutureListenerArray() {
|
||||
return GenericFutureListener[].class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getChannelHandlerContext() {
|
||||
return ChannelHandlerContext.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toEncodedText(CompressedImage image) {
|
||||
final ByteBuf buffer = Unpooled.wrappedBuffer(image.getDataCopy());
|
||||
String computed = "data:" + image.getMime() + ";base64," +
|
||||
Base64.encode(buffer).toString(Charsets.UTF_8);
|
||||
return computed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf decode(byte[] encoded) {
|
||||
return new NettyByteBuf(Base64.decode(Unpooled.wrappedBuffer(encoded)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtocolInjector getProtocolInjector(Plugin plugin, ListenerInvoker invoker, ErrorReporter reporter) {
|
||||
return new NettyProtocolInjector(plugin, invoker, reporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf packetReader(DataInputStream input) {
|
||||
return new NettyByteBuf(NettyByteBufAdapter.packetReader(input));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf packetWriter(DataOutputStream output) {
|
||||
return new NettyByteBuf(NettyByteBufAdapter.packetWriter(output));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf copiedBuffer(byte[] array) {
|
||||
return new NettyByteBuf(Unpooled.copiedBuffer(array));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedByteBuf buffer() {
|
||||
return new NettyByteBuf(Unpooled.buffer());
|
||||
}
|
||||
}
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty.independent;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import com.comphenix.protocol.compat.netty.WrappedByteBuf;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class NettyByteBuf implements WrappedByteBuf {
|
||||
private WeakReference<ByteBuf> handle;
|
||||
|
||||
public NettyByteBuf(ByteBuf handle) {
|
||||
this.handle = new WeakReference<ByteBuf>(handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ObjectInputStream input, int id) throws IOException {
|
||||
handle.get().writeBytes(input, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return handle.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readableBytes() {
|
||||
return handle.get().readableBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readBytes(ObjectOutputStream output, int readableBytes) throws IOException {
|
||||
handle.get().readBytes(output, readableBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readBytes(byte[] data) {
|
||||
handle.get().readBytes(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeByte(byte b) {
|
||||
handle.get().writeByte(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeByte(int i) {
|
||||
handle.get().writeByte(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(byte[] bytes) {
|
||||
handle.get().writeBytes(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] array() {
|
||||
return handle.get().array();
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import com.comphenix.protocol.compat.netty.WrappedByteBuf;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WirePacket {
|
||||
private final int id;
|
||||
private final byte[] bytes;
|
||||
|
||||
public WirePacket(int id, byte[] bytes) {
|
||||
this.id = id;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void writeId(WrappedByteBuf output) {
|
||||
int i = id;
|
||||
while ((i & -128) != 0) {
|
||||
output.writeByte(i & 127 | 128);
|
||||
i >>>= 7;
|
||||
}
|
||||
|
||||
output.writeByte(i);
|
||||
}
|
||||
|
||||
public void writeBytes(WrappedByteBuf output) {
|
||||
output.writeBytes(bytes);
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package com.comphenix.protocol.utility;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
/**
|
||||
* Allows us to stay backwards compatible with older versions of Bukkit.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
public class WrappedScheduler {
|
||||
/**
|
||||
* Represents a backwards compatible Bukkit task.
|
||||
*/
|
||||
public static interface TaskWrapper {
|
||||
/**
|
||||
* Cancel the current task.
|
||||
*/
|
||||
public void cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a given task for a single asynchronous execution.
|
||||
* @param plugin - the owner plugin.
|
||||
* @param runnable - the task to run.
|
||||
* @param firstDelay - the amount of time to wait until executing the task.
|
||||
* @return A cancel token.
|
||||
*/
|
||||
public static TaskWrapper runAsynchronouslyOnce(final Plugin plugin, Runnable runnable, long firstDelay) {
|
||||
return runAsynchronouslyRepeat(plugin, plugin.getServer().getScheduler(), runnable, firstDelay, -1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a given task for multiple asynchronous executions.
|
||||
* @param plugin - the owner plugin.
|
||||
* @param runnable - the task to run.
|
||||
* @param firstDelay - the amount of time to wait until executing the task for the first time.
|
||||
* @param repeatDelay - the amount of time inbetween each execution. If less than zero, the task is only executed once.
|
||||
* @return A cancel token.
|
||||
*/
|
||||
public static TaskWrapper runAsynchronouslyRepeat(final Plugin plugin, Runnable runnable, long firstDelay, long repeatDelay) {
|
||||
return runAsynchronouslyRepeat(plugin, plugin.getServer().getScheduler(), runnable, firstDelay, repeatDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a given task for asynchronous execution.
|
||||
* @param plugin - the owner plugin.
|
||||
* @param scheduler - the current Bukkit scheduler.
|
||||
* @param runnable - the task to run.
|
||||
* @param firstDelay - the amount of time to wait until executing the task for the first time.
|
||||
* @param repeatDelay - the amount of time inbetween each execution. If less than zero, the task is only executed once.
|
||||
* @return A cancel token.
|
||||
*/
|
||||
public static TaskWrapper runAsynchronouslyRepeat(final Plugin plugin, final BukkitScheduler scheduler, Runnable runnable, long firstDelay, long repeatDelay) {
|
||||
try {
|
||||
@SuppressWarnings("deprecation")
|
||||
final int taskID = scheduler.scheduleAsyncRepeatingTask(plugin, runnable, firstDelay, repeatDelay);
|
||||
|
||||
// Return the cancellable object
|
||||
return new TaskWrapper() {
|
||||
@Override
|
||||
public void cancel() {
|
||||
scheduler.cancelTask(taskID);
|
||||
}
|
||||
};
|
||||
|
||||
} catch (NoSuchMethodError e) {
|
||||
return tryUpdatedVersion(plugin, scheduler, runnable, firstDelay, repeatDelay);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to do the same with the updated scheduling method.
|
||||
* @param plugin - the owner plugin.
|
||||
* @param scheduler - the current Bukkit scheduler.
|
||||
* @param runnable - the task to run.
|
||||
* @param firstDelay - the amount of time to wait until executing the task for the first time.
|
||||
* @param repeatDelay - the amount of time inbetween each execution. If less than zero, the task is only executed once.
|
||||
* @return A cancel token.
|
||||
*/
|
||||
private static TaskWrapper tryUpdatedVersion(final Plugin plugin, final BukkitScheduler scheduler, Runnable runnable, long firstDelay, long repeatDelay) {
|
||||
final BukkitTask task = scheduler.runTaskTimerAsynchronously(plugin, runnable, firstDelay, repeatDelay);
|
||||
|
||||
return new TaskWrapper() {
|
||||
@Override
|
||||
public void cancel() {
|
||||
task.cancel();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,924 +0,0 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2012 Kristian S. Stangeland
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||
import com.comphenix.protocol.reflect.FieldUtils;
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
|
||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||
import com.comphenix.protocol.reflect.accessors.ReadOnlyFieldAccessor;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.collection.ConvertedMap;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* Wraps a DataWatcher that is used to transmit arbitrary key-value pairs with a given entity.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
public class WrappedDataWatcher extends AbstractWrapper implements Iterable<WrappedWatchableObject> {
|
||||
/**
|
||||
* Every custom watchable type in the Spigot protocol hack.
|
||||
* @author Kristian
|
||||
*/
|
||||
public enum CustomType {
|
||||
BYTE_SHORT("org.spigotmc.ProtocolData$ByteShort", 0, short.class),
|
||||
DUAL_BYTE("org.spigotmc.ProtocolData$DualByte", 0, byte.class, byte.class),
|
||||
HIDDEN_BYTE("org.spigotmc.ProtocolData$HiddenByte", 0, byte.class),
|
||||
INT_BYTE("org.spigotmc.ProtocolData$IntByte", 2, int.class, byte.class),
|
||||
DUAL_INT("org.spigotmc.ProtocolData$DualInt", 2, int.class, int.class);
|
||||
|
||||
private Class<?> spigotClass;
|
||||
private ConstructorAccessor constructor;
|
||||
private FieldAccessor secondaryValue;
|
||||
private int typeId;
|
||||
|
||||
private CustomType(String className, int typeId, Class<?>... parameters) {
|
||||
try {
|
||||
this.spigotClass = Class.forName(className);
|
||||
this.constructor = Accessors.getConstructorAccessor(spigotClass, parameters);
|
||||
this.secondaryValue = parameters.length > 1 ? Accessors.getFieldAccessor(spigotClass, "value2", true) : null;
|
||||
} catch (ClassNotFoundException e) {
|
||||
// ProtocolLibrary.log(Level.WARNING, "Unable to find " + className);
|
||||
this.spigotClass = null;
|
||||
}
|
||||
|
||||
this.typeId = typeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance of this Spigot type.
|
||||
* @param value - the value. Cannot be NULL.
|
||||
* @return The instance to construct.
|
||||
*/
|
||||
Object newInstance(Object value) {
|
||||
return newInstance(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance of this Spigot type.
|
||||
* <p>
|
||||
* The secondary value may be NULL if this custom type does not contain a secondary value.
|
||||
* @param value - the value.
|
||||
* @param secondary - optional secondary value.
|
||||
* @return
|
||||
*/
|
||||
Object newInstance(Object value, Object secondary) {
|
||||
Preconditions.checkNotNull(value, "value cannot be NULL.");
|
||||
|
||||
if (hasSecondary()) {
|
||||
return constructor.invoke(value, secondary);
|
||||
} else {
|
||||
if (secondary != null) {
|
||||
throw new IllegalArgumentException("Cannot construct " + this + " with a secondary value");
|
||||
}
|
||||
return constructor.invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the secondary value of a given type.
|
||||
* @param instance - the instance.
|
||||
* @param secondary - the secondary value.
|
||||
*/
|
||||
void setSecondary(Object instance, Object secondary) {
|
||||
if (!hasSecondary()) {
|
||||
throw new IllegalArgumentException(this + " does not have a secondary value.");
|
||||
}
|
||||
secondaryValue.set(instance, secondary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the secondary value of a type.
|
||||
* @param instance - the instance.
|
||||
* @return The secondary value.
|
||||
*/
|
||||
Object getSecondary(Object instance) {
|
||||
if (!hasSecondary()) {
|
||||
throw new IllegalArgumentException(this + " does not have a secondary value.");
|
||||
}
|
||||
return secondaryValue.get(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this type has a secondary value.
|
||||
* @return TRUE if it does, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasSecondary() {
|
||||
return secondaryValue != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Underlying Spigot class.
|
||||
* @return The class.
|
||||
*/
|
||||
public Class<?> getSpigotClass() {
|
||||
return spigotClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* The equivalent type ID.
|
||||
* @return The equivalent ID.
|
||||
*/
|
||||
public int getTypeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the custom Spigot type of a value.
|
||||
* @param value - the value.
|
||||
* @return The Spigot type, or NULL if not found.
|
||||
*/
|
||||
public static CustomType fromValue(Object value) {
|
||||
for (CustomType type : CustomType.values()) {
|
||||
if (type.getSpigotClass().isInstance(value)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to assign integer IDs to given types.
|
||||
*/
|
||||
private static Map<Class<?>, Integer> TYPE_MAP;
|
||||
|
||||
/**
|
||||
* Custom types in the bountiful update.
|
||||
*/
|
||||
private static Map<Class<?>, Integer> CUSTOM_MAP;
|
||||
|
||||
// Accessors
|
||||
private static FieldAccessor TYPE_MAP_ACCESSOR;
|
||||
private static FieldAccessor VALUE_MAP_ACCESSOR;
|
||||
|
||||
// Fields
|
||||
private static Field READ_WRITE_LOCK_FIELD;
|
||||
private static Field ENTITY_FIELD;
|
||||
|
||||
// Methods
|
||||
private static Method CREATE_KEY_VALUE_METHOD;
|
||||
private static Method UPDATE_KEY_VALUE_METHOD;
|
||||
private static Method GET_KEY_VALUE_METHOD;
|
||||
|
||||
// Constructors
|
||||
private static Constructor<?> CREATE_DATA_WATCHER_CONSTRUCTOR;
|
||||
|
||||
// Entity methods
|
||||
private volatile static Field ENTITY_DATA_FIELD;
|
||||
|
||||
/**
|
||||
* Whether or not this class has already been initialized.
|
||||
*/
|
||||
private static boolean HAS_INITIALIZED;
|
||||
|
||||
// Lock
|
||||
private ReadWriteLock readWriteLock;
|
||||
|
||||
// Map of watchable objects
|
||||
private Map<Integer, Object> watchableObjects;
|
||||
|
||||
// A map view of all the watchable objects
|
||||
private Map<Integer, WrappedWatchableObject> mapView;
|
||||
|
||||
/**
|
||||
* Initialize a new data watcher.
|
||||
* @throws FieldAccessException If we're unable to wrap a DataWatcher.
|
||||
*/
|
||||
public WrappedDataWatcher() {
|
||||
super(MinecraftReflection.getDataWatcherClass());
|
||||
|
||||
// Just create a new watcher
|
||||
try {
|
||||
if (MinecraftReflection.isUsingNetty()) {
|
||||
setHandle(newEntityHandle(null));
|
||||
} else {
|
||||
setHandle(getHandleType().newInstance());
|
||||
}
|
||||
initialize();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to construct DataWatcher.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a wrapper for a given data watcher.
|
||||
* @param handle - the data watcher to wrap.
|
||||
* @throws FieldAccessException If we're unable to wrap a DataWatcher.
|
||||
*/
|
||||
public WrappedDataWatcher(Object handle) {
|
||||
super(MinecraftReflection.getDataWatcherClass());
|
||||
setHandle(handle);
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new data watcher with the given entity.
|
||||
* <p>
|
||||
* In 1.6.4 and ealier, this will fall back to using {@link #WrappedDataWatcher()}.
|
||||
* @param entity - the entity.
|
||||
* @return The wrapped data watcher.
|
||||
*/
|
||||
public static WrappedDataWatcher newWithEntity(Entity entity) {
|
||||
// Use the old constructor
|
||||
if (!MinecraftReflection.isUsingNetty())
|
||||
return new WrappedDataWatcher();
|
||||
return new WrappedDataWatcher(newEntityHandle(entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new native DataWatcher with the given entity.
|
||||
* <p>
|
||||
* Warning: This is only supported in 1.7.2 and above.
|
||||
* @param entity - the entity, or NULL.
|
||||
* @return The data watcher.
|
||||
*/
|
||||
private static Object newEntityHandle(Entity entity) {
|
||||
Class<?> dataWatcher = MinecraftReflection.getDataWatcherClass();
|
||||
|
||||
try {
|
||||
if (CREATE_DATA_WATCHER_CONSTRUCTOR == null)
|
||||
CREATE_DATA_WATCHER_CONSTRUCTOR = dataWatcher.getConstructor(MinecraftReflection.getEntityClass());
|
||||
|
||||
return CREATE_DATA_WATCHER_CONSTRUCTOR.newInstance(
|
||||
BukkitUnwrapper.getInstance().unwrapItem(entity)
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot construct data watcher.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new data watcher for a list of watchable objects.
|
||||
* <p>
|
||||
* Note that the watchable objects are not cloned, and will be modified in place. Use "deepClone" if
|
||||
* that is not desirable.
|
||||
* <p>
|
||||
* The {@link #removeObject(int)} method will not modify the given list, however.
|
||||
*
|
||||
* @param watchableObjects - list of watchable objects that will be copied.
|
||||
* @throws FieldAccessException Unable to read watchable objects.
|
||||
*/
|
||||
public WrappedDataWatcher(List<WrappedWatchableObject> watchableObjects) throws FieldAccessException {
|
||||
this();
|
||||
|
||||
Lock writeLock = getReadWriteLock().writeLock();
|
||||
Map<Integer, Object> map = getWatchableObjectMap();
|
||||
|
||||
writeLock.lock();
|
||||
|
||||
try {
|
||||
// Add the watchable objects by reference
|
||||
for (WrappedWatchableObject watched : watchableObjects) {
|
||||
map.put(watched.getIndex(), watched.handle);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the ID of a given type, if it's allowed to be watched.
|
||||
* @param clazz - Class to check for.
|
||||
* @return The ID, or NULL if it cannot be watched.
|
||||
* @throws FieldAccessException If we cannot initialize the reflection machinery.
|
||||
*/
|
||||
public static Integer getTypeID(Class<?> clazz) throws FieldAccessException {
|
||||
initialize();
|
||||
Integer result = TYPE_MAP.get(WrappedWatchableObject.getUnwrappedType(clazz));
|
||||
|
||||
if (result == null) {
|
||||
result = CUSTOM_MAP.get(clazz);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the type of a given ID, if it's allowed to be watched.
|
||||
* @param id - id to get type for
|
||||
* @return The type using a given ID, or NULL if it cannot be watched.
|
||||
* @throws FieldAccessException If we cannot initialize the reflection machinery.
|
||||
*/
|
||||
public static Class<?> getTypeClass(int id) throws FieldAccessException {
|
||||
initialize();
|
||||
|
||||
for (Map.Entry<Class<?>, Integer> entry : TYPE_MAP.entrySet()) {
|
||||
if (Objects.equal(entry.getValue(), id)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown class type
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a watched byte.
|
||||
* @param index - index of the watched byte.
|
||||
* @return The watched byte, or NULL if this value doesn't exist.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public Byte getByte(int index) throws FieldAccessException {
|
||||
return (Byte) getObject(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a watched short.
|
||||
* @param index - index of the watched short.
|
||||
* @return The watched short, or NULL if this value doesn't exist.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public Short getShort(int index) throws FieldAccessException {
|
||||
return (Short) getObject(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a watched integer.
|
||||
* @param index - index of the watched integer.
|
||||
* @return The watched integer, or NULL if this value doesn't exist.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public Integer getInteger(int index) throws FieldAccessException {
|
||||
return (Integer) getObject(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a watched float.
|
||||
* @param index - index of the watched float.
|
||||
* @return The watched float, or NULL if this value doesn't exist.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public Float getFloat(int index) throws FieldAccessException {
|
||||
return (Float) getObject(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a watched string.
|
||||
* @param index - index of the watched string.
|
||||
* @return The watched string, or NULL if this value doesn't exist.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public String getString(int index) throws FieldAccessException {
|
||||
return (String) getObject(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a watched string.
|
||||
* @param index - index of the watched string.
|
||||
* @return The watched string, or NULL if this value doesn't exist.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public ItemStack getItemStack(int index) throws FieldAccessException {
|
||||
return (ItemStack) getObject(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a watched string.
|
||||
* @param index - index of the watched string.
|
||||
* @return The watched string, or NULL if this value doesn't exist.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public WrappedChunkCoordinate getChunkCoordinate(int index) throws FieldAccessException {
|
||||
return (WrappedChunkCoordinate) getObject(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a watchable object by index.
|
||||
* @param index - index of the object to retrieve.
|
||||
* @return The watched object.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public Object getObject(int index) throws FieldAccessException {
|
||||
Object watchable = getWatchedObject(index);
|
||||
|
||||
if (watchable != null) {
|
||||
return new WrappedWatchableObject(watchable).getValue();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve every watchable object in this watcher.
|
||||
* @return Every watchable object.
|
||||
* @throws FieldAccessException If reflection failed.
|
||||
*/
|
||||
public List<WrappedWatchableObject> getWatchableObjects() throws FieldAccessException {
|
||||
Lock readLock = getReadWriteLock().readLock();
|
||||
readLock.lock();
|
||||
|
||||
try {
|
||||
List<WrappedWatchableObject> result = new ArrayList<WrappedWatchableObject>();
|
||||
|
||||
// Add each watchable object to the list
|
||||
for (Object watchable : getWatchableObjectMap().values()) {
|
||||
if (watchable != null) {
|
||||
result.add(new WrappedWatchableObject(watchable));
|
||||
} else {
|
||||
result.add(null);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Quick checks
|
||||
if (obj == this)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
if (obj instanceof WrappedDataWatcher) {
|
||||
WrappedDataWatcher other = (WrappedDataWatcher) obj;
|
||||
Iterator<WrappedWatchableObject> first = iterator(), second = other.iterator();
|
||||
|
||||
// Make sure they're the same size
|
||||
if (size() != other.size())
|
||||
return false;
|
||||
|
||||
for (; first.hasNext() && second.hasNext(); ) {
|
||||
// See if the two elements are equal
|
||||
if (!first.next().equals(second.next()))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getWatchableObjects().hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a copy of every index associated with a watched object.
|
||||
* @return Every watched object index.
|
||||
* @throws FieldAccessException If we're unable to read the underlying object.
|
||||
*/
|
||||
public Set<Integer> indexSet() throws FieldAccessException {
|
||||
Lock readLock = getReadWriteLock().readLock();
|
||||
readLock.lock();
|
||||
|
||||
try {
|
||||
return new HashSet<Integer>(getWatchableObjectMap().keySet());
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the content of the current DataWatcher.
|
||||
* @return A cloned data watcher.
|
||||
*/
|
||||
public WrappedDataWatcher deepClone() {
|
||||
WrappedDataWatcher clone = new WrappedDataWatcher();
|
||||
|
||||
// Make a new copy instead
|
||||
for (WrappedWatchableObject watchable : this) {
|
||||
clone.setObject(watchable.getIndex(), watchable.getClonedValue());
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the number of watched objects.
|
||||
* @return Watched object count.
|
||||
* @throws FieldAccessException If we're unable to read the underlying object.
|
||||
*/
|
||||
public int size() throws FieldAccessException {
|
||||
Lock readLock = getReadWriteLock().readLock();
|
||||
readLock.lock();
|
||||
|
||||
try {
|
||||
return getWatchableObjectMap().size();
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a given object from the underlying DataWatcher.
|
||||
* @param index - index of the object to remove.
|
||||
* @return The watchable object that was removed, or NULL If none could be found.
|
||||
*/
|
||||
public WrappedWatchableObject removeObject(int index) {
|
||||
Lock writeLock = getReadWriteLock().writeLock();
|
||||
writeLock.lock();
|
||||
|
||||
try {
|
||||
Object removed = getWatchableObjectMap().remove(index);
|
||||
return removed != null ? new WrappedWatchableObject(removed) : null;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a watched byte.
|
||||
* @param index - index of the watched byte.
|
||||
* @param newValue - the new watched value.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public void setObject(int index, Object newValue) throws FieldAccessException {
|
||||
setObject(index, newValue, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a watched byte.
|
||||
* @param index - index of the watched byte.
|
||||
* @param newValue - the new watched value.
|
||||
* @param update - whether or not to refresh every listening client.
|
||||
* @throws FieldAccessException Cannot read underlying field.
|
||||
*/
|
||||
public void setObject(int index, Object newValue, boolean update) throws FieldAccessException {
|
||||
// Aquire write lock
|
||||
Lock writeLock = getReadWriteLock().writeLock();
|
||||
writeLock.lock();
|
||||
|
||||
try {
|
||||
Object watchable = getWatchedObject(index);
|
||||
|
||||
if (watchable != null) {
|
||||
new WrappedWatchableObject(watchable).setValue(newValue, update);
|
||||
} else {
|
||||
CREATE_KEY_VALUE_METHOD.invoke(handle, index, WrappedWatchableObject.getUnwrapped(newValue));
|
||||
}
|
||||
|
||||
// Handle invoking the method
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new FieldAccessException("Cannot convert arguments.", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new FieldAccessException("Illegal access.", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new FieldAccessException("Checked exception in Minecraft.", e);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a watched byte with an optional secondary value.
|
||||
* @param index - index of the watched byte.
|
||||
* @param newValue - the new watched value.
|
||||
* @param secondary - optional secondary value.
|
||||
* @param update - whether or not to refresh every listening client.
|
||||
* @param type - custom type.
|
||||
* @throws FieldAccessException If we cannot read the underlying field.
|
||||
*/
|
||||
public void setObject(int index, Object newValue, Object secondary, boolean update, CustomType type) throws FieldAccessException {
|
||||
Object created = type.newInstance(newValue, secondary);
|
||||
|
||||
// Now update the watcher
|
||||
setObject(index, created, update);
|
||||
}
|
||||
|
||||
private Object getWatchedObject(int index) throws FieldAccessException {
|
||||
// We use the get-method first and foremost
|
||||
if (GET_KEY_VALUE_METHOD != null) {
|
||||
try {
|
||||
return GET_KEY_VALUE_METHOD.invoke(handle, index);
|
||||
} catch (Exception e) {
|
||||
throw new FieldAccessException("Cannot invoke get key method for index " + index, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
getReadWriteLock().readLock().lock();
|
||||
return getWatchableObjectMap().get(index);
|
||||
|
||||
} finally {
|
||||
getReadWriteLock().readLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current read write lock.
|
||||
* @return Current read write lock.
|
||||
* @throws FieldAccessException If we're unable to read the underlying field.
|
||||
*/
|
||||
protected ReadWriteLock getReadWriteLock() throws FieldAccessException {
|
||||
try {
|
||||
// Cache the read write lock
|
||||
if (readWriteLock != null)
|
||||
return readWriteLock;
|
||||
else if (READ_WRITE_LOCK_FIELD != null)
|
||||
return readWriteLock = (ReadWriteLock) FieldUtils.readField(READ_WRITE_LOCK_FIELD, handle, true);
|
||||
else
|
||||
return readWriteLock = new ReentrantReadWriteLock();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new FieldAccessException("Unable to read lock field.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the underlying map of key values that stores watchable objects.
|
||||
* @return A map of watchable objects.
|
||||
* @throws FieldAccessException If we don't have permission to perform reflection.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map<Integer, Object> getWatchableObjectMap() throws FieldAccessException {
|
||||
if (watchableObjects == null)
|
||||
watchableObjects = (Map<Integer, Object>) VALUE_MAP_ACCESSOR.get(handle);
|
||||
return watchableObjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the data watcher associated with an entity.
|
||||
* @param entity - the entity to read from.
|
||||
* @return Associated data watcher.
|
||||
* @throws FieldAccessException Reflection failed.
|
||||
*/
|
||||
public static WrappedDataWatcher getEntityWatcher(Entity entity) throws FieldAccessException {
|
||||
if (ENTITY_DATA_FIELD == null)
|
||||
ENTITY_DATA_FIELD = FuzzyReflection.fromClass(MinecraftReflection.getEntityClass(), true).
|
||||
getFieldByType("datawatcher", MinecraftReflection.getDataWatcherClass());
|
||||
|
||||
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
|
||||
|
||||
try {
|
||||
Object nsmWatcher = FieldUtils.readField(ENTITY_DATA_FIELD, unwrapper.unwrapItem(entity), true);
|
||||
|
||||
if (nsmWatcher != null)
|
||||
return new WrappedDataWatcher(nsmWatcher);
|
||||
else
|
||||
return null;
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new FieldAccessException("Cannot access DataWatcher field.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a data watcher is first used.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void initialize() throws FieldAccessException {
|
||||
// This method should only be run once, even if an exception is thrown
|
||||
if (!HAS_INITIALIZED)
|
||||
HAS_INITIALIZED = true;
|
||||
else
|
||||
return;
|
||||
|
||||
FuzzyReflection fuzzy = FuzzyReflection.fromClass(MinecraftReflection.getDataWatcherClass(), true);
|
||||
|
||||
for (Field lookup : fuzzy.getFieldListByType(Map.class)) {
|
||||
if (Modifier.isStatic(lookup.getModifiers())) {
|
||||
// This must be the type map
|
||||
TYPE_MAP_ACCESSOR = Accessors.getFieldAccessor(lookup, true);
|
||||
} else {
|
||||
// If not, then we're probably dealing with the value map
|
||||
VALUE_MAP_ACCESSOR = Accessors.getFieldAccessor(lookup, true);
|
||||
}
|
||||
}
|
||||
// Spigot workaround (not necessary
|
||||
initializeSpigot(fuzzy);
|
||||
|
||||
// Any custom types
|
||||
CUSTOM_MAP = initializeCustom();
|
||||
|
||||
// Initialize static type type
|
||||
TYPE_MAP = (Map<Class<?>, Integer>) TYPE_MAP_ACCESSOR.get(null);
|
||||
|
||||
try {
|
||||
READ_WRITE_LOCK_FIELD = fuzzy.getFieldByType("readWriteLock", ReadWriteLock.class);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// It's not a big deal
|
||||
}
|
||||
|
||||
// Check for the entity field as well
|
||||
if (MinecraftReflection.isUsingNetty()) {
|
||||
ENTITY_FIELD = fuzzy.getFieldByType("entity", MinecraftReflection.getEntityClass());
|
||||
ENTITY_FIELD.setAccessible(true);
|
||||
}
|
||||
initializeMethods(fuzzy);
|
||||
}
|
||||
|
||||
// For Spigot's bountiful update patch
|
||||
private static Map<Class<?>, Integer> initializeCustom() {
|
||||
Map<Class<?>, Integer> map = Maps.newHashMap();
|
||||
|
||||
for (CustomType type : CustomType.values()) {
|
||||
if (type.getSpigotClass() != null) {
|
||||
map.put(type.getSpigotClass(), type.getTypeId());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// TODO: Remove, as this was fixed in build #1189 of Spigot
|
||||
private static void initializeSpigot(FuzzyReflection fuzzy) {
|
||||
// See if the workaround is needed
|
||||
if (TYPE_MAP_ACCESSOR != null && VALUE_MAP_ACCESSOR != null)
|
||||
return;
|
||||
|
||||
for (Field lookup : fuzzy.getFields()) {
|
||||
final Class<?> type = lookup.getType();
|
||||
|
||||
if (TroveWrapper.isTroveClass(type)) {
|
||||
// Create a wrapper accessor
|
||||
final ReadOnlyFieldAccessor accessor = TroveWrapper.wrapMapField(
|
||||
Accessors.getFieldAccessor(lookup, true), new Function<Integer, Integer>() {
|
||||
@Override
|
||||
public Integer apply(@Nullable Integer value) {
|
||||
// Do not use zero for no entry value
|
||||
if (value == 0)
|
||||
return -1;
|
||||
return value;
|
||||
}
|
||||
});
|
||||
|
||||
if (Modifier.isStatic(lookup.getModifiers())) {
|
||||
TYPE_MAP_ACCESSOR = accessor;
|
||||
} else {
|
||||
VALUE_MAP_ACCESSOR = accessor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TYPE_MAP_ACCESSOR == null)
|
||||
throw new IllegalArgumentException("Unable to find static type map.");
|
||||
if (VALUE_MAP_ACCESSOR == null)
|
||||
throw new IllegalArgumentException("Unable to find static value map.");
|
||||
}
|
||||
|
||||
private static void initializeMethods(FuzzyReflection fuzzy) {
|
||||
List<Method> candidates = fuzzy.getMethodListByParameters(Void.TYPE,
|
||||
new Class<?>[] { int.class, Object.class});
|
||||
|
||||
// Load the get-method
|
||||
try {
|
||||
GET_KEY_VALUE_METHOD = fuzzy.getMethodByParameters(
|
||||
"getWatchableObject", MinecraftReflection.getWatchableObjectClass(), new Class[] { int.class });
|
||||
GET_KEY_VALUE_METHOD.setAccessible(true);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Use the fallback method
|
||||
}
|
||||
|
||||
for (Method method : candidates) {
|
||||
if (!method.getName().startsWith("watch")) {
|
||||
CREATE_KEY_VALUE_METHOD = method;
|
||||
} else {
|
||||
UPDATE_KEY_VALUE_METHOD = method;
|
||||
}
|
||||
}
|
||||
|
||||
// Did we succeed?
|
||||
if (UPDATE_KEY_VALUE_METHOD == null || CREATE_KEY_VALUE_METHOD == null) {
|
||||
// Go by index instead
|
||||
if (candidates.size() > 1) {
|
||||
CREATE_KEY_VALUE_METHOD = candidates.get(0);
|
||||
UPDATE_KEY_VALUE_METHOD = candidates.get(1);
|
||||
} else {
|
||||
throw new IllegalStateException("Unable to find create and update watchable object. Update ProtocolLib.");
|
||||
}
|
||||
|
||||
// Be a little scientist - see if this in fact IS the right way around
|
||||
try {
|
||||
WrappedDataWatcher watcher = new WrappedDataWatcher();
|
||||
watcher.setObject(0, 0);
|
||||
watcher.setObject(0, 1);
|
||||
|
||||
if (watcher.getInteger(0) != 1) {
|
||||
throw new IllegalStateException("This cannot be!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Nope
|
||||
UPDATE_KEY_VALUE_METHOD = candidates.get(0);
|
||||
CREATE_KEY_VALUE_METHOD = candidates.get(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<WrappedWatchableObject> iterator() {
|
||||
// We'll wrap the iterator instead of creating a new list every time
|
||||
return Iterators.transform(getWatchableObjectMap().values().iterator(),
|
||||
new Function<Object, WrappedWatchableObject>() {
|
||||
|
||||
@Override
|
||||
public WrappedWatchableObject apply(@Nullable Object item) {
|
||||
if (item != null)
|
||||
return new WrappedWatchableObject(item);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a view of this DataWatcher as a map.
|
||||
* <p>
|
||||
* Any changes to the map will be reflected in this DataWatcher, and vice versa.
|
||||
* @return A view of the data watcher as a map.
|
||||
*/
|
||||
public Map<Integer, WrappedWatchableObject> asMap() {
|
||||
// Construct corresponding map
|
||||
if (mapView == null) {
|
||||
mapView = new ConvertedMap<Integer, Object, WrappedWatchableObject>(getWatchableObjectMap()) {
|
||||
@Override
|
||||
protected Object toInner(WrappedWatchableObject outer) {
|
||||
if (outer == null)
|
||||
return null;
|
||||
return outer.getHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WrappedWatchableObject toOuter(Object inner) {
|
||||
if (inner == null)
|
||||
return null;
|
||||
return new WrappedWatchableObject(inner);
|
||||
}
|
||||
};
|
||||
}
|
||||
return mapView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return asMap().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the entity associated with this data watcher.
|
||||
* <p>
|
||||
* <b>Warning:</b> This is only supported on 1.7.2 and above.
|
||||
* @return The entity, or NULL.
|
||||
*/
|
||||
public Entity getEntity() {
|
||||
if (!MinecraftReflection.isUsingNetty())
|
||||
throw new IllegalStateException("This method is only supported on 1.7.2 and above.");
|
||||
|
||||
try {
|
||||
return (Entity) MinecraftReflection.getBukkitEntity(ENTITY_FIELD.get(handle));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to retrieve entity.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the entity associated with this data watcher.
|
||||
* <p>
|
||||
* <b>Warning:</b> This is only supported on 1.7.2 and above.
|
||||
* @param entity - the new entity.
|
||||
*/
|
||||
public void setEntity(Entity entity) {
|
||||
if (!MinecraftReflection.isUsingNetty())
|
||||
throw new IllegalStateException("This method is only supported on 1.7.2 and above.");
|
||||
|
||||
try {
|
||||
ENTITY_FIELD.set(handle, BukkitUnwrapper.getInstance().unwrapItem(entity));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to set entity.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
-467
@@ -1,467 +0,0 @@
|
||||
/*
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2012 Kristian S. Stangeland
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Represents a watchable object.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
public class WrappedWatchableObject extends AbstractWrapper {
|
||||
// Whether or not the reflection machinery has been initialized
|
||||
private static boolean hasInitialized;
|
||||
|
||||
// The field containing the value itself
|
||||
private static StructureModifier<Object> baseModifier;
|
||||
|
||||
// Used to create new watchable objects
|
||||
private static Constructor<?> watchableConstructor;
|
||||
|
||||
// The watchable object class type
|
||||
private static Class<?> watchableObjectClass;
|
||||
|
||||
protected StructureModifier<Object> modifier;
|
||||
|
||||
// Type of the stored value
|
||||
private Class<?> typeClass;
|
||||
|
||||
/**
|
||||
* Wrap a given raw Minecraft watchable object.
|
||||
* @param handle - the raw watchable object to wrap.
|
||||
*/
|
||||
public WrappedWatchableObject(Object handle) {
|
||||
super(MinecraftReflection.getWatchableObjectClass());
|
||||
load(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a watchable object from an index and a given value.
|
||||
* @param index - the index.
|
||||
* @param value - non-null value of specific types.
|
||||
*/
|
||||
public WrappedWatchableObject(int index, Object value) {
|
||||
super(MinecraftReflection.getWatchableObjectClass());
|
||||
|
||||
if (value == null)
|
||||
throw new IllegalArgumentException("Value cannot be NULL.");
|
||||
|
||||
// Get the correct type ID
|
||||
Integer typeID = WrappedDataWatcher.getTypeID(value.getClass());
|
||||
|
||||
if (typeID != null) {
|
||||
if (watchableConstructor == null) {
|
||||
try {
|
||||
watchableConstructor = MinecraftReflection.getWatchableObjectClass().
|
||||
getConstructor(int.class, int.class, Object.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot get the WatchableObject(int, int, Object) constructor.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the object
|
||||
try {
|
||||
load(watchableConstructor.newInstance(typeID, index, getUnwrapped(value)));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot construct underlying WatchableObject.", e);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Cannot watch the type " + value.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Construct a custom watchable object from an index, value and custom type.
|
||||
// * @param index - the index.
|
||||
// * @param primary - non-null value of specific types.
|
||||
// * @param secondary - optional secondary value, if the type can store it.
|
||||
// * @param type - the custom Spigot type.
|
||||
// */
|
||||
// public WrappedWatchableObject(int index, Object value, Object secondary, CustomType type) {
|
||||
// this(index, type.newInstance(value, secondary));
|
||||
// }
|
||||
|
||||
// Wrap a NMS object
|
||||
private void load(Object handle) {
|
||||
initialize();
|
||||
this.handle = handle;
|
||||
this.modifier = baseModifier.withTarget(handle);
|
||||
|
||||
// Make sure the type is correct
|
||||
if (!watchableObjectClass.isAssignableFrom(handle.getClass())) {
|
||||
throw new ClassCastException("Cannot cast the class " + handle.getClass().getName() +
|
||||
" to " + watchableObjectClass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize reflection machinery.
|
||||
*/
|
||||
private static void initialize() {
|
||||
if (!hasInitialized) {
|
||||
hasInitialized = true;
|
||||
watchableObjectClass = MinecraftReflection.getWatchableObjectClass();
|
||||
baseModifier = new StructureModifier<Object>(watchableObjectClass, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Retrieve the custom type of this object.
|
||||
// * @return The custom type, or NULL if not applicable.
|
||||
// */
|
||||
// public CustomType getCustomType() {
|
||||
// return CustomType.fromValue(getValue());
|
||||
// }
|
||||
|
||||
/**
|
||||
* Retrieve the correct super type of the current value.
|
||||
* @return Super type.
|
||||
* @throws FieldAccessException Unable to read values.
|
||||
*/
|
||||
public Class<?> getType() throws FieldAccessException {
|
||||
return getWrappedType(getTypeRaw());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the correct super type of the current value, given the raw NMS object.
|
||||
* @return Super type.
|
||||
* @throws FieldAccessException Unable to read values.
|
||||
*/
|
||||
private Class<?> getTypeRaw() throws FieldAccessException {
|
||||
if (typeClass == null) {
|
||||
typeClass = WrappedDataWatcher.getTypeClass(getTypeID());
|
||||
|
||||
if (typeClass == null) {
|
||||
throw new IllegalStateException("Unrecognized data type: " + getTypeID());
|
||||
}
|
||||
}
|
||||
|
||||
return typeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the index of this watchable object. This is used to identify a value.
|
||||
* @return Object index.
|
||||
* @throws FieldAccessException Reflection failed.
|
||||
*/
|
||||
public int getIndex() throws FieldAccessException {
|
||||
return modifier.<Integer>withType(int.class).read(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the the index of this watchable object.
|
||||
* @param index - the new object index.
|
||||
* @throws FieldAccessException Reflection failed.
|
||||
*/
|
||||
public void setIndex(int index) throws FieldAccessException {
|
||||
modifier.<Integer>withType(int.class).write(1, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the type ID of a watchable object.
|
||||
* <table border=1>
|
||||
* <caption>Type to Value</caption>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <th>Type ID</th>
|
||||
* <th>Data Type</th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>0</td>
|
||||
* <td>Byte</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>1</td>
|
||||
* <td>Short</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>2</td>
|
||||
* <td>Int</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>3</td>
|
||||
* <td>Float</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>4</td>
|
||||
* <td>{@link String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>5</td>
|
||||
* <td>{@link org.bukkit.inventory.ItemStack ItemStack}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>6<sup>*</sup></td>
|
||||
* <td>{@link com.comphenix.protocol.wrappers.ChunkPosition ChunkPosition}</td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @return Type ID that identifies the type of the value.
|
||||
* @throws FieldAccessException Reflection failed.
|
||||
*/
|
||||
public int getTypeID() throws FieldAccessException {
|
||||
return modifier.<Integer>withType(int.class).read(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type ID of a watchable object.
|
||||
* @param id - the new ID.
|
||||
* @throws FieldAccessException Reflection failed.
|
||||
* @see #getTypeID()
|
||||
*/
|
||||
public void setTypeID(int id) throws FieldAccessException {
|
||||
modifier.<Integer>withType(int.class).write(0, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the value field.
|
||||
* @param newValue - new value.
|
||||
* @throws FieldAccessException Unable to use reflection.
|
||||
*/
|
||||
public void setValue(Object newValue) throws FieldAccessException {
|
||||
setValue(newValue, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the value field.
|
||||
* @param newValue - new value.
|
||||
* @param updateClient - whether or not to update listening clients.
|
||||
* @throws FieldAccessException Unable to use reflection.
|
||||
*/
|
||||
public void setValue(Object newValue, boolean updateClient) throws FieldAccessException {
|
||||
// Verify a few quick things
|
||||
if (newValue == null)
|
||||
throw new IllegalArgumentException("Cannot watch a NULL value.");
|
||||
if (!getType().isAssignableFrom(newValue.getClass()))
|
||||
throw new IllegalArgumentException("Object " + newValue + " must be of type " + getType().getName());
|
||||
|
||||
// See if we should update the client to
|
||||
if (updateClient)
|
||||
setDirtyState(true);
|
||||
|
||||
// Use the modifier to set the value
|
||||
modifier.withType(Object.class).write(0, getUnwrapped(newValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the underlying value field.
|
||||
* @return The underlying value.
|
||||
*/
|
||||
private Object getNMSValue() {
|
||||
return modifier.withType(Object.class).read(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value field.
|
||||
* @return The watched value.
|
||||
* @throws FieldAccessException Unable to use reflection.
|
||||
*/
|
||||
public Object getValue() throws FieldAccessException {
|
||||
return getWrapped(modifier.withType(Object.class).read(0));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Retrieve the secondary value associated with this watchable object.
|
||||
// * <p>
|
||||
// * This is only applicable for certain {@link CustomType}.
|
||||
// * @return The secondary value, or NULL if not found.
|
||||
// */
|
||||
// public Object getSecondaryValue() {
|
||||
// CustomType type = getCustomType();
|
||||
// return type != null ? type.getSecondary(getValue()) : null;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Set the secondary value.
|
||||
// * @param secondary - the secondary value.
|
||||
// * @throws IllegalStateException If this watchable object does not have a secondary value.
|
||||
// */
|
||||
// public void setSecondaryValue(Object secondary) {
|
||||
// CustomType type = getCustomType();
|
||||
//
|
||||
// if (type == null) {
|
||||
// throw new IllegalStateException(this + " does not have a custom type.");
|
||||
// }
|
||||
// type.setSecondary(getValue(), secondary);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Set whether or not the value must be synchronized with the client.
|
||||
* @param dirty - TRUE if the value should be synchronized, FALSE otherwise.
|
||||
* @throws FieldAccessException Unable to use reflection.
|
||||
*/
|
||||
public void setDirtyState(boolean dirty) throws FieldAccessException {
|
||||
modifier.<Boolean>withType(boolean.class).write(0, dirty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve whether or not the value must be synchronized with the client.
|
||||
* @return TRUE if the value should be synchronized, FALSE otherwise.
|
||||
* @throws FieldAccessException Unable to use reflection.
|
||||
*/
|
||||
public boolean getDirtyState() throws FieldAccessException {
|
||||
return modifier.<Boolean>withType(boolean.class).read(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the wrapped object value, if needed.
|
||||
* @param value - the raw NMS object to wrap.
|
||||
* @return The wrapped object.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
static Object getWrapped(Object value) {
|
||||
// Handle the special cases
|
||||
if (MinecraftReflection.isItemStack(value)) {
|
||||
return BukkitConverters.getItemStackConverter().getSpecific(value);
|
||||
} else if (MinecraftReflection.isChunkCoordinates(value)) {
|
||||
return new WrappedChunkCoordinate((Comparable) value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the wrapped type, if needed.
|
||||
* @param wrapped - the wrapped class type.
|
||||
* @return The wrapped class type.
|
||||
*/
|
||||
static Class<?> getWrappedType(Class<?> unwrapped) {
|
||||
if (unwrapped.equals(MinecraftReflection.getChunkPositionClass()))
|
||||
return ChunkPosition.class;
|
||||
else if (unwrapped.equals(MinecraftReflection.getBlockPositionClass()))
|
||||
return BlockPosition.class;
|
||||
else if (unwrapped.equals(MinecraftReflection.getChunkCoordinatesClass()))
|
||||
return WrappedChunkCoordinate.class;
|
||||
else if (unwrapped.equals(MinecraftReflection.getItemStackClass()))
|
||||
return ItemStack.class;
|
||||
else
|
||||
return unwrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the raw NMS value.
|
||||
* @param wrapped - the wrapped position.
|
||||
* @return The raw NMS object.
|
||||
*/
|
||||
static Object getUnwrapped(Object wrapped) {
|
||||
// Convert special cases
|
||||
if (wrapped instanceof ChunkPosition)
|
||||
return ChunkPosition.getConverter().getGeneric(MinecraftReflection.getChunkPositionClass(), (ChunkPosition) wrapped);
|
||||
else if (wrapped instanceof BlockPosition)
|
||||
return BlockPosition.getConverter().getGeneric(MinecraftReflection.getBlockPositionClass(), (BlockPosition) wrapped);
|
||||
else if (wrapped instanceof WrappedChunkCoordinate)
|
||||
return ((WrappedChunkCoordinate) wrapped).getHandle();
|
||||
else if (wrapped instanceof ItemStack)
|
||||
return BukkitConverters.getItemStackConverter().getGeneric(MinecraftReflection.getItemStackClass(), (ItemStack) wrapped);
|
||||
else
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the unwrapped type, if needed.
|
||||
* @param wrapped - the unwrapped class type.
|
||||
* @return The unwrapped class type.
|
||||
*/
|
||||
static Class<?> getUnwrappedType(Class<?> wrapped) {
|
||||
if (wrapped.equals(ChunkPosition.class))
|
||||
return MinecraftReflection.getChunkPositionClass();
|
||||
else if (wrapped.equals(BlockPosition.class))
|
||||
return MinecraftReflection.getBlockPositionClass();
|
||||
else if (wrapped.equals(WrappedChunkCoordinate.class))
|
||||
return MinecraftReflection.getChunkCoordinatesClass();
|
||||
else if (ItemStack.class.isAssignableFrom(wrapped))
|
||||
return MinecraftReflection.getItemStackClass();
|
||||
else
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the current wrapped watchable object, along with any contained objects.
|
||||
* @return A deep clone of the current watchable object.
|
||||
* @throws FieldAccessException If we're unable to use reflection.
|
||||
*/
|
||||
public WrappedWatchableObject deepClone() throws FieldAccessException {
|
||||
WrappedWatchableObject clone = new WrappedWatchableObject(
|
||||
DefaultInstances.DEFAULT.getDefault(MinecraftReflection.getWatchableObjectClass()));
|
||||
|
||||
clone.setDirtyState(getDirtyState());
|
||||
clone.setIndex(getIndex());
|
||||
clone.setTypeID(getTypeID());
|
||||
clone.setValue(getClonedValue(), false);
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Helper
|
||||
Object getClonedValue() throws FieldAccessException {
|
||||
Object value = getNMSValue();
|
||||
|
||||
// Only a limited set of references types are supported
|
||||
if (MinecraftReflection.isBlockPosition(value)) {
|
||||
EquivalentConverter<BlockPosition> converter = BlockPosition.getConverter();
|
||||
return converter.getGeneric(MinecraftReflection.getBlockPositionClass(), converter.getSpecific(value));
|
||||
} else if (MinecraftReflection.isChunkPosition(value)) {
|
||||
EquivalentConverter<ChunkPosition> converter = ChunkPosition.getConverter();
|
||||
return converter.getGeneric(MinecraftReflection.getChunkPositionClass(), converter.getSpecific(value));
|
||||
} else if (MinecraftReflection.isItemStack(value)) {
|
||||
return MinecraftReflection.getMinecraftItemStack(MinecraftReflection.getBukkitItemStack(value).clone());
|
||||
} else {
|
||||
// A string or primitive wrapper, which are all immutable.
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Quick checks
|
||||
if (obj == this)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
if (obj instanceof WrappedWatchableObject) {
|
||||
WrappedWatchableObject other = (WrappedWatchableObject) obj;
|
||||
|
||||
return Objects.equal(getIndex(), other.getIndex()) &&
|
||||
Objects.equal(getTypeID(), other.getTypeID()) &&
|
||||
Objects.equal(getValue(), other.getValue());
|
||||
}
|
||||
|
||||
// No, this is not equivalent
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(getIndex(), getTypeID(), getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%s: %s (%s)]", getIndex(), getValue(), getType().getSimpleName());
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.comphenix.protocol.PacketType.Protocol;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.compat.netty.independent.NettyProtocolRegistry;
|
||||
import com.comphenix.protocol.injector.netty.ProtocolRegistry;
|
||||
|
||||
public class PacketTypeTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeReflection() {
|
||||
BukkitInitialization.initializePackage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCurrent() {
|
||||
assertEquals(PacketType.Play.Client.STEER_VEHICLE, PacketType.findCurrent(Protocol.PLAY, Sender.CLIENT, "SteerVehicle"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureAllExist() {
|
||||
ProtocolRegistry registry = new NettyProtocolRegistry();
|
||||
Map<PacketType, Class<?>> lookup = registry.getPacketTypeLookup();
|
||||
for (Entry<PacketType, Class<?>> entry : lookup.entrySet()) {
|
||||
PacketType type = entry.getKey();
|
||||
Class<?> clazz = entry.getValue();
|
||||
|
||||
assertFalse("Packet " + clazz + " does not have a corresponding PacketType!", type.isDynamic());
|
||||
}
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
package com.comphenix.protocol.reflect.cloning;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
|
||||
public class AggregateClonerTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeBukkit() {
|
||||
BukkitInitialization.initializePackage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrays() {
|
||||
List<Integer> input = Arrays.asList(1, 2, 3);
|
||||
assertEquals(input, AggregateCloner.DEFAULT.clone(input));
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,8 @@ Currently maintained by dmulloy2 on behalf of [Spigot](http://www.spigotmc.org/)
|
||||
### Resources
|
||||
|
||||
* [Resource Page](http://www.spigotmc.org/resources/protocollib.1997/)
|
||||
* [Downloads](http://ci.shadowvolt.com/job/ProtocolLib)
|
||||
* [JavaDoc](http://ci.shadowvolt.com/job/ProtocolLib/javadoc)
|
||||
* [Dev Builds](http://ci.dmulloy2.net/job/ProtocolLib)
|
||||
* [JavaDoc](http://ci.dmulloy2.net/job/ProtocolLib/javadoc)
|
||||
|
||||
### Compilation
|
||||
|
||||
@@ -47,13 +47,13 @@ You can also add ProtocolLib as a Maven dependency:
|
||||
<url>http://repo.dmulloy2.net/content/groups/public/</url>
|
||||
</repository>
|
||||
...
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>3.6.4</version>
|
||||
<version>3.6.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
````
|
||||
@@ -131,6 +131,7 @@ you don't have to create an ArrayList with this version:
|
||||
|
||||
````java
|
||||
|
||||
PacketContainer fakeExplosion = new PacketContainer(PacketType.Play.Server.EXPLOSION);
|
||||
fakeExplosion.getDoubles().
|
||||
write(0, player.getLocation().getX()).
|
||||
write(1, player.getLocation().getY()).
|
||||
@@ -159,4 +160,4 @@ types. It's remarkably consistent across different versions.
|
||||
### Incompatibility
|
||||
|
||||
The following plugins (to be expanded) are not compatible with ProtocolLib:
|
||||
* TagAPI
|
||||
* TagAPI
|
||||
@@ -1,275 +1,195 @@
|
||||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>ProtocolLib-v1_7_R4</artifactId>
|
||||
<name>ProtocolLib-v1_7_R4</name>
|
||||
<version>3.6.5</version>
|
||||
|
||||
<description>Provides read/write access to the Minecraft protocol.</description>
|
||||
<url>http://www.spigotmc.org/resources/protocollib.1997/</url>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib-Parent</artifactId>
|
||||
<version>v3-SNAPSHOT</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.build.number></project.build.number>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>md_5-repo</id>
|
||||
<url>http://repo.md-5.net/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<defaultGoal>clean install</defaultGoal>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<testSourceDirectory>src/test/java</testSourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>net.sf</pattern>
|
||||
<shadedPattern>com.comphenix.net.sf</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.spigotmc:spigot</exclude>
|
||||
<exclude>org.spigotmc:spigot-api</exclude>
|
||||
<exclude>junit:junit</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Main-Class>com.comphenix.protocol.Application</Main-Class>
|
||||
<Implementation-Title>ProtocolLib</Implementation-Title>
|
||||
<Implementation-Version>${project.version}${project.build.number}</Implementation-Version>
|
||||
<Implementation-Vendor>dmulloy2</Implementation-Vendor>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
<finalName>ProtocolLib</finalName>
|
||||
<outputDirectory>../../target/</outputDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<id>attach-javadocs</id>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
<configuration>
|
||||
<threshold>High</threshold>
|
||||
<effort>Default</effort>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jenkins</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>env.BUILD_NUMBER</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<project.build.number>-b${env.BUILD_NUMBER}</project.build.number>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>release-sign-artifacts</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/dmulloy2/ProtocolLib.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:dmulloy2/ProtocolLib.git</developerConnection>
|
||||
<url>https://github.com/dmulloy2/ProtocolLib</url>
|
||||
</scm>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU GENERAL PUBLIC LICENSE - Version 2, June 1991</name>
|
||||
<url>http://www.gnu.org/licenses/gpl-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>dmulloy2</id>
|
||||
<name>Dan Mulloy</name>
|
||||
<url>http://dmulloy2.net/</url>
|
||||
<roles>
|
||||
<role>developer</role>
|
||||
<role>maintainer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>aadnk</id>
|
||||
<name>Kristian S. Stangeland</name>
|
||||
<email>kr_stang@hotmail.com</email>
|
||||
<url>http://comphenix.net/</url>
|
||||
<roles>
|
||||
<role>former author</role>
|
||||
</roles>
|
||||
<timezone>1</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.7.10-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.7.10-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<version>2.2.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.executors</groupId>
|
||||
<artifactId>BukkitExecutors</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>ProtocolLib-API</artifactId>
|
||||
<name>ProtocolLib-API</name>
|
||||
<version>${minorVersion}</version>
|
||||
|
||||
<description>Provides read/write access to the Minecraft protocol.</description>
|
||||
<url>http://www.spigotmc.org/resources/protocollib.1997/</url>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib-Parent</artifactId>
|
||||
<version>v4-SNAPSHOT</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.build.number></project.build.number>
|
||||
<project.fullVersion>${project.version}</project.fullVersion>
|
||||
<spigotVersion>1.12-pre2-SNAPSHOT</spigotVersion>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<defaultGoal>clean install</defaultGoal>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<testSourceDirectory>src/test/java</testSourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Main-Class>com.comphenix.protocol.Application</Main-Class>
|
||||
<Implementation-Title>ProtocolLib</Implementation-Title>
|
||||
<Implementation-Version>${project.fullVersion}</Implementation-Version>
|
||||
<Implementation-Vendor>dmulloy2</Implementation-Vendor>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
<finalName>ProtocolLib</finalName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.10</version>
|
||||
<configuration>
|
||||
<systemProperties>
|
||||
<property>
|
||||
<name>projectVersion</name>
|
||||
<value>${project.version}</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jenkins</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>env.BUILD_NUMBER</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<project.build.number>-b${env.BUILD_NUMBER}</project.build.number>
|
||||
<project.fullVersion>${project.version}${project.build.number}</project.fullVersion>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>release-sign-artifacts</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<project.fullVersion>${project.version}</project.fullVersion>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- TODO: Look into signing releases
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/dmulloy2/ProtocolLib.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:dmulloy2/ProtocolLib.git</developerConnection>
|
||||
<url>https://github.com/dmulloy2/ProtocolLib</url>
|
||||
</scm>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU GENERAL PUBLIC LICENSE - Version 2, June 1991</name>
|
||||
<url>http://www.gnu.org/licenses/gpl-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>dmulloy2</id>
|
||||
<name>Dan Mulloy</name>
|
||||
<url>http://dmulloy2.net/</url>
|
||||
<roles>
|
||||
<role>developer</role>
|
||||
<role>maintainer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>aadnk</id>
|
||||
<name>Kristian S. Stangeland</name>
|
||||
<email>kr_stang@hotmail.com</email>
|
||||
<url>http://comphenix.net/</url>
|
||||
<roles>
|
||||
<role>former author</role>
|
||||
</roles>
|
||||
<timezone>1</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
</project>
|
||||
+1
-1
@@ -152,4 +152,4 @@ public interface AsynchronousManager {
|
||||
* @return Set of every asynchronous packet listener.
|
||||
*/
|
||||
public abstract Set<PacketListener> getAsyncHandlers();
|
||||
}
|
||||
}
|
||||
File renamed without changes.
+321
-202
@@ -1,9 +1,14 @@
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
@@ -15,7 +20,6 @@ import org.bukkit.Bukkit;
|
||||
import com.comphenix.protocol.PacketTypeLookup.ClassLookup;
|
||||
import com.comphenix.protocol.events.ConnectionSide;
|
||||
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
||||
import com.comphenix.protocol.reflect.ObjectEnum;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
import com.google.common.base.Objects;
|
||||
@@ -31,12 +35,12 @@ import com.google.common.util.concurrent.Futures;
|
||||
* Note that vanilla Minecraft reuses packet IDs per protocol (ping, game, login) and IDs are subject to change, so they are not reliable.
|
||||
* @author Kristian
|
||||
*/
|
||||
public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
public class PacketType implements Serializable, Cloneable, Comparable<PacketType> {
|
||||
// Increment whenever the type changes
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* Represents an unknown legacy packet ID.
|
||||
* Represents an unknown packet ID.
|
||||
*/
|
||||
public static final int UNKNOWN_PACKET = -1;
|
||||
|
||||
@@ -51,17 +55,15 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* Incoming packets.
|
||||
* @author Kristian
|
||||
*/
|
||||
public static class Client extends ObjectEnum<PacketType> {
|
||||
public static class Client extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.CLIENT;
|
||||
/**
|
||||
* Legacy name: HANDSHAKE.
|
||||
*/
|
||||
public static final PacketType SET_PROTOCOL = new PacketType(PROTOCOL, SENDER, 0x00, 2, "SetProtocol");
|
||||
|
||||
public static final PacketType SET_PROTOCOL = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "SetProtocol");
|
||||
|
||||
private final static Client INSTANCE = new Client();
|
||||
|
||||
// Prevent accidental construction
|
||||
private Client() { super(PacketType.class); }
|
||||
private Client() { super(); }
|
||||
|
||||
public static Client getInstance() {
|
||||
return INSTANCE;
|
||||
@@ -75,10 +77,10 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* An empty enum, as the server will not send any packets in this protocol.
|
||||
* @author Kristian
|
||||
*/
|
||||
public static class Server extends ObjectEnum<PacketType> {
|
||||
public static class Server extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.CLIENT;
|
||||
private final static Server INSTANCE = new Server();
|
||||
private Server() { super(PacketType.class); }
|
||||
private Server() { super(); }
|
||||
|
||||
public static Server getInstance() {
|
||||
return INSTANCE;
|
||||
@@ -104,101 +106,148 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* Outgoing packets.
|
||||
* @author Kristian
|
||||
*/
|
||||
public static class Server extends ObjectEnum<PacketType> {
|
||||
public static class Server extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.SERVER;
|
||||
|
||||
public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x00, 0, "KeepAlive");
|
||||
public static final PacketType LOGIN = new PacketType(PROTOCOL, SENDER, 0x01, 1, "Login");
|
||||
public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x02, 3, "Chat");
|
||||
public static final PacketType UPDATE_TIME = new PacketType(PROTOCOL, SENDER, 0x03, 4, "UpdateTime");
|
||||
public static final PacketType ENTITY_EQUIPMENT = new PacketType(PROTOCOL, SENDER, 0x04, 5, "EntityEquipment");
|
||||
public static final PacketType SPAWN_POSITION = new PacketType(PROTOCOL, SENDER, 0x05, 6, "SpawnPosition");
|
||||
public static final PacketType UPDATE_HEALTH = new PacketType(PROTOCOL, SENDER, 0x06, 8, "UpdateHealth");
|
||||
public static final PacketType RESPAWN = new PacketType(PROTOCOL, SENDER, 0x07, 9, "Respawn");
|
||||
public static final PacketType POSITION = new PacketType(PROTOCOL, SENDER, 0x08, 13, "Position");
|
||||
public static final PacketType HELD_ITEM_SLOT = new PacketType(PROTOCOL, SENDER, 0x09, 16, "HeldItemSlot");
|
||||
/**
|
||||
* Note that this was Packets.Server.ENTITY_LOCATION_ACTION.
|
||||
*/
|
||||
public static final PacketType BED = new PacketType(PROTOCOL, SENDER, 0x0A, 17, "Bed");
|
||||
public static final PacketType ANIMATION = new PacketType(PROTOCOL, SENDER, 0x0B, 18, "Animation");
|
||||
public static final PacketType NAMED_ENTITY_SPAWN = new PacketType(PROTOCOL, SENDER, 0x0C, 20, "NamedEntitySpawn");
|
||||
public static final PacketType COLLECT = new PacketType(PROTOCOL, SENDER, 0x0D, 22, "Collect");
|
||||
public static final PacketType SPAWN_ENTITY = new PacketType(PROTOCOL, SENDER, 0x0E, 23, "SpawnEntity");
|
||||
public static final PacketType SPAWN_ENTITY_LIVING = new PacketType(PROTOCOL, SENDER, 0x0F, 24, "SpawnEntityLiving");
|
||||
public static final PacketType SPAWN_ENTITY_PAINTING = new PacketType(PROTOCOL, SENDER, 0x10, 25, "SpawnEntityPainting");
|
||||
public static final PacketType SPAWN_ENTITY_EXPERIENCE_ORB =
|
||||
new PacketType(PROTOCOL, SENDER, 0x11, 26, "SpawnEntityExperienceOrb");
|
||||
public static final PacketType ENTITY_VELOCITY = new PacketType(PROTOCOL, SENDER, 0x12, 28, "EntityVelocity");
|
||||
public static final PacketType ENTITY_DESTROY = new PacketType(PROTOCOL, SENDER, 0x13, 29, "EntityDestroy");
|
||||
public static final PacketType ENTITY = new PacketType(PROTOCOL, SENDER, 0x14, 30, "Entity");
|
||||
public static final PacketType REL_ENTITY_MOVE = new PacketType(PROTOCOL, SENDER, 0x15, 31, "RelEntityMove");
|
||||
public static final PacketType ENTITY_LOOK = new PacketType(PROTOCOL, SENDER, 0x16, 32, "EntityLook");
|
||||
public static final PacketType ENTITY_MOVE_LOOK = new PacketType(PROTOCOL, SENDER, 0x17, 33, "RelEntityMoveLook");
|
||||
public static final PacketType ENTITY_TELEPORT = new PacketType(PROTOCOL, SENDER, 0x18, 34, "EntityTeleport");
|
||||
public static final PacketType ENTITY_HEAD_ROTATION = new PacketType(PROTOCOL, SENDER, 0x19, 35, "EntityHeadRotation");
|
||||
public static final PacketType ENTITY_STATUS = new PacketType(PROTOCOL, SENDER, 0x1A, 38, "EntityStatus");
|
||||
public static final PacketType ATTACH_ENTITY = new PacketType(PROTOCOL, SENDER, 0x1B, 39, "AttachEntity");
|
||||
public static final PacketType ENTITY_METADATA = new PacketType(PROTOCOL, SENDER, 0x1C, 40, "EntityMetadata");
|
||||
public static final PacketType ENTITY_EFFECT = new PacketType(PROTOCOL, SENDER, 0x1D, 41, "EntityEffect");
|
||||
public static final PacketType REMOVE_ENTITY_EFFECT = new PacketType(PROTOCOL, SENDER, 0x1E, 42, "RemoveEntityEffect");
|
||||
public static final PacketType EXPERIENCE = new PacketType(PROTOCOL, SENDER, 0x1F, 43, "Experience");
|
||||
public static final PacketType UPDATE_ATTRIBUTES = new PacketType(PROTOCOL, SENDER, 0x20, 44, "UpdateAttributes");
|
||||
public static final PacketType MAP_CHUNK = new PacketType(PROTOCOL, SENDER, 0x21, 51, "MapChunk");
|
||||
public static final PacketType MULTI_BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x22, 52, "MultiBlockChange");
|
||||
public static final PacketType BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x23, 53, "BlockChange");
|
||||
public static final PacketType BLOCK_ACTION = new PacketType(PROTOCOL, SENDER, 0x24, 54, "BlockAction");
|
||||
public static final PacketType BLOCK_BREAK_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x25, 55, "BlockBreakAnimation");
|
||||
public static final PacketType MAP_CHUNK_BULK = new PacketType(PROTOCOL, SENDER, 0x26, 56, "MapChunkBulk");
|
||||
public static final PacketType EXPLOSION = new PacketType(PROTOCOL, SENDER, 0x27, 60, "Explosion");
|
||||
public static final PacketType WORLD_EVENT = new PacketType(PROTOCOL, SENDER, 0x28, 61, "WorldEvent");
|
||||
public static final PacketType NAMED_SOUND_EFFECT = new PacketType(PROTOCOL, SENDER, 0x29, 62, "NamedSoundEffect");
|
||||
public static final PacketType WORLD_PARTICLES = new PacketType(PROTOCOL, SENDER, 0x2A, 63, "WorldParticles");
|
||||
/**
|
||||
* Note that this was Packets.Server.BED.
|
||||
*/
|
||||
public static final PacketType GAME_STATE_CHANGE = new PacketType(PROTOCOL, SENDER, 0x2B, 70, "GameStateChange");
|
||||
public static final PacketType SPAWN_ENTITY_WEATHER = new PacketType(PROTOCOL, SENDER, 0x2C, 71, "SpawnEntityWeather");
|
||||
public static final PacketType OPEN_WINDOW = new PacketType(PROTOCOL, SENDER, 0x2D, 100, "OpenWindow");
|
||||
public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x2E, 101, "CloseWindow");
|
||||
public static final PacketType SET_SLOT = new PacketType(PROTOCOL, SENDER, 0x2F, 103, "SetSlot");
|
||||
public static final PacketType WINDOW_ITEMS = new PacketType(PROTOCOL, SENDER, 0x30, 104, "WindowItems");
|
||||
/**
|
||||
* Should be WINDOW_DATA.
|
||||
*/
|
||||
public static final PacketType CRAFT_PROGRESS_BAR = new PacketType(PROTOCOL, SENDER, 0x31, 105, "WindowData");
|
||||
public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x32, 106, "Transaction");
|
||||
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x33, 130, "UpdateSign");
|
||||
public static final PacketType MAP = new PacketType(PROTOCOL, SENDER, 0x34, 131, "Map");
|
||||
public static final PacketType TILE_ENTITY_DATA = new PacketType(PROTOCOL, SENDER, 0x35, 132, "TileEntityData");
|
||||
public static final PacketType OPEN_SIGN_ENTITY = new PacketType(PROTOCOL, SENDER, 0x36, 133, "OpenSignEditor");
|
||||
public static final PacketType STATISTICS = new PacketType(PROTOCOL, SENDER, 0x37, 200, "Statistic");
|
||||
public static final PacketType PLAYER_INFO = new PacketType(PROTOCOL, SENDER, 0x38, 201, "PlayerInfo");
|
||||
public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x39, 202, "Abilities");
|
||||
public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x3A, 203, "TabComplete");
|
||||
public static final PacketType SCOREBOARD_OBJECTIVE = new PacketType(PROTOCOL, SENDER, 0x3B, 206, "ScoreboardObjective");
|
||||
public static final PacketType SCOREBOARD_SCORE = new PacketType(PROTOCOL, SENDER, 0x3C, 207, "ScoreboardScore");
|
||||
public static final PacketType SCOREBOARD_DISPLAY_OBJECTIVE =
|
||||
new PacketType(PROTOCOL, SENDER, 0x3D, 208, "ScoreboardDisplayObjective");
|
||||
public static final PacketType SCOREBOARD_TEAM = new PacketType(PROTOCOL, SENDER, 0x3E, 209, "ScoreboardTeam");
|
||||
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x3F, 250, "CustomPayload");
|
||||
public static final PacketType KICK_DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x40, 255, "KickDisconnect");
|
||||
public static final PacketType SERVER_DIFFICULTY = new PacketType(PROTOCOL, SENDER, 0x41, -1, "ServerDifficulty");
|
||||
public static final PacketType COMBAT_EVENT = new PacketType(PROTOCOL, SENDER, 0x42, -1, "CombatEvent");
|
||||
public static final PacketType CAMERA = new PacketType(PROTOCOL, SENDER, 0x43, -1, "Camera");
|
||||
public static final PacketType WORLD_BORDER = new PacketType(PROTOCOL, SENDER, 0x44, -1, "WorldBorder");
|
||||
public static final PacketType TITLE = new PacketType(PROTOCOL, SENDER, 0x45, -1, "Title");
|
||||
public static final PacketType SET_COMPRESSION = new PacketType(PROTOCOL, SENDER, 0x46, -1, "SetCompression");
|
||||
public static final PacketType PLAYER_LIST_HEADER_FOOTER =
|
||||
new PacketType(PROTOCOL, SENDER, 0x47, -1, "PlayerListHeaderFooter");
|
||||
public static final PacketType RESOURCE_PACK_SEND = new PacketType(PROTOCOL, SENDER, 0x48, -1, "ResourcePackSend");
|
||||
public static final PacketType UPDATE_ENTITY_NBT = new PacketType(PROTOCOL, SENDER, 0x49, -1, "UpdateEntityNBT");
|
||||
public static final PacketType SPAWN_ENTITY = new PacketType(PROTOCOL, SENDER, 0x00, 0x0E, "SpawnEntity");
|
||||
public static final PacketType SPAWN_ENTITY_EXPERIENCE_ORB = new PacketType(PROTOCOL, SENDER, 0x01, 0x11, "SpawnEntityExperienceOrb");
|
||||
public static final PacketType SPAWN_ENTITY_WEATHER = new PacketType(PROTOCOL, SENDER, 0x02, 0x2C, "SpawnEntityWeather");
|
||||
public static final PacketType SPAWN_ENTITY_LIVING = new PacketType(PROTOCOL, SENDER, 0x03, 0x0F, "SpawnEntityLiving");
|
||||
public static final PacketType SPAWN_ENTITY_PAINTING = new PacketType(PROTOCOL, SENDER, 0x04, 0x10, "SpawnEntityPainting");
|
||||
public static final PacketType NAMED_ENTITY_SPAWN = new PacketType(PROTOCOL, SENDER, 0x05, 0x0C, "NamedEntitySpawn");
|
||||
public static final PacketType ANIMATION = new PacketType(PROTOCOL, SENDER, 0x06, 0x0B, "Animation");
|
||||
public static final PacketType STATISTIC = new PacketType(PROTOCOL, SENDER, 0x07, 0x37, "Statistic");
|
||||
public static final PacketType BLOCK_BREAK_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x08, 0x25, "BlockBreakAnimation");
|
||||
public static final PacketType TILE_ENTITY_DATA = new PacketType(PROTOCOL, SENDER, 0x09, 0x35, "TileEntityData");
|
||||
public static final PacketType BLOCK_ACTION = new PacketType(PROTOCOL, SENDER, 0x0A, 0x24, "BlockAction");
|
||||
public static final PacketType BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x0B, 0x23, "BlockChange");
|
||||
public static final PacketType BOSS = new PacketType(PROTOCOL, SENDER, 0x0C, 0xFF, "Boss");
|
||||
public static final PacketType SERVER_DIFFICULTY = new PacketType(PROTOCOL, SENDER, 0x0D, 0x41, "ServerDifficulty");
|
||||
public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x0E, 0x3A, "TabComplete");
|
||||
public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x0F, 0x02, "Chat");
|
||||
public static final PacketType MULTI_BLOCK_CHANGE = new PacketType(PROTOCOL, SENDER, 0x10, 0x22, "MultiBlockChange");
|
||||
public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x11, 0x32, "Transaction");
|
||||
public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x12, 0x2E, "CloseWindow");
|
||||
public static final PacketType OPEN_WINDOW = new PacketType(PROTOCOL, SENDER, 0x13, 0x2D, "OpenWindow");
|
||||
public static final PacketType WINDOW_ITEMS = new PacketType(PROTOCOL, SENDER, 0x14, 0x30, "WindowItems");
|
||||
public static final PacketType WINDOW_DATA = new PacketType(PROTOCOL, SENDER, 0x15, 0x31, "WindowData");
|
||||
public static final PacketType SET_SLOT = new PacketType(PROTOCOL, SENDER, 0x16, 0x2F, "SetSlot");
|
||||
public static final PacketType SET_COOLDOWN = new PacketType(PROTOCOL, SENDER, 0x17, 0xFC, "SetCooldown");
|
||||
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x18, 0x3F, "CustomPayload");
|
||||
public static final PacketType CUSTOM_SOUND_EFFECT = new PacketType(PROTOCOL, SENDER, 0x19, 0xFD, "CustomSoundEffect");
|
||||
public static final PacketType KICK_DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x1A, 0x40, "KickDisconnect");
|
||||
public static final PacketType ENTITY_STATUS = new PacketType(PROTOCOL, SENDER, 0x1B, 0x1A, "EntityStatus");
|
||||
public static final PacketType EXPLOSION = new PacketType(PROTOCOL, SENDER, 0x1C, 0x27, "Explosion");
|
||||
public static final PacketType UNLOAD_CHUNK = new PacketType(PROTOCOL, SENDER, 0x1D, 0xFA, "UnloadChunk");
|
||||
public static final PacketType GAME_STATE_CHANGE = new PacketType(PROTOCOL, SENDER, 0x1E, 0x2B, "GameStateChange");
|
||||
public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x1F, 0x00, "KeepAlive");
|
||||
public static final PacketType MAP_CHUNK = new PacketType(PROTOCOL, SENDER, 0x20, 0x21, "MapChunk");
|
||||
public static final PacketType WORLD_EVENT = new PacketType(PROTOCOL, SENDER, 0x21, 0x28, "WorldEvent");
|
||||
public static final PacketType WORLD_PARTICLES = new PacketType(PROTOCOL, SENDER, 0x22, 0x2A, "WorldParticles");
|
||||
public static final PacketType LOGIN = new PacketType(PROTOCOL, SENDER, 0x23, 0x01, "Login");
|
||||
public static final PacketType MAP = new PacketType(PROTOCOL, SENDER, 0x24, 0x34, "Map");
|
||||
public static final PacketType ENTITY = new PacketType(PROTOCOL, SENDER, 0x25, 0x14, "Entity");
|
||||
public static final PacketType REL_ENTITY_MOVE = new PacketType(PROTOCOL, SENDER, 0x26, 0x15, "RelEntityMove");
|
||||
public static final PacketType REL_ENTITY_MOVE_LOOK = new PacketType(PROTOCOL, SENDER, 0x27, 0x17, "RelEntityMoveLook");
|
||||
public static final PacketType ENTITY_LOOK = new PacketType(PROTOCOL, SENDER, 0x28, 0x16, "EntityLook");
|
||||
public static final PacketType VEHICLE_MOVE = new PacketType(PROTOCOL, SENDER, 0x29, 0xFE, "VehicleMove");
|
||||
public static final PacketType OPEN_SIGN_EDITOR = new PacketType(PROTOCOL, SENDER, 0x2A, 0x36, "OpenSignEditor");
|
||||
public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x2B, 0x39, "Abilities");
|
||||
public static final PacketType COMBAT_EVENT = new PacketType(PROTOCOL, SENDER, 0x2C, 0x42, "CombatEvent");
|
||||
public static final PacketType PLAYER_INFO = new PacketType(PROTOCOL, SENDER, 0x2D, 0x38, "PlayerInfo");
|
||||
public static final PacketType POSITION = new PacketType(PROTOCOL, SENDER, 0x2E, 0x08, "Position");
|
||||
public static final PacketType BED = new PacketType(PROTOCOL, SENDER, 0x2F, 0x0A, "Bed");
|
||||
public static final PacketType RECIPES = new PacketType(PROTOCOL, SENDER, 0x30, -1, "Recipes");
|
||||
public static final PacketType ENTITY_DESTROY = new PacketType(PROTOCOL, SENDER, 0x31, 0x13, "EntityDestroy");
|
||||
public static final PacketType REMOVE_ENTITY_EFFECT = new PacketType(PROTOCOL, SENDER, 0x32, 0x1E, "RemoveEntityEffect");
|
||||
public static final PacketType RESOURCE_PACK_SEND = new PacketType(PROTOCOL, SENDER, 0x33, 0x48, "ResourcePackSend");
|
||||
public static final PacketType RESPAWN = new PacketType(PROTOCOL, SENDER, 0x34, 0x07, "Respawn");
|
||||
public static final PacketType ENTITY_HEAD_ROTATION = new PacketType(PROTOCOL, SENDER, 0x35, 0x19, "EntityHeadRotation");
|
||||
public static final PacketType SELECT_ADVANCEMENT_TAB = new PacketType(PROTOCOL, SENDER, 0x36, -1, "SelectAdvancementTab");
|
||||
public static final PacketType WORLD_BORDER = new PacketType(PROTOCOL, SENDER, 0x37, 0x44, "WorldBorder");
|
||||
public static final PacketType CAMERA = new PacketType(PROTOCOL, SENDER, 0x38, 0x43, "Camera");
|
||||
public static final PacketType HELD_ITEM_SLOT = new PacketType(PROTOCOL, SENDER, 0x39, 0x09, "HeldItemSlot");
|
||||
public static final PacketType SCOREBOARD_DISPLAY_OBJECTIVE = new PacketType(PROTOCOL, SENDER, 0x3A, 0x3D, "ScoreboardDisplayObjective");
|
||||
public static final PacketType ENTITY_METADATA = new PacketType(PROTOCOL, SENDER, 0x3B, 0x1C, "EntityMetadata");
|
||||
public static final PacketType ATTACH_ENTITY = new PacketType(PROTOCOL, SENDER, 0x3C, 0x1B, "AttachEntity");
|
||||
public static final PacketType ENTITY_VELOCITY = new PacketType(PROTOCOL, SENDER, 0x3D, 0x12, "EntityVelocity");
|
||||
public static final PacketType ENTITY_EQUIPMENT = new PacketType(PROTOCOL, SENDER, 0x3E, 0x04, "EntityEquipment");
|
||||
public static final PacketType EXPERIENCE = new PacketType(PROTOCOL, SENDER, 0x3F, 0x1F, "Experience");
|
||||
public static final PacketType UPDATE_HEALTH = new PacketType(PROTOCOL, SENDER, 0x40, 0x06, "UpdateHealth");
|
||||
public static final PacketType SCOREBOARD_OBJECTIVE = new PacketType(PROTOCOL, SENDER, 0x41, 0x3B, "ScoreboardObjective");
|
||||
public static final PacketType MOUNT = new PacketType(PROTOCOL, SENDER, 0x42, 0xFB, "Mount");
|
||||
public static final PacketType SCOREBOARD_TEAM = new PacketType(PROTOCOL, SENDER, 0x43, 0x3E, "ScoreboardTeam");
|
||||
public static final PacketType SCOREBOARD_SCORE = new PacketType(PROTOCOL, SENDER, 0x44, 0x3C, "ScoreboardScore");
|
||||
public static final PacketType SPAWN_POSITION = new PacketType(PROTOCOL, SENDER, 0x45, 0x05, "SpawnPosition");
|
||||
public static final PacketType UPDATE_TIME = new PacketType(PROTOCOL, SENDER, 0x46, 0x03, "UpdateTime");
|
||||
public static final PacketType TITLE = new PacketType(PROTOCOL, SENDER, 0x47, 0x45, "Title");
|
||||
public static final PacketType NAMED_SOUND_EFFECT = new PacketType(PROTOCOL, SENDER, 0x48, 0x29, "NamedSoundEffect");
|
||||
public static final PacketType PLAYER_LIST_HEADER_FOOTER = new PacketType(PROTOCOL, SENDER, 0x49, 0x47, "PlayerListHeaderFooter");
|
||||
public static final PacketType COLLECT = new PacketType(PROTOCOL, SENDER, 0x4A, 0x0D, "Collect");
|
||||
public static final PacketType ENTITY_TELEPORT = new PacketType(PROTOCOL, SENDER, 0x4B, 0x18, "EntityTeleport");
|
||||
public static final PacketType ADVANCEMENTS = new PacketType(PROTOCOL, SENDER, 0x4C, -1, "Advancements");
|
||||
public static final PacketType UPDATE_ATTRIBUTES = new PacketType(PROTOCOL, SENDER, 0x4D, 0x20, "UpdateAttributes");
|
||||
public static final PacketType ENTITY_EFFECT = new PacketType(PROTOCOL, SENDER, 0x4E, 0x1D, "EntityEffect");
|
||||
|
||||
// ---- Removed in 1.9
|
||||
|
||||
/**
|
||||
* @deprecated Removed in 1.9
|
||||
*/
|
||||
@Deprecated
|
||||
public static final PacketType MAP_CHUNK_BULK = new PacketType(PROTOCOL, SENDER, 255, 255, "MapChunkBulk");
|
||||
|
||||
/**
|
||||
* @deprecated Removed in 1.9
|
||||
*/
|
||||
@Deprecated
|
||||
public static final PacketType SET_COMPRESSION = new PacketType(PROTOCOL, SENDER, 254, 254, "SetCompression");
|
||||
|
||||
/**
|
||||
* @deprecated Removed in 1.9
|
||||
*/
|
||||
@Deprecated
|
||||
public static final PacketType UPDATE_ENTITY_NBT = new PacketType(PROTOCOL, SENDER, 253, 253, "UpdateEntityNBT");
|
||||
|
||||
// ----- Renamed packets
|
||||
|
||||
/**
|
||||
* @deprecated Renamed to {@link #WINDOW_DATA}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final PacketType CRAFT_PROGRESS_BAR = WINDOW_DATA.clone();
|
||||
|
||||
/**
|
||||
* @deprecated Renamed to {@link #REL_ENTITY_MOVE_LOOK}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final PacketType ENTITY_MOVE_LOOK = REL_ENTITY_MOVE_LOOK.clone();
|
||||
|
||||
/**
|
||||
* @deprecated Renamed to {@link #STATISTIC}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final PacketType STATISTICS = STATISTIC.clone();
|
||||
|
||||
/**
|
||||
* @deprecated Renamed to {@link #OPEN_SIGN_EDITOR}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final PacketType OPEN_SIGN_ENTITY = OPEN_SIGN_EDITOR.clone();
|
||||
|
||||
// ----- Replaced in 1.9.4
|
||||
|
||||
/**
|
||||
* @deprecated Replaced by {@link #TILE_ENTITY_DATA}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final PacketType UPDATE_SIGN = MinecraftReflection.signUpdateExists() ? new PacketType(PROTOCOL, SENDER, 252, 252, "UpdateSign") :
|
||||
TILE_ENTITY_DATA.clone();
|
||||
|
||||
// The instance must
|
||||
private final static Server INSTANCE = new Server();
|
||||
|
||||
// Prevent accidental construction
|
||||
private Server() { super(PacketType.class); }
|
||||
private Server() { super(); }
|
||||
|
||||
public static Sender getSender() {
|
||||
return SENDER;
|
||||
@@ -212,40 +261,47 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* Incoming packets.
|
||||
* @author Kristian
|
||||
*/
|
||||
public static class Client extends ObjectEnum<PacketType> {
|
||||
public static class Client extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.CLIENT;
|
||||
|
||||
public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x00, 0, "KeepAlive");
|
||||
public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x01, 3, "Chat");
|
||||
public static final PacketType USE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x02, 7, "UseEntity");
|
||||
public static final PacketType FLYING = new PacketType(PROTOCOL, SENDER, 0x03, 10, "Flying");
|
||||
public static final PacketType POSITION = new PacketType(PROTOCOL, SENDER, 0x04, 11, "Position");
|
||||
public static final PacketType LOOK = new PacketType(PROTOCOL, SENDER, 0x05, 12, "Look");
|
||||
public static final PacketType POSITION_LOOK = new PacketType(PROTOCOL, SENDER, 0x06, 13, "PositionLook");
|
||||
public static final PacketType BLOCK_DIG = new PacketType(PROTOCOL, SENDER, 0x07, 14, "BlockDig");
|
||||
public static final PacketType BLOCK_PLACE = new PacketType(PROTOCOL, SENDER, 0x08, 15, "BlockPlace");
|
||||
public static final PacketType HELD_ITEM_SLOT = new PacketType(PROTOCOL, SENDER, 0x09, 16, "HeldItemSlot");
|
||||
public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x0A, 18, "ArmAnimation");
|
||||
public static final PacketType ENTITY_ACTION = new PacketType(PROTOCOL, SENDER, 0x0B, 19, "EntityAction");
|
||||
public static final PacketType STEER_VEHICLE = new PacketType(PROTOCOL, SENDER, 0x0C, 27, "SteerVehicle");
|
||||
public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x0D, 101, "CloseWindow");
|
||||
public static final PacketType WINDOW_CLICK = new PacketType(PROTOCOL, SENDER, 0x0E, 102, "WindowClick");
|
||||
public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x0F, 106, "Transaction");
|
||||
public static final PacketType SET_CREATIVE_SLOT = new PacketType(PROTOCOL, SENDER, 0x10, 107, "SetCreativeSlot");
|
||||
public static final PacketType ENCHANT_ITEM = new PacketType(PROTOCOL, SENDER, 0x11, 108, "EnchantItem");
|
||||
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x12, 130, "UpdateSign");
|
||||
public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x13, 202, "Abilities");
|
||||
public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x14, 203, "TabComplete");
|
||||
public static final PacketType SETTINGS = new PacketType(PROTOCOL, SENDER, 0x15, 204, "Settings");
|
||||
public static final PacketType CLIENT_COMMAND = new PacketType(PROTOCOL, SENDER, 0x16, 205, "ClientCommand");
|
||||
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x17, 250, "CustomPayload");
|
||||
public static final PacketType SPECTATE = new PacketType(PROTOCOL, SENDER, 0x18, -1, "Spectate");
|
||||
public static final PacketType RESOURCE_PACK_STATUS = new PacketType(PROTOCOL, SENDER, 0x19, -1, "ResourcePackStatus");
|
||||
public static final PacketType TELEPORT_ACCEPT = new PacketType(PROTOCOL, SENDER, 0x00, 0xF9, "TeleportAccept");
|
||||
public static final PacketType AUTO_RECIPE = new PacketType(PROTOCOL, SENDER, 0x01, -1, "AutoRecipe");
|
||||
public static final PacketType TAB_COMPLETE = new PacketType(PROTOCOL, SENDER, 0x02, 0x14, "TabComplete");
|
||||
public static final PacketType CHAT = new PacketType(PROTOCOL, SENDER, 0x03, 0x01, "Chat");
|
||||
public static final PacketType CLIENT_COMMAND = new PacketType(PROTOCOL, SENDER, 0x04, 0x16, "ClientCommand");
|
||||
public static final PacketType SETTINGS = new PacketType(PROTOCOL, SENDER, 0x05, 0x15, "Settings");
|
||||
public static final PacketType TRANSACTION = new PacketType(PROTOCOL, SENDER, 0x06, 0x0F, "Transaction");
|
||||
public static final PacketType ENCHANT_ITEM = new PacketType(PROTOCOL, SENDER, 0x07, 0x11, "EnchantItem");
|
||||
public static final PacketType WINDOW_CLICK = new PacketType(PROTOCOL, SENDER, 0x08, 0x0E, "WindowClick");
|
||||
public static final PacketType CLOSE_WINDOW = new PacketType(PROTOCOL, SENDER, 0x09, 0x0D, "CloseWindow");
|
||||
public static final PacketType CUSTOM_PAYLOAD = new PacketType(PROTOCOL, SENDER, 0x0A, 0x17, "CustomPayload");
|
||||
public static final PacketType USE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x0B, 0x02, "UseEntity");
|
||||
public static final PacketType KEEP_ALIVE = new PacketType(PROTOCOL, SENDER, 0x0C, 0x00, "KeepAlive");
|
||||
public static final PacketType FLYING = new PacketType(PROTOCOL, SENDER, 0x0D, 0x03, "Flying");
|
||||
public static final PacketType POSITION = new PacketType(PROTOCOL, SENDER, 0x0E, 0x04, "Position");
|
||||
public static final PacketType POSITION_LOOK = new PacketType(PROTOCOL, SENDER, 0x0F, 0x06, "PositionLook");
|
||||
public static final PacketType LOOK = new PacketType(PROTOCOL, SENDER, 0x10, 0x05, "Look");
|
||||
public static final PacketType VEHICLE_MOVE = new PacketType(PROTOCOL, SENDER, 0x11, 0xF8, "VehicleMove");
|
||||
public static final PacketType BOAT_MOVE = new PacketType(PROTOCOL, SENDER, 0x12, 0xF7, "BoatMove");
|
||||
public static final PacketType ABILITIES = new PacketType(PROTOCOL, SENDER, 0x13, 0x13, "Abilities");
|
||||
public static final PacketType BLOCK_DIG = new PacketType(PROTOCOL, SENDER, 0x14, 0x07, "BlockDig");
|
||||
public static final PacketType ENTITY_ACTION = new PacketType(PROTOCOL, SENDER, 0x15, 0x0B, "EntityAction");
|
||||
public static final PacketType STEER_VEHICLE = new PacketType(PROTOCOL, SENDER, 0x16, 0x0C, "SteerVehicle");
|
||||
public static final PacketType RECIPE_DISPLAYED = new PacketType(PROTOCOL, SENDER, 0x17, -1, "RecipeDisplayed");
|
||||
public static final PacketType RESOURCE_PACK_STATUS = new PacketType(PROTOCOL, SENDER, 0x18, 0x19, "ResourcePackStatus");
|
||||
public static final PacketType ADVANCEMENTS = new PacketType(PROTOCOL, SENDER, 0x19, -1, "Advancements");
|
||||
public static final PacketType HELD_ITEM_SLOT = new PacketType(PROTOCOL, SENDER, 0x1A, 0x09, "HeldItemSlot");
|
||||
public static final PacketType SET_CREATIVE_SLOT = new PacketType(PROTOCOL, SENDER, 0x1B, 0x10, "SetCreativeSlot");
|
||||
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x1C, 0x12, "UpdateSign");
|
||||
public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x1D, 0x0A, "ArmAnimation");
|
||||
public static final PacketType SPECTATE = new PacketType(PROTOCOL, SENDER, 0x1E, 0x18, "Spectate");
|
||||
public static final PacketType USE_ITEM = new PacketType(PROTOCOL, SENDER, 0x1F, 0xF6, "UseItem");
|
||||
public static final PacketType BLOCK_PLACE = new PacketType(PROTOCOL, SENDER, 0x20, 0x08, "BlockPlace");
|
||||
|
||||
private final static Client INSTANCE = new Client();
|
||||
|
||||
// Prevent accidental construction
|
||||
private Client() { super(PacketType.class); }
|
||||
private Client() { super(); }
|
||||
|
||||
public static Sender getSender() {
|
||||
return SENDER;
|
||||
@@ -271,16 +327,24 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* Outgoing packets.
|
||||
* @author Kristian
|
||||
*/
|
||||
public static class Server extends ObjectEnum<PacketType> {
|
||||
public static class Server extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.SERVER;
|
||||
|
||||
public static final PacketType OUT_SERVER_INFO = new PacketType(PROTOCOL, SENDER, 0x00, 255, "ServerInfo").forceAsync(true);
|
||||
public static final PacketType OUT_PING = new PacketType(PROTOCOL, SENDER, 0x01, 230, "Pong");
|
||||
@ForceAsync
|
||||
public static final PacketType SERVER_INFO = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "ServerInfo");
|
||||
public static final PacketType PONG = new PacketType(PROTOCOL, SENDER, 0x01, 0x01, "Pong");
|
||||
|
||||
/**
|
||||
* @deprecated Renamed to {@link #SERVER_INFO}
|
||||
*/
|
||||
@Deprecated
|
||||
@ForceAsync
|
||||
public static final PacketType OUT_SERVER_INFO = SERVER_INFO.clone();
|
||||
|
||||
private final static Server INSTANCE = new Server();
|
||||
|
||||
// Prevent accidental construction
|
||||
private Server() { super(PacketType.class); }
|
||||
private Server() { super(); }
|
||||
|
||||
public static Sender getSender() {
|
||||
return SENDER;
|
||||
@@ -294,16 +358,16 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* Incoming packets.
|
||||
* @author Kristian
|
||||
*/
|
||||
public static class Client extends ObjectEnum<PacketType> {
|
||||
public static class Client extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.CLIENT;
|
||||
|
||||
public static final PacketType IN_START = new PacketType(PROTOCOL, SENDER, 0x00, 254, "Start");
|
||||
public static final PacketType IN_PING = new PacketType(PROTOCOL, SENDER, 0x01, 230, "Ping");
|
||||
public static final PacketType START = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "Start");
|
||||
public static final PacketType PING = new PacketType(PROTOCOL, SENDER, 0x01, 0x01, "Ping");
|
||||
|
||||
private final static Client INSTANCE = new Client();
|
||||
|
||||
// Prevent accidental construction
|
||||
private Client() { super(PacketType.class); }
|
||||
private Client() { super(); }
|
||||
|
||||
public static Sender getSender() {
|
||||
return SENDER;
|
||||
@@ -329,18 +393,18 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* Outgoing packets.
|
||||
* @author Kristian
|
||||
*/
|
||||
public static class Server extends ObjectEnum<PacketType> {
|
||||
public static class Server extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.SERVER;
|
||||
|
||||
public static final PacketType DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x00, 255, "Disconnect");
|
||||
public static final PacketType ENCRYPTION_BEGIN = new PacketType(PROTOCOL, SENDER, 0x01, 253, "EncryptionBegin");
|
||||
public static final PacketType SUCCESS = new PacketType(PROTOCOL, SENDER, 0x02, 232, "Success");
|
||||
public static final PacketType SET_COMPRESSION = new PacketType(PROTOCOL, SENDER, 0x03, -1, "SetCompression");
|
||||
public static final PacketType DISCONNECT = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "Disconnect");
|
||||
public static final PacketType ENCRYPTION_BEGIN = new PacketType(PROTOCOL, SENDER, 0x01, 0x01, "EncryptionBegin");
|
||||
public static final PacketType SUCCESS = new PacketType(PROTOCOL, SENDER, 0x02, 0x02, "Success");
|
||||
public static final PacketType SET_COMPRESSION = new PacketType(PROTOCOL, SENDER, 0x03, 0x03, "SetCompression");
|
||||
|
||||
private final static Server INSTANCE = new Server();
|
||||
|
||||
// Prevent accidental construction
|
||||
private Server() { super(PacketType.class); }
|
||||
private Server() { super(); }
|
||||
|
||||
public static Sender getSender() {
|
||||
return SENDER;
|
||||
@@ -354,16 +418,16 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* Incoming packets.
|
||||
* @author Kristian
|
||||
*/
|
||||
public static class Client extends ObjectEnum<PacketType> {
|
||||
public static class Client extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.CLIENT;
|
||||
|
||||
public static final PacketType START = new PacketType(PROTOCOL, SENDER, 0x00, 231, "Start");
|
||||
public static final PacketType ENCRYPTION_BEGIN = new PacketType(PROTOCOL, SENDER, 0x01, 252, "EncryptionBegin");
|
||||
public static final PacketType START = new PacketType(PROTOCOL, SENDER, 0x00, 0x00, "Start");
|
||||
public static final PacketType ENCRYPTION_BEGIN = new PacketType(PROTOCOL, SENDER, 0x01, 0x01, "EncryptionBegin");
|
||||
|
||||
private final static Client INSTANCE = new Client();
|
||||
|
||||
// Prevent accidental construction
|
||||
private Client() { super(PacketType.class); }
|
||||
private Client() { super(); }
|
||||
|
||||
public static Sender getSender() {
|
||||
return SENDER;
|
||||
@@ -390,7 +454,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* @author Kristian
|
||||
*/
|
||||
// Missing server packets: [10, 11, 12, 21, 107, 252]
|
||||
public static class Server extends ObjectEnum<PacketType> {
|
||||
public static class Server extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.SERVER;
|
||||
|
||||
public static final PacketType PLAYER_FLYING = PacketType.newLegacy(SENDER, 10);
|
||||
@@ -414,7 +478,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
|
||||
// Prevent accidental construction
|
||||
private Server() {
|
||||
super(PacketType.class);
|
||||
super();
|
||||
}
|
||||
|
||||
public static Sender getSender() {
|
||||
@@ -430,7 +494,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* @author Kristian
|
||||
*/
|
||||
// Missing client packets: [1, 9, 255]
|
||||
public static class Client extends ObjectEnum<PacketType> {
|
||||
public static class Client extends PacketTypeEnum {
|
||||
private final static Sender SENDER = Sender.CLIENT;
|
||||
|
||||
public static final PacketType LOGIN = PacketType.newLegacy(SENDER, 1);
|
||||
@@ -440,7 +504,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
private final static Client INSTANCE = new Client();
|
||||
|
||||
// Prevent accidental construction
|
||||
private Client() { super(PacketType.class); }
|
||||
private Client() { super(); }
|
||||
|
||||
public static Sender getSender() {
|
||||
return SENDER;
|
||||
@@ -490,7 +554,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
}
|
||||
|
||||
public String getPacketName() {
|
||||
return WordUtils.capitalize(name().toLowerCase());
|
||||
return WordUtils.capitalize(name().toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,13 +587,20 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not packets of this type must be handled asynchronously.
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ForceAsync { }
|
||||
|
||||
// Lookup of packet types
|
||||
private static PacketTypeLookup LOOKUP;
|
||||
|
||||
/**
|
||||
* Protocol version of all the current IDs.
|
||||
*/
|
||||
private static final MinecraftVersion PROTOCOL_VERSION = MinecraftVersion.BOUNTIFUL_UPDATE;
|
||||
private static final MinecraftVersion PROTOCOL_VERSION = MinecraftVersion.EXPLORATION_UPDATE;
|
||||
|
||||
private final Protocol protocol;
|
||||
private final Sender sender;
|
||||
@@ -538,7 +609,10 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
private final MinecraftVersion version;
|
||||
private final String[] classNames;
|
||||
|
||||
private String name;
|
||||
private boolean deprecated;
|
||||
private boolean forceAsync;
|
||||
|
||||
private boolean dynamic;
|
||||
|
||||
/**
|
||||
@@ -590,7 +664,9 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* @param packetId - the legacy packet ID.
|
||||
* @return The corresponding packet type.
|
||||
* @throws IllegalArgumentException If the legacy packet could not be found.
|
||||
* @deprecated Legacy IDs haven't functioned properly for some time
|
||||
*/
|
||||
@Deprecated
|
||||
public static PacketType findLegacy(int packetId) {
|
||||
PacketType type = getLookup().getFromLegacy(packetId);
|
||||
|
||||
@@ -605,7 +681,9 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* @param preference - the preferred sender, or NULL for any arbitrary sender.
|
||||
* @return The corresponding packet type.
|
||||
* @throws IllegalArgumentException If the legacy packet could not be found.
|
||||
* @deprecated Legacy IDs haven't functioned properly for some time
|
||||
*/
|
||||
@Deprecated
|
||||
public static PacketType findLegacy(int packetId, Sender preference) {
|
||||
if (preference == null)
|
||||
return findLegacy(packetId);
|
||||
@@ -620,7 +698,9 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* Determine if the given legacy packet exists.
|
||||
* @param packetId - the legacy packet ID.
|
||||
* @return TRUE if it does, FALSE otherwise.
|
||||
* @deprecated Legacy IDs haven't functioned properly for some time
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean hasLegacy(int packetId) {
|
||||
return getLookup().getFromLegacy(packetId) != null;
|
||||
}
|
||||
@@ -628,18 +708,19 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
/**
|
||||
* Retrieve a packet type from a protocol, sender and packet ID.
|
||||
* <p>
|
||||
* It is usually better to access the packet types statically, like so:
|
||||
* It is almost always better to access the packet types statically, like so:
|
||||
* <ul>
|
||||
* <li>{@link PacketType.Play.Server#SPAWN_ENTITY}
|
||||
* </ul>
|
||||
* However there are some valid uses for packet IDs. Please note that IDs
|
||||
* change almost every Minecraft version.
|
||||
*
|
||||
* @param protocol - the current protocol.
|
||||
* @param sender - the sender.
|
||||
* @param packetId - the packet ID.
|
||||
* @return The corresponding packet type.
|
||||
* @throws IllegalArgumentException If the current packet could not be found.
|
||||
* @deprecated IDs are no longer reliable
|
||||
*/
|
||||
@Deprecated
|
||||
public static PacketType findCurrent(Protocol protocol, Sender sender, int packetId) {
|
||||
PacketType type = getLookup().getFromCurrent(protocol, sender, packetId);
|
||||
|
||||
@@ -665,7 +746,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
if (name.contains("Packet"))
|
||||
return name;
|
||||
|
||||
return String.format("Packet%s%s%s", protocol.getPacketName(), sender.getPacketName(), name);
|
||||
return String.format("Packet%s%s%s", protocol.getPacketName(), sender.getPacketName(), WordUtils.capitalize(name));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -674,9 +755,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* @param sender - the sender.
|
||||
* @param packetId - the packet ID.
|
||||
* @return TRUE if it exists, FALSE otherwise.
|
||||
* @deprecated IDs are no longer reliable
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean hasCurrent(Protocol protocol, Sender sender, int packetId) {
|
||||
return getLookup().getFromCurrent(protocol, sender, packetId) != null;
|
||||
}
|
||||
@@ -689,7 +768,9 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* @param sender - the sender of the packet, or NULL if unknown.
|
||||
* @return The packet type.
|
||||
* @throws IllegalArgumentException If the sender is NULL and the packet doesn't exist.
|
||||
* @deprecated Legacy IDs haven't functioned properly for some time
|
||||
*/
|
||||
@Deprecated
|
||||
public static PacketType fromLegacy(int id, Sender sender) {
|
||||
PacketType type = getLookup().getFromLegacy(id, sender);
|
||||
|
||||
@@ -743,24 +824,11 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
Map<String, PacketType> map = lookup.getMap(protocol, sender);
|
||||
|
||||
// Check the map first
|
||||
String className = packetClass.getSimpleName();
|
||||
PacketType type = map.get(className);
|
||||
String clazz = packetClass.getSimpleName();
|
||||
PacketType type = find(map, clazz);
|
||||
if (type == null) {
|
||||
// Then check any aliases
|
||||
for (PacketType check : map.values()) {
|
||||
String[] aliases = check.getClassNames();
|
||||
if (aliases.length > 1) {
|
||||
for (String alias : aliases) {
|
||||
if (alias.equals(className)) {
|
||||
// We have a match!
|
||||
type = check;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Guess we don't support this packet :/
|
||||
type = new PacketType(protocol, sender, packetId, -1, PROTOCOL_VERSION, className);
|
||||
type = new PacketType(protocol, sender, packetId, -1, PROTOCOL_VERSION, clazz);
|
||||
type.dynamic = true;
|
||||
|
||||
// Many may be scheduled, but only the first will be executed
|
||||
@@ -770,6 +838,28 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
return type;
|
||||
}
|
||||
|
||||
private static PacketType find(Map<String, PacketType> map, String clazz) {
|
||||
PacketType ret = map.get(clazz);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Check any aliases
|
||||
for (PacketType check : map.values()) {
|
||||
String[] aliases = check.getClassNames();
|
||||
if (aliases.length > 1) {
|
||||
for (String alias : aliases) {
|
||||
if (alias.equals(clazz)) {
|
||||
// We have a match!
|
||||
return check;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a packet type from a packet class.
|
||||
* @param packetClass - the packet class.
|
||||
@@ -815,7 +905,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
Callable<Boolean> callable = new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
ObjectEnum<PacketType> objEnum;
|
||||
PacketTypeEnum objEnum;
|
||||
|
||||
// A bit ugly, but performance is critical
|
||||
objEnum = getObjectEnum(type);
|
||||
@@ -829,7 +919,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
};
|
||||
|
||||
// Execute in the main thread if possible
|
||||
if (Bukkit.getServer() == null || Application.isPrimaryThread()) {
|
||||
if (Bukkit.getServer() == null || Bukkit.isPrimaryThread()) {
|
||||
try {
|
||||
return Futures.immediateFuture(callable.call());
|
||||
} catch (Exception e) {
|
||||
@@ -844,7 +934,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* @param type - the packet type.
|
||||
* @return The corresponding object enum.
|
||||
*/
|
||||
public static ObjectEnum<PacketType> getObjectEnum(final PacketType type) {
|
||||
public static PacketTypeEnum getObjectEnum(final PacketType type) {
|
||||
switch (type.getProtocol()) {
|
||||
case HANDSHAKING:
|
||||
return type.isClient() ? Handshake.Client.getInstance() : Handshake.Server.getInstance();
|
||||
@@ -948,11 +1038,9 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* <p>
|
||||
* This is only unique within a specific protocol and target.
|
||||
* <p>
|
||||
* It is only unknown if the packet was removed in Minecraft 1.7.2.
|
||||
* It is unknown if the packet was removed at any point.
|
||||
* @return The current ID, or {@link #UNKNOWN_PACKET} if unknown.
|
||||
* @deprecated IDs are subject to change
|
||||
*/
|
||||
@Deprecated
|
||||
public int getCurrentId() {
|
||||
return currentId;
|
||||
}
|
||||
@@ -973,12 +1061,47 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
}
|
||||
}
|
||||
|
||||
// Only used by Enum processor
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the declared enum name of this packet type.
|
||||
* @return The enum name.
|
||||
*/
|
||||
public String name() {
|
||||
return getObjectEnum(this).getDeclaredName(this);
|
||||
return name;
|
||||
}
|
||||
|
||||
// Only used by enum processor
|
||||
void setDeprecated() {
|
||||
this.deprecated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this packet is deprecated. Deprecated packet types have either been renamed, replaced, or removed.
|
||||
* Kind of like the thing they use to tell children to recycle except with packets you probably shouldn't be using.
|
||||
*
|
||||
* @return True if the type is deprecated, false if not
|
||||
*/
|
||||
public boolean isDeprecated() {
|
||||
return deprecated;
|
||||
}
|
||||
|
||||
// Only used by enum processor
|
||||
void forceAsync() {
|
||||
this.forceAsync = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the processing of this packet must take place on a thread different than the main thread. You don't
|
||||
* get a choice. If this is false it's up to you.
|
||||
*
|
||||
* @return True if async processing is forced, false if not.
|
||||
*/
|
||||
public boolean isAsyncForced() {
|
||||
return forceAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -994,7 +1117,9 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
* <p>
|
||||
* This ID is globally unique.
|
||||
* @return The legacy ID, or {@link #UNKNOWN_PACKET} if unknown.
|
||||
* @deprecated Legacy IDs haven't functioned properly for some time
|
||||
*/
|
||||
@Deprecated
|
||||
public int getLegacyId() {
|
||||
return legacyId;
|
||||
}
|
||||
@@ -1007,22 +1132,9 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
return dynamic;
|
||||
}
|
||||
|
||||
private PacketType forceAsync(boolean forceAsync) {
|
||||
this.forceAsync = forceAsync;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this packet must be processed asynchronously.
|
||||
* @return True if it must be, false if not.
|
||||
*/
|
||||
public boolean forceAsync() {
|
||||
return forceAsync;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(protocol, sender, currentId, legacyId);
|
||||
return Objects.hashCode(protocol, sender, currentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1034,8 +1146,7 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
PacketType other = (PacketType) obj;
|
||||
return protocol == other.protocol &&
|
||||
sender == other.sender &&
|
||||
currentId == other.currentId &&
|
||||
legacyId == other.legacyId;
|
||||
currentId == other.currentId;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1046,7 +1157,6 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
compare(protocol, other.getProtocol()).
|
||||
compare(sender, other.getSender()).
|
||||
compare(currentId, other.getCurrentId()).
|
||||
compare(legacyId, other.getLegacyId()).
|
||||
result();
|
||||
}
|
||||
|
||||
@@ -1055,8 +1165,17 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
Class<?> clazz = getPacketClass();
|
||||
|
||||
if (clazz == null)
|
||||
return "UNREGISTERED[" + protocol + ", " + sender + ", " + currentId + ", legacy: " + legacyId + ", classNames: " + Arrays.toString(classNames) + "]";
|
||||
return name() + "[" + protocol + ", " + sender + ", " + currentId + ", classNames: " + Arrays.toString(classNames) + " (unregistered)]";
|
||||
else
|
||||
return clazz.getSimpleName() + "[" + currentId + ", legacy: " + legacyId + "]";
|
||||
return name() + "[class=" + clazz.getSimpleName() + ", id=" + currentId + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketType clone() {
|
||||
try {
|
||||
return (PacketType) super.clone();
|
||||
} catch (CloneNotSupportedException ex) {
|
||||
throw new Error("This shouldn't happen", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
+58
-43
@@ -15,7 +15,7 @@
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.comphenix.protocol.reflect;
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
@@ -23,8 +23,10 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Represents a more modern object-based enum.
|
||||
@@ -33,41 +35,53 @@ import com.google.common.collect.HashBiMap;
|
||||
* want to prevent the creation of additional members dynamically.
|
||||
* @author Kristian
|
||||
*/
|
||||
public class ObjectEnum<T> implements Iterable<T> {
|
||||
public class PacketTypeEnum implements Iterable<PacketType> {
|
||||
// Used to convert between IDs and names
|
||||
protected BiMap<T, String> members = HashBiMap.create();
|
||||
protected Set<PacketType> members = Sets.newHashSet();
|
||||
|
||||
/**
|
||||
* Registers every declared integer field.
|
||||
* @param fieldType Field type
|
||||
* Registers every declared PacketType field.
|
||||
*/
|
||||
public ObjectEnum(Class<T> fieldType) {
|
||||
registerAll(fieldType);
|
||||
public PacketTypeEnum() {
|
||||
registerAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers every public assignable static field as a member.
|
||||
* @param fieldType Field type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void registerAll(Class<T> fieldType) {
|
||||
protected void registerAll() {
|
||||
try {
|
||||
// Register every int field
|
||||
// Register every non-deprecated field
|
||||
for (Field entry : this.getClass().getFields()) {
|
||||
if (Modifier.isStatic(entry.getModifiers()) && fieldType.isAssignableFrom(entry.getType())) {
|
||||
T value = (T) entry.get(null);
|
||||
|
||||
if (value == null)
|
||||
throw new IllegalArgumentException("Field " + entry + " was NULL. Remember to " +
|
||||
"construct the object after the field has been declared.");
|
||||
registerMember(value, entry.getName());
|
||||
if (Modifier.isStatic(entry.getModifiers()) && PacketType.class.isAssignableFrom(entry.getType())) {
|
||||
PacketType value = (PacketType) entry.get(null);
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("Field " + entry.getName() + " was null!");
|
||||
}
|
||||
|
||||
value.setName(entry.getName());
|
||||
|
||||
if (entry.getAnnotation(PacketType.ForceAsync.class) != null) {
|
||||
value.forceAsync();
|
||||
}
|
||||
|
||||
boolean deprecated = entry.getAnnotation(Deprecated.class) != null;
|
||||
if (deprecated) value.setDeprecated();
|
||||
|
||||
if (members.contains(value)) {
|
||||
// Replace potentially deprecated packet types with non-deprecated ones
|
||||
if (!deprecated) {
|
||||
members.remove(value);
|
||||
members.add(value);
|
||||
}
|
||||
} else {
|
||||
members.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,11 +91,14 @@ public class ObjectEnum<T> implements Iterable<T> {
|
||||
* @param name - name of member.
|
||||
* @return TRUE if the member was registered, FALSE otherwise.
|
||||
*/
|
||||
public boolean registerMember(T instance, String name) {
|
||||
if (!members.containsKey(instance)) {
|
||||
members.put(instance, name);
|
||||
public boolean registerMember(PacketType instance, String name) {
|
||||
instance.setName(name);
|
||||
|
||||
if (!members.contains(instance)) {
|
||||
members.add(instance);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -90,38 +107,36 @@ public class ObjectEnum<T> implements Iterable<T> {
|
||||
* @param member - the member to check.
|
||||
* @return TRUE if the given member has been registered, FALSE otherwise.
|
||||
*/
|
||||
public boolean hasMember(T member) {
|
||||
return members.containsKey(member);
|
||||
public boolean hasMember(PacketType member) {
|
||||
return members.contains(member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a member by name,
|
||||
* @param name - name of member to retrieve.
|
||||
* @return The member, or NULL if not found.
|
||||
* @deprecated Don't use this
|
||||
*/
|
||||
public T valueOf(String name) {
|
||||
return members.inverse().get(name);
|
||||
@Deprecated
|
||||
public PacketType valueOf(String name) {
|
||||
for (PacketType member : members) {
|
||||
if (member.name().equals(name))
|
||||
return member;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the name of the given member.
|
||||
* @param member - the member to retrieve.
|
||||
* @return Declared name of the member, or NULL if not found.
|
||||
*/
|
||||
public String getDeclaredName(T member) {
|
||||
return members.get(member);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve every registered member.
|
||||
* @return Enumeration of every value.
|
||||
*/
|
||||
public Set<T> values() {
|
||||
return new HashSet<T>(members.keySet());
|
||||
public Set<PacketType> values() {
|
||||
return new HashSet<>(members);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return members.keySet().iterator();
|
||||
public Iterator<PacketType> iterator() {
|
||||
return members.iterator();
|
||||
}
|
||||
}
|
||||
File renamed without changes.
+2
-48
@@ -17,10 +17,6 @@
|
||||
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.comphenix.protocol.injector.PacketFilterManager;
|
||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||
import com.comphenix.protocol.reflect.IntEnum;
|
||||
|
||||
/**
|
||||
@@ -165,30 +161,7 @@ public final class Packets {
|
||||
public static Server getRegistry() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given packet is a valid server packet in the current version of Minecraft.
|
||||
* <p>
|
||||
* Use {@link PacketType#isSupported()} instead.
|
||||
* @param packetID - the packet to test.
|
||||
* @return TRUE if this packet is supported, FALSE otherwise.
|
||||
* @throws FieldAccessException If we're unable to retrieve the server packet data from Minecraft.
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isSupported(int packetID) throws FieldAccessException {
|
||||
return PacketFilterManager.getServerPackets().contains(packetID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve every client packet the current version of Minecraft is aware of.
|
||||
* @return Every supported server packet.
|
||||
* @throws FieldAccessException If we're unable to retrieve the server packet data from Minecraft.
|
||||
*/
|
||||
@Deprecated
|
||||
public static Set<Integer> getSupported() throws FieldAccessException {
|
||||
return PacketFilterManager.getServerPackets();
|
||||
}
|
||||
|
||||
|
||||
// We only allow a single instance of this class
|
||||
private Server() {
|
||||
super();
|
||||
@@ -262,26 +235,7 @@ public final class Packets {
|
||||
public static Client getRegistry() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given packet is a valid client packet in the current version of Minecraft.
|
||||
* @param packetID - the packet to test.
|
||||
* @return TRUE if this packet is supported, FALSE otherwise.
|
||||
* @throws FieldAccessException If we're unable to retrieve the client packet data from Minecraft.
|
||||
*/
|
||||
public static boolean isSupported(int packetID) throws FieldAccessException {
|
||||
return PacketFilterManager.getClientPackets().contains(packetID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve every client packet the current version of Minecraft is aware of.
|
||||
* @return Every supported client packet.
|
||||
* @throws FieldAccessException If we're unable to retrieve the client packet data from Minecraft.
|
||||
*/
|
||||
public static Set<Integer> getSupported() throws FieldAccessException {
|
||||
return PacketFilterManager.getClientPackets();
|
||||
}
|
||||
|
||||
|
||||
// Like above
|
||||
private Client() {
|
||||
super();
|
||||
+8
-4
@@ -20,12 +20,13 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.injector.PacketFilterManager.PlayerInjectHooks;
|
||||
import com.comphenix.protocol.injector.PlayerInjectHooks;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -157,6 +158,9 @@ public class ProtocolConfig {
|
||||
}
|
||||
if (global != null) {
|
||||
updater = global.getConfigurationSection(SECTION_AUTOUPDATER);
|
||||
if (updater.getValues(true).isEmpty()) {
|
||||
plugin.getLogger().warning("Updater section is missing, regenerate your config!");
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically copy defaults
|
||||
@@ -256,7 +260,7 @@ public class ProtocolConfig {
|
||||
* @return TRUE if it should, FALSE otherwise.
|
||||
*/
|
||||
public boolean isAutoDownload() {
|
||||
return updater != null && getUpdaterValue(UPDATER_DOWNLAD, true);
|
||||
return updater != null && getUpdaterValue(UPDATER_DOWNLAD, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -461,7 +465,7 @@ public class ProtocolConfig {
|
||||
PlayerInjectHooks hook = getDefaultMethod();
|
||||
|
||||
if (text != null)
|
||||
hook = PlayerInjectHooks.valueOf(text.toUpperCase().replace(" ", "_"));
|
||||
hook = PlayerInjectHooks.valueOf(text.toUpperCase(Locale.ENGLISH).replace(" ", "_"));
|
||||
return hook;
|
||||
}
|
||||
|
||||
@@ -497,4 +501,4 @@ public class ProtocolConfig {
|
||||
valuesChanged = false;
|
||||
configChanged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.error.BasicErrorReporter;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
|
||||
|
||||
/**
|
||||
* The main entry point for ProtocolLib.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class ProtocolLibrary {
|
||||
/**
|
||||
* The minimum version ProtocolLib has been tested with.
|
||||
*/
|
||||
public static final String MINIMUM_MINECRAFT_VERSION = "1.8";
|
||||
|
||||
/**
|
||||
* The maximum version ProtocolLib has been tested with.
|
||||
*/
|
||||
public static final String MAXIMUM_MINECRAFT_VERSION = "1.12";
|
||||
|
||||
/**
|
||||
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (1.12) was released.
|
||||
*/
|
||||
public static final String MINECRAFT_LAST_RELEASE_DATE = "2017-06-07";
|
||||
|
||||
/**
|
||||
* Plugins that are currently incompatible with ProtocolLib.
|
||||
*/
|
||||
public static final List<String> INCOMPATIBLE = Arrays.asList("TagAPI");
|
||||
|
||||
private static Plugin plugin;
|
||||
private static ProtocolConfig config;
|
||||
private static ProtocolManager manager;
|
||||
private static ErrorReporter reporter = new BasicErrorReporter();
|
||||
|
||||
private static ListeningScheduledExecutorService executorAsync;
|
||||
private static ListeningScheduledExecutorService executorSync;
|
||||
|
||||
private static boolean updatesDisabled;
|
||||
private static boolean initialized;
|
||||
|
||||
protected static void init(Plugin plugin, ProtocolConfig config, ProtocolManager manager, ErrorReporter reporter,
|
||||
ListeningScheduledExecutorService executorAsync, ListeningScheduledExecutorService executorSync) {
|
||||
Validate.isTrue(!initialized, "ProtocolLib has already been initialized.");
|
||||
ProtocolLibrary.plugin = plugin;
|
||||
ProtocolLibrary.config = config;
|
||||
ProtocolLibrary.manager = manager;
|
||||
ProtocolLibrary.reporter = reporter;
|
||||
ProtocolLibrary.executorAsync = executorAsync;
|
||||
ProtocolLibrary.executorSync = executorSync;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ProtocolLib plugin instance.
|
||||
* @return The plugin instance
|
||||
*/
|
||||
public static Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ProtocolLib's configuration
|
||||
* @return The config
|
||||
*/
|
||||
public static ProtocolConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the packet protocol manager.
|
||||
* @return Packet protocol manager
|
||||
*/
|
||||
public static ProtocolManager getProtocolManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current error reporter.
|
||||
* @return Current error reporter.
|
||||
*/
|
||||
public static ErrorReporter getErrorReporter() {
|
||||
return reporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an executor service for performing asynchronous tasks on the behalf of ProtocolLib.
|
||||
* <p>
|
||||
* Note that this service is NULL if ProtocolLib has not been initialized yet.
|
||||
* @return The executor service, or NULL.
|
||||
*/
|
||||
public static ListeningScheduledExecutorService getExecutorAsync() {
|
||||
return executorAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an executor service for performing synchronous tasks (main thread) on the behalf of ProtocolLib.
|
||||
* <p>
|
||||
* Note that this service is NULL if ProtocolLib has not been initialized yet.
|
||||
* @return The executor service, or NULL.
|
||||
*/
|
||||
public static ListeningScheduledExecutorService getExecutorSync() {
|
||||
return executorSync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the ProtocolLib update checker.
|
||||
*/
|
||||
public static void disableUpdates() {
|
||||
updatesDisabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not updates are currently disabled.
|
||||
* @return True if it is, false if not
|
||||
*/
|
||||
public static boolean updatesDisabled() {
|
||||
return updatesDisabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class ProtocolLogger {
|
||||
private static Plugin plugin;
|
||||
|
||||
protected static void init(Plugin plugin) {
|
||||
ProtocolLogger.plugin = plugin;
|
||||
}
|
||||
|
||||
private static boolean isDebugEnabled() {
|
||||
try {
|
||||
return plugin.getConfig().getBoolean("global.debug", false);
|
||||
} catch (Throwable ex) { // Maybe we're testing or something
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message to console with a given level.
|
||||
* @param level Logging level
|
||||
* @param message Message to log
|
||||
* @param args Arguments to format in
|
||||
*/
|
||||
public static void log(Level level, String message, Object... args) {
|
||||
plugin.getLogger().log(level, MessageFormat.format(message, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a method to console with the INFO level.
|
||||
* @param message Message to log
|
||||
* @param args Arguments to format in
|
||||
*/
|
||||
public static void log(String message, Object... args) {
|
||||
log(Level.INFO, message, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message to console with a given level and exception.
|
||||
* @param level Logging level
|
||||
* @param message Message to log
|
||||
* @param ex Exception to log
|
||||
*/
|
||||
public static void log(Level level, String message, Throwable ex) {
|
||||
plugin.getLogger().log(level, message, ex);
|
||||
}
|
||||
|
||||
public static void debug(String message, Object... args) {
|
||||
if (isDebugEnabled()) {
|
||||
log("[Debug] " + message, args);
|
||||
}
|
||||
}
|
||||
|
||||
public static void debug(String message, Throwable ex) {
|
||||
if (isDebugEnabled()) {
|
||||
plugin.getLogger().log(Level.WARNING, "[Debug] " + message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -29,6 +29,7 @@ import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.async.AsyncMarker;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
import com.comphenix.protocol.injector.PacketConstructor;
|
||||
@@ -279,4 +280,6 @@ public interface ProtocolManager extends PacketStream {
|
||||
* @return Asynchronous packet manager.
|
||||
*/
|
||||
public AsynchronousManager getAsynchronousManager();
|
||||
}
|
||||
|
||||
public void verifyWhitelist(PacketListener listener, ListeningWhitelist whitelist);
|
||||
}
|
||||
+2
-3
@@ -35,7 +35,6 @@ import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
import com.comphenix.protocol.injector.PacketFilterManager;
|
||||
import com.comphenix.protocol.injector.PrioritizedListener;
|
||||
import com.comphenix.protocol.injector.SortedPacketListenerList;
|
||||
import com.comphenix.protocol.injector.packet.PacketRegistry;
|
||||
@@ -181,11 +180,11 @@ public class AsyncFilterManager implements AsynchronousManager {
|
||||
|
||||
// Add listener to either or both processing queue
|
||||
if (hasValidWhitelist(sendingWhitelist)) {
|
||||
PacketFilterManager.verifyWhitelist(listener, sendingWhitelist);
|
||||
manager.verifyWhitelist(listener, sendingWhitelist);
|
||||
serverProcessingQueue.addListener(handler, sendingWhitelist);
|
||||
}
|
||||
if (hasValidWhitelist(receivingWhitelist)) {
|
||||
PacketFilterManager.verifyWhitelist(listener, receivingWhitelist);
|
||||
manager.verifyWhitelist(listener, receivingWhitelist);
|
||||
clientProcessingQueue.addListener(handler, receivingWhitelist);
|
||||
}
|
||||
|
||||
+3
-5
@@ -24,8 +24,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.error.Report;
|
||||
import com.comphenix.protocol.error.ReportType;
|
||||
@@ -36,10 +34,11 @@ import com.comphenix.protocol.events.PacketListener;
|
||||
import com.comphenix.protocol.timing.TimedListenerManager;
|
||||
import com.comphenix.protocol.timing.TimedListenerManager.ListenerType;
|
||||
import com.comphenix.protocol.timing.TimedTracker;
|
||||
import com.comphenix.protocol.utility.WrappedScheduler;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents a handler for an asynchronous event.
|
||||
* <p>
|
||||
@@ -345,8 +344,7 @@ public class AsyncListenerHandler {
|
||||
}
|
||||
|
||||
private void scheduleAsync(Runnable runnable) {
|
||||
// Handle deprecation
|
||||
WrappedScheduler.runAsynchronouslyRepeat(listener.getPlugin(), filterManager.getScheduler(), runnable, 0L, -1L);
|
||||
listener.getPlugin().getServer().getScheduler().runTaskAsynchronously(listener.getPlugin(), runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
+5
-3
@@ -28,7 +28,7 @@ import java.util.logging.Level;
|
||||
|
||||
import com.comphenix.protocol.PacketStream;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolLogger;
|
||||
import com.comphenix.protocol.events.NetworkMarker;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.injector.PrioritizedListener;
|
||||
@@ -429,15 +429,17 @@ public class AsyncMarker implements Serializable, Comparable<AsyncMarker> {
|
||||
// Incoming chat packets are async only if they aren't commands
|
||||
return ! content.startsWith("/");
|
||||
} else {
|
||||
ProtocolLibrary.log(Level.WARNING, "Failed to determine contents of incoming chat packet!");
|
||||
ProtocolLogger.log(Level.WARNING, "Failed to determine contents of incoming chat packet!");
|
||||
alwaysSync = true;
|
||||
}
|
||||
} else if (event.getPacketType() == PacketType.Status.Server.SERVER_INFO) {
|
||||
return true;
|
||||
} else {
|
||||
// TODO: Find more cases of async packets
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
ProtocolLibrary.log(Level.INFO, "Could not determine asynchronous state of packets (this can probably be ignored)");
|
||||
ProtocolLogger.log(Level.INFO, "Could not determine asynchronous state of packets (this can probably be ignored)");
|
||||
alwaysSync = true;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -243,4 +243,4 @@ public class ExpireHashMap<K, V> {
|
||||
return valueView.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+1
-2
@@ -23,7 +23,6 @@ import java.util.NavigableMap;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.comphenix.protocol.compat.guava.Guava;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
@@ -68,7 +67,7 @@ public abstract class AbstractIntervalTree<TKey extends Comparable<TKey>, TValue
|
||||
|
||||
@Override
|
||||
public Range<TKey> getKey() {
|
||||
return Guava.closedRange(left.key, right.key);
|
||||
return Range.closed(left.key, right.key);
|
||||
}
|
||||
|
||||
@Override
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+6
-4
@@ -35,7 +35,7 @@ import org.apache.commons.lang.builder.ToStringStyle;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolLogger;
|
||||
import com.comphenix.protocol.collections.ExpireHashMap;
|
||||
import com.comphenix.protocol.error.Report.ReportBuilder;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
@@ -464,13 +464,15 @@ public class DetailedErrorReporter implements ErrorReporter {
|
||||
} else {
|
||||
try {
|
||||
if (!apacheCommonsMissing)
|
||||
return (ToStringBuilder.reflectionToString(value, ToStringStyle.MULTI_LINE_STYLE, false, null));
|
||||
return ToStringBuilder.reflectionToString(value, ToStringStyle.MULTI_LINE_STYLE, false, null);
|
||||
} catch (LinkageError ex) {
|
||||
// Apache is probably missing
|
||||
apacheCommonsMissing = true;
|
||||
} catch (Exception e) {
|
||||
} catch (ThreadDeath | OutOfMemoryError e) {
|
||||
throw e;
|
||||
} catch (Throwable ex) {
|
||||
// Don't use the error logger to log errors in error logging (that could lead to infinite loops)
|
||||
ProtocolLibrary.log(Level.WARNING, "Cannot convert to a String with Apache: " + e.getMessage());
|
||||
ProtocolLogger.log(Level.WARNING, "Cannot convert to a String with Apache: " + ex.getMessage());
|
||||
}
|
||||
|
||||
// Use our custom object printer instead
|
||||
+1
-1
@@ -87,4 +87,4 @@ public interface ErrorReporter {
|
||||
* @param reportBuilder - an error report builder that will be used to get the report.
|
||||
*/
|
||||
public abstract void reportDetailed(Object sender, ReportBuilder reportBuilder);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
@@ -2,6 +2,7 @@ package com.comphenix.protocol.events;
|
||||
|
||||
import com.comphenix.protocol.injector.GamePhase;
|
||||
|
||||
|
||||
/**
|
||||
* Represents additional options a listener may require.
|
||||
*
|
||||
File renamed without changes.
+1
-6
@@ -238,12 +238,7 @@ public class ListeningWhitelist {
|
||||
if (this == EMPTY_WHITELIST)
|
||||
return "EMPTY_WHITELIST";
|
||||
else
|
||||
return Objects.toStringHelper(this).
|
||||
add("priority", priority).
|
||||
add("packets", types).
|
||||
add("gamephase", gamePhase).
|
||||
add("options", options).
|
||||
toString();
|
||||
return "ListeningWhitelist[priority=" + priority + ", packets=" + types + ", gamephase=" + gamePhase + ", options=" + options + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+279
-34
@@ -33,22 +33,23 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.PacketType.Protocol;
|
||||
import com.comphenix.protocol.compat.netty.Netty;
|
||||
import com.comphenix.protocol.compat.netty.WrappedByteBuf;
|
||||
import com.comphenix.protocol.injector.StructureCache;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
@@ -61,6 +62,7 @@ import com.comphenix.protocol.reflect.cloning.Cloner;
|
||||
import com.comphenix.protocol.reflect.cloning.CollectionCloner;
|
||||
import com.comphenix.protocol.reflect.cloning.FieldCloner;
|
||||
import com.comphenix.protocol.reflect.cloning.ImmutableDetector;
|
||||
import com.comphenix.protocol.reflect.cloning.OptionalCloner;
|
||||
import com.comphenix.protocol.reflect.cloning.SerializableCloner;
|
||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
||||
@@ -72,11 +74,16 @@ import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||
import com.comphenix.protocol.wrappers.ChunkCoordIntPair;
|
||||
import com.comphenix.protocol.wrappers.ChunkPosition;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.ChatType;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.ChatVisibility;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.ClientCommand;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.CombatEventType;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.Difficulty;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.Direction;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.EntityUseAction;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.EnumConverter;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.Hand;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.ItemSlot;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.Particle;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.PlayerAction;
|
||||
@@ -84,6 +91,7 @@ import com.comphenix.protocol.wrappers.EnumWrappers.PlayerDigType;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.PlayerInfoAction;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.ResourcePackStatus;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.ScoreboardAction;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.SoundCategory;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.TitleAction;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.WorldBorderAction;
|
||||
import com.comphenix.protocol.wrappers.MultiBlockChangeInfo;
|
||||
@@ -97,11 +105,16 @@ import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||
import com.comphenix.protocol.wrappers.WrappedStatistic;
|
||||
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtBase;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
|
||||
/**
|
||||
* Represents a Minecraft packet indirectly.
|
||||
*
|
||||
@@ -125,6 +138,7 @@ public class PacketContainer implements Serializable {
|
||||
instanceProvider(DefaultInstances.DEFAULT).
|
||||
andThen(BukkitCloner.class).
|
||||
andThen(ImmutableDetector.class).
|
||||
andThen(OptionalCloner.class).
|
||||
andThen(CollectionCloner.class).
|
||||
andThen(getSpecializedDeepClonerFactory()).
|
||||
build();
|
||||
@@ -147,8 +161,8 @@ public class PacketContainer implements Serializable {
|
||||
|
||||
// Packets that cannot be cloned by our default deep cloner
|
||||
private static final Set<PacketType> CLONING_UNSUPPORTED = Sets.newHashSet(
|
||||
PacketType.Play.Server.UPDATE_ATTRIBUTES, PacketType.Status.Server.OUT_SERVER_INFO);
|
||||
|
||||
PacketType.Play.Server.UPDATE_ATTRIBUTES, PacketType.Status.Server.SERVER_INFO);
|
||||
|
||||
/**
|
||||
* Creates a packet container for a new packet.
|
||||
* <p>
|
||||
@@ -321,7 +335,15 @@ public class PacketContainer implements Serializable {
|
||||
public StructureModifier<String> getStrings() {
|
||||
return structureModifier.withType(String.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a read/write structure for every UUID field.
|
||||
* @return A modifier for every UUID field.
|
||||
*/
|
||||
public StructureModifier<UUID> getUUIDs() {
|
||||
return structureModifier.withType(UUID.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a read/write structure for every String array field.
|
||||
* @return A modifier for every String array field.
|
||||
@@ -357,7 +379,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for ItemStack.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between the Bukkit ItemStack and the
|
||||
* This modifier will automatically marshal between the Bukkit ItemStack and the
|
||||
* internal Minecraft ItemStack.
|
||||
* @return A modifier for ItemStack fields.
|
||||
*/
|
||||
@@ -370,7 +392,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for arrays of ItemStacks.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between the Bukkit ItemStack and the
|
||||
* This modifier will automatically marshal between the Bukkit ItemStack and the
|
||||
* internal Minecraft ItemStack.
|
||||
* @return A modifier for ItemStack array fields.
|
||||
*/
|
||||
@@ -380,7 +402,25 @@ public class PacketContainer implements Serializable {
|
||||
MinecraftReflection.getItemStackArrayClass(),
|
||||
BukkitConverters.getIgnoreNull(new ItemStackArrayConverter()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a read/write structure for lists of ItemStacks.
|
||||
* <p>
|
||||
* This modifier will automatically marshal between the Bukkit ItemStack and the
|
||||
* internal Minecraft ItemStack.
|
||||
* @return A modifier for ItemStack list fields.
|
||||
*/
|
||||
public StructureModifier<List<ItemStack>> getItemListModifier() {
|
||||
// Convert to and from the Bukkit wrapper
|
||||
return structureModifier.withType(
|
||||
List.class,
|
||||
BukkitConverters.getListConverter(
|
||||
MinecraftReflection.getItemStackClass(),
|
||||
BukkitConverters.getItemStackConverter()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for maps of statistics.
|
||||
* <p>
|
||||
@@ -399,7 +439,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for the world type enum.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between the Bukkit world type and the
|
||||
* This modifier will automatically marshal between the Bukkit world type and the
|
||||
* internal Minecraft world type.
|
||||
* @return A modifier for world type fields.
|
||||
*/
|
||||
@@ -499,6 +539,21 @@ public class PacketContainer implements Serializable {
|
||||
BukkitConverters.getNbtConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a read/write structure for lists of NBT classes.
|
||||
* @return A modifier for lists of NBT classes.
|
||||
*/
|
||||
public StructureModifier<List<NbtBase<?>>> getListNbtModifier() {
|
||||
// Convert to and from the ProtocolLib wrapper
|
||||
return structureModifier.withType(
|
||||
Collection.class,
|
||||
BukkitConverters.getListConverter(
|
||||
MinecraftReflection.getNBTBaseClass(),
|
||||
BukkitConverters.getNbtConverter()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a read/write structure for Vectors.
|
||||
* @return A modifier for Vectors.
|
||||
@@ -513,7 +568,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for collections of attribute snapshots.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between the visible ProtocolLib WrappedAttribute and the
|
||||
* This modifier will automatically marshal between the visible ProtocolLib WrappedAttribute and the
|
||||
* internal Minecraft AttributeSnapshot.
|
||||
* @return A modifier for AttributeSnapshot collection fields.
|
||||
*/
|
||||
@@ -530,7 +585,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for collections of chunk positions.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between the visible ProtocolLib ChunkPosition and the
|
||||
* This modifier will automatically marshal between the visible ProtocolLib ChunkPosition and the
|
||||
* internal Minecraft ChunkPosition.
|
||||
*
|
||||
* @return A modifier for ChunkPosition list fields.
|
||||
@@ -548,7 +603,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for collections of chunk positions.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between the visible ProtocolLib BlockPosition and the
|
||||
* This modifier will automatically marshal between the visible ProtocolLib BlockPosition and the
|
||||
* internal Minecraft BlockPosition.
|
||||
*
|
||||
* @return A modifier for ChunkPosition list fields.
|
||||
@@ -566,7 +621,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for collections of watchable objects.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between the visible WrappedWatchableObject and the
|
||||
* This modifier will automatically marshal between the visible WrappedWatchableObject and the
|
||||
* internal Minecraft WatchableObject.
|
||||
* @return A modifier for watchable object list fields.
|
||||
*/
|
||||
@@ -575,16 +630,15 @@ public class PacketContainer implements Serializable {
|
||||
return structureModifier.withType(
|
||||
Collection.class,
|
||||
BukkitConverters.getListConverter(
|
||||
MinecraftReflection.getWatchableObjectClass(),
|
||||
MinecraftReflection.getDataWatcherItemClass(),
|
||||
BukkitConverters.getWatchableObjectConverter())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a read/write structure for block fields.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between Material and the
|
||||
* This modifier will automatically marshal between Material and the
|
||||
* internal Minecraft Block.
|
||||
* @return A modifier for GameProfile fields.
|
||||
*/
|
||||
@@ -597,7 +651,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for game profiles in Minecraft 1.7.2.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between WrappedGameProfile and the
|
||||
* This modifier will automatically marshal between WrappedGameProfile and the
|
||||
* internal Minecraft GameProfile.
|
||||
* @return A modifier for GameProfile fields.
|
||||
*/
|
||||
@@ -610,7 +664,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for BlockData in Minecraft 1.8.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between WrappedBlockData and the
|
||||
* This modifier will automatically marshal between WrappedBlockData and the
|
||||
* internal Minecraft IBlockData.
|
||||
* @return A modifier for BlockData fields.
|
||||
*/
|
||||
@@ -623,7 +677,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for MultiBlockChangeInfo arrays in Minecraft 1.8.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between MultiBlockChangeInfo and the
|
||||
* This modifier will automatically marshal between MultiBlockChangeInfo and the
|
||||
* internal Minecraft MultiBlockChangeInfo.
|
||||
* @return A modifier for BlockData fields.
|
||||
*/
|
||||
@@ -638,7 +692,7 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for chat components in Minecraft 1.7.2.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between WrappedChatComponent and the
|
||||
* This modifier will automatically marshal between WrappedChatComponent and the
|
||||
* internal Minecraft IChatBaseComponent.
|
||||
* @return A modifier for ChatComponent fields.
|
||||
*/
|
||||
@@ -651,15 +705,19 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for arrays of chat components.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between WrappedChatComponent and the
|
||||
* internal Minecraft IChatBaseComponent.
|
||||
* This modifier will automatically marshal between WrappedChatComponent and the
|
||||
* internal Minecraft IChatBaseComponent (1.9.2 and below) or the internal
|
||||
* NBTCompound (1.9.4 and up).
|
||||
* <p>
|
||||
* Note that in 1.9.4 and up this modifier only works properly with sign
|
||||
* tile entities.
|
||||
* @return A modifier for ChatComponent array fields.
|
||||
*/
|
||||
public StructureModifier<WrappedChatComponent[]> getChatComponentArrays() {
|
||||
// Convert to and from the Bukkit wrapper
|
||||
return structureModifier.<WrappedChatComponent[]>withType(
|
||||
MinecraftReflection.getIChatBaseComponentArrayClass(),
|
||||
BukkitConverters.getIgnoreNull(new WrappedChatComponentArrayConverter()));
|
||||
ComponentArrayConverter.getGenericType(),
|
||||
BukkitConverters.getIgnoreNull(new ComponentArrayConverter()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -842,6 +900,99 @@ public class PacketContainer implements Serializable {
|
||||
EnumWrappers.getParticleClass(), EnumWrappers.getParticleConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for the MobEffectList class in 1.9.
|
||||
* @return A modifier for MobEffectList fields.
|
||||
*/
|
||||
public StructureModifier<PotionEffectType> getEffectTypes() {
|
||||
// Convert to and from Bukkit
|
||||
return structureModifier.<PotionEffectType>withType(
|
||||
MinecraftReflection.getMobEffectListClass(), BukkitConverters.getEffectTypeConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for the SoundCategory enum in 1.9.
|
||||
* @return A modifier for SoundCategory enum fields.
|
||||
*/
|
||||
public StructureModifier<SoundCategory> getSoundCategories() {
|
||||
// Convert to and from the enums
|
||||
return structureModifier.<SoundCategory>withType(
|
||||
EnumWrappers.getSoundCategoryClass(), EnumWrappers.getSoundCategoryConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for the SoundEffect enum in 1.9.
|
||||
* @return A modifier for SoundEffect enum fields.
|
||||
*/
|
||||
public StructureModifier<Sound> getSoundEffects() {
|
||||
// Convert to and from Bukkit
|
||||
return structureModifier.<Sound>withType(
|
||||
MinecraftReflection.getSoundEffectClass(), BukkitConverters.getSoundConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for the ItemSlot enum in 1.9.
|
||||
* @return A modifier for ItemSlot enum fields.
|
||||
*/
|
||||
public StructureModifier<ItemSlot> getItemSlots() {
|
||||
return structureModifier.<ItemSlot>withType(
|
||||
EnumWrappers.getItemSlotClass(), EnumWrappers.getItemSlotConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for the Hand enum in 1.9.
|
||||
* @return A modifier for Hand enum fields.
|
||||
*/
|
||||
public StructureModifier<Hand> getHands() {
|
||||
return structureModifier.<Hand>withType(
|
||||
EnumWrappers.getHandClass(), EnumWrappers.getHandConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for the Direction enum in 1.10.
|
||||
* @return A modifier for Direction enum fields.
|
||||
*/
|
||||
public StructureModifier<Direction> getDirections() {
|
||||
return structureModifier.<Direction>withType(
|
||||
EnumWrappers.getDirectionClass(), EnumWrappers.getDirectionConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for the ChatType enum in 1.12.
|
||||
* @return A modifier for ChatType enum fields.
|
||||
*/
|
||||
public StructureModifier<ChatType> getChatTypes() {
|
||||
return structureModifier.<ChatType>withType(
|
||||
EnumWrappers.getChatTypeClass(), EnumWrappers.getChatTypeConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for an enum. This allows for the use of
|
||||
* user-created enums that may not exist in ProtocolLib. The specific (user
|
||||
* created) enum constants must match up perfectly with their generic (NMS)
|
||||
* counterparts.
|
||||
*
|
||||
* @param enumClass The specific Enum class
|
||||
* @param nmsClass The generic Enum class
|
||||
* @return The modifier
|
||||
*/
|
||||
public <T extends Enum<T>> StructureModifier<T> getEnumModifier(Class<T> enumClass, Class<?> nmsClass) {
|
||||
return structureModifier.<T>withType(nmsClass, new EnumConverter<T>(enumClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a read/write structure for an enum. This method is for convenience,
|
||||
* see {@link #getEnumModifier(Class, Class)} for more information.
|
||||
*
|
||||
* @param enumClass The specific Enum class
|
||||
* @param index Index of the generic Enum
|
||||
* @return The modifier
|
||||
* @see #getEnumModifier(Class, Class)
|
||||
*/
|
||||
public <T extends Enum<T>> StructureModifier<T> getEnumModifier(Class<T> enumClass, int index) {
|
||||
return getEnumModifier(enumClass, structureModifier.getField(index).getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the ID of this packet.
|
||||
* <p>
|
||||
@@ -928,8 +1079,8 @@ public class PacketContainer implements Serializable {
|
||||
|
||||
try {
|
||||
if (MinecraftReflection.isUsingNetty()) {
|
||||
WrappedByteBuf buffer = createPacketBuffer();
|
||||
MinecraftMethods.getPacketWriteByteBufMethod().invoke(handle, buffer.getHandle());
|
||||
ByteBuf buffer = createPacketBuffer();
|
||||
MinecraftMethods.getPacketWriteByteBufMethod().invoke(handle, buffer);
|
||||
|
||||
output.writeInt(buffer.readableBytes());
|
||||
buffer.readBytes(output, buffer.readableBytes());
|
||||
@@ -965,10 +1116,10 @@ public class PacketContainer implements Serializable {
|
||||
// Call the read method
|
||||
try {
|
||||
if (MinecraftReflection.isUsingNetty()) {
|
||||
WrappedByteBuf buffer = createPacketBuffer();
|
||||
ByteBuf buffer = createPacketBuffer();
|
||||
buffer.writeBytes(input, input.readInt());
|
||||
|
||||
MinecraftMethods.getPacketReadByteBufMethod().invoke(handle, buffer.getHandle());
|
||||
MinecraftMethods.getPacketReadByteBufMethod().invoke(handle, buffer);
|
||||
} else {
|
||||
if (input.readInt() != -1)
|
||||
throw new IllegalArgumentException("Cannot load a packet from 1.7.2 in 1.6.4.");
|
||||
@@ -993,8 +1144,15 @@ public class PacketContainer implements Serializable {
|
||||
* Construct a new packet data serializer.
|
||||
* @return The packet data serializer.
|
||||
*/
|
||||
private WrappedByteBuf createPacketBuffer() {
|
||||
return Netty.createPacketBuffer();
|
||||
public static ByteBuf createPacketBuffer() {
|
||||
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
|
||||
Class<?> packetSerializer = MinecraftReflection.getPacketDataSerializerClass();
|
||||
|
||||
try {
|
||||
return (ByteBuf) packetSerializer.getConstructor(ByteBuf.class).newInstance(buffer);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot construct packet serializer.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Metadata
|
||||
@@ -1134,11 +1292,11 @@ public class PacketContainer implements Serializable {
|
||||
* Represents an equivalent converter for ChatComponent arrays.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
private static class WrappedChatComponentArrayConverter implements EquivalentConverter<WrappedChatComponent[]> {
|
||||
private static class LegacyComponentConverter implements EquivalentConverter<WrappedChatComponent[]> {
|
||||
final EquivalentConverter<WrappedChatComponent> componentConverter = BukkitConverters.getWrappedChatComponentConverter();
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?>genericType, WrappedChatComponent[] specific) {
|
||||
public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) {
|
||||
Class<?> nmsComponent = MinecraftReflection.getIChatBaseComponentClass();
|
||||
Object[] result = (Object[]) Array.newInstance(nmsComponent, specific.length);
|
||||
|
||||
@@ -1167,8 +1325,95 @@ public class PacketContainer implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts from NBT to WrappedChatComponent arrays
|
||||
* @author dmulloy2
|
||||
*/
|
||||
private static class NBTComponentConverter implements EquivalentConverter<WrappedChatComponent[]> {
|
||||
private EquivalentConverter<NbtBase<?>> nbtConverter = BukkitConverters.getNbtConverter();
|
||||
private final int lines = 4;
|
||||
|
||||
@Override
|
||||
public WrappedChatComponent[] getSpecific(Object generic) {
|
||||
NbtBase<?> nbtBase = nbtConverter.getSpecific(generic);
|
||||
NbtCompound compound = (NbtCompound) nbtBase;
|
||||
|
||||
WrappedChatComponent[] components = new WrappedChatComponent[lines];
|
||||
for (int i = 0; i < lines; i++) {
|
||||
if (compound.containsKey("Text" + (i + 1))) {
|
||||
components[i] = WrappedChatComponent.fromJson(compound.getString("Text" + (i + 1)));
|
||||
} else {
|
||||
components[i] = WrappedChatComponent.fromText("");
|
||||
}
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) {
|
||||
NbtCompound compound = NbtFactory.ofCompound("");
|
||||
|
||||
for (int i = 0; i < lines; i++) {
|
||||
WrappedChatComponent component;
|
||||
if (i < specific.length && specific[i] != null) {
|
||||
component = specific[i];
|
||||
} else {
|
||||
component = WrappedChatComponent.fromText("");
|
||||
}
|
||||
|
||||
compound.put("Text" + (i + 1), component.getJson());
|
||||
}
|
||||
|
||||
return nbtConverter.getGeneric(genericType, compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<WrappedChatComponent[]> getSpecificType() {
|
||||
return WrappedChatComponent[].class;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A delegated converter that supports NBT to Component Array and regular Component Array
|
||||
* @author dmulloy2
|
||||
*/
|
||||
private static class ComponentArrayConverter implements EquivalentConverter<WrappedChatComponent[]> {
|
||||
private static final EquivalentConverter<WrappedChatComponent[]> DELEGATE;
|
||||
static {
|
||||
if (!PacketType.Play.Server.UPDATE_SIGN.isDeprecated()) {
|
||||
DELEGATE = new LegacyComponentConverter();
|
||||
} else {
|
||||
DELEGATE = new NBTComponentConverter();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedChatComponent[] getSpecific(Object generic) {
|
||||
return DELEGATE.getSpecific(generic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) {
|
||||
return DELEGATE.getGeneric(genericType, specific);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<WrappedChatComponent[]> getSpecificType() {
|
||||
return DELEGATE.getSpecificType();
|
||||
}
|
||||
|
||||
public static Class<?> getGenericType() {
|
||||
if (DELEGATE instanceof NBTComponentConverter) {
|
||||
return MinecraftReflection.getNBTCompoundClass();
|
||||
} else {
|
||||
return MinecraftReflection.getIChatBaseComponentArrayClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PacketContainer[type=" + type + ", structureModifier=" + structureModifier + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -23,13 +23,14 @@ import java.io.ObjectOutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.EventObject;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
|
||||
import com.comphenix.protocol.Application;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.async.AsyncMarker;
|
||||
import com.comphenix.protocol.error.PluginContext;
|
||||
import com.comphenix.protocol.error.Report;
|
||||
import com.comphenix.protocol.error.ReportType;
|
||||
import com.google.common.base.Objects;
|
||||
@@ -202,7 +203,7 @@ public class PacketEvent extends EventObject implements Cancellable {
|
||||
* @return TRUE if we are, FALSE otherwise.
|
||||
*/
|
||||
public boolean isAsync() {
|
||||
return !Application.isPrimaryThread();
|
||||
return !Bukkit.isPrimaryThread();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +232,7 @@ public class PacketEvent extends EventObject implements Cancellable {
|
||||
if (CHANGE_WARNINGS.put(oldType, newType)) {
|
||||
ProtocolLibrary.getErrorReporter().reportWarning(this,
|
||||
Report.newBuilder(REPORT_CHANGING_PACKET_TYPE_IS_CONFUSING).
|
||||
messageParam(oldType, newType).
|
||||
messageParam(PluginContext.getPluginCaller(new Exception()), oldType, newType).
|
||||
build());
|
||||
}
|
||||
}
|
||||
@@ -452,4 +453,4 @@ public class PacketEvent extends EventObject implements Cancellable {
|
||||
public String toString() {
|
||||
return "PacketEvent[player=" + getPlayer() + ", packet=" + packet + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-6
@@ -7,7 +7,6 @@ import org.bukkit.entity.Player;
|
||||
import com.comphenix.protocol.PacketStream;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
@@ -138,10 +137,6 @@ public class ScheduledPacket {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toStringHelper(this)
|
||||
.add("packet", packet)
|
||||
.add("target", target)
|
||||
.add("filtered", filtered)
|
||||
.toString();
|
||||
return "ScheduledPacket[packet=" + packet + ", target=" + target + ", filtered=" + filtered + "]";
|
||||
}
|
||||
}
|
||||
-1
@@ -139,7 +139,6 @@ class SerializedOfflinePlayer implements OfflinePlayer, Serializable {
|
||||
return banned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBanned(boolean banned) {
|
||||
this.banned = banned;
|
||||
}
|
||||
+42
-3
@@ -24,6 +24,9 @@ import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.error.Report;
|
||||
@@ -31,6 +34,7 @@ import com.comphenix.protocol.error.ReportType;
|
||||
import com.comphenix.protocol.injector.PacketConstructor.Unwrapper;
|
||||
import com.comphenix.protocol.reflect.FieldUtils;
|
||||
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.google.common.primitives.Primitives;
|
||||
|
||||
/**
|
||||
@@ -182,20 +186,55 @@ public class BukkitUnwrapper implements Unwrapper {
|
||||
Report.newBuilder(REPORT_SECURITY_LIMITATION).error(e).callerParam(type)
|
||||
);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Maybe it's a proxy?
|
||||
Unwrapper proxyUnwrapper = getProxyUnwrapper(type);
|
||||
if (proxyUnwrapper != null)
|
||||
return proxyUnwrapper;
|
||||
|
||||
// Try getting the field unwrapper too
|
||||
Unwrapper fieldUnwrapper = getFieldUnwrapper(type);
|
||||
|
||||
if (fieldUnwrapper != null)
|
||||
return fieldUnwrapper;
|
||||
else
|
||||
reporter.reportDetailed(this,
|
||||
Report.newBuilder(REPORT_CANNOT_FIND_UNWRAP_METHOD).error(e).callerParam(type));
|
||||
}
|
||||
|
||||
|
||||
// Default method
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Players should /always/ be able to be unwrapped
|
||||
// We should only get here if the 'Player' is a proxy
|
||||
private Unwrapper getProxyUnwrapper(final Class<?> type) {
|
||||
try {
|
||||
if (Player.class.isAssignableFrom(type)) {
|
||||
final Method getHandle = MinecraftReflection.getCraftPlayerClass().getMethod("getHandle");
|
||||
|
||||
Unwrapper unwrapper = new Unwrapper() {
|
||||
@Override
|
||||
public Object unwrapItem(Object wrapped) {
|
||||
try {
|
||||
return getHandle.invoke(((Player) wrapped).getPlayer());
|
||||
} catch (Throwable ex) {
|
||||
try {
|
||||
return getHandle.invoke(Bukkit.getPlayer(((Player) wrapped).getUniqueId()));
|
||||
} catch (ReflectiveOperationException ex1) {
|
||||
throw new RuntimeException("Failed to unwrap proxy " + wrapped, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unwrapperCache.put(type, unwrapper);
|
||||
return unwrapper;
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a cached unwrapper using the handle field.
|
||||
* @param type - a cached field unwrapper.
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,31 @@
|
||||
package com.comphenix.protocol.injector;
|
||||
|
||||
/**
|
||||
* Sets the inject hook type. Different types allow for maximum compatibility.
|
||||
* @author Kristian
|
||||
*/
|
||||
public enum PlayerInjectHooks {
|
||||
/**
|
||||
* The injection hook that does nothing. Set when every other inject hook fails.
|
||||
*/
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Override the network handler object itself. Only works in 1.3.
|
||||
* <p>
|
||||
* Cannot intercept MapChunk packets.
|
||||
*/
|
||||
NETWORK_MANAGER_OBJECT,
|
||||
|
||||
/**
|
||||
* Override the packet queue lists in NetworkHandler.
|
||||
* <p>
|
||||
* Cannot intercept MapChunk packets.
|
||||
*/
|
||||
NETWORK_HANDLER_FIELDS,
|
||||
|
||||
/**
|
||||
* Override the server handler object. Versatile, but a tad slower.
|
||||
*/
|
||||
NETWORK_SERVER_OBJECT;
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+5
-3
@@ -67,9 +67,11 @@ public class StructureCache {
|
||||
// TODO: Optimize DefaultInstances
|
||||
Object result = DefaultInstances.DEFAULT.create(clazz);
|
||||
|
||||
if (result != null) {
|
||||
return result;
|
||||
if (result == null) {
|
||||
throw new IllegalArgumentException("Failed to create packet for type: " + type);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
throw new IllegalArgumentException("Cannot find associated packet class: " + type);
|
||||
}
|
||||
@@ -172,4 +174,4 @@ public class StructureCache {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
-3
@@ -14,7 +14,7 @@
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty.independent;
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import io.netty.buffer.AbstractByteBuf;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
@@ -28,6 +28,7 @@ import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
@@ -44,6 +45,7 @@ import com.google.common.io.ByteStreams;
|
||||
* all indexing in the byte buffer.
|
||||
* @author Kristian
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class NettyByteBufAdapter extends AbstractByteBuf {
|
||||
private DataInputStream input;
|
||||
private DataOutputStream output;
|
||||
@@ -214,7 +216,7 @@ public class NettyByteBufAdapter extends AbstractByteBuf {
|
||||
|
||||
@Override
|
||||
public ByteBufAllocator alloc() {
|
||||
return null;
|
||||
return ByteBufAllocator.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -389,4 +391,48 @@ public class NettyByteBufAdapter extends AbstractByteBuf {
|
||||
public ByteBuf retain() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
protected int _getIntLE(int arg0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected long _getLongLE(int arg0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected short _getShortLE(int arg0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected int _getUnsignedMediumLE(int arg0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected void _setIntLE(int arg0, int arg1) {
|
||||
}
|
||||
|
||||
protected void _setLongLE(int arg0, long arg1) {
|
||||
}
|
||||
|
||||
protected void _setMediumLE(int arg0, int arg1) {
|
||||
}
|
||||
|
||||
protected void _setShortLE(int arg0, int arg1) {
|
||||
}
|
||||
|
||||
public int getBytes(int arg0, FileChannel arg1, long arg2, int arg3) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int setBytes(int arg0, FileChannel arg1, long arg2, int arg3) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ByteBuf touch() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ByteBuf touch(Object arg0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+108
-104
@@ -1,104 +1,108 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.compat.netty.independent;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.PacketType.Protocol;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.injector.netty.ProtocolRegistry;
|
||||
import com.comphenix.protocol.injector.packet.MapContainer;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class NettyProtocolRegistry extends ProtocolRegistry {
|
||||
|
||||
@Override
|
||||
protected synchronized void initialize() {
|
||||
Object[] protocols = enumProtocol.getEnumConstants();
|
||||
|
||||
// ID to Packet class maps
|
||||
Map<Object, Map<Integer, Class<?>>> serverMaps = Maps.newLinkedHashMap();
|
||||
Map<Object, Map<Integer, Class<?>>> clientMaps = Maps.newLinkedHashMap();
|
||||
|
||||
Register result = new Register();
|
||||
StructureModifier<Object> modifier = null;
|
||||
|
||||
// Iterate through the protocols
|
||||
for (Object protocol : protocols) {
|
||||
if (modifier == null)
|
||||
modifier = new StructureModifier<Object>(protocol.getClass().getSuperclass(), false);
|
||||
StructureModifier<Map<Object, Map<Integer, Class<?>>>> maps = modifier.withTarget(protocol).withType(Map.class);
|
||||
for (Entry<Object, Map<Integer, Class<?>>> entry : maps.read(0).entrySet()) {
|
||||
String direction = entry.getKey().toString();
|
||||
if (direction.contains("CLIENTBOUND")) { // Sent by Server
|
||||
serverMaps.put(protocol, entry.getValue());
|
||||
} else if (direction.contains("SERVERBOUND")) { // Sent by Client
|
||||
clientMaps.put(protocol, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maps we have to occationally check have changed
|
||||
for (Map<Integer, Class<?>> map : serverMaps.values()) {
|
||||
result.containers.add(new MapContainer(map));
|
||||
}
|
||||
|
||||
for (Map<Integer, Class<?>> map : clientMaps.values()) {
|
||||
result.containers.add(new MapContainer(map));
|
||||
}
|
||||
|
||||
for (int i = 0; i < protocols.length; i++) {
|
||||
Object protocol = protocols[i];
|
||||
Enum<?> enumProtocol = (Enum<?>) protocol;
|
||||
Protocol equivalent = Protocol.fromVanilla(enumProtocol);
|
||||
|
||||
// Associate known types
|
||||
if (serverMaps.containsKey(protocol))
|
||||
associatePackets(result, serverMaps.get(protocol), equivalent, Sender.SERVER);
|
||||
if (clientMaps.containsKey(protocol))
|
||||
associatePackets(result, clientMaps.get(protocol), equivalent, Sender.CLIENT);
|
||||
}
|
||||
|
||||
// Exchange (thread safe, as we have only one writer)
|
||||
this.register = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void associatePackets(Register register, Map<Integer, Class<?>> lookup, Protocol protocol, Sender sender) {
|
||||
for (Entry<Integer, Class<?>> entry : lookup.entrySet()) {
|
||||
PacketType type = PacketType.fromCurrent(protocol, sender, entry.getKey(), entry.getValue());
|
||||
|
||||
try {
|
||||
register.typeToClass.put(type, entry.getValue());
|
||||
|
||||
if (sender == Sender.SERVER)
|
||||
register.serverPackets.add(type);
|
||||
if (sender == Sender.CLIENT)
|
||||
register.clientPackets.add(type);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Sometimes this happens with fake packets, just ignore it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLogger;
|
||||
import com.comphenix.protocol.PacketType.Protocol;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.injector.netty.ProtocolRegistry;
|
||||
import com.comphenix.protocol.injector.packet.MapContainer;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class NettyProtocolRegistry extends ProtocolRegistry {
|
||||
|
||||
public NettyProtocolRegistry() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void initialize() {
|
||||
Object[] protocols = enumProtocol.getEnumConstants();
|
||||
|
||||
// ID to Packet class maps
|
||||
Map<Object, Map<Integer, Class<?>>> serverMaps = Maps.newLinkedHashMap();
|
||||
Map<Object, Map<Integer, Class<?>>> clientMaps = Maps.newLinkedHashMap();
|
||||
|
||||
Register result = new Register();
|
||||
StructureModifier<Object> modifier = null;
|
||||
|
||||
// Iterate through the protocols
|
||||
for (Object protocol : protocols) {
|
||||
if (modifier == null)
|
||||
modifier = new StructureModifier<Object>(protocol.getClass().getSuperclass(), false);
|
||||
StructureModifier<Map<Object, Map<Integer, Class<?>>>> maps = modifier.withTarget(protocol).withType(Map.class);
|
||||
for (Entry<Object, Map<Integer, Class<?>>> entry : maps.read(0).entrySet()) {
|
||||
String direction = entry.getKey().toString();
|
||||
if (direction.contains("CLIENTBOUND")) { // Sent by Server
|
||||
serverMaps.put(protocol, entry.getValue());
|
||||
} else if (direction.contains("SERVERBOUND")) { // Sent by Client
|
||||
clientMaps.put(protocol, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maps we have to occasionally check have changed
|
||||
for (Map<Integer, Class<?>> map : serverMaps.values()) {
|
||||
result.containers.add(new MapContainer(map));
|
||||
}
|
||||
|
||||
for (Map<Integer, Class<?>> map : clientMaps.values()) {
|
||||
result.containers.add(new MapContainer(map));
|
||||
}
|
||||
|
||||
for (Object protocol : protocols) {
|
||||
Enum<?> enumProtocol = (Enum<?>) protocol;
|
||||
Protocol equivalent = Protocol.fromVanilla(enumProtocol);
|
||||
|
||||
// Associate known types
|
||||
if (serverMaps.containsKey(protocol))
|
||||
associatePackets(result, serverMaps.get(protocol), equivalent, Sender.SERVER);
|
||||
if (clientMaps.containsKey(protocol))
|
||||
associatePackets(result, clientMaps.get(protocol), equivalent, Sender.CLIENT);
|
||||
}
|
||||
|
||||
// Exchange (thread safe, as we have only one writer)
|
||||
this.register = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void associatePackets(Register register, Map<Integer, Class<?>> lookup, Protocol protocol, Sender sender) {
|
||||
for (Entry<Integer, Class<?>> entry : lookup.entrySet()) {
|
||||
PacketType type = PacketType.fromCurrent(protocol, sender, entry.getKey(), entry.getValue());
|
||||
|
||||
try {
|
||||
register.typeToClass.put(type, entry.getValue());
|
||||
|
||||
if (sender == Sender.SERVER)
|
||||
register.serverPackets.add(type);
|
||||
if (sender == Sender.CLIENT)
|
||||
register.clientPackets.add(type);
|
||||
} catch (Exception ex) {
|
||||
ProtocolLogger.debug("Encountered an exception associating packet " + type, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -19,7 +19,7 @@ import com.google.common.collect.Sets;
|
||||
* Represents a way of accessing the new netty Protocol enum.
|
||||
* @author Kristian
|
||||
*/
|
||||
// TODO: Handle modifications to the BiMap
|
||||
|
||||
public abstract class ProtocolRegistry {
|
||||
/**
|
||||
* Represents a register we are currently building.
|
||||
@@ -97,7 +97,7 @@ public abstract class ProtocolRegistry {
|
||||
* This operation may block the calling thread.
|
||||
*/
|
||||
public synchronized void synchronize() {
|
||||
// See if the register is outdated
|
||||
// Check if the packet registry has changed
|
||||
if (register.isOutdated()) {
|
||||
initialize();
|
||||
}
|
||||
@@ -122,4 +122,4 @@ public abstract class ProtocolRegistry {
|
||||
count += map.size();
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program;
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.utility.MinecraftMethods;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* A packet represented only by its id and bytes.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class WirePacket {
|
||||
private final int id;
|
||||
private final byte[] bytes;
|
||||
|
||||
/**
|
||||
* Constructs a new WirePacket with a given type and contents
|
||||
* @param type Type of the packet
|
||||
* @param bytes Contents of the packet
|
||||
*/
|
||||
public WirePacket(PacketType type, byte[] bytes) {
|
||||
this.id = checkNotNull(type, "type cannot be null").getCurrentId();
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new WirePacket with a given id and contents
|
||||
* @param id ID of the packet
|
||||
* @param bytes Contents of the packet
|
||||
*/
|
||||
public WirePacket(int id, byte[] bytes) {
|
||||
this.id = id;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this packet's ID
|
||||
* @return The ID
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this packet's contents as a byte array
|
||||
* @return The contents
|
||||
*/
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the id of this packet to a given output
|
||||
* @param output Output to write to
|
||||
*/
|
||||
public void writeId(ByteBuf output) {
|
||||
writeVarInt(output, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the contents of this packet to a given output
|
||||
* @param output Output to write to
|
||||
*/
|
||||
public void writeBytes(ByteBuf output) {
|
||||
checkNotNull(output, "output cannot be null!");
|
||||
output.writeBytes(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully writes the ID and contents of this packet to a given output
|
||||
* @param output Output to write to
|
||||
*/
|
||||
public void writeFully(ByteBuf output) {
|
||||
writeId(output);
|
||||
writeBytes(output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes this packet into a byte buffer
|
||||
* @return The buffer
|
||||
*/
|
||||
public ByteBuf serialize() {
|
||||
ByteBuf buffer = Unpooled.buffer();
|
||||
writeFully(buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
|
||||
if (obj instanceof WirePacket) {
|
||||
WirePacket that = (WirePacket) obj;
|
||||
return this.id == that.id &&
|
||||
Arrays.equals(this.bytes, that.bytes);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(bytes);
|
||||
result = prime * result + id;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WirePacket[id=" + id + ", bytes=" + Arrays.toString(bytes) + "]";
|
||||
}
|
||||
|
||||
private static byte[] getBytes(ByteBuf buffer) {
|
||||
byte[] array = new byte[buffer.readableBytes()];
|
||||
buffer.readBytes(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a WirePacket from an existing PacketContainer
|
||||
* @param packet Existing packet
|
||||
* @return The resulting WirePacket
|
||||
*/
|
||||
public static WirePacket fromPacket(PacketContainer packet) {
|
||||
int id = packet.getType().getCurrentId();
|
||||
return new WirePacket(id, bytesFromPacket(packet));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a byte array from an existing PacketContainer containing all the
|
||||
* bytes from that packet
|
||||
*
|
||||
* @param packet Existing packet
|
||||
* @return The ByteBuf
|
||||
*/
|
||||
public static byte[] bytesFromPacket(PacketContainer packet) {
|
||||
checkNotNull(packet, "packet cannot be null!");
|
||||
|
||||
ByteBuf buffer = PacketContainer.createPacketBuffer();
|
||||
ByteBuf store = PacketContainer.createPacketBuffer();
|
||||
|
||||
// Read the bytes once
|
||||
Method write = MinecraftMethods.getPacketWriteByteBufMethod();
|
||||
|
||||
try {
|
||||
write.invoke(packet.getHandle(), buffer);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new RuntimeException("Failed to read packet contents.", ex);
|
||||
}
|
||||
|
||||
byte[] bytes = getBytes(buffer);
|
||||
|
||||
// Rewrite them to the packet to avoid issues with certain packets
|
||||
if (packet.getType() == PacketType.Play.Server.CUSTOM_PAYLOAD
|
||||
|| packet.getType() == PacketType.Play.Client.CUSTOM_PAYLOAD) {
|
||||
// Make a copy of the array before writing
|
||||
byte[] ret = Arrays.copyOf(bytes, bytes.length);
|
||||
store.writeBytes(bytes);
|
||||
|
||||
Method read = MinecraftMethods.getPacketReadByteBufMethod();
|
||||
|
||||
try {
|
||||
read.invoke(packet.getHandle(), store);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new RuntimeException("Failed to rewrite packet contents.", ex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a WirePacket from an existing Minecraft packet
|
||||
* @param packet Existing Minecraft packet
|
||||
* @return The resulting WirePacket
|
||||
* @throws IllegalArgumentException If the packet is null or not a Minecraft packet
|
||||
*/
|
||||
public static WirePacket fromPacket(Object packet) {
|
||||
checkNotNull(packet, "packet cannot be null!");
|
||||
checkArgument(MinecraftReflection.isPacketClass(packet), "packet must be a Minecraft packet");
|
||||
|
||||
PacketType type = PacketType.fromClass(packet.getClass());
|
||||
int id = type.getCurrentId();
|
||||
|
||||
ByteBuf buffer = PacketContainer.createPacketBuffer();
|
||||
Method write = MinecraftMethods.getPacketWriteByteBufMethod();
|
||||
|
||||
try {
|
||||
write.invoke(packet, buffer);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new RuntimeException("Failed to serialize packet contents.", ex);
|
||||
}
|
||||
|
||||
return new WirePacket(id, getBytes(buffer));
|
||||
}
|
||||
|
||||
public static void writeVarInt(ByteBuf output, int i) {
|
||||
checkNotNull(output, "output cannot be null!");
|
||||
|
||||
while ((i & -128) != 0) {
|
||||
output.writeByte(i & 127 | 128);
|
||||
i >>>= 7;
|
||||
}
|
||||
|
||||
output.writeByte(i);
|
||||
}
|
||||
|
||||
public static int readVarInt(ByteBuf input) {
|
||||
checkNotNull(input, "input cannot be null!");
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
byte b0;
|
||||
|
||||
do {
|
||||
b0 = input.readByte();
|
||||
i |= (b0 & 127) << j++ * 7;
|
||||
if (j > 5) {
|
||||
throw new RuntimeException("VarInt too big");
|
||||
}
|
||||
} while ((b0 & 128) == 128);
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
+13
-9
@@ -3,6 +3,7 @@ package com.comphenix.protocol.injector.packet;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.comphenix.protocol.reflect.FieldUtils;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a class that can detect if a map has changed.
|
||||
@@ -10,17 +11,20 @@ import com.comphenix.protocol.reflect.FieldUtils;
|
||||
*/
|
||||
public class MapContainer {
|
||||
// For detecting changes
|
||||
private Field modCountField;
|
||||
private final Field modCountField;
|
||||
private int lastModCount;
|
||||
|
||||
// The object along with whether or not this is the initial run
|
||||
private Object source;
|
||||
private final Object source;
|
||||
private boolean changed;
|
||||
|
||||
public MapContainer(Object source) {
|
||||
this.source = source;
|
||||
this.changed = true;
|
||||
this.modCountField = FieldUtils.getField(source.getClass(), "modCount", true);
|
||||
this.changed = false;
|
||||
|
||||
Field modCountField = FieldUtils.getField(source.getClass(), "modCount", true);
|
||||
this.modCountField = checkNotNull(modCountField, "Could not obtain modCount field");
|
||||
this.lastModCount = getModificationCount();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,13 +59,13 @@ public class MapContainer {
|
||||
|
||||
/**
|
||||
* Retrieve the current modification count.
|
||||
* @return The current count, or something different than lastModCount if not accessible.
|
||||
* @return The current count
|
||||
*/
|
||||
private int getModificationCount() {
|
||||
try {
|
||||
return modCountField != null ? modCountField.getInt(source) : lastModCount + 1;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to retrieve modCount.", e);
|
||||
return modCountField.getInt(source);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new RuntimeException("Unable to retrieve modCount.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+82
-176
@@ -18,23 +18,18 @@
|
||||
package com.comphenix.protocol.injector.packet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.compat.netty.LegacyProtocolRegistry;
|
||||
import com.comphenix.protocol.compat.netty.independent.NettyProtocolRegistry;
|
||||
import com.comphenix.protocol.error.Report;
|
||||
import com.comphenix.protocol.error.ReportType;
|
||||
import com.comphenix.protocol.injector.netty.NettyProtocolRegistry;
|
||||
import com.comphenix.protocol.injector.netty.ProtocolRegistry;
|
||||
import com.comphenix.protocol.injector.packet.LegacyPacketRegistry.InsufficientPacketsException;
|
||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
import com.comphenix.protocol.wrappers.TroveWrapper.CannotFindTroveNoEntryValue;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -50,45 +45,30 @@ public class PacketRegistry {
|
||||
public static final ReportType REPORT_INSUFFICIENT_SERVER_PACKETS = new ReportType("Too few server packets detected: %s");
|
||||
public static final ReportType REPORT_INSUFFICIENT_CLIENT_PACKETS = new ReportType("Too few client packets detected: %s");
|
||||
|
||||
// Two different packet registry
|
||||
private static volatile LegacyPacketRegistry LEGACY;
|
||||
// The Netty packet registry
|
||||
private static volatile ProtocolRegistry NETTY;
|
||||
|
||||
// Cached for legacy
|
||||
private static volatile Set<PacketType> NETTY_SERVER_PACKETS;
|
||||
private static volatile Set<PacketType> NETTY_CLIENT_PACKETS;
|
||||
|
||||
|
||||
// Cached for Netty
|
||||
private static volatile Set<Integer> LEGACY_SERVER_PACKETS;
|
||||
private static volatile Set<Integer> LEGACY_CLIENT_PACKETS;
|
||||
private static volatile Map<Integer, Class> LEGACY_PREVIOUS_PACKETS;
|
||||
|
||||
// Whether or not the registry has
|
||||
private static boolean INITIALIZED;
|
||||
|
||||
|
||||
// Whether or not the registry has been initialized
|
||||
private static volatile boolean INITIALIZED = false;
|
||||
|
||||
/**
|
||||
* Initialize the packet registry.
|
||||
* Initializes the packet registry.
|
||||
*/
|
||||
private static void initialize() {
|
||||
if (INITIALIZED) {
|
||||
// Make sure they were initialized
|
||||
if (NETTY == null && LEGACY == null)
|
||||
throw new IllegalStateException("No initialized registry.");
|
||||
if (NETTY == null) {
|
||||
throw new IllegalStateException("Failed to initialize packet registry.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for netty
|
||||
if (MinecraftReflection.isUsingNetty()) {
|
||||
if (NETTY == null) {
|
||||
if (MinecraftVersion.getCurrentVersion().isAtLeast(MinecraftVersion.BOUNTIFUL_UPDATE)) {
|
||||
NETTY = new NettyProtocolRegistry();
|
||||
} else {
|
||||
NETTY = new LegacyProtocolRegistry();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
initializeLegacy();
|
||||
}
|
||||
|
||||
NETTY = new NettyProtocolRegistry();
|
||||
INITIALIZED = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,41 +78,9 @@ public class PacketRegistry {
|
||||
*/
|
||||
public static boolean isSupported(PacketType type) {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null)
|
||||
return NETTY.getPacketTypeLookup().containsKey(type);
|
||||
|
||||
// Look up the correct type
|
||||
return type.isClient() ?
|
||||
LEGACY.getClientPackets().contains(type.getLegacyId()) :
|
||||
LEGACY.getServerPackets().contains(type.getLegacyId());
|
||||
return NETTY.getPacketTypeLookup().containsKey(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the legacy packet registry.
|
||||
*/
|
||||
private static void initializeLegacy() {
|
||||
if (LEGACY == null) {
|
||||
try {
|
||||
LEGACY = new LegacyPacketRegistry();
|
||||
LEGACY.initialize();
|
||||
} catch (InsufficientPacketsException e) {
|
||||
if (e.isClient()) {
|
||||
ProtocolLibrary.getErrorReporter().reportWarning(
|
||||
PacketRegistry.class, Report.newBuilder(REPORT_INSUFFICIENT_CLIENT_PACKETS).messageParam(e.getPacketCount())
|
||||
);
|
||||
} else {
|
||||
ProtocolLibrary.getErrorReporter().reportWarning(
|
||||
PacketRegistry.class, Report.newBuilder(REPORT_INSUFFICIENT_SERVER_PACKETS).messageParam(e.getPacketCount())
|
||||
);
|
||||
}
|
||||
} catch (CannotFindTroveNoEntryValue e) {
|
||||
ProtocolLibrary.getErrorReporter().reportWarning(PacketRegistry.class,
|
||||
Report.newBuilder(REPORT_CANNOT_CORRECT_TROVE_MAP).error(e.getCause()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a map of every packet class to every ID.
|
||||
* <p>
|
||||
@@ -142,38 +90,29 @@ public class PacketRegistry {
|
||||
@Deprecated
|
||||
public static Map<Class, Integer> getPacketToID() {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Class, Integer> result = (Map)Maps.transformValues(NETTY.getPacketClassLookup(), new Function<PacketType, Integer>() {
|
||||
@Override
|
||||
public Integer apply(PacketType type) {
|
||||
return type.getLegacyId();
|
||||
};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
return LEGACY.getPacketToID();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Class, Integer> result = (Map) Maps.transformValues(
|
||||
NETTY.getPacketClassLookup(),
|
||||
new Function<PacketType, Integer>() {
|
||||
@Override
|
||||
public Integer apply(PacketType type) {
|
||||
return type.getLegacyId();
|
||||
};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a map of every packet class to the respective packet type.
|
||||
* @return A map of packet classes and their corresponding packet type.
|
||||
*/
|
||||
public static Map<Class, PacketType> getPacketToType() {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Class, PacketType> result = (Map)NETTY.getPacketClassLookup();
|
||||
return result;
|
||||
}
|
||||
return Maps.transformValues(LEGACY.getPacketToID(), new Function<Integer, PacketType>() {
|
||||
@Override
|
||||
public PacketType apply(Integer packetId) {
|
||||
return PacketType.findLegacy(packetId);
|
||||
};
|
||||
});
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Class, PacketType> result = (Map) NETTY.getPacketClassLookup();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,12 +124,9 @@ public class PacketRegistry {
|
||||
@Deprecated
|
||||
public static Map<Integer, Class> getOverwrittenPackets() {
|
||||
initialize();
|
||||
|
||||
if (LEGACY != null)
|
||||
return LEGACY.getOverwrittenPackets();
|
||||
throw new IllegalStateException("Not supported on Netty.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the vanilla classes handling each packet ID.
|
||||
* @return Vanilla classes.
|
||||
@@ -198,22 +134,19 @@ public class PacketRegistry {
|
||||
@Deprecated
|
||||
public static Map<Integer, Class> getPreviousPackets() {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null) {
|
||||
// Construct it first
|
||||
if (LEGACY_PREVIOUS_PACKETS == null) {
|
||||
Map<Integer, Class> map = Maps.newHashMap();
|
||||
|
||||
for (Entry<PacketType, Class<?>> entry : NETTY.getPacketTypeLookup().entrySet()) {
|
||||
map.put(entry.getKey().getLegacyId(), entry.getValue());
|
||||
}
|
||||
LEGACY_PREVIOUS_PACKETS = Collections.unmodifiableMap(map);
|
||||
|
||||
// Construct it first
|
||||
if (LEGACY_PREVIOUS_PACKETS == null) {
|
||||
Map<Integer, Class> map = Maps.newHashMap();
|
||||
|
||||
for (Entry<PacketType, Class<?>> entry : NETTY.getPacketTypeLookup().entrySet()) {
|
||||
map.put(entry.getKey().getLegacyId(), entry.getValue());
|
||||
}
|
||||
return LEGACY_PREVIOUS_PACKETS;
|
||||
LEGACY_PREVIOUS_PACKETS = Collections.unmodifiableMap(map);
|
||||
}
|
||||
return LEGACY.getPreviousPackets();
|
||||
return LEGACY_PREVIOUS_PACKETS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve every known and supported server packet.
|
||||
* <p>
|
||||
@@ -223,15 +156,11 @@ public class PacketRegistry {
|
||||
*/
|
||||
@Deprecated
|
||||
public static Set<Integer> getServerPackets() throws FieldAccessException {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null) {
|
||||
if (LEGACY_SERVER_PACKETS == null) {
|
||||
LEGACY_SERVER_PACKETS = toLegacy(NETTY.getServerPackets());
|
||||
}
|
||||
return LEGACY_SERVER_PACKETS;
|
||||
if (LEGACY_SERVER_PACKETS == null) {
|
||||
LEGACY_SERVER_PACKETS = toLegacy(getServerPacketTypes());
|
||||
}
|
||||
return LEGACY.getServerPackets();
|
||||
|
||||
return LEGACY_SERVER_PACKETS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,17 +169,9 @@ public class PacketRegistry {
|
||||
*/
|
||||
public static Set<PacketType> getServerPacketTypes() {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null) {
|
||||
NETTY.synchronize();
|
||||
return NETTY.getServerPackets();
|
||||
}
|
||||
|
||||
// Handle legacy
|
||||
if (NETTY_SERVER_PACKETS == null) {
|
||||
NETTY_SERVER_PACKETS = toPacketTypes(LEGACY.getServerPackets(), Sender.SERVER);
|
||||
}
|
||||
return NETTY_SERVER_PACKETS;
|
||||
NETTY.synchronize();
|
||||
|
||||
return NETTY.getServerPackets();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,15 +183,11 @@ public class PacketRegistry {
|
||||
*/
|
||||
@Deprecated
|
||||
public static Set<Integer> getClientPackets() throws FieldAccessException {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null) {
|
||||
if (LEGACY_CLIENT_PACKETS == null) {
|
||||
LEGACY_CLIENT_PACKETS = toLegacy(NETTY.getClientPackets());
|
||||
}
|
||||
return LEGACY_CLIENT_PACKETS;
|
||||
if (LEGACY_CLIENT_PACKETS == null) {
|
||||
LEGACY_CLIENT_PACKETS = toLegacy(getClientPacketTypes());
|
||||
}
|
||||
return LEGACY.getClientPackets();
|
||||
|
||||
return LEGACY_CLIENT_PACKETS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -279,17 +196,9 @@ public class PacketRegistry {
|
||||
*/
|
||||
public static Set<PacketType> getClientPacketTypes() {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null) {
|
||||
NETTY.synchronize();
|
||||
return NETTY.getClientPackets();
|
||||
}
|
||||
|
||||
// Handle legacy
|
||||
if (NETTY_CLIENT_PACKETS == null) {
|
||||
NETTY_CLIENT_PACKETS = toPacketTypes(LEGACY.getClientPackets(), Sender.CLIENT);
|
||||
}
|
||||
return NETTY_CLIENT_PACKETS;
|
||||
NETTY.synchronize();
|
||||
|
||||
return NETTY.getClientPackets();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -338,10 +247,7 @@ public class PacketRegistry {
|
||||
@Deprecated
|
||||
public static Class getPacketClassFromID(int packetID) {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null)
|
||||
return NETTY.getPacketTypeLookup().get(PacketType.findLegacy(packetID));
|
||||
return LEGACY.getPacketClassFromID(packetID);
|
||||
return NETTY.getPacketTypeLookup().get(PacketType.findLegacy(packetID));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,12 +269,26 @@ public class PacketRegistry {
|
||||
*/
|
||||
public static Class getPacketClassFromType(PacketType type, boolean forceVanilla) {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null)
|
||||
return NETTY.getPacketTypeLookup().get(type);
|
||||
return LEGACY.getPacketClassFromID(type.getLegacyId(), forceVanilla);
|
||||
|
||||
// Try the lookup first
|
||||
Class<?> clazz = NETTY.getPacketTypeLookup().get(type);
|
||||
if (clazz != null) {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
// Then try looking up the class names
|
||||
for (String name : type.getClassNames()) {
|
||||
try {
|
||||
clazz = MinecraftReflection.getMinecraftClass(name);
|
||||
break;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Cache the result?
|
||||
return clazz;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the correct packet class from a given packet ID.
|
||||
* <p>
|
||||
@@ -380,12 +300,9 @@ public class PacketRegistry {
|
||||
@Deprecated
|
||||
public static Class getPacketClassFromID(int packetID, boolean forceVanilla) {
|
||||
initialize();
|
||||
|
||||
if (LEGACY != null)
|
||||
return LEGACY.getPacketClassFromID(packetID, forceVanilla);
|
||||
return getPacketClassFromID(packetID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the packet ID of a given packet.
|
||||
* <p>
|
||||
@@ -397,12 +314,9 @@ public class PacketRegistry {
|
||||
@Deprecated
|
||||
public static int getPacketID(Class<?> packet) {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null)
|
||||
return NETTY.getPacketClassLookup().get(packet).getLegacyId();
|
||||
return LEGACY.getPacketID(packet);
|
||||
return NETTY.getPacketClassLookup().get(packet).getLegacyId();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the packet type of a given packet.
|
||||
* @param packet - the class of the packet.
|
||||
@@ -420,14 +334,6 @@ public class PacketRegistry {
|
||||
*/
|
||||
public static PacketType getPacketType(Class<?> packet, Sender sender) {
|
||||
initialize();
|
||||
|
||||
if (NETTY != null) {
|
||||
return NETTY.getPacketClassLookup().get(packet);
|
||||
} else {
|
||||
final int id = LEGACY.getPacketID(packet);
|
||||
|
||||
return PacketType.hasLegacy(id) ?
|
||||
PacketType.fromLegacy(id, sender) : null;
|
||||
}
|
||||
return NETTY.getPacketClassLookup().get(packet);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -11,4 +11,4 @@
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
package com.comphenix.protocol;
|
||||
package com.comphenix.protocol;
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+63
-9
@@ -17,10 +17,7 @@
|
||||
|
||||
package com.comphenix.protocol.reflect;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -29,6 +26,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.fuzzy.AbstractFuzzyMatcher;
|
||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||
@@ -168,13 +167,42 @@ public class FuzzyReflection {
|
||||
*/
|
||||
public Method getMethod(AbstractFuzzyMatcher<MethodInfo> matcher) {
|
||||
List<Method> result = getMethodList(matcher);
|
||||
|
||||
if (result.size() > 0)
|
||||
|
||||
if (result.size() > 0) {
|
||||
return result.get(0);
|
||||
else
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unable to find a method that matches " + matcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a method that matches. If there are multiple methods that match, the first one with the preferred
|
||||
* name is selected.
|
||||
* <p>
|
||||
* ForceAccess must be TRUE in order for this method to access private, protected and package level method.
|
||||
* @param matcher - the matcher to use.
|
||||
* @param preferred - the preferred name.
|
||||
* @return The first method that satisfies the given matcher.
|
||||
* @throws IllegalArgumentException If the method cannot be found.
|
||||
*/
|
||||
public Method getMethod(AbstractFuzzyMatcher<MethodInfo> matcher, String preferred) {
|
||||
List<Method> result = getMethodList(matcher);
|
||||
|
||||
if (result.size() > 1) {
|
||||
for (Method method : result) {
|
||||
if (method.getName().equals(preferred)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.size() > 0) {
|
||||
return result.get(0);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unable to find a method that matches " + matcher);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a list of every method that matches the given matcher.
|
||||
* <p>
|
||||
@@ -390,6 +418,30 @@ public class FuzzyReflection {
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a field with a given type and parameters. This is most useful
|
||||
* when dealing with Collections.
|
||||
*
|
||||
* @param fieldType Type of the field
|
||||
* @param params Variable length array of type parameters
|
||||
* @return The field
|
||||
*
|
||||
* @throws IllegalArgumentException If the field cannot be found
|
||||
*/
|
||||
public Field getParameterizedField(Class<?> fieldType, Class<?>... params) {
|
||||
for (Field field : getFields()) {
|
||||
if (field.getType().equals(fieldType)) {
|
||||
Type type = field.getGenericType();
|
||||
if (type instanceof ParameterizedType) {
|
||||
if (Arrays.equals(((ParameterizedType) type).getActualTypeArguments(), params))
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unable to find a field with type " + fieldType + " and params " + Arrays.toString(params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the first field that matches.
|
||||
@@ -548,6 +600,8 @@ public class FuzzyReflection {
|
||||
* @return Every field.
|
||||
*/
|
||||
public Set<Field> getFields() {
|
||||
Validate.notNull(source, "source cannot be null!");
|
||||
|
||||
// We will only consider private fields in the declared class
|
||||
if (forceAccess)
|
||||
return setUnion(source.getDeclaredFields(), source.getFields());
|
||||
@@ -603,7 +657,7 @@ public class FuzzyReflection {
|
||||
|
||||
// Prevent duplicate fields
|
||||
|
||||
// @SafeVarargs
|
||||
@SafeVarargs
|
||||
private static <T> Set<T> setUnion(T[]... array) {
|
||||
Set<T> result = new LinkedHashSet<T>();
|
||||
|
||||
Loaded 100 of 359 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user