package crazypants.util; import java.util.UUID; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.UsernameCache; import com.enderio.core.common.util.PlayerUtil; import com.google.common.base.Charsets; import com.mojang.authlib.GameProfile; import crazypants.enderio.Log; public class UserIdent { private static final String NONE_MARKER = "none"; private final @Nullable UUID uuid; private final @Nonnull UUID uuid_offline; private final @Nonnull String playerName; public @Nonnull String getPlayerName() { if (uuid != null) { String lastKnownName = UsernameCache.getLastKnownUsername(uuid); if (lastKnownName != null) { return lastKnownName; } } return playerName; } public UUID getUUID() { return uuid != null ? uuid : uuid_offline; } @SuppressWarnings("null") // it's final(!), eclipse... public String getUUIDString() { return uuid != null ? uuid.toString() : NONE_MARKER; } /** * Create a UserIdent from a UUID object and a name. Use this when reading * stored data, it will check for username changes, implement them and write a * log message. */ public static @Nonnull UserIdent create(@Nullable UUID uuid, @Nullable String playerName) { if (uuid != null) { if (nobody.equals(uuid)) { return nobody; } if (playerName != null) { String lastKnownName = UsernameCache.getLastKnownUsername(uuid); if (lastKnownName != null && !lastKnownName.equals(playerName)) { Log.warn("The user with the UUID " + uuid + " changed name from '" + playerName + "' to '" + lastKnownName + "'"); return new UserIdent(uuid, lastKnownName); } } return new UserIdent(uuid, playerName); } else if (playerName != null) { return new UserIdent(null, playerName); } else { return nobody; } } /** * Create a UserIdent from a UUID string and a name. Use this when reading * stored data, it will check for username changes, implement them and write a * log message. */ public static @Nonnull UserIdent create(@Nonnull String suuid, @Nullable String playerName) { if (NONE_MARKER.equals(suuid)) { return new UserIdent(null, playerName); } try { UUID uuid = UUID.fromString(suuid); if (nobody.equals(uuid)) { return nobody; } return create(uuid, playerName); } catch (IllegalArgumentException e) { return nobody; } } /** * Create a UserIdent from a legacy string. The string can either be a UUID or * a player name. Use this when reading legacy data or user configured values. */ public static @Nonnull UserIdent create(@Nullable String legacyData) { UUID uuid = PlayerUtil.getPlayerUIDUnstable(legacyData); if (uuid != null) { return new UserIdent(uuid, legacyData); } else if (legacyData != null) { return new UserIdent(null, legacyData); } else { return nobody; } } /** * Create a UserIdent from a GameProfile. Use this when creating a UserIdent * for a currently active player. */ public static @Nonnull UserIdent create(@Nullable GameProfile gameProfile) { if (gameProfile != null && (gameProfile.getId() != null || gameProfile.getName() != null)) { if (gameProfile.getId() != null && gameProfile.getName() != null && gameProfile.getId().equals(offlineUUID(gameProfile.getName()))) { return new UserIdent(null, gameProfile.getName()); } else { return new UserIdent(gameProfile.getId(), gameProfile.getName()); } } else { return nobody; } } private static @Nonnull UUID offlineUUID(String playerName) { UUID result = UUID.nameUUIDFromBytes(("OfflinePlayer:" + playerName).getBytes(Charsets.UTF_8)); return result != null ? result : new UUID(-1, -1); } private UserIdent(UUID uuid, String playerName) { this.uuid = uuid; this.uuid_offline = offlineUUID(playerName); this.playerName = playerName != null ? playerName : "[" + uuid + "]"; } @SuppressWarnings("null") // it's final(!), eclipse... @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + playerName.hashCode(); result = prime * result + ((uuid == null) ? 0 : uuid.hashCode()); return result; } /** * Please note that a UserIdent will successfully equal against GameProfiles * and UUIDs. */ @SuppressWarnings("null") // it's final(!), eclipse... @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof UserIdent) { UserIdent other = (UserIdent) obj; if (this.uuid != null && other.uuid != null) { return this.uuid.equals(other.uuid); } return this.uuid_offline.equals(other.uuid_offline); } else if (obj instanceof GameProfile) { GameProfile other = (GameProfile) obj; UUID other_uuid = other.getId(); if (this.uuid != null && other_uuid != null) { return this.uuid.equals(other_uuid); } UUID uuid_offline_other = offlineUUID(other.getName()); return uuid_offline_other.equals(this.uuid) || this.uuid_offline.equals(uuid_offline_other); } else if (obj instanceof UUID) { return obj.equals(uuid) || obj.equals(uuid_offline); } return false; } @SuppressWarnings("null") // it's final(!), eclipse... public void saveToNbt(NBTTagCompound nbt, String prefix) { if (uuid != null) { nbt.setString(prefix + ".uuid", uuid.toString()); } nbt.setString(prefix + ".login", playerName); } public static boolean existsInNbt(NBTTagCompound nbt, String prefix) { return nbt.hasKey(prefix + ".uuid") || nbt.hasKey(prefix + ".login"); } public static @Nonnull UserIdent readfromNbt(NBTTagCompound nbt, String prefix) { String suuid = nbt.getString(prefix + ".uuid"); String login = nbt.getString(prefix + ".login"); if (Nobody.NOBODY_MARKER.equals(suuid)) { return nobody; } try { UUID uuid = UUID.fromString(suuid); return create(uuid, login); } catch (IllegalArgumentException e) { if (login != null && !login.isEmpty()) { return new UserIdent(null, login); } else { return nobody; } } } @Override public String toString() { return "User [uuid=" + (uuid != null ? uuid : "(unknown)") + ", name=" + playerName + "]"; } public static final @Nonnull Nobody nobody = new Nobody(); private static class Nobody extends UserIdent { private static final String NOBODY_MARKER = "nobody"; private Nobody() { super(null, "[unknown player]"); } @Override public boolean equals(Object obj) { return this == obj; } @Override public void saveToNbt(NBTTagCompound nbt, String prefix) { nbt.setString(prefix + ".uuid", NOBODY_MARKER); } } }