mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2024-11-27 21:26:17 +01:00
parent
13b905e762
commit
0e6a7a39a0
@ -46,6 +46,7 @@ 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;
|
||||
@ -86,6 +87,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;
|
||||
@ -578,12 +580,11 @@ 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>
|
||||
@ -845,6 +846,26 @@ 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the ID of this packet.
|
||||
* <p>
|
||||
|
@ -1341,6 +1341,11 @@ public class MinecraftReflection {
|
||||
return getMinecraftClass("MinecraftKey");
|
||||
}
|
||||
|
||||
public static Class<?> getMobEffectListClass() {
|
||||
// TODO Implement a fallback
|
||||
return getMinecraftClass("MobEffectList");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the ServerConnection abstract class.
|
||||
* @return The ServerConnection class.
|
||||
|
@ -1105,7 +1105,7 @@ public class BukkitConverters {
|
||||
put(MinecraftReflection.getItemStackClass(), (EquivalentConverter) getItemStackConverter()).
|
||||
put(MinecraftReflection.getNBTBaseClass(), (EquivalentConverter) getNbtConverter()).
|
||||
put(MinecraftReflection.getNBTCompoundClass(), (EquivalentConverter) getNbtConverter()).
|
||||
put(MinecraftReflection.getWatchableObjectClass(), (EquivalentConverter) getWatchableObjectConverter()).
|
||||
put(MinecraftReflection.getDataWatcherItemClass(), (EquivalentConverter) getWatchableObjectConverter()).
|
||||
put(MinecraftReflection.getMobEffectClass(), (EquivalentConverter) getPotionEffectConverter()).
|
||||
put(MinecraftReflection.getNmsWorldClass(), (EquivalentConverter) getWorldConverter());
|
||||
|
||||
@ -1146,4 +1146,38 @@ public class BukkitConverters {
|
||||
}
|
||||
return unwrappers;
|
||||
}
|
||||
|
||||
private static MethodAccessor getMobEffectId = null;
|
||||
private static MethodAccessor getMobEffect = null;
|
||||
|
||||
public static EquivalentConverter<PotionEffectType> getEffectTypeConverter() {
|
||||
return new IgnoreNullConverter<PotionEffectType>() {
|
||||
|
||||
@Override
|
||||
public Class<PotionEffectType> getSpecificType() {
|
||||
return PotionEffectType.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getGenericValue(Class<?> genericType, PotionEffectType specific) {
|
||||
if (getMobEffect == null) {
|
||||
getMobEffect = Accessors.getMethodAccessor(genericType, "fromId", int.class);
|
||||
}
|
||||
|
||||
int id = specific.getId();
|
||||
return getMobEffect.invoke(null, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PotionEffectType getSpecificValue(Object generic) {
|
||||
Class<?> clazz = MinecraftReflection.getMobEffectListClass();
|
||||
if (getMobEffectId == null) {
|
||||
getMobEffectId = Accessors.getMethodAccessor(clazz, "getId", clazz);
|
||||
}
|
||||
|
||||
int id = (int) getMobEffectId.invoke(null, generic);
|
||||
return PotionEffectType.getById(id);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -272,6 +272,40 @@ public abstract class EnumWrappers {
|
||||
}
|
||||
}
|
||||
|
||||
public enum SoundCategory {
|
||||
MASTER("master"),
|
||||
MUSIC("music"),
|
||||
RECORDS("record"),
|
||||
WEATHER("weather"),
|
||||
BLOCKS("block"),
|
||||
HOSTILE("hostile"),
|
||||
NEUTRAL("neutral"),
|
||||
PLAYERS("player"),
|
||||
AMBIENT("ambient"),
|
||||
VOICE("voice");
|
||||
|
||||
private static final Map<String, SoundCategory> LOOKUP;
|
||||
static {
|
||||
LOOKUP = new HashMap<>();
|
||||
for (SoundCategory category : values()) {
|
||||
LOOKUP.put(category.key, category);
|
||||
}
|
||||
}
|
||||
|
||||
private final String key;
|
||||
private SoundCategory(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public static SoundCategory getByKey(String key) {
|
||||
return LOOKUP.get(key.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> PROTOCOL_CLASS = null;
|
||||
private static Class<?> CLIENT_COMMAND_CLASS = null;
|
||||
private static Class<?> CHAT_VISIBILITY_CLASS = null;
|
||||
@ -287,6 +321,7 @@ public abstract class EnumWrappers {
|
||||
private static Class<?> PLAYER_ACTION_CLASS = null;
|
||||
private static Class<?> SCOREBOARD_ACTION_CLASS = null;
|
||||
private static Class<?> PARTICLE_CLASS = null;
|
||||
private static Class<?> SOUND_CATEGORY_CLASS = null;
|
||||
|
||||
private static boolean INITIALIZED = false;
|
||||
private static Map<Class<?>, EquivalentConverter<?>> FROM_NATIVE = Maps.newHashMap();
|
||||
@ -319,6 +354,7 @@ public abstract class EnumWrappers {
|
||||
PLAYER_ACTION_CLASS = getEnum(PacketType.Play.Client.ENTITY_ACTION.getPacketClass(), 0);
|
||||
SCOREBOARD_ACTION_CLASS = getEnum(PacketType.Play.Server.SCOREBOARD_SCORE.getPacketClass(), 0);
|
||||
PARTICLE_CLASS = getEnum(PacketType.Play.Server.WORLD_PARTICLES.getPacketClass(), 0);
|
||||
SOUND_CATEGORY_CLASS = getEnum(PacketType.Play.Server.CUSTOM_SOUND_EFFECT.getPacketClass(), 0);
|
||||
|
||||
associate(PROTOCOL_CLASS, Protocol.class, getClientCommandConverter());
|
||||
associate(CLIENT_COMMAND_CLASS, ClientCommand.class, getClientCommandConverter());
|
||||
@ -335,6 +371,7 @@ public abstract class EnumWrappers {
|
||||
associate(PLAYER_ACTION_CLASS, PlayerAction.class, getEntityActionConverter());
|
||||
associate(SCOREBOARD_ACTION_CLASS, ScoreboardAction.class, getUpdateScoreActionConverter());
|
||||
associate(PARTICLE_CLASS, Particle.class, getParticleConverter());
|
||||
associate(SOUND_CATEGORY_CLASS, SoundCategory.class, getSoundCategoryConverter());
|
||||
INITIALIZED = true;
|
||||
}
|
||||
|
||||
@ -443,6 +480,11 @@ public abstract class EnumWrappers {
|
||||
return PARTICLE_CLASS;
|
||||
}
|
||||
|
||||
public static Class<?> getSoundCategoryClass() {
|
||||
initialize();
|
||||
return SOUND_CATEGORY_CLASS;
|
||||
}
|
||||
|
||||
// Get the converters
|
||||
public static EquivalentConverter<Protocol> getProtocolConverter() {
|
||||
return new EnumConverter<Protocol>(Protocol.class);
|
||||
@ -504,6 +546,10 @@ public abstract class EnumWrappers {
|
||||
return new EnumConverter<Particle>(Particle.class);
|
||||
}
|
||||
|
||||
public static EquivalentConverter<SoundCategory> getSoundCategoryConverter() {
|
||||
return new EnumConverter<SoundCategory>(SoundCategory.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a generic enum converter for use with StructureModifiers.
|
||||
* @param enumClass - Enum class
|
||||
|
@ -25,37 +25,61 @@ import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Represents an immutable PlayerInfoData in the PLAYER_INFO packet.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class PlayerInfoData {
|
||||
private static Constructor<?> constructor;
|
||||
|
||||
protected final WrappedGameProfile profile;
|
||||
protected final int ping;
|
||||
protected final NativeGameMode gameMode;
|
||||
protected final WrappedChatComponent displayName;
|
||||
private final int latency;
|
||||
private final NativeGameMode gameMode;
|
||||
private final WrappedGameProfile profile;
|
||||
private final WrappedChatComponent displayName;
|
||||
|
||||
// This is the same order as the NMS class, minus the packet (which isn't a field)
|
||||
public PlayerInfoData(WrappedGameProfile profile, int ping, NativeGameMode gameMode, WrappedChatComponent displayName) {
|
||||
this.ping = ping;
|
||||
this.gameMode = gameMode;
|
||||
public PlayerInfoData(WrappedGameProfile profile, int latency, NativeGameMode gameMode, WrappedChatComponent displayName) {
|
||||
this.profile = profile;
|
||||
this.latency = latency;
|
||||
this.gameMode = gameMode;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GameProfile of the player represented by this data.
|
||||
* @return The GameProfile
|
||||
*/
|
||||
public WrappedGameProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Replaced by {@link #getLatency()}
|
||||
*/
|
||||
@Deprecated
|
||||
public int getPing() {
|
||||
return ping;
|
||||
return latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latency between the client and the server.
|
||||
* @return The latency
|
||||
*/
|
||||
public int getLatency() {
|
||||
return latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GameMode of the player represented by this data.
|
||||
* @return The GameMode
|
||||
*/
|
||||
public NativeGameMode getGameMode() {
|
||||
return gameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display name of the player represented by this data.
|
||||
* @return The display name
|
||||
*/
|
||||
public WrappedChatComponent getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
@ -91,7 +115,7 @@ public class PlayerInfoData {
|
||||
Object result = constructor.newInstance(
|
||||
null,
|
||||
specific.profile.handle,
|
||||
specific.ping,
|
||||
specific.latency,
|
||||
EnumWrappers.getGameModeConverter().getGeneric(EnumWrappers.getGameModeClass(), specific.gameMode),
|
||||
specific.displayName != null ? specific.displayName.handle : null
|
||||
);
|
||||
@ -112,7 +136,7 @@ public class PlayerInfoData {
|
||||
WrappedGameProfile gameProfile = gameProfiles.read(0);
|
||||
|
||||
StructureModifier<Integer> ints = modifier.withType(int.class);
|
||||
int ping = ints.read(0);
|
||||
int latency = ints.read(0);
|
||||
|
||||
StructureModifier<NativeGameMode> gameModes = modifier.withType(
|
||||
EnumWrappers.getGameModeClass(), EnumWrappers.getGameModeConverter());
|
||||
@ -122,7 +146,7 @@ public class PlayerInfoData {
|
||||
MinecraftReflection.getIChatBaseComponentClass(), BukkitConverters.getWrappedChatComponentConverter());
|
||||
WrappedChatComponent displayName = displayNames.read(0);
|
||||
|
||||
return new PlayerInfoData(gameProfile, ping, gameMode, displayName);
|
||||
return new PlayerInfoData(gameProfile, latency, gameMode, displayName);
|
||||
}
|
||||
|
||||
// Otherwise, return null
|
||||
@ -146,7 +170,7 @@ public class PlayerInfoData {
|
||||
// Only compare objects of similar type
|
||||
if (obj instanceof PlayerInfoData) {
|
||||
PlayerInfoData other = (PlayerInfoData) obj;
|
||||
return profile.equals(other.profile) && ping == other.ping && gameMode == other.gameMode
|
||||
return profile.equals(other.profile) && latency == other.latency && gameMode == other.gameMode
|
||||
&& displayName.equals(other.displayName);
|
||||
}
|
||||
return false;
|
||||
@ -154,12 +178,12 @@ public class PlayerInfoData {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(profile, ping, gameMode, displayName);
|
||||
return Objects.hashCode(latency, gameMode, profile, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PlayerInfoData { profile=%s, ping=%s, gameMode=%s, displayName=%s }",
|
||||
profile, ping, gameMode, displayName);
|
||||
return String.format("PlayerInfoData[latency=%s, gameMode=%s, profile=%s, displayName=%s",
|
||||
latency, gameMode, profile, displayName);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class SimpleMinecraftClient {
|
||||
/**
|
||||
* Query the local server for ping information.
|
||||
* @return The server information.
|
||||
* @throws IOException
|
||||
* @throws IOException
|
||||
*/
|
||||
public String queryLocalPing() throws IOException {
|
||||
return queryServerPing(new InetSocketAddress("localhost", 25565));
|
||||
@ -173,7 +173,7 @@ public class SimpleMinecraftClient {
|
||||
}
|
||||
}
|
||||
|
||||
private static class HandshakePacket extends SimplePacket {
|
||||
private static class HandshakePacket extends SimplePacket {
|
||||
private int protocol;
|
||||
private String host;
|
||||
private int port;
|
||||
@ -209,6 +209,7 @@ public class SimpleMinecraftClient {
|
||||
serializer.serializeVarInt(output, type.getCurrentId());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void read(PacketType type, DataInputStream input) throws IOException {
|
||||
// Note - we don't read the packet id
|
||||
if (this.type != type) {
|
||||
|
Loading…
Reference in New Issue
Block a user