feat: compartmentalization

This commit is contained in:
ineanto 2023-08-19 14:59:11 +02:00
parent b64f56a0bb
commit e471d86801
18 changed files with 300 additions and 267 deletions

View file

@ -11,20 +11,28 @@ import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.i18n.I18N; import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict; import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.mojang.MojangUtils; import xyz.atnrch.nicko.mojang.MojangUtils;
import xyz.atnrch.nicko.profile.AppearanceData;
import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore; import xyz.atnrch.nicko.storage.PlayerDataStore;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional;
public class AnvilManager { public class AnvilManager {
private final Player player; private final Player player;
private final AppearanceManager appearanceManager; private final AppearanceManager appearanceManager;
private final PlayerDataStore dataStore; private final AppearanceData appearanceData;
private final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
private final NickoProfile profile;
public AnvilManager(Player player) { public AnvilManager(Player player) {
this.player = player; this.player = player;
this.appearanceManager = AppearanceManager.get(player);
this.dataStore = NickoBukkit.getInstance().getDataStore(); final Optional<NickoProfile> optionalProfile = dataStore.getData(player.getUniqueId());
this.profile = optionalProfile.orElse(NickoProfile.EMPTY_PROFILE.clone());
this.appearanceManager = optionalProfile.map(NickoProfile::getAppearanceManager).orElse(null);
this.appearanceData = optionalProfile.map(NickoProfile::getAppearanceData).orElse(null);
} }
public void openNameThenSkinAnvil() { public void openNameThenSkinAnvil() {
@ -49,8 +57,8 @@ public class AnvilManager {
if (MojangUtils.isUsernameInvalid(snapshot.getText())) { if (MojangUtils.isUsernameInvalid(snapshot.getText())) {
return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!")); return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!"));
} else { } else {
appearanceManager.setName(snapshot.getText()); appearanceData.setName(snapshot.getText());
dataStore.updateCache(player.getUniqueId(), appearanceManager.getProfile()); dataStore.updateCache(player.getUniqueId(), profile);
openSkinAnvil(); openSkinAnvil();
return Collections.singletonList(AnvilGUI.ResponseAction.close()); return Collections.singletonList(AnvilGUI.ResponseAction.close());
} }
@ -70,8 +78,8 @@ public class AnvilManager {
if (MojangUtils.isUsernameInvalid(snapshot.getText())) { if (MojangUtils.isUsernameInvalid(snapshot.getText())) {
return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!")); return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!"));
} else { } else {
appearanceManager.setName(snapshot.getText()); appearanceData.setName(snapshot.getText());
dataStore.updateCache(player.getUniqueId(), appearanceManager.getProfile()); dataStore.updateCache(player.getUniqueId(), profile);
final ActionResult actionResult = appearanceManager.updatePlayer(false, false); final ActionResult actionResult = appearanceManager.updatePlayer(false, false);
return sendResultAndClose(actionResult); return sendResultAndClose(actionResult);
} }
@ -91,8 +99,8 @@ public class AnvilManager {
if (MojangUtils.isUsernameInvalid(snapshot.getText())) { if (MojangUtils.isUsernameInvalid(snapshot.getText())) {
return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!")); return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!"));
} else { } else {
appearanceManager.setSkin(snapshot.getText()); appearanceData.setSkin(snapshot.getText());
dataStore.updateCache(player.getUniqueId(), appearanceManager.getProfile()); dataStore.updateCache(player.getUniqueId(), profile);
final ActionResult actionResult = appearanceManager.updatePlayer(true, false); final ActionResult actionResult = appearanceManager.updatePlayer(true, false);
return sendResultAndClose(actionResult); return sendResultAndClose(actionResult);
} }

View file

@ -11,9 +11,9 @@ import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.i18n.I18NDict; import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.Locale;
import xyz.atnrch.nicko.mojang.MojangAPI; import xyz.atnrch.nicko.mojang.MojangAPI;
import xyz.atnrch.nicko.mojang.MojangSkin; import xyz.atnrch.nicko.mojang.MojangSkin;
import xyz.atnrch.nicko.profile.AppearanceData;
import xyz.atnrch.nicko.profile.NickoProfile; import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore; import xyz.atnrch.nicko.storage.PlayerDataStore;
import xyz.atnrch.nicko.storage.name.PlayerNameStore; import xyz.atnrch.nicko.storage.name.PlayerNameStore;
@ -26,93 +26,45 @@ import java.util.UUID;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
public class AppearanceManager { public class AppearanceManager {
private final NickoProfile profile;
private final Player player;
private final UUID uuid;
private final NickoBukkit instance = NickoBukkit.getInstance(); private final NickoBukkit instance = NickoBukkit.getInstance();
private final PlayerDataStore dataStore = instance.getDataStore(); private final PlayerDataStore dataStore = instance.getDataStore();
private final PlayerNameStore nameStore = instance.getNameStore(); private final PlayerNameStore nameStore = instance.getNameStore();
private AppearanceManager(UUID uuid) { private final NickoProfile profile;
this.player = Bukkit.getPlayer(uuid); private final AppearanceData appearanceData;
this.uuid = uuid; private final Player player;
this.profile = dataStore.getData(uuid).orElse(NickoProfile.EMPTY_PROFILE.clone()); private final UUID uuid;
}
private AppearanceManager(String name) { public AppearanceManager(Player player) {
this.player = null; this.uuid = player.getUniqueId();
this.uuid = null; this.player = player;
this.profile = dataStore.getOfflineData(name).orElse(NickoProfile.EMPTY_PROFILE.clone());
}
public static AppearanceManager get(Player player) { final Optional<NickoProfile> optionalProfile = dataStore.getData(player.getUniqueId());
return new AppearanceManager(player.getUniqueId()); if (!optionalProfile.isPresent()) {
} this.profile = NickoProfile.EMPTY_PROFILE.clone();
this.appearanceData = profile.getAppearanceData();
public static AppearanceManager get(String name) { instance.getLogger().warning("Unable to appearance data for: " + player.getUniqueId() + ".");
return new AppearanceManager(name); } else {
} this.profile = optionalProfile.get();
this.appearanceData = profile.getAppearanceData();
public boolean hasData() { }
return !profile.isEmpty();
}
public void setSkin(String skin) {
profile.setSkin(skin);
dataStore.getCache().cache(uuid, profile);
}
public String getSkin() {
return profile.getSkin();
}
public boolean needsASkinChange() {
return profile.getSkin() != null && !profile.getSkin().equals(player.getName());
}
public void setName(String name) {
profile.setName(name);
dataStore.getCache().cache(uuid, profile);
}
public String getName() {
return profile.getName();
}
public void setLocale(Locale locale) {
profile.setLocale(locale);
dataStore.getCache().cache(uuid, profile);
}
public Locale getLocale() {
return profile.getLocale();
}
public NickoProfile getProfile() {
return profile;
}
public void setNameAndSkin(String name, String skin) {
this.profile.setName(name);
this.profile.setSkin(skin);
dataStore.getCache().cache(uuid, profile);
} }
public ActionResult reset() { public ActionResult reset() {
final String defaultName = nameStore.getStoredName(player); final String defaultName = nameStore.getStoredName(player);
this.profile.setName(defaultName); appearanceData.setName(defaultName);
this.profile.setSkin(defaultName); appearanceData.setSkin(defaultName);
final ActionResult actionResult = updatePlayer(true, true); final ActionResult actionResult = updatePlayer(true, true);
if (!actionResult.isError()) { if (!actionResult.isError()) {
this.profile.setSkin(null); appearanceData.setSkin(null);
this.profile.setName(null); appearanceData.setName(null);
dataStore.getCache().cache(uuid, profile); dataStore.getCache().cache(uuid, profile);
} }
return actionResult; return actionResult;
} }
public ActionResult updatePlayer(boolean skinChange, boolean reset) { public ActionResult updatePlayer(boolean skinChange, boolean reset) {
final String displayName = profile.getName() == null ? player.getName() : profile.getName(); final String displayName = appearanceData.getName() == null ? player.getName() : appearanceData.getName();
final WrappedGameProfile gameProfile = WrappedGameProfile.fromPlayer(player).withName(displayName); final WrappedGameProfile gameProfile = WrappedGameProfile.fromPlayer(player).withName(displayName);
final ActionResult result = updateGameProfileSkin(gameProfile, skinChange, reset); final ActionResult result = updateGameProfileSkin(gameProfile, skinChange, reset);
if (!result.isError()) { if (!result.isError()) {
@ -139,15 +91,15 @@ public class AppearanceManager {
private ActionResult updateGameProfileSkin(WrappedGameProfile gameProfile, boolean skinChange, boolean reset) { private ActionResult updateGameProfileSkin(WrappedGameProfile gameProfile, boolean skinChange, boolean reset) {
final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName()); final boolean changeOnlyName = appearanceData.getSkin() != null && !appearanceData.getSkin().equalsIgnoreCase(player.getName());
if (skinChange || changeOnlyName) { if (skinChange || changeOnlyName) {
Optional<MojangSkin> skin; Optional<MojangSkin> skin;
try { try {
final MojangAPI mojang = NickoBukkit.getInstance().getMojangAPI(); final MojangAPI mojangAPI = NickoBukkit.getInstance().getMojangAPI();
final Optional<String> uuid = mojang.getUUID(profile.getSkin()); final Optional<String> uuid = mojangAPI.getUUID(appearanceData.getSkin());
if (uuid.isPresent()) { if (uuid.isPresent()) {
skin = reset ? mojang.getSkinWithoutCaching(uuid.get()) : mojang.getSkin(uuid.get()); skin = reset ? mojangAPI.getSkinWithoutCaching(uuid.get()) : mojangAPI.getSkin(uuid.get());
if (skin.isPresent()) { if (skin.isPresent()) {
final MojangSkin skinResult = skin.get(); final MojangSkin skinResult = skin.get();
final Multimap<String, WrappedSignedProperty> properties = gameProfile.getProperties(); final Multimap<String, WrappedSignedProperty> properties = gameProfile.getProperties();
@ -187,7 +139,7 @@ public class AppearanceManager {
respawn.sendPacket(player); respawn.sendPacket(player);
player.setFlying(wasFlying); player.setFlying(wasFlying);
player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
player.updateInventory(); player.updateInventory(); // Marked as unstable.
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")

View file

@ -1,8 +1,7 @@
package xyz.atnrch.nicko.command; package xyz.atnrch.nicko.command;
import org.jetbrains.annotations.NotNull;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.command.sub.NickoCheckSubCmd;
import xyz.atnrch.nicko.command.sub.NickoDebugSubCmd;
import xyz.atnrch.nicko.gui.HomeGUI; import xyz.atnrch.nicko.gui.HomeGUI;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -17,25 +16,19 @@ public class NickoCommand implements CommandExecutor {
"§6/nicko help §f- §7Print this help message.\n"; "§6/nicko help §f- §7Print this help message.\n";
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
if (sender instanceof Player) { if (sender instanceof Player) {
final Player player = (Player) sender; final Player player = (Player) sender;
if (args.length >= 1) { if (args.length >= 1) {
switch (args[0]) { if (args[0].equals("debug")) {
case "debug": new NickoDebugCmd().execute(player, args);
new NickoDebugSubCmd().execute(player, args); } else {
break; sendHelpMessage(sender);
case "check":
new NickoCheckSubCmd().execute(player, args);
break;
default:
sendHelpMessage(sender);
break;
} }
return false; return false;
} }
if(player.isOp() || player.hasPermission("nicko.use") || player.hasPermission("nicko.*")) { if (player.isOp() || player.hasPermission("nicko.use") || player.hasPermission("nicko.*")) {
new HomeGUI(player).open(); new HomeGUI(player).open();
} else { } else {
final I18N i18N = new I18N(player); final I18N i18N = new I18N(player);

View file

@ -1,21 +1,27 @@
package xyz.atnrch.nicko.command.sub; package xyz.atnrch.nicko.command;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.appearance.ActionResult; import xyz.atnrch.nicko.appearance.ActionResult;
import xyz.atnrch.nicko.appearance.AppearanceManager; import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.i18n.I18N; import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.mojang.MojangUtils; import xyz.atnrch.nicko.mojang.MojangUtils;
import org.bukkit.Bukkit; import xyz.atnrch.nicko.profile.AppearanceData;
import org.bukkit.Sound; import xyz.atnrch.nicko.profile.NickoProfile;
import org.bukkit.command.CommandSender; import xyz.atnrch.nicko.storage.PlayerDataStore;
import org.bukkit.entity.Player;
public class NickoDebugSubCmd { import java.util.Optional;
public class NickoDebugCmd {
public void execute(CommandSender sender, String[] args) { public void execute(CommandSender sender, String[] args) {
final String prefix = NickoBukkit.getInstance().getNickoConfig().getPrefix(); final String prefix = NickoBukkit.getInstance().getNickoConfig().getPrefix();
Player target; Player target;
String name, skin; String name, skin;
String playerName = null;
if (args.length == 3) { if (args.length == 3) {
target = (Player) sender; target = (Player) sender;
name = args[1]; name = args[1];
@ -26,7 +32,7 @@ public class NickoDebugSubCmd {
return; return;
} }
final String playerName = args[1]; playerName = args[1];
name = args[2]; name = args[2];
skin = args[3]; skin = args[3];
@ -47,15 +53,25 @@ public class NickoDebugSubCmd {
return; return;
} }
final AppearanceManager appearanceManager = AppearanceManager.get(target.getPlayer()); final Optional<NickoProfile> optionalProfile = NickoProfile.get(target);
appearanceManager.setNameAndSkin(name, skin); if (optionalProfile.isPresent()) {
final ActionResult result = appearanceManager.updatePlayer(true, false); final NickoProfile profile = optionalProfile.get();
if (!result.isError()) { final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
target.sendMessage(prefix + "§aWhoosh!"); final AppearanceData appearanceData = profile.getAppearanceData();
target.playSound(target.getLocation(), Sound.ENTITY_ITEM_FRAME_PLACE, 1, 1); final AppearanceManager appearanceManager = profile.getAppearanceManager();
} else { appearanceData.setName(name);
final I18N i18n = new I18N(target); appearanceData.setSkin(skin);
target.sendMessage(prefix + "§cWhoops. Something happened: " + i18n.translatePrefixless(result.getErrorKey())); dataStore.updateCache(target.getUniqueId(), profile);
final ActionResult result = appearanceManager.updatePlayer(true, false);
if (!result.isError()) {
target.sendMessage(prefix + "§aWhoosh!");
target.playSound(target.getLocation(), Sound.ENTITY_ITEM_FRAME_PLACE, 1, 1);
} else {
final I18N i18n = new I18N(target);
target.sendMessage(prefix + "§cWhoops. Something happened: " + i18n.translatePrefixless(result.getErrorKey()));
}
} }
} }
} }

View file

@ -1,44 +0,0 @@
package xyz.atnrch.nicko.command.sub;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.mojang.MojangUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.StringJoiner;
public class NickoCheckSubCmd {
public void execute(Player player, String[] args) {
final String targetName = args[1];
final Player target = Bukkit.getPlayerExact(targetName);
final I18N i18n = new I18N(player);
AppearanceManager appearanceManager;
if (MojangUtils.isUsernameInvalid(targetName)) {
player.sendMessage(i18n.translate(I18NDict.Error.INVALID_USERNAME));
return;
}
if (target == null) {
appearanceManager = AppearanceManager.get(targetName);
} else {
appearanceManager = AppearanceManager.get(target);
}
final StringJoiner builder = new StringJoiner("\n");
builder.add("§c" + NickoBukkit.getInstance().getNickoConfig().getPrefix() + "§cCheck for: §f§o" + targetName);
if (appearanceManager.hasData()) {
builder.add("§cNicked: §a✔");
builder.add("§cName: §6" + appearanceManager.getName());
builder.add("§cSkin: §6" + appearanceManager.getSkin());
} else {
builder.add("§cNicked: §c❌");
builder.add("§cName: §7N/A");
builder.add("§cSkin: §7N/A");
}
player.sendMessage(builder.toString());
}
}

View file

@ -10,8 +10,12 @@ import xyz.atnrch.nicko.appearance.ActionResult;
import xyz.atnrch.nicko.appearance.AppearanceManager; import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.i18n.I18N; import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict; import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore;
import xyz.atnrch.nicko.storage.name.PlayerNameStore; import xyz.atnrch.nicko.storage.name.PlayerNameStore;
import java.util.Optional;
public class PlayerJoinListener implements Listener { public class PlayerJoinListener implements Listener {
@EventHandler @EventHandler
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
@ -19,20 +23,25 @@ public class PlayerJoinListener implements Listener {
final NickoBukkit instance = NickoBukkit.getInstance(); final NickoBukkit instance = NickoBukkit.getInstance();
final I18N i18n = new I18N(player); final I18N i18n = new I18N(player);
final PlayerNameStore nameStore = instance.getNameStore(); final PlayerNameStore nameStore = instance.getNameStore();
final PlayerDataStore dataStore = instance.getDataStore();
// TODO: 2/20/23 Fetch data from BungeeCord // TODO: 2/20/23 Fetch data from BungeeCord
nameStore.storeName(player); nameStore.storeName(player);
Bukkit.getScheduler().runTaskLater(instance, () -> { Bukkit.getScheduler().runTaskLater(instance, () -> {
final AppearanceManager appearanceManager = AppearanceManager.get(player); final Optional<NickoProfile> optionalProfile = dataStore.getData(player.getUniqueId());
if (appearanceManager.hasData()) {
final ActionResult actionResult = appearanceManager.updatePlayer(appearanceManager.needsASkinChange(), false); optionalProfile.map(NickoProfile::getAppearanceData).ifPresent(appearanceData -> {
if (!actionResult.isError()) { final AppearanceManager appearanceManager = new AppearanceManager(player);
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Restore.OK)); if (!appearanceData.isEmpty()) {
} else { final boolean needsASkinChange = appearanceData.getSkin() != null && !appearanceData.getSkin().equals(player.getName());
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Restore.ERROR, i18n.translatePrefixless(actionResult.getErrorKey()))); final ActionResult actionResult = appearanceManager.updatePlayer(needsASkinChange, false);
if (!actionResult.isError()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Restore.OK));
} else {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Restore.ERROR, i18n.translatePrefixless(actionResult.getErrorKey())));
}
} }
} });
}, 20L); }, 20L);
System.out.println("i18n.getPlayerLocale().getCode() = " + i18n.getPlayerLocale().getCode());
} }
} }

View file

@ -4,12 +4,15 @@ import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.mojang.MojangAPI; import xyz.atnrch.nicko.mojang.MojangAPI;
import xyz.atnrch.nicko.profile.AppearanceData;
import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore;
import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.builder.SkullBuilder; import xyz.xenondevs.invui.item.builder.SkullBuilder;
import xyz.xenondevs.invui.item.impl.AsyncItem; import xyz.xenondevs.invui.item.impl.AsyncItem;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public class PlayerInformationItem extends AsyncItem { public class PlayerInformationItem extends AsyncItem {
@ -19,23 +22,28 @@ public class PlayerInformationItem extends AsyncItem {
super(new ItemBuilder(Material.PAINTING).setDisplayName("§7§oLoading..."), () -> { super(new ItemBuilder(Material.PAINTING).setDisplayName("§7§oLoading..."), () -> {
final Player player = Bukkit.getPlayer(uuid); final Player player = Bukkit.getPlayer(uuid);
final SkullBuilder skull = new SkullBuilder(uuid); final SkullBuilder skull = new SkullBuilder(uuid);
final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
final Optional<NickoProfile> optionalProfile = dataStore.getData(uuid);
final AppearanceManager appearanceManager = AppearanceManager.get(player); optionalProfile.ifPresent(profile -> {
if (appearanceManager.hasData()) { final AppearanceData appearanceData = profile.getAppearanceData();
skull.addLoreLines( if (!appearanceData.isEmpty()) {
"§cNicked: §a✔", skull.addLoreLines(
"§cName: §6" + appearanceManager.getName(), "§cNicked: §a✔",
"§cSkin: §6" + appearanceManager.getSkin() "§cName: §6" + appearanceData.getName(),
); "§cSkin: §6" + appearanceData.getSkin()
} else { );
skull.addLoreLines( } else {
"§cNicked: §c❌", skull.addLoreLines(
"§cName: §7N/A", "§cNicked: §c❌",
"§cSkin: §7N/A" "§cName: §7N/A",
); "§cSkin: §7N/A"
} );
}
skull.setDisplayName("§6" + player.getName());
});
skull.setDisplayName("§6" + player.getName());
return skull; return skull;
}); });
} }

View file

@ -1,14 +1,17 @@
package xyz.atnrch.nicko.gui.items.home; package xyz.atnrch.nicko.gui.items.home;
import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem; import xyz.xenondevs.invui.item.impl.SuppliedItem;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
public class ResetItem extends SuppliedItem { public class ResetItem extends SuppliedItem {
public ResetItem() { public ResetItem() {
super(() -> { super(() -> {
@ -22,21 +25,24 @@ public class ResetItem extends SuppliedItem {
final ClickType clickType = event.getClickType(); final ClickType clickType = event.getClickType();
if (clickType.isLeftClick() || clickType.isRightClick()) { if (clickType.isLeftClick() || clickType.isRightClick()) {
final AppearanceManager appearanceManager = AppearanceManager.get(player); final Optional<NickoProfile> optionalProfile = NickoProfile.get(player);
final AtomicBoolean result = new AtomicBoolean(false);
optionalProfile.ifPresent(profile -> {
if (profile.getAppearanceData().isEmpty()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.MISSING));
event.getEvent().getView().close();
result.set(true);
}
if (!appearanceManager.hasData()) { if (!profile.getAppearanceManager().reset().isError()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.MISSING)); player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.OK));
event.getEvent().getView().close(); result.set(false);
return true; } else {
} player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.ERROR));
result.set(true);
if (!appearanceManager.reset().isError()) { }
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.OK)); });
return true; return result.get();
} else {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.ERROR));
return false;
}
} }
return false; return false;
}); });

View file

@ -8,6 +8,7 @@ import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict; import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation; import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.atnrch.nicko.profile.NickoProfile; import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore;
import xyz.xenondevs.invui.item.ItemProvider; import xyz.xenondevs.invui.item.ItemProvider;
import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.AbstractItem; import xyz.xenondevs.invui.item.impl.AbstractItem;
@ -31,12 +32,14 @@ public class BungeeCordCyclingItem {
} }
public AbstractItem get() { public AbstractItem get() {
final Optional<NickoProfile> profile = NickoBukkit.getInstance().getDataStore().getData(player.getUniqueId()); final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
final Optional<NickoProfile> profile = dataStore.getData(player.getUniqueId());
if (profile.isPresent()) { if (profile.isPresent()) {
final NickoProfile nickoProfile = profile.get(); final NickoProfile nickoProfile = profile.get();
int startingState = nickoProfile.isBungeecordTransfer() ? 0 : 1; int startingState = nickoProfile.isBungeecordTransfer() ? 0 : 1;
return CycleItem.withStateChangeHandler((observer, integer) -> { return CycleItem.withStateChangeHandler((observer, integer) -> {
nickoProfile.setBungeecordTransfer(integer != 1); nickoProfile.setBungeecordTransfer(integer != 1);
dataStore.updateCache(player.getUniqueId(), nickoProfile);
observer.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 0.707107f); // 0.707107 ~= C observer.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 0.707107f); // 0.707107 ~= C
}, startingState, providers); }, startingState, providers);
} }

View file

@ -1,5 +1,6 @@
package xyz.atnrch.nicko.gui.items.settings; package xyz.atnrch.nicko.gui.items.settings;
import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -29,6 +30,7 @@ public class LanguageCyclingItem {
public LanguageCyclingItem(Player player) { public LanguageCyclingItem(Player player) {
this.player = player; this.player = player;
this.i18n = new I18N(player); this.i18n = new I18N(player);
Bukkit.broadcastMessage(i18n.getPlayerLocale().getCode());
this.providers = getItems(); this.providers = getItems();
} }

View file

@ -3,12 +3,13 @@ package xyz.atnrch.nicko.i18n;
import com.github.jsixface.YamlConfig; import com.github.jsixface.YamlConfig;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.appearance.AppearanceManager; import xyz.atnrch.nicko.profile.NickoProfile;
import java.io.InputStream; import java.io.InputStream;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.Optional;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -126,11 +127,10 @@ public class I18N {
} }
public Locale getPlayerLocale() { public Locale getPlayerLocale() {
try { final Optional<NickoProfile> optionalProfile = NickoProfile.get(player);
final AppearanceManager appearanceManager = AppearanceManager.get(player); if (optionalProfile.isPresent()) {
return !appearanceManager.hasData() ? Locale.FALLBACK_LOCALE : appearanceManager.getLocale(); return optionalProfile.get().getLocale();
} catch (IllegalArgumentException exception) { } else {
instance.getLogger().severe("Invalid locale provided by " + player.getName() + ", defaulting to " + Locale.FALLBACK_LOCALE.getCode() + ".");
return Locale.FALLBACK_LOCALE; return Locale.FALLBACK_LOCALE;
} }
} }

View file

@ -2,14 +2,17 @@ package xyz.atnrch.nicko.i18n;
public class I18NDict { public class I18NDict {
public static class Error { public static class Error {
public static final String GENERIC = "error.generic"; public static final String ERROR_KEY = "error.";
public static final String PERMISSION = "error.permission";
public static final String CACHE = "error.cache"; public static final String GENERIC = ERROR_KEY + "generic";
public static final String MOJANG_NAME = "error.mojang_name"; public static final String PERMISSION = ERROR_KEY + "permission";
public static final String MOJANG_SKIN = "error.mojang_skin"; public static final String CACHE = ERROR_KEY + "cache";
public static final String INVALID_USERNAME = "error.invalid_username"; public static final String MOJANG_NAME = ERROR_KEY + "mojang_name";
public static final String SQL_ERROR = "error.sql"; public static final String MOJANG_SKIN = ERROR_KEY + "mojang_skin";
public static final String JSON_ERROR = "error.json"; @Deprecated
public static final String INVALID_USERNAME = ERROR_KEY + "invalid_username";
public static final String SQL_ERROR = ERROR_KEY + "sql";
public static final String JSON_ERROR = ERROR_KEY + "json";
} }
public static class Event { public static class Event {

View file

@ -5,6 +5,7 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.profile.AppearanceData;
import xyz.atnrch.nicko.profile.NickoProfile; import xyz.atnrch.nicko.profile.NickoProfile;
import java.util.Optional; import java.util.Optional;
@ -51,20 +52,26 @@ public class NickoExpansion extends PlaceholderExpansion {
final Optional<NickoProfile> optionalProfile = instance.getDataStore().getData(player.getUniqueId()); final Optional<NickoProfile> optionalProfile = instance.getDataStore().getData(player.getUniqueId());
if (optionalProfile.isPresent()) { if (optionalProfile.isPresent()) {
final NickoProfile profile = optionalProfile.get(); final NickoProfile profile = optionalProfile.get();
if (!profile.isEmpty()) { final AppearanceData appearanceData = profile.getAppearanceData();
name = profile.getName(); if (!appearanceData.isEmpty()) {
skin = profile.getSkin(); name = appearanceData.getName();
skin = appearanceData.getSkin();
} }
locale = profile.getLocale().getName(); locale = profile.getLocale().getName();
bungeecord = profile.isBungeecordTransfer(); bungeecord = profile.isBungeecordTransfer();
} }
switch (params) { switch (params) {
case "name": return name; case "name":
case "skin": return skin; return name;
case "locale": return locale; case "skin":
case "bungeecord": return String.valueOf(bungeecord); return skin;
default: return null; case "locale":
return locale;
case "bungeecord":
return String.valueOf(bungeecord);
default:
return null;
} }
} }
} }

View file

@ -0,0 +1,31 @@
package xyz.atnrch.nicko.profile;
public class AppearanceData {
private String name;
private String skin;
public AppearanceData(String name, String skin) {
this.name = name;
this.skin = skin;
}
public boolean isEmpty() {
return name == null && skin == null;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSkin() {
return skin;
}
public void setSkin(String skin) {
this.skin = skin;
}
}

View file

@ -1,45 +1,70 @@
package xyz.atnrch.nicko.profile; package xyz.atnrch.nicko.profile;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.i18n.Locale; import xyz.atnrch.nicko.i18n.Locale;
import xyz.atnrch.nicko.storage.PlayerDataStore;
import java.util.Optional;
import java.util.UUID;
public class NickoProfile implements Cloneable { public class NickoProfile implements Cloneable {
public static final NickoProfile EMPTY_PROFILE = new NickoProfile(null, null, Locale.ENGLISH, true); public static final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
public static final NickoProfile EMPTY_PROFILE = new NickoProfile(new AppearanceData(null, null), Locale.ENGLISH, true);
private String name; private final AppearanceData appearanceData;
private String skin; private final Player player;
private Locale locale; private Locale locale;
private boolean bungeecordTransfer; private boolean bungeecordTransfer;
public NickoProfile(String name, String skin, Locale locale, boolean bungeecordTransfer) { public NickoProfile(AppearanceData appearanceData, Locale locale, boolean bungeecordTransfer) {
this.name = name; this.appearanceData = appearanceData;
this.skin = skin; this.locale = locale;
this.bungeecordTransfer = bungeecordTransfer;
this.player = null;
}
public NickoProfile(Player player, AppearanceData appearanceData, Locale locale, boolean bungeecordTransfer) {
this.player = player;
this.appearanceData = appearanceData;
this.locale = locale; this.locale = locale;
this.bungeecordTransfer = bungeecordTransfer; this.bungeecordTransfer = bungeecordTransfer;
} }
public boolean isEmpty() { public NickoProfile(UUID uuid, AppearanceData appearanceData, Locale locale, boolean bungeecordTransfer) {
return name == null && skin == null; this.appearanceData = appearanceData;
this.locale = locale;
this.bungeecordTransfer = bungeecordTransfer;
this.player = Bukkit.getPlayer(uuid);
} }
public String getName() { public static Optional<NickoProfile> get(Player player) {
return name; return dataStore.getData(player.getUniqueId());
} }
public void setName(String name) { public static Optional<NickoProfile> get(UUID uuid) {
this.name = name; return dataStore.getData(uuid);
} }
public String getSkin() { public AppearanceManager getAppearanceManager() {
return skin; if (player == null) return null;
return new AppearanceManager(player);
} }
public void setSkin(String skin) { public AppearanceData getAppearanceData() {
this.skin = skin; return appearanceData;
} }
public Locale getLocale() { return locale; } public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
public void setLocale(Locale locale) { this.locale = locale; }
public boolean isBungeecordTransfer() { public boolean isBungeecordTransfer() {
return bungeecordTransfer; return bungeecordTransfer;
@ -52,11 +77,11 @@ public class NickoProfile implements Cloneable {
@Override @Override
public String toString() { public String toString() {
return "NickoProfile{" + return "NickoProfile{" +
"name='" + name + '\'' + "name='" + appearanceData.getName() + '\'' +
", skin='" + skin + '\'' + ", skin='" + appearanceData.getSkin() + '\'' +
", locale=" + locale + ", locale=" + locale +
", bungeecordTransfer=" + bungeecordTransfer + ", bungeecordTransfer=" + bungeecordTransfer +
'}'; '}';
} }
@Override @Override

View file

@ -4,6 +4,7 @@ import xyz.atnrch.nicko.appearance.ActionResult;
import xyz.atnrch.nicko.config.Configuration; import xyz.atnrch.nicko.config.Configuration;
import xyz.atnrch.nicko.i18n.I18NDict; import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.Locale; import xyz.atnrch.nicko.i18n.Locale;
import xyz.atnrch.nicko.profile.AppearanceData;
import xyz.atnrch.nicko.profile.NickoProfile; import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.Storage; import xyz.atnrch.nicko.storage.Storage;
@ -95,7 +96,7 @@ public class SQLStorage extends Storage {
System.out.println("skin = " + skin); System.out.println("skin = " + skin);
System.out.println("locale = " + locale); System.out.println("locale = " + locale);
final NickoProfile profile = new NickoProfile(name, skin, Locale.fromCode(locale), bungeecord); final NickoProfile profile = new NickoProfile(new AppearanceData(name, skin), Locale.fromCode(locale), bungeecord);
return Optional.of(profile); return Optional.of(profile);
} catch (SQLException e) { } catch (SQLException e) {
logger.warning("Couldn't fetch profile: " + e.getMessage()); logger.warning("Couldn't fetch profile: " + e.getMessage());
@ -123,9 +124,10 @@ public class SQLStorage extends Storage {
private PreparedStatement getInsertStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException { private PreparedStatement getInsertStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException {
final String sql = "INSERT IGNORE INTO nicko.DATA (`uuid`, `name`, `skin`, `locale`, `bungeecord`) VALUES (?, ?, ?, ?, ?)"; final String sql = "INSERT IGNORE INTO nicko.DATA (`uuid`, `name`, `skin`, `locale`, `bungeecord`) VALUES (?, ?, ?, ?, ?)";
final PreparedStatement statement = connection.prepareStatement(sql); final PreparedStatement statement = connection.prepareStatement(sql);
final AppearanceData appearanceData = profile.getAppearanceData();
statement.setString(1, uuid.toString()); statement.setString(1, uuid.toString());
statement.setString(2, profile.getName() == null ? null : profile.getName()); statement.setString(2, appearanceData.getName() == null ? null : appearanceData.getName());
statement.setString(3, profile.getSkin() == null ? null : profile.getSkin()); statement.setString(3, appearanceData.getSkin() == null ? null : appearanceData.getSkin());
statement.setString(4, profile.getLocale().getCode()); statement.setString(4, profile.getLocale().getCode());
statement.setBoolean(5, profile.isBungeecordTransfer()); statement.setBoolean(5, profile.isBungeecordTransfer());
return statement; return statement;
@ -134,8 +136,9 @@ public class SQLStorage extends Storage {
private PreparedStatement getUpdateStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException { private PreparedStatement getUpdateStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException {
final String sql = "UPDATE nicko.DATA SET name = ?, skin = ?, locale = ?, bungeecord = ? WHERE uuid = ?"; final String sql = "UPDATE nicko.DATA SET name = ?, skin = ?, locale = ?, bungeecord = ? WHERE uuid = ?";
final PreparedStatement statement = connection.prepareStatement(sql); final PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, profile.getName() == null ? null : profile.getName()); final AppearanceData appearanceData = profile.getAppearanceData();
statement.setString(2, profile.getSkin() == null ? null : profile.getSkin()); statement.setString(1, appearanceData.getName() == null ? null : appearanceData.getName());
statement.setString(2, appearanceData.getSkin() == null ? null : appearanceData.getSkin());
statement.setString(3, profile.getLocale().getCode()); statement.setString(3, profile.getLocale().getCode());
statement.setBoolean(4, profile.isBungeecordTransfer()); statement.setBoolean(4, profile.isBungeecordTransfer());
statement.setString(5, uuid.toString()); statement.setString(5, uuid.toString());

View file

@ -7,6 +7,7 @@ import xyz.atnrch.nicko.appearance.ActionResult;
import xyz.atnrch.nicko.config.Configuration; import xyz.atnrch.nicko.config.Configuration;
import xyz.atnrch.nicko.config.DataSourceConfiguration; import xyz.atnrch.nicko.config.DataSourceConfiguration;
import xyz.atnrch.nicko.i18n.Locale; import xyz.atnrch.nicko.i18n.Locale;
import xyz.atnrch.nicko.profile.AppearanceData;
import xyz.atnrch.nicko.profile.NickoProfile; import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore; import xyz.atnrch.nicko.storage.PlayerDataStore;
@ -46,7 +47,7 @@ public class SQLStorageTest {
@DisplayName("Store empty profile") @DisplayName("Store empty profile")
@Order(2) @Order(2)
public void storeEmptyProfile() { public void storeEmptyProfile() {
final Optional<NickoProfile> optionalProfile = dataStore.getData(uuid); final Optional<NickoProfile> optionalProfile = NickoProfile.get(uuid);
assertTrue(optionalProfile.isPresent()); assertTrue(optionalProfile.isPresent());
} }
@ -54,15 +55,18 @@ public class SQLStorageTest {
@DisplayName("Update profile") @DisplayName("Update profile")
@Order(3) @Order(3)
public void updateProfile() { public void updateProfile() {
final Optional<NickoProfile> optionalProfile = dataStore.getData(uuid); final Optional<NickoProfile> optionalProfile = NickoProfile.get(uuid);
assertTrue(optionalProfile.isPresent());
final NickoProfile profile = optionalProfile.get(); final NickoProfile profile = optionalProfile.get();
assertNull(profile.getName()); final AppearanceData appearanceData = profile.getAppearanceData();
assertNull(profile.getSkin()); assertNull(appearanceData.getName());
assertNull(appearanceData.getSkin());
assertEquals(profile.getLocale(), Locale.ENGLISH); assertEquals(profile.getLocale(), Locale.ENGLISH);
assertTrue(profile.isBungeecordTransfer()); assertTrue(profile.isBungeecordTransfer());
profile.setName("Notch"); appearanceData.setName("Notch");
profile.setSkin("Notch"); appearanceData.setSkin("Notch");
profile.setLocale(Locale.FRENCH); profile.setLocale(Locale.FRENCH);
profile.setBungeecordTransfer(false); profile.setBungeecordTransfer(false);
@ -74,12 +78,13 @@ public class SQLStorageTest {
@DisplayName("Get updated profile") @DisplayName("Get updated profile")
@Order(4) @Order(4)
public void hasProfileBeenUpdated() { public void hasProfileBeenUpdated() {
final Optional<NickoProfile> profile = dataStore.getData(uuid); final Optional<NickoProfile> optionalProfile = NickoProfile.get(uuid);
assertTrue(profile.isPresent()); assertTrue(optionalProfile.isPresent());
final NickoProfile updatedProfile = profile.get(); final NickoProfile updatedProfile = optionalProfile.get();
assertEquals(updatedProfile.getName(), "Notch"); final AppearanceData appearanceData = updatedProfile.getAppearanceData();
assertEquals(updatedProfile.getSkin(), "Notch"); assertEquals(appearanceData.getName(), "Notch");
assertEquals(appearanceData.getSkin(), "Notch");
assertEquals(updatedProfile.getLocale(), Locale.FRENCH); assertEquals(updatedProfile.getLocale(), Locale.FRENCH);
assertFalse(updatedProfile.isBungeecordTransfer()); assertFalse(updatedProfile.isBungeecordTransfer());
} }

View file

@ -6,9 +6,9 @@ import be.seeseemelk.mockbukkit.entity.PlayerMock;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.appearance.ActionResult; import xyz.atnrch.nicko.appearance.ActionResult;
import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.config.Configuration; import xyz.atnrch.nicko.config.Configuration;
import xyz.atnrch.nicko.config.DataSourceConfiguration; import xyz.atnrch.nicko.config.DataSourceConfiguration;
import xyz.atnrch.nicko.profile.AppearanceData;
import xyz.atnrch.nicko.profile.NickoProfile; import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore; import xyz.atnrch.nicko.storage.PlayerDataStore;
@ -46,14 +46,20 @@ public class RedisCacheTest {
@DisplayName("Update Cache Profile") @DisplayName("Update Cache Profile")
@Order(2) @Order(2)
public void updateCache() { public void updateCache() {
final Optional<NickoProfile> optionalProfile = NickoProfile.get(player);
assertTrue(optionalProfile.isPresent());
final NickoProfile profile = optionalProfile.get();
final PlayerDataStore dataStore = plugin.getDataStore(); final PlayerDataStore dataStore = plugin.getDataStore();
final AppearanceManager appearanceManager = AppearanceManager.get(player); final AppearanceData appearanceData = profile.getAppearanceData();
appearanceManager.setName("Notch"); appearanceData.setName("Notch");
dataStore.updateCache(player.getUniqueId(), appearanceManager.getProfile()); dataStore.updateCache(player.getUniqueId(), profile);
final Optional<NickoProfile> retrieve = dataStore.getCache().retrieve(player.getUniqueId()); final Optional<NickoProfile> retrieve = dataStore.getCache().retrieve(player.getUniqueId());
assertTrue(retrieve.isPresent()); assertTrue(retrieve.isPresent());
final NickoProfile retrieved = retrieve.get(); final NickoProfile retrieved = retrieve.get();
assertEquals(retrieved.getName(), "Notch"); final AppearanceData retrievedAppearanceData = retrieved.getAppearanceData();
assertEquals(retrievedAppearanceData.getName(), "Notch");
} }
@Test @Test