Add wrapper for PlayerInfoData

This commit is contained in:
Dan Mulloy 2014-12-18 21:25:49 -05:00
parent f145d32016
commit 5f4867eb1f
3 changed files with 180 additions and 0 deletions

View File

@ -85,6 +85,7 @@ import com.comphenix.protocol.wrappers.EnumWrappers.ResourcePackStatus;
import com.comphenix.protocol.wrappers.EnumWrappers.ScoreboardAction;
import com.comphenix.protocol.wrappers.EnumWrappers.TitleAction;
import com.comphenix.protocol.wrappers.EnumWrappers.WorldBorderAction;
import com.comphenix.protocol.wrappers.PlayerInfoData;
import com.comphenix.protocol.wrappers.WrappedAttribute;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
@ -650,6 +651,23 @@ public class PacketContainer implements Serializable {
MinecraftReflection.getServerPingClass(), BukkitConverters.getWrappedServerPingConverter());
}
/**
* Retrieve a read/write structure for the PlayerInfoData list fields in the following packet: <br>
* <ul>
* <li>{@link PacketType.Play.Server.PLAYER_INFO}</li>
* </ul>
* @return A modifier for PlayerInfoData list fields.
*/
public StructureModifier<List<PlayerInfoData>> getPlayerInfoDataLists() {
// Convert to and from the ProtocolLib wrapper
return structureModifier.withType(
Collection.class,
BukkitConverters.getListConverter(
MinecraftReflection.getPlayerInfoDataClass(),
PlayerInfoData.getConverter())
);
}
/**
* Retrieve a read/write structure for the Protocol enum in 1.7.2.
* @return A modifier for Protocol enum fields.

View File

@ -1896,6 +1896,24 @@ public class MinecraftReflection {
return unwrapper.unwrapItem(stack);
}
/**
* Retrieve the PlayerInfoData class in 1.8.
* @return The PlayerInfoData class
*/
public static Class<?> getPlayerInfoDataClass() {
return getMinecraftClass("PlayerInfoData");
}
/**
* Determine if the given object is a PlayerInfoData.
* @param obj - the given object.
* @return TRUE if it is, FALSE otherwise.
*/
public static boolean isPlayerInfoData(Object obj) {
Class<?> clazz = getPlayerInfoDataClass();
return clazz != null && obj.getClass().equals(clazz);
}
/**
* Retrieve the given class by name.
* @param className - name of the class.

View File

@ -0,0 +1,144 @@
/**
* (c) 2014 dmulloy2
*/
package com.comphenix.protocol.wrappers;
import java.lang.reflect.Constructor;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode;
import com.google.common.base.Objects;
/**
* @author dmulloy2
*/
public class PlayerInfoData {
private static Constructor<?> constructor;
protected final int ping;
protected final NativeGameMode gameMode;
protected final WrappedGameProfile profile;
protected final WrappedChatComponent displayName;
public PlayerInfoData(int ping, NativeGameMode gameMode, WrappedGameProfile profile, WrappedChatComponent displayName) {
this.ping = ping;
this.gameMode = gameMode;
this.profile = profile;
this.displayName = displayName;
}
public int getPing() {
return ping;
}
public NativeGameMode getGameMode() {
return gameMode;
}
public WrappedGameProfile getProfile() {
return profile;
}
public WrappedChatComponent getDisplayName() {
return displayName;
}
/**
* Used to convert between NMS PlayerInfoData and the wrapper instance.
* @return A new converter.
*/
public static EquivalentConverter<PlayerInfoData> getConverter() {
return new EquivalentConverter<PlayerInfoData>() {
@Override
public Object getGeneric(Class<?> genericType, PlayerInfoData specific) {
if (constructor == null) {
try {
constructor = MinecraftReflection.getPlayerInfoDataClass().getConstructor(
int.class,
EnumWrappers.getGameModeClass(),
MinecraftReflection.getGameProfileClass(),
MinecraftReflection.getIChatBaseComponentClass()
);
} catch (Exception e) {
throw new RuntimeException("Cannot find PlayerInfoData constructor.", e);
}
}
// Construct the underlying PlayerInfoData
try {
Object result = constructor.newInstance(
specific.ping,
EnumWrappers.getGameModeConverter().getGeneric(EnumWrappers.getGameModeClass(), specific.gameMode),
specific.profile.handle,
specific.displayName.handle
);
return result;
} catch (Exception e) {
throw new RuntimeException("Cannot construct BlockPosition.", e);
}
}
@Override
public PlayerInfoData getSpecific(Object generic) {
if (MinecraftReflection.isPlayerInfoData(generic)) {
StructureModifier<Object> modifier = new StructureModifier<Object>(generic.getClass(), null, false)
.withTarget(generic);
StructureModifier<Integer> ints = modifier.withType(int.class);
int ping = ints.read(0);
StructureModifier<NativeGameMode> gameModes = modifier.withType(
EnumWrappers.getGameModeClass(), EnumWrappers.getGameModeConverter());
NativeGameMode gameMode = gameModes.read(0);
StructureModifier<WrappedGameProfile> gameProfiles = modifier.withType(
MinecraftReflection.getGameProfileClass(), BukkitConverters.getWrappedGameProfileConverter());
WrappedGameProfile gameProfile = gameProfiles.read(0);
StructureModifier<WrappedChatComponent> displayNames = modifier.withType(
MinecraftReflection.getIChatBaseComponentClass(), BukkitConverters.getWrappedChatComponentConverter());
WrappedChatComponent displayName = displayNames.read(0);
return new PlayerInfoData(ping, gameMode, gameProfile, displayName);
}
// Otherwise, return NULL
return null;
}
// Thanks Java Generics!
@Override
public Class<PlayerInfoData> getSpecificType() {
return PlayerInfoData.class;
}
};
}
@Override
public boolean equals(Object obj) {
// Fast checks
if (this == obj) return true;
if (obj == null) return false;
// Only compare objects of similar type
if (obj instanceof PlayerInfoData) {
PlayerInfoData other = (PlayerInfoData) obj;
return ping == other.ping && gameMode == other.gameMode
&& profile.equals(other.profile) && displayName.equals(other.displayName);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(ping, gameMode, profile, displayName);
}
@Override
public String toString() {
return String.format("PlayerInfoData[ping=%s,gameMode=%s,profile=%s,displayName=%s]", ping, gameMode, profile, displayName);
}
}