package launcher.client;
import launcher.LauncherAPI;
import launcher.helper.IOHelper;
import launcher.helper.SecurityHelper;
import launcher.helper.SecurityHelper.DigestAlgorithm;
import launcher.helper.VerifyHelper;
import launcher.serialize.HInput;
import launcher.serialize.HOutput;
import launcher.serialize.stream.StreamObject;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Objects;
import java.util.UUID;
public final class PlayerProfile extends StreamObject
{
@LauncherAPI
public final UUID uuid;
@LauncherAPI
public final String username;
@LauncherAPI
public final Texture skin, cloak;
@LauncherAPI
public PlayerProfile(HInput input) throws IOException
{
uuid = input.readUUID();
username = VerifyHelper.verifyUsername(input.readString(64));
skin = input.readBoolean() ? new Texture(input) : null;
cloak = input.readBoolean() ? new Texture(input) : null;
}
@LauncherAPI
public PlayerProfile(UUID uuid, String username, Texture skin, Texture cloak)
{
this.uuid = Objects.requireNonNull(uuid, "uuid");
this.username = VerifyHelper.verifyUsername(username);
this.skin = skin;
this.cloak = cloak;
}
@LauncherAPI
public static PlayerProfile newOfflineProfile(String username)
{
return new PlayerProfile(offlineUUID(username), username, null, null);
}
@LauncherAPI
public static UUID offlineUUID(String username)
{
return UUID.nameUUIDFromBytes(IOHelper.encodeASCII("OfflinePlayer:" + username));
}
@Override
public void write(HOutput output) throws IOException
{
output.writeUUID(uuid);
output.writeString(username, 64);
// Write textures
output.writeBoolean(skin != null);
if (skin != null)
{
skin.write(output);
}
output.writeBoolean(cloak != null);
if (cloak != null)
{
cloak.write(output);
}
}
public static final class Texture extends StreamObject
{
private static final DigestAlgorithm DIGEST_ALGO = DigestAlgorithm.SHA256;
// Instance
@LauncherAPI
public final String url;
@LauncherAPI
public final byte[] digest;
@LauncherAPI
public Texture(String url, byte[] digest)
{
this.url = IOHelper.verifyURL(url);
this.digest = Objects.requireNonNull(digest, "digest");
}
@LauncherAPI
public Texture(String url, boolean cloak) throws IOException
{
this.url = IOHelper.verifyURL(url);
// Fetch texture
byte[] texture;
try (InputStream input = IOHelper.newInput(new URL(url)))
{
texture = IOHelper.read(input);
}
try (ByteArrayInputStream input = new ByteArrayInputStream(texture))
{
IOHelper.readTexture(input, cloak); // Verify texture
}
// Get digest of texture
digest = SecurityHelper.digest(DIGEST_ALGO, new URL(url));
}
@LauncherAPI
public Texture(HInput input) throws IOException
{
url = IOHelper.verifyURL(input.readASCII(2048));
digest = input.readByteArray(-DIGEST_ALGO.bytes);
}
@Override
public void write(HOutput output) throws IOException
{
output.writeASCII(url, 2048);
output.writeByteArray(digest, -DIGEST_ALGO.bytes);
}
}
}