Fix setting ping player sample in 1.19.4

This commit is contained in:
Dan Mulloy 2023-03-26 13:31:39 -05:00
parent 0c6fa46871
commit 1912a9c871
No known key found for this signature in database
GPG Key ID: E3B02DE32FB04AC1
5 changed files with 132 additions and 93 deletions

View File

@ -17,6 +17,7 @@ package com.comphenix.protocol.wrappers;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -310,4 +311,22 @@ public class Converters {
} }
}; };
} }
public static <T> List<T> toList(Iterable<? extends T> iterable) {
if (iterable instanceof List) {
return (List<T>) iterable;
}
List<T> result = new ArrayList<>();
if (iterable instanceof Collection) {
Collection<T> coll = (Collection<T>) iterable;
result.addAll(coll);
} else {
for (T elem : iterable) {
result.add(elem);
}
}
return result;
}
} }

View File

@ -39,16 +39,9 @@ import java.util.List;
public class WrappedServerPing implements ClonableWrapper { public class WrappedServerPing implements ClonableWrapper {
private static final Class<?> GAME_PROFILE = MinecraftReflection.getGameProfileClass(); private static final Class<?> GAME_PROFILE = MinecraftReflection.getGameProfileClass();
// For converting to the underlying array
private static final EquivalentConverter<Iterable<? extends WrappedGameProfile>> PROFILE_CONVERT =
BukkitConverters.getArrayConverter(GAME_PROFILE, BukkitConverters.getWrappedGameProfileConverter());
// Get profile from player // Get profile from player
private static final FieldAccessor ENTITY_HUMAN_PROFILE = Accessors.getFieldAccessor( private static final FieldAccessor ENTITY_HUMAN_PROFILE = Accessors.getFieldAccessor(
MinecraftReflection.getEntityPlayerClass().getSuperclass(), GAME_PROFILE, true); MinecraftReflection.getEntityPlayerClass().getSuperclass(), GAME_PROFILE, true);
// Server ping fields
private static final Class<?> SERVER_PING = MinecraftReflection.getServerPingClass();
private final ServerPingImpl impl; private final ServerPingImpl impl;
@ -59,9 +52,6 @@ public class WrappedServerPing implements ClonableWrapper {
*/ */
public WrappedServerPing() { public WrappedServerPing() {
this.impl = newImpl(); this.impl = newImpl();
resetPlayers();
resetVersion();
} }
private WrappedServerPing(Object handle) { private WrappedServerPing(Object handle) {
@ -119,10 +109,11 @@ public class WrappedServerPing implements ClonableWrapper {
/** /**
* Retrieve the message of the day. * Retrieve the message of the day.
* @return The messge of the day. * @return The message of the day.
*/ */
public WrappedChatComponent getMotD() { public WrappedChatComponent getMotD() {
return WrappedChatComponent.fromHandle(impl.getMotD()); Object handle = impl.getMotD();
return handle != null ? WrappedChatComponent.fromHandle(handle) : null;
} }
/** /**
@ -130,7 +121,7 @@ public class WrappedServerPing implements ClonableWrapper {
* @param description - message of the day. * @param description - message of the day.
*/ */
public void setMotD(WrappedChatComponent description) { public void setMotD(WrappedChatComponent description) {
impl.setMotD(description.getHandle()); impl.setMotD(description != null ? description.getHandle() : null);
} }
/** /**
@ -267,12 +258,7 @@ public class WrappedServerPing implements ClonableWrapper {
* @return Logged in players or an empty list if no player names will be displayed. * @return Logged in players or an empty list if no player names will be displayed.
*/ */
public ImmutableList<WrappedGameProfile> getPlayers() { public ImmutableList<WrappedGameProfile> getPlayers() {
if (!isPlayersVisible()) return impl.getPlayers();
return ImmutableList.of();
Object playerProfiles = impl.getPlayers();
if (playerProfiles == null)
return ImmutableList.of();
return ImmutableList.copyOf(PROFILE_CONVERT.getSpecific(playerProfiles));
} }
/** /**
@ -282,7 +268,7 @@ public class WrappedServerPing implements ClonableWrapper {
public void setPlayers(Iterable<? extends WrappedGameProfile> profile) { public void setPlayers(Iterable<? extends WrappedGameProfile> profile) {
if (!isPlayersVisible()) if (!isPlayersVisible())
resetPlayers(); resetPlayers();
impl.setPlayers((profile != null) ? PROFILE_CONVERT.getGeneric(profile) : null); impl.setPlayers(profile);
} }
/** /**

View File

@ -14,6 +14,8 @@ import com.comphenix.protocol.wrappers.AbstractWrapper;
import com.comphenix.protocol.wrappers.BukkitConverters; import com.comphenix.protocol.wrappers.BukkitConverters;
import com.comphenix.protocol.wrappers.WrappedChatComponent; import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile; import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -27,7 +29,7 @@ import java.util.List;
* Represents a server ping packet data. * Represents a server ping packet data.
* @author Kristian * @author Kristian
*/ */
public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl { public final class LegacyServerPing extends AbstractWrapper implements ServerPingImpl {
private static final Class<?> GAME_PROFILE = MinecraftReflection.getGameProfileClass(); private static final Class<?> GAME_PROFILE = MinecraftReflection.getGameProfileClass();
// For converting to the underlying array // For converting to the underlying array
@ -132,32 +134,27 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
/** /**
* Retrieve the message of the day. * Retrieve the message of the day.
* @return The messge of the day. * @return The message of the day.
*/ */
public WrappedChatComponent getMotD() { @Override
return WrappedChatComponent.fromHandle(DESCRIPTION.get(handle)); public Object getMotD() {
return DESCRIPTION.get(handle);
} }
/** /**
* Set the message of the day. * Set the message of the day.
* @param description - message of the day. * @param description - message of the day.
*/ */
@Override
public void setMotD(Object description) { public void setMotD(Object description) {
DESCRIPTION.set(handle, description); DESCRIPTION.set(handle, description);
} }
/**
* Set the message of the day.
* @param message - the message.
*/
public void setMotD(String message) {
setMotD(WrappedChatComponent.fromLegacyText(message));
}
/** /**
* Retrieve the compressed PNG file that is being displayed as a favicon. * Retrieve the compressed PNG file that is being displayed as a favicon.
* @return The favicon, or NULL if no favicon will be displayed. * @return The favicon, or NULL if no favicon will be displayed.
*/ */
@Override
public String getFavicon() { public String getFavicon() {
return (String) FAVICON.get(handle); return (String) FAVICON.get(handle);
} }
@ -166,6 +163,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* Set the compressed PNG file that is being displayed. * Set the compressed PNG file that is being displayed.
* @param image - the new compressed image or NULL if no favicon should be displayed. * @param image - the new compressed image or NULL if no favicon should be displayed.
*/ */
@Override
public void setFavicon(String image) { public void setFavicon(String image) {
FAVICON.set(handle, image); FAVICON.set(handle, image);
} }
@ -197,6 +195,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* @return whether the server enforces secure chat. * @return whether the server enforces secure chat.
* @since 1.19.1 * @since 1.19.1
*/ */
@Override
public boolean isEnforceSecureChat() { public boolean isEnforceSecureChat() {
int index = MinecraftVersion.FEATURE_PREVIEW_UPDATE.atOrAbove() ? 0 : 1; int index = MinecraftVersion.FEATURE_PREVIEW_UPDATE.atOrAbove() ? 0 : 1;
return (Boolean) BOOLEAN_ACCESSORS[index].get(handle); return (Boolean) BOOLEAN_ACCESSORS[index].get(handle);
@ -207,6 +206,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* @param enforceSecureChat true if enabled, false otherwise. * @param enforceSecureChat true if enabled, false otherwise.
* @since 1.19.1 * @since 1.19.1
*/ */
@Override
public void setEnforceSecureChat(boolean enforceSecureChat) { public void setEnforceSecureChat(boolean enforceSecureChat) {
int index = MinecraftVersion.FEATURE_PREVIEW_UPDATE.atOrAbove() ? 0 : 1; int index = MinecraftVersion.FEATURE_PREVIEW_UPDATE.atOrAbove() ? 0 : 1;
BOOLEAN_ACCESSORS[index].set(handle, enforceSecureChat); BOOLEAN_ACCESSORS[index].set(handle, enforceSecureChat);
@ -218,6 +218,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* @throws IllegalStateException If the player count has been hidden via {@link #setPlayersVisible(boolean)}. * @throws IllegalStateException If the player count has been hidden via {@link #setPlayersVisible(boolean)}.
* @see #setPlayersOnline(int) * @see #setPlayersOnline(int)
*/ */
@Override
public int getPlayersOnline() { public int getPlayersOnline() {
if (players == null) if (players == null)
throw new IllegalStateException("The player count has been hidden."); throw new IllegalStateException("The player count has been hidden.");
@ -231,6 +232,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* negative, as well as higher than the player maximum. * negative, as well as higher than the player maximum.
* @param online - online players. * @param online - online players.
*/ */
@Override
public void setPlayersOnline(int online) { public void setPlayersOnline(int online) {
if (players == null) if (players == null)
resetPlayers(); resetPlayers();
@ -243,6 +245,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* @throws IllegalStateException If the player maximum has been hidden via {@link #setPlayersVisible(boolean)}. * @throws IllegalStateException If the player maximum has been hidden via {@link #setPlayersVisible(boolean)}.
* @see #setPlayersMaximum(int) * @see #setPlayersMaximum(int)
*/ */
@Override
public int getPlayersMaximum() { public int getPlayersMaximum() {
if (players == null) if (players == null)
throw new IllegalStateException("The player maximum has been hidden."); throw new IllegalStateException("The player maximum has been hidden.");
@ -256,6 +259,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* is less than the player count. * is less than the player count.
* @param maximum - maximum player count. * @param maximum - maximum player count.
*/ */
@Override
public void setPlayersMaximum(int maximum) { public void setPlayersMaximum(int maximum) {
if (players == null) if (players == null)
resetPlayers(); resetPlayers();
@ -268,6 +272,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* Note that this may set the current player count and maximum to their respective real values. * Note that this may set the current player count and maximum to their respective real values.
* @param visible - TRUE if it should be visible, FALSE otherwise. * @param visible - TRUE if it should be visible, FALSE otherwise.
*/ */
@Override
public void setPlayersVisible(boolean visible) { public void setPlayersVisible(boolean visible) {
if (arePlayersVisible() != visible) { if (arePlayersVisible() != visible) {
if (visible) { if (visible) {
@ -287,6 +292,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* If not, the client will display ??? in the same location. * If not, the client will display ??? in the same location.
* @return TRUE if the player statistics is visible, FALSE otherwise. * @return TRUE if the player statistics is visible, FALSE otherwise.
*/ */
@Override
public boolean arePlayersVisible() { public boolean arePlayersVisible() {
return players != null; return players != null;
} }
@ -295,6 +301,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* Retrieve a copy of all the logged in players. * Retrieve a copy of all the logged in players.
* @return Logged in players or an empty list if no player names will be displayed. * @return Logged in players or an empty list if no player names will be displayed.
*/ */
@Override
public ImmutableList<WrappedGameProfile> getPlayers() { public ImmutableList<WrappedGameProfile> getPlayers() {
if (players == null) if (players == null)
return ImmutableList.of(); return ImmutableList.of();
@ -306,33 +313,21 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
/** /**
* Set the displayed list of logged in players. * Set the displayed list of logged in players.
* @param profile - every logged in player. * @param playerSample - every logged in player.
*/ */
public void setPlayers(Object profile) { @Override
public void setPlayers(Iterable<? extends WrappedGameProfile> playerSample) {
if (players == null) if (players == null)
resetPlayers(); resetPlayers();
PLAYERS_PROFILES.set(players, profile);
}
/** PLAYERS_PROFILES.set(players, PROFILE_CONVERT.getGeneric(playerSample));
* Set the displayed lst of logged in players.
* @param players - the players to display.
*/
public void setBukkitPlayers(Iterable<? extends Player> players) {
final List<WrappedGameProfile> profiles = new ArrayList<>();
for (Player player : players) {
Object profile = ENTITY_HUMAN_PROFILE.get(BukkitUnwrapper.getInstance().unwrapItem(player));
profiles.add(WrappedGameProfile.fromHandle(profile));
}
setPlayers(profiles);
} }
/** /**
* Retrieve the version name of the current server. * Retrieve the version name of the current server.
* @return The version name. * @return The version name.
*/ */
@Override
public String getVersionName() { public String getVersionName() {
return (String) VERSION_NAME.get(version); return (String) VERSION_NAME.get(version);
} }
@ -341,6 +336,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* Set the version name of the current server. * Set the version name of the current server.
* @param name - the new version name. * @param name - the new version name.
*/ */
@Override
public void setVersionName(String name) { public void setVersionName(String name) {
VERSION_NAME.set(version, name); VERSION_NAME.set(version, name);
} }
@ -349,6 +345,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* Retrieve the protocol number. * Retrieve the protocol number.
* @return The protocol. * @return The protocol.
*/ */
@Override
public int getVersionProtocol() { public int getVersionProtocol() {
return (Integer) VERSION_PROTOCOL.get(version); return (Integer) VERSION_PROTOCOL.get(version);
} }
@ -357,6 +354,7 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
* Set the version protocol * Set the version protocol
* @param protocol - the protocol number. * @param protocol - the protocol number.
*/ */
@Override
public void setVersionProtocol(int protocol) { public void setVersionProtocol(int protocol) {
VERSION_PROTOCOL.set(version, protocol); VERSION_PROTOCOL.set(version, protocol);
} }
@ -367,11 +365,11 @@ public class LegacyServerPing extends AbstractWrapper implements ServerPingImpl
*/ */
public LegacyServerPing deepClone() { public LegacyServerPing deepClone() {
LegacyServerPing copy = new LegacyServerPing(); LegacyServerPing copy = new LegacyServerPing();
WrappedChatComponent motd = getMotD(); Object motd = getMotD();
copy.setPlayers(getPlayers()); copy.setPlayers(getPlayers());
copy.setFavicon(getFavicon()); copy.setFavicon(getFavicon());
copy.setMotD(motd != null ? motd.deepClone() : null); copy.setMotD(motd != null ? WrappedChatComponent.fromHandle(motd).getHandle() : null);
copy.setVersionName(getVersionName()); copy.setVersionName(getVersionName());
copy.setVersionProtocol(getVersionProtocol()); copy.setVersionProtocol(getVersionProtocol());

View File

@ -1,20 +1,20 @@
package com.comphenix.protocol.wrappers.ping; package com.comphenix.protocol.wrappers.ping;
import java.util.List; import java.util.Optional;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedGameProfile; import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedServerPing.CompressedImage;
public interface ServerPingImpl { import com.google.common.collect.ImmutableList;
public interface ServerPingImpl extends Cloneable {
Object getMotD(); Object getMotD();
void setMotD(Object description); void setMotD(Object description);
int getPlayersMaximum(); int getPlayersMaximum();
void setPlayersMaximum(int maxPlayers); void setPlayersMaximum(int maxPlayers);
int getPlayersOnline(); int getPlayersOnline();
void setPlayersOnline(int onlineCount); void setPlayersOnline(int onlineCount);
Object getPlayers(); ImmutableList<WrappedGameProfile> getPlayers();
void setPlayers(Object playerSample); void setPlayers(Iterable<? extends WrappedGameProfile> playerSample);
String getVersionName(); String getVersionName();
void setVersionName(String versionName); void setVersionName(String versionName);
int getVersionProtocol(); int getVersionProtocol();

View File

@ -1,12 +1,11 @@
package com.comphenix.protocol.wrappers.ping; package com.comphenix.protocol.wrappers.ping;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import com.comphenix.protocol.events.AbstractStructure;
import com.comphenix.protocol.events.InternalStructure; import com.comphenix.protocol.events.InternalStructure;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.reflect.StructureModifier; import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.accessors.Accessors; import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
@ -15,9 +14,10 @@ import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.MinecraftVersion; import com.comphenix.protocol.utility.MinecraftVersion;
import com.comphenix.protocol.wrappers.*; import com.comphenix.protocol.wrappers.*;
import com.google.common.collect.ImmutableList;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
public class ServerPingRecord implements ServerPingImpl { public final class ServerPingRecord implements ServerPingImpl {
private static Class<?> SERVER_PING; private static Class<?> SERVER_PING;
private static Class<?> PLAYER_SAMPLE_CLASS; private static Class<?> PLAYER_SAMPLE_CLASS;
private static Class<?> SERVER_DATA_CLASS; private static Class<?> SERVER_DATA_CLASS;
@ -26,6 +26,8 @@ public class ServerPingRecord implements ServerPingImpl {
private static ConstructorAccessor PING_CTOR; private static ConstructorAccessor PING_CTOR;
private static EquivalentConverter<List<WrappedGameProfile>> PROFILE_LIST_CONVERTER;
private static boolean initialized = false; private static boolean initialized = false;
private static void initialize() { private static void initialize() {
@ -46,6 +48,8 @@ public class ServerPingRecord implements ServerPingImpl {
SAMPLE_WRAPPER = AutoWrapper.wrap(PlayerSample.class, PLAYER_SAMPLE_CLASS); SAMPLE_WRAPPER = AutoWrapper.wrap(PlayerSample.class, PLAYER_SAMPLE_CLASS);
FAVICON_WRAPPER = AutoWrapper.wrap(Favicon.class, MinecraftReflection.getMinecraftClass("network.protocol.status.ServerPing$a")); FAVICON_WRAPPER = AutoWrapper.wrap(Favicon.class, MinecraftReflection.getMinecraftClass("network.protocol.status.ServerPing$a"));
PROFILE_LIST_CONVERTER = BukkitConverters.getListConverter(BukkitConverters.getWrappedGameProfileConverter());
DEFAULT_DESCRIPTION = WrappedChatComponent.fromLegacyText("A Minecraft Server"); DEFAULT_DESCRIPTION = WrappedChatComponent.fromLegacyText("A Minecraft Server");
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); // TODO ex.printStackTrace(); // TODO
@ -56,15 +60,44 @@ public class ServerPingRecord implements ServerPingImpl {
public int max; public int max;
public int online; public int online;
public Object sample; public Object sample;
public PlayerSample(int max, int online, Object sample) {
this.max = max;
this.online = online;
this.sample = sample;
}
public PlayerSample() {
this(0, 0, null);
}
} }
public static final class ServerData { public static final class ServerData {
public String name; public String name;
public int protocol; public int protocol;
public ServerData(String name, int protocol) {
this.name = name;
this.protocol = protocol;
}
public ServerData() {
this("", 0);
}
} }
static final byte[] EMPTY_FAVICON = new byte[0];
public static final class Favicon { public static final class Favicon {
public byte[] iconBytes; public byte[] iconBytes;
public Favicon(byte[] iconBytes) {
this.iconBytes = iconBytes;
}
public Favicon() {
this(EMPTY_FAVICON);
}
} }
private static AutoWrapper<PlayerSample> SAMPLE_WRAPPER; private static AutoWrapper<PlayerSample> SAMPLE_WRAPPER;
@ -81,24 +114,21 @@ public class ServerPingRecord implements ServerPingImpl {
private boolean playersVisible = true; private boolean playersVisible = true;
private static ServerData defaultData() { private static ServerData defaultData() {
ServerData data = new ServerData(); String name = MinecraftVersion.getCurrentVersion().toString();
data.name = MinecraftVersion.getCurrentVersion().toString(); int protocol = MinecraftProtocolVersion.getCurrentVersion();
data.protocol = MinecraftProtocolVersion.getCurrentVersion();
return data; return new ServerData(name, protocol);
} }
private static PlayerSample defaultSample() { private static PlayerSample defaultSample() {
PlayerSample sample = new PlayerSample(); int max = Bukkit.getMaxPlayers();
sample.max = Bukkit.getMaxPlayers(); int online = Bukkit.getOnlinePlayers().size();
sample.online = Bukkit.getOnlinePlayers().size();
sample.sample = null; return new PlayerSample(max, online, null);
return sample;
} }
private static Favicon defaultFavicon() { private static Favicon defaultFavicon() {
Favicon favicon = new Favicon(); return new Favicon();
favicon.iconBytes = new byte[0];
return favicon;
} }
public ServerPingRecord(Object handle) { public ServerPingRecord(Object handle) {
@ -112,25 +142,13 @@ public class ServerPingRecord implements ServerPingImpl {
StructureModifier<Optional<Object>> optionals = structure.getOptionals(Converters.passthrough(Object.class)); StructureModifier<Optional<Object>> optionals = structure.getOptionals(Converters.passthrough(Object.class));
Optional<Object> sampleHandle = optionals.readSafely(0); Optional<Object> sampleHandle = optionals.readSafely(0);
if (sampleHandle.isPresent()) { this.playerSample = sampleHandle.isPresent() ? SAMPLE_WRAPPER.wrap(sampleHandle.get()) : defaultSample();
this.playerSample = SAMPLE_WRAPPER.wrap(sampleHandle.get());
} else {
this.playerSample = defaultSample();
}
Optional<Object> dataHandle = optionals.readSafely(1); Optional<Object> dataHandle = optionals.readSafely(1);
if (dataHandle.isPresent()) { this.serverData = dataHandle.isPresent() ? DATA_WRAPPER.wrap(dataHandle.get()) : defaultData();
this.serverData = DATA_WRAPPER.wrap(dataHandle.get());
} else {
this.serverData = defaultData();
}
Optional<Object> faviconHandle = optionals.readSafely(2); Optional<Object> faviconHandle = optionals.readSafely(2);
if (faviconHandle.isPresent()) { this.favicon = faviconHandle.isPresent() ? FAVICON_WRAPPER.wrap(faviconHandle.get()) : defaultFavicon();
this.favicon = FAVICON_WRAPPER.wrap(faviconHandle.get());
} else {
this.favicon = defaultFavicon();
}
this.enforceSafeChat = structure.getBooleans().readSafely(0); this.enforceSafeChat = structure.getBooleans().readSafely(0);
} }
@ -139,6 +157,8 @@ public class ServerPingRecord implements ServerPingImpl {
initialize(); initialize();
this.description = DEFAULT_DESCRIPTION; this.description = DEFAULT_DESCRIPTION;
this.playerSample = defaultSample();
this.serverData = defaultData();
this.favicon = defaultFavicon(); this.favicon = defaultFavicon();
} }
@ -173,13 +193,28 @@ public class ServerPingRecord implements ServerPingImpl {
} }
@Override @Override
public Object getPlayers() { public ImmutableList<WrappedGameProfile> getPlayers() {
return playerSample; if (playerSample.sample == null) {
return ImmutableList.of();
}
List<WrappedGameProfile> list = PROFILE_LIST_CONVERTER.getSpecific(playerSample.sample);
if (list == null) {
return ImmutableList.of();
}
return ImmutableList.copyOf(list);
} }
@Override @Override
public void setPlayers(Object playerSample) { public void setPlayers(Iterable<? extends WrappedGameProfile> playerSample) {
this.playerSample.sample = playerSample; if (playerSample == null) {
this.playerSample.sample = null;
return;
}
List<WrappedGameProfile> list = Converters.toList(playerSample);
this.playerSample.sample = PROFILE_LIST_CONVERTER.getGeneric(list);
} }
@Override @Override
@ -244,10 +279,11 @@ public class ServerPingRecord implements ServerPingImpl {
@Override @Override
public Object getHandle() { public Object getHandle() {
Object descHandle = description != null ? description : DEFAULT_DESCRIPTION;
Optional<Object> playersHandle = Optional.ofNullable(playerSample != null ? SAMPLE_WRAPPER.unwrap(playerSample) : null); Optional<Object> playersHandle = Optional.ofNullable(playerSample != null ? SAMPLE_WRAPPER.unwrap(playerSample) : null);
Optional<Object> versionHandle = Optional.ofNullable(serverData != null ? DATA_WRAPPER.unwrap(serverData) : null); Optional<Object> versionHandle = Optional.ofNullable(serverData != null ? DATA_WRAPPER.unwrap(serverData) : null);
Optional<Object> favHandle = Optional.ofNullable(favicon != null ? FAVICON_WRAPPER.unwrap(favicon) : null); Optional<Object> favHandle = Optional.ofNullable(favicon != null ? FAVICON_WRAPPER.unwrap(favicon) : null);
return PING_CTOR.invoke(description, playersHandle, versionHandle, favHandle, enforceSafeChat); return PING_CTOR.invoke(descHandle, playersHandle, versionHandle, favHandle, enforceSafeChat);
} }
} }