package com.forgeessentials.api; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.UUID; import net.minecraft.command.ICommandSender; import net.minecraft.command.PlayerSelector; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayerFactory; import com.forgeessentials.util.ServerUtil; import com.google.gson.annotations.Expose; import com.mojang.authlib.GameProfile; import cpw.mods.fml.common.eventhandler.Event; public class UserIdent { public static class UserIdentInvalidatedEvent extends Event { public final UserIdent oldValue; public final UserIdent newValue; public UserIdentInvalidatedEvent(UserIdent oldValue, UserIdent newValue) { this.oldValue = oldValue; this.newValue = newValue; } } /* ------------------------------------------------------------ */ private static final Map<UUID, UserIdent> byUuid = new HashMap<>(); private static final Map<String, UserIdent> byUsername = new HashMap<>(); /* ------------------------------------------------------------ */ private UUID uuid; private String username; @Expose(serialize = false) private int hashCode; @Expose(serialize = false) protected EntityPlayer player; @Expose(serialize = false) protected GameProfile gameProfile; /* ------------------------------------------------------------ */ private UserIdent(EntityPlayer player) { this.player = player; this.uuid = player.getPersistentID(); this.username = player.getCommandSenderName(); byUuid.put(uuid, this); byUsername.put(username.toLowerCase(), this); } private UserIdent(UUID uuid, String username, EntityPlayer player) { this.player = player; if (player != null) { this.uuid = player.getPersistentID(); this.username = player.getCommandSenderName(); byUuid.put(uuid, this); byUsername.put(username.toLowerCase(), this); } else { this.uuid = uuid; this.username = username; if (uuid != null) byUuid.put(uuid, this); if (username != null) byUsername.put(username.toLowerCase(), this); } } /* ------------------------------------------------------------ */ public static synchronized UserIdent get(UUID uuid, String username) { if (uuid == null && (username == null || username.isEmpty())) throw new IllegalArgumentException(); if (uuid != null) { UserIdent ident = byUuid.get(uuid); if (ident != null) return ident; } if (username != null) { UserIdent ident = byUsername.get(username.toLowerCase()); if (ident != null) return ident; } return new UserIdent(uuid, username, UserIdent.getPlayerByUuid(uuid)); } public static synchronized UserIdent get(String uuid, String username) { return get(uuid != null && !uuid.isEmpty() ? UUID.fromString(uuid) : null, username); } public static synchronized UserIdent get(UUID uuid) { if (uuid == null) throw new IllegalArgumentException(); UserIdent ident = byUuid.get(uuid); if (ident != null) return ident; return new UserIdent(uuid, null, UserIdent.getPlayerByUuid(uuid)); } public static synchronized UserIdent get(EntityPlayer player) { if (player == null) throw new IllegalArgumentException(); UserIdent ident = byUuid.get(player.getPersistentID()); if (ident != null) return ident; ident = byUsername.get(player.getCommandSenderName().toLowerCase()); if (ident != null) return ident; return new UserIdent(player); } public static synchronized UserIdent get(String uuidOrUsername, ICommandSender sender, boolean mustExist) { if (uuidOrUsername == null) throw new IllegalArgumentException(); try { return get(UUID.fromString(uuidOrUsername)); } catch (IllegalArgumentException e) { UserIdent ident = byUsername.get(uuidOrUsername.toLowerCase()); if (ident != null) return ident; EntityPlayer player = sender != null ? UserIdent.getPlayerByMatchOrUsername(sender, uuidOrUsername) : // UserIdent.getPlayerByUsername(uuidOrUsername); if (player != null) return get(player.getPersistentID()); return mustExist ? null : new UserIdent(null, uuidOrUsername, null); } } public static synchronized UserIdent get(String uuidOrUsername, ICommandSender sender) { return get(uuidOrUsername, sender, false); } public static synchronized UserIdent get(String uuidOrUsername, boolean mustExist) { return get(uuidOrUsername, (ICommandSender) null, mustExist); } public static synchronized UserIdent get(String uuidOrUsername) { return get(uuidOrUsername, false); } public static synchronized void login(EntityPlayer player) { UserIdent ident = byUuid.get(player.getPersistentID()); UserIdent usernameIdent = byUsername.get(player.getCommandSenderName().toLowerCase()); if (ident == null) { if (usernameIdent == null) ident = new UserIdent(player); else { ident = usernameIdent; byUuid.put(player.getPersistentID(), ident); } } ident.player = player; ident.username = player.getCommandSenderName(); ident.uuid = player.getPersistentID(); ident.gameProfile = null; if (usernameIdent != null && usernameIdent != ident) { APIRegistry.getFEEventBus().post(new UserIdentInvalidatedEvent(usernameIdent, ident)); // Change data for already existing references to old UserIdent usernameIdent.player = player; usernameIdent.username = player.getCommandSenderName(); // Replace entry in username map by the one from uuid map byUsername.remove(usernameIdent.username.toLowerCase()); byUsername.put(ident.username.toLowerCase(), ident); } } public static synchronized void logout(EntityPlayer player) { UserIdent ident = UserIdent.get(player); ident.player = null; } /* ------------------------------------------------------------ */ public boolean hasUsername() { return username != null; } public boolean hasUuid() { return uuid != null; } public boolean hasPlayer() { return player != null; } public boolean isFakePlayer() { return player instanceof FakePlayer; } /* ------------------------------------------------------------ */ public UUID getUuid() { return uuid; } public String getUsername() { return username; } public String getUsernameOrUuid() { return username == null ? uuid.toString() : username; } public EntityPlayer getPlayer() { return player; } public EntityPlayerMP getPlayerMP() { return (EntityPlayerMP) player; } public EntityPlayer getFakePlayer() { if (player != null) return player; return FakePlayerFactory.get(MinecraftServer.getServer().worldServers[0], getGameProfile()); } public EntityPlayerMP getFakePlayer(WorldServer world) { if (player != null) return (EntityPlayerMP) player; return FakePlayerFactory.get(world, getGameProfile()); } /** * Returns the player's UUID, or a generated one if it is not available. Use this if you need to make sure that * there is always a UUID available (for example for storage in maps). * * @return */ public UUID getOrGenerateUuid() { if (uuid != null) return uuid; return getUsernameUuid(); } /** * Returns a different UUID generated by the username * * @return */ public UUID getUsernameUuid() { return UUID.nameUUIDFromBytes(username.getBytes()); } public GameProfile getGameProfile() { if (gameProfile == null) { if (player != null) gameProfile = player.getGameProfile(); else gameProfile = new GameProfile(getOrGenerateUuid(), username); } return gameProfile; } /* ------------------------------------------------------------ */ public static UserIdent fromString(String string) { if (string.charAt(0) != '(' || string.charAt(string.length() - 1) != ')' || string.indexOf('|') < 0) throw new IllegalArgumentException("UserIdent string needs to be in the format \"(<uuid>|<username>)\""); String[] parts = string.substring(1, string.length() - 1).split("\\|", 2); try { return get(UUID.fromString(parts[0]), parts[1]); } catch (IllegalArgumentException e) { return get((UUID) null, parts[1]); } } public String toSerializeString() { return "(" + (uuid == null ? "" : uuid.toString()) + "|" + username + ")"; } @Override public String toString() { return toSerializeString(); } @Override public int hashCode() { if (hashCode != 0) return hashCode; return hashCode = getOrGenerateUuid().hashCode(); } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (other instanceof UserIdent) { if (this == other) return true; // It might happen, that one UserIdent was previously initialized by username and another one by UUID, but // after the player in question logged in, they still become equal. UserIdent ident = (UserIdent) other; if (uuid != null && ident.uuid != null) return uuid.equals(ident.uuid); if (username != null && ident.username != null) return username.equalsIgnoreCase(ident.username); return false; } else if (other instanceof String) { if (this.uuid != null) { try { return this.uuid.equals(UUID.fromString((String) other)); } catch (IllegalArgumentException e) { // The string was a username and not a UUID } } return username == null ? false : this.username.equalsIgnoreCase((String) other); } else if (other instanceof UUID) { return other.equals(uuid); } else if (other instanceof EntityPlayer) { return ((EntityPlayer) other).getPersistentID().equals(uuid); } else { return false; } } /* ------------------------------------------------------------ */ public boolean checkPermission(String permissionNode) { return APIRegistry.perms.checkUserPermission(this, permissionNode); } public String getPermissionProperty(String permissionNode) { return APIRegistry.perms.getUserPermissionProperty(this, permissionNode); } /* ------------------------------------------------------------ */ public static EntityPlayerMP getPlayerByUsername(String username) { return MinecraftServer.getServer().getConfigurationManager().func_152612_a(username); } public static EntityPlayerMP getPlayerByMatchOrUsername(ICommandSender sender, String match) { EntityPlayerMP player = PlayerSelector.matchOnePlayer(sender, match); if (player != null) return player; return getPlayerByUsername(match); } public static EntityPlayerMP getPlayerByUuid(UUID uuid) { for (EntityPlayerMP player : ServerUtil.getPlayerList()) if (player.getPersistentID().equals(uuid)) return player; return null; } public static GameProfile getGameProfileByUuid(UUID uuid) { GameProfile profile = MinecraftServer.getServer().func_152358_ax().func_152652_a(uuid); return profile; } public static String join(Iterable<UserIdent> users, String glue) { StringBuilder sb = new StringBuilder(); Iterator<UserIdent> it = users.iterator(); if (it.hasNext()) { while (true) { UserIdent next = it.next(); sb.append(next == null ? "server" : next.getUsernameOrUuid()); if (it.hasNext()) sb.append(glue); else break; } } return sb.toString(); } public static String join(Iterable<UserIdent> users, String glue, String lastGlue) { StringBuilder sb = new StringBuilder(); Iterator<UserIdent> it = users.iterator(); if (it.hasNext()) { UserIdent next = it.next(); while (true) { sb.append(next == null ? "server" : next.getUsernameOrUuid()); if (it.hasNext()) { next = it.next(); if (it.hasNext()) sb.append(glue); else sb.append(lastGlue); } else break; } } return sb.toString(); } }