Dynamically translate GUI (#3)

Reviewed-on: https://ineanto.xyz/git/ineanto/nicko/pulls/3
This commit is contained in:
ineanto 2023-09-17 17:36:17 +02:00
parent f157831641
commit 649e23409a
61 changed files with 1243 additions and 629 deletions

16
pom.xml
View file

@ -43,8 +43,8 @@
MINECRAFT MINECRAFT
--> -->
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>io.papermc.paper</groupId>
<artifactId>spigot</artifactId> <artifactId>paper-api</artifactId>
<version>1.20.1-R0.1-SNAPSHOT</version> <version>1.20.1-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@ -63,7 +63,7 @@
<dependency> <dependency>
<groupId>xyz.xenondevs.invui</groupId> <groupId>xyz.xenondevs.invui</groupId>
<artifactId>invui</artifactId> <artifactId>invui</artifactId>
<version>1.11</version> <version>1.14</version>
<type>pom</type> <type>pom</type>
</dependency> </dependency>
<dependency> <dependency>
@ -73,8 +73,8 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.seeseemelk</groupId> <groupId>com.github.seeseemelk</groupId>
<artifactId>MockBukkit-v1.19</artifactId> <artifactId>MockBukkit-v1.20</artifactId>
<version>2.29.0</version> <version>3.9.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
@ -95,7 +95,7 @@
<dependency> <dependency>
<groupId>com.github.jsixface</groupId> <groupId>com.github.jsixface</groupId>
<artifactId>yamlconfig</artifactId> <artifactId>yamlconfig</artifactId>
<version>1.1.2</version> <version>1.2</version>
</dependency> </dependency>
<!-- Jackson Core --> <!-- Jackson Core -->
<dependency> <dependency>
@ -120,12 +120,12 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M7</version> <version>3.0.0-M9</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version> <version>3.5.0</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>

View file

@ -3,15 +3,12 @@ package xyz.atnrch.nicko;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
import xyz.atnrch.nicko.command.NickoCommand; import xyz.atnrch.nicko.command.NickoCommand;
import xyz.atnrch.nicko.config.Configuration; import xyz.atnrch.nicko.config.Configuration;
import xyz.atnrch.nicko.config.ConfigurationManager; import xyz.atnrch.nicko.config.ConfigurationManager;
import xyz.atnrch.nicko.event.PlayerJoinListener; import xyz.atnrch.nicko.event.PlayerJoinListener;
import xyz.atnrch.nicko.event.PlayerQuitListener; import xyz.atnrch.nicko.event.PlayerQuitListener;
import xyz.atnrch.nicko.gui.items.common.UnavailableItem;
import xyz.atnrch.nicko.i18n.Locale; import xyz.atnrch.nicko.i18n.Locale;
import xyz.atnrch.nicko.i18n.LocaleFileManager; import xyz.atnrch.nicko.i18n.LocaleFileManager;
import xyz.atnrch.nicko.mojang.MojangAPI; import xyz.atnrch.nicko.mojang.MojangAPI;
@ -22,7 +19,6 @@ import xyz.xenondevs.invui.gui.structure.Structure;
import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SimpleItem; import xyz.xenondevs.invui.item.impl.SimpleItem;
import java.io.File;
import java.io.IOException; import java.io.IOException;
public class NickoBukkit extends JavaPlugin { public class NickoBukkit extends JavaPlugin {
@ -44,16 +40,8 @@ public class NickoBukkit extends JavaPlugin {
/** /**
* Used by MockBukkit * Used by MockBukkit
*/ */
protected NickoBukkit(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) { protected NickoBukkit(Configuration configuration) {
this(loader, description, dataFolder, file, null); this.unitTesting = true;
}
/**
* Used by MockBukkit
*/
protected NickoBukkit(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file, Configuration configuration) {
super(loader, description, dataFolder, file);
unitTesting = true;
this.configuration = configuration; this.configuration = configuration;
getLogger().info("Unit Testing Mode enabled."); getLogger().info("Unit Testing Mode enabled.");
} }
@ -103,7 +91,6 @@ public class NickoBukkit extends JavaPlugin {
Structure.addGlobalIngredient('#', new SimpleItem(new ItemBuilder(Material.AIR))); Structure.addGlobalIngredient('#', new SimpleItem(new ItemBuilder(Material.AIR)));
Structure.addGlobalIngredient('%', new SimpleItem(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setDisplayName(" "))); Structure.addGlobalIngredient('%', new SimpleItem(new ItemBuilder(Material.BLACK_STAINED_GLASS_PANE).setDisplayName(" ")));
Structure.addGlobalIngredient('U', new UnavailableItem());
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
getLogger().info("Enabling PlaceHolderAPI support..."); getLogger().info("Enabling PlaceHolderAPI support...");
@ -120,11 +107,12 @@ public class NickoBukkit extends JavaPlugin {
@Override @Override
public void onDisable() { public void onDisable() {
if (!getDataStore().getStorage().isError()) { if (!getDataStore().getStorage().isError()) {
getLogger().info("Closing persistence...");
nameStore.clearStoredNames(); nameStore.clearStoredNames();
Bukkit.getOnlinePlayers().forEach(player -> dataStore.saveData(player)); Bukkit.getOnlinePlayers().forEach(player -> dataStore.saveData(player));
if (!dataStore.getStorage().getProvider().close()) { if (!dataStore.getStorage().getProvider().close()) {
getLogger().severe("Failed to close persistence!"); getLogger().severe("Failed to close persistence!");
} else {
getLogger().info("Persistence closed.");
} }
} }

View file

@ -11,20 +11,25 @@ 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.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 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 = new AppearanceManager(player);
} }
public void openNameThenSkinAnvil() { public void openNameThenSkinAnvil() {
@ -39,7 +44,7 @@ public class AnvilManager {
getNameAnvil().open(player); getNameAnvil().open(player);
} }
public AnvilGUI.Builder getNameThenSkinAnvil() { private AnvilGUI.Builder getNameThenSkinAnvil() {
return new AnvilGUI.Builder() return new AnvilGUI.Builder()
.plugin(NickoBukkit.getInstance()) .plugin(NickoBukkit.getInstance())
.itemLeft(getLeftItem(false)) .itemLeft(getLeftItem(false))
@ -49,8 +54,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()); profile.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());
} }
@ -60,7 +65,7 @@ public class AnvilManager {
.text("New name..."); .text("New name...");
} }
public AnvilGUI.Builder getNameAnvil() { private AnvilGUI.Builder getNameAnvil() {
return new AnvilGUI.Builder() return new AnvilGUI.Builder()
.plugin(NickoBukkit.getInstance()) .plugin(NickoBukkit.getInstance())
.itemLeft(getLeftItem(false)) .itemLeft(getLeftItem(false))
@ -70,8 +75,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()); profile.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 +96,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()); profile.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,7 +11,6 @@ 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.NickoProfile; import xyz.atnrch.nicko.profile.NickoProfile;
@ -22,96 +21,36 @@ import xyz.atnrch.nicko.wrapper.*;
import java.io.IOException; import java.io.IOException;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.Optional; import java.util.Optional;
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 Player player;
this.player = Bukkit.getPlayer(uuid);
this.uuid = uuid;
this.profile = dataStore.getData(uuid).orElse(NickoProfile.EMPTY_PROFILE.clone());
}
private AppearanceManager(String name) { public AppearanceManager(Player player) {
this.player = null; this.player = player;
this.uuid = null;
this.profile = dataStore.getOfflineData(name).orElse(NickoProfile.EMPTY_PROFILE.clone());
}
public static AppearanceManager get(Player player) {
return new AppearanceManager(player.getUniqueId());
}
public static AppearanceManager get(String name) {
return new AppearanceManager(name);
}
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 NickoProfile profile = getNickoProfile();
final String defaultName = nameStore.getStoredName(player); final String defaultName = nameStore.getStoredName(player);
this.profile.setName(defaultName); profile.setName(defaultName);
this.profile.setSkin(defaultName); profile.setSkin(defaultName);
dataStore.getCache().cache(player.getUniqueId(), profile);
final ActionResult actionResult = updatePlayer(true, true); final ActionResult actionResult = updatePlayer(true, true);
if (!actionResult.isError()) { if (!actionResult.isError()) {
this.profile.setSkin(null); profile.setSkin(null);
this.profile.setName(null); profile.setName(null);
dataStore.getCache().cache(uuid, profile); dataStore.getCache().cache(player.getUniqueId(), profile);
} }
return actionResult; return actionResult;
} }
public ActionResult updatePlayer(boolean skinChange, boolean reset) { public ActionResult updatePlayer(boolean skinChange, boolean reset) {
final NickoProfile profile = getNickoProfile();
final String displayName = profile.getName() == null ? player.getName() : profile.getName(); final String displayName = profile.getName() == null ? player.getName() : profile.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);
@ -124,6 +63,11 @@ public class AppearanceManager {
return result; return result;
} }
private NickoProfile getNickoProfile() {
final Optional<NickoProfile> optionalProfile = dataStore.getData(player.getUniqueId());
return optionalProfile.orElse(NickoProfile.EMPTY_PROFILE.clone());
}
public void updateOthers() { public void updateOthers() {
final WrapperPlayServerEntityDestroy destroy = new WrapperPlayServerEntityDestroy(); final WrapperPlayServerEntityDestroy destroy = new WrapperPlayServerEntityDestroy();
final WrapperPlayServerNamedEntitySpawn spawn = new WrapperPlayServerNamedEntitySpawn(); final WrapperPlayServerNamedEntitySpawn spawn = new WrapperPlayServerNamedEntitySpawn();
@ -139,15 +83,16 @@ 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 NickoProfile profile = getNickoProfile();
final boolean changeOnlyName = profile.getSkin() != null && profile.getSkin().equals(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(profile.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();
@ -177,6 +122,7 @@ public class AppearanceManager {
private void respawnPlayer() { private void respawnPlayer() {
final World world = player.getWorld(); final World world = player.getWorld();
final boolean wasFlying = player.isFlying(); final boolean wasFlying = player.isFlying();
final boolean wasAllowedToFly = player.getAllowFlight();
final WrapperPlayServerRespawn respawn = new WrapperPlayServerRespawn(); final WrapperPlayServerRespawn respawn = new WrapperPlayServerRespawn();
respawn.setDimension(world); respawn.setDimension(world);
respawn.setSeed(world.getSeed()); respawn.setSeed(world.getSeed());
@ -185,9 +131,10 @@ public class AppearanceManager {
respawn.setDifficulty(world.getDifficulty()); respawn.setDifficulty(world.getDifficulty());
respawn.setCopyMetadata(true); respawn.setCopyMetadata(true);
respawn.sendPacket(player); respawn.sendPacket(player);
player.setFlying(wasFlying);
player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
player.updateInventory(); player.setAllowFlight(wasAllowedToFly);
player.setFlying(wasFlying);
player.updateInventory(); // Marked as unstable.
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -218,6 +165,9 @@ public class AppearanceManager {
// No, I'll not waste another day fixing their mess. // No, I'll not waste another day fixing their mess.
// Go cry about it to Mojang. // Go cry about it to Mojang.
// (Long live NoEncryption!) // (Long live NoEncryption!)
// TODO (Ineanto, 9/1/23):
// Try to provide chat session data after ProtocolLib's update to support Chat Sessions.
// This could remove the mandatory NoEncryption (or similar "encryption removing") dependency with Nicko.
add.setData(ImmutableList.of(new PlayerInfoData( add.setData(ImmutableList.of(new PlayerInfoData(
player.getUniqueId(), player.getUniqueId(),
player.getPing(), player.getPing(),

View file

@ -1,13 +1,12 @@
package xyz.atnrch.nicko.command; package xyz.atnrch.nicko.command;
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 org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.gui.HomeGUI;
import xyz.atnrch.nicko.i18n.I18N; import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict; import xyz.atnrch.nicko.i18n.I18NDict;
@ -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);
@ -49,7 +42,7 @@ public class NickoCommand implements CommandExecutor {
} }
public void sendHelpMessage(CommandSender sender) { public void sendHelpMessage(CommandSender sender) {
helpMessage = helpMessage.replace("{version}", NickoBukkit.getInstance().getDescription().getVersion()); helpMessage = helpMessage.replace("{version}", NickoBukkit.getInstance().getPluginMeta().getVersion());
sender.sendMessage(helpMessage); sender.sendMessage(helpMessage);
} }
} }

View file

@ -1,21 +1,26 @@
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.NickoProfile;
import org.bukkit.Sound; import xyz.atnrch.nicko.storage.PlayerDataStore;
import org.bukkit.command.CommandSender;
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 +31,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 +52,22 @@ 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!"); profile.setName(name);
target.playSound(target.getLocation(), Sound.ENTITY_ITEM_FRAME_PLACE, 1, 1); profile.setSkin(skin);
} else { dataStore.updateCache(target.getUniqueId(), profile);
final I18N i18n = new I18N(target); final AppearanceManager appearanceManager = new AppearanceManager(target);
target.sendMessage(prefix + "§cWhoops. Something happened: " + i18n.translatePrefixless(result.getErrorKey())); 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,19 +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.ifPresent(profile -> {
if (!actionResult.isError()) { if (profile.hasData()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Restore.OK)); final AppearanceManager appearanceManager = new AppearanceManager(player);
} else { final boolean needsASkinChange = profile.getSkin() != null && !profile.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);
} }
} }

View file

@ -4,25 +4,36 @@ import xyz.atnrch.nicko.gui.items.admin.ManageCacheItem;
import xyz.atnrch.nicko.gui.items.admin.ManagePlayerItem; import xyz.atnrch.nicko.gui.items.admin.ManagePlayerItem;
import xyz.atnrch.nicko.gui.items.common.GoBackItem; import xyz.atnrch.nicko.gui.items.common.GoBackItem;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import xyz.atnrch.nicko.gui.items.common.UnavailableItem;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.window.Window; import xyz.xenondevs.invui.window.Window;
public class AdminGUI { public class AdminGUI {
private final String title = "Nicko > Administration";
private final Player player; private final Player player;
private final Gui gui; private final Gui gui;
private final String title;
public AdminGUI(Player player) { public AdminGUI(Player player) {
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.ADMIN);
final HomeGUI parent = new HomeGUI(player); final HomeGUI parent = new HomeGUI(player);
final GoBackItem backItem = new GoBackItem(player);
final UnavailableItem unavailableItem = new UnavailableItem(player);
final ManagePlayerItem managePlayerItem = new ManagePlayerItem(i18n, player);
this.gui = Gui.normal() this.gui = Gui.normal()
.setStructure( .setStructure(
"# # # # # # # # #", "# # # # # # # # #",
"# # # S C U # # #", "# # # S C X # # #",
"B # # # # # # # #" "B # # # # # # # #"
) )
.addIngredient('S', new ManageCacheItem()) .addIngredient('S', new ManageCacheItem(i18n))
.addIngredient('C', new ManagePlayerItem()) .addIngredient('C', managePlayerItem.get())
.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle())) .addIngredient('U', unavailableItem.get())
.addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()))
.build(); .build();
this.player = player; this.player = player;
} }

View file

@ -3,28 +3,39 @@ package xyz.atnrch.nicko.gui;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import xyz.atnrch.nicko.gui.items.admin.cache.CacheStatisticsItem; import xyz.atnrch.nicko.gui.items.admin.cache.CacheStatisticsItem;
import xyz.atnrch.nicko.gui.items.admin.cache.InvalidateCacheItem; import xyz.atnrch.nicko.gui.items.admin.cache.InvalidateCacheItem;
import xyz.atnrch.nicko.gui.items.admin.cache.InvalidateEntryItem; import xyz.atnrch.nicko.gui.items.admin.cache.InvalidateSkinItem;
import xyz.atnrch.nicko.gui.items.common.GoBackItem; import xyz.atnrch.nicko.gui.items.common.GoBackItem;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.window.Window; import xyz.xenondevs.invui.window.Window;
public class CacheManagementGUI { public class CacheManagementGUI {
private final String title = "Nicko > Admin... > Cache";
private final Player player; private final Player player;
private final Gui gui; private final Gui gui;
private final String title;
public CacheManagementGUI(Player player) { public CacheManagementGUI(Player player) {
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.CACHE);
final AdminGUI parent = new AdminGUI(player); final AdminGUI parent = new AdminGUI(player);
final GoBackItem backItem = new GoBackItem(player);
final CacheStatisticsItem cacheStatisticsItem = new CacheStatisticsItem(player);
final InvalidateCacheItem invalidateCacheItem = new InvalidateCacheItem(player);
final InvalidateSkinItem invalidateSkinItem = new InvalidateSkinItem(player);
this.gui = Gui.normal() this.gui = Gui.normal()
.setStructure( .setStructure(
"# # # # # # # # #", "# # # # # # # # #",
"# # # S A D # # #", "# # # S C E # # #",
"B # # # # # # # #" "B # # # # # # # #"
) )
.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle())) .addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()))
.addIngredient('S', new CacheStatisticsItem()) .addIngredient('S', cacheStatisticsItem.get())
.addIngredient('A', new InvalidateCacheItem()) .addIngredient('C', invalidateCacheItem.get())
.addIngredient('D', new InvalidateEntryItem()) .addIngredient('E', invalidateSkinItem.get())
.build(); .build();
this.player = player; this.player = player;
} }

View file

@ -0,0 +1,42 @@
package xyz.atnrch.nicko.gui;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.gui.items.common.choice.CancelItem;
import xyz.atnrch.nicko.gui.items.common.choice.ChoiceCallback;
import xyz.atnrch.nicko.gui.items.common.choice.ConfirmItem;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SimpleItem;
import xyz.xenondevs.invui.window.Window;
public class ChoiceGUI {
private final Player player;
private final Gui gui;
public ChoiceGUI(Player player, ChoiceCallback callback) {
final I18N i18n = new I18N(player);
final ConfirmItem confirmItem = new ConfirmItem(player, callback);
final CancelItem cancelItem = new CancelItem(player, callback);
final ItemTranslation chooseItemTranslation = i18n.translateItem(I18NDict.GUI.Choice.CHOOSE);
this.gui = Gui.normal()
.setStructure(
"@ @ @ @ % & & & &",
"@ @ @ @ I & & & &",
"@ @ @ @ % & & & &"
)
.addIngredient('@', confirmItem.get())
.addIngredient('&', cancelItem.get())
.addIngredient('I', new SimpleItem(new ItemBuilder(Material.PAPER).setDisplayName(chooseItemTranslation.getName()).get()))
.build();
this.player = player;
}
public void open() {
Window.single().setGui(gui).setTitle("... > Invalidate > Confirm").open(player);
}
}

View file

@ -1,34 +0,0 @@
package xyz.atnrch.nicko.gui;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.gui.items.common.confirm.ChoiceCallback;
import xyz.atnrch.nicko.gui.items.common.confirm.CancelItem;
import xyz.atnrch.nicko.gui.items.common.confirm.ConfirmItem;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SimpleItem;
import xyz.xenondevs.invui.window.Window;
public class ConfirmGUI {
private final Player player;
private final Gui gui;
public ConfirmGUI(Player player, ChoiceCallback callback) {
this.gui = Gui.normal()
.setStructure(
"@ @ @ @ % & & & &",
"@ @ @ @ I & & & &",
"@ @ @ @ % & & & &"
)
.addIngredient('@', new ConfirmItem(callback))
.addIngredient('&', new CancelItem(callback))
.addIngredient('I', new SimpleItem(new ItemBuilder(Material.PAPER).setDisplayName("§6Select an option").get()))
.build();
this.player = player;
}
public void open() {
Window.single().setGui(gui).setTitle("... > Invalidate > Confirm").open(player);
}
}

View file

@ -8,13 +8,15 @@ import xyz.atnrch.nicko.gui.items.home.AdminAccessItem;
import xyz.atnrch.nicko.gui.items.home.ExitItem; import xyz.atnrch.nicko.gui.items.home.ExitItem;
import xyz.atnrch.nicko.gui.items.home.ResetItem; import xyz.atnrch.nicko.gui.items.home.ResetItem;
import xyz.atnrch.nicko.gui.items.home.SettingsAccessItem; import xyz.atnrch.nicko.gui.items.home.SettingsAccessItem;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.window.Window; import xyz.xenondevs.invui.window.Window;
public class HomeGUI { public class HomeGUI {
private final String title = "Nicko - Home";
private final Player player; private final Player player;
private final Gui gui; private final Gui gui;
private final String title;
public HomeGUI(Player player) { public HomeGUI(Player player) {
final String[] dynamicStructure = new String[]{ final String[] dynamicStructure = new String[]{
@ -26,15 +28,26 @@ public class HomeGUI {
dynamicStructure[2] = dynamicStructure[2].replace("A", "#"); dynamicStructure[2] = dynamicStructure[2].replace("A", "#");
} }
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.HOME);
final ExitItem exitItem = new ExitItem(player);
final ResetItem resetItem = new ResetItem(player);
final ChangeNameItem changeNameItem = new ChangeNameItem(player);
final ChangeBothItem changeBothItem = new ChangeBothItem(player);
final ChangeSkinItem changeSkinItem = new ChangeSkinItem(player);
final SettingsAccessItem settingsAccessItem = new SettingsAccessItem(player);
final AdminAccessItem adminAccessItem = new AdminAccessItem(player);
this.gui = Gui.normal() this.gui = Gui.normal()
.setStructure(dynamicStructure) .setStructure(dynamicStructure)
.addIngredient('E', new ExitItem()) .addIngredient('E', exitItem.get())
.addIngredient('R', new ResetItem()) .addIngredient('R', resetItem.get())
.addIngredient('N', new ChangeNameItem()) .addIngredient('N', changeNameItem.get())
.addIngredient('B', new ChangeBothItem()) .addIngredient('B', changeBothItem.get())
.addIngredient('S', new ChangeSkinItem(player)) .addIngredient('S', changeSkinItem.get())
.addIngredient('P', new SettingsAccessItem()) .addIngredient('P', settingsAccessItem.get())
.addIngredient('A', new AdminAccessItem()) .addIngredient('A', adminAccessItem.get())
.build(); .build();
this.player = player; this.player = player;
} }

View file

@ -2,6 +2,8 @@ package xyz.atnrch.nicko.gui;
import xyz.atnrch.nicko.gui.items.common.GoBackItem; import xyz.atnrch.nicko.gui.items.common.GoBackItem;
import xyz.atnrch.nicko.gui.items.common.ScrollUpItem; import xyz.atnrch.nicko.gui.items.common.ScrollUpItem;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.mojang.MojangSkin; import xyz.atnrch.nicko.mojang.MojangSkin;
import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.gui.ScrollGui; import xyz.xenondevs.invui.gui.ScrollGui;
@ -19,13 +21,15 @@ import java.util.Optional;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class CacheDetailedGUI { public class InvalidateSkinGUI {
public static final String TITLE = "... > Cache > Invalidate";
private final Player player; private final Player player;
private final Gui gui; private final Gui gui;
private final String title;
public InvalidateSkinGUI(Player player) {
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.INVALIDATE_SKIN);
public CacheDetailedGUI(Player player) {
final ConcurrentMap<String, Optional<MojangSkin>> skins = NickoBukkit.getInstance().getMojangAPI().getSkinCache().asMap(); final ConcurrentMap<String, Optional<MojangSkin>> skins = NickoBukkit.getInstance().getMojangAPI().getSkinCache().asMap();
final List<String> loadedSkins = skins.entrySet().stream() final List<String> loadedSkins = skins.entrySet().stream()
.filter(entry -> entry.getValue().isPresent()) .filter(entry -> entry.getValue().isPresent())
@ -37,6 +41,10 @@ public class CacheDetailedGUI {
.collect(Collectors.toList()); .collect(Collectors.toList());
final CacheManagementGUI parent = new CacheManagementGUI(player); final CacheManagementGUI parent = new CacheManagementGUI(player);
final ScrollUpItem scrollUpItem = new ScrollUpItem(i18n);
final ScrollDownItem scrollDownItem = new ScrollDownItem(i18n);
final GoBackItem backItem = new GoBackItem(player);
gui = ScrollGui.items(guiItemBuilder -> { gui = ScrollGui.items(guiItemBuilder -> {
guiItemBuilder.setStructure( guiItemBuilder.setStructure(
"x x x x x x x x U", "x x x x x x x x U",
@ -46,9 +54,9 @@ public class CacheDetailedGUI {
"x x x x x x x x D", "x x x x x x x x D",
"B % % % % % % % %"); "B % % % % % % % %");
guiItemBuilder.addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL); guiItemBuilder.addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL);
guiItemBuilder.addIngredient('U', new ScrollUpItem()); guiItemBuilder.addIngredient('U', scrollUpItem);
guiItemBuilder.addIngredient('D', new ScrollDownItem()); guiItemBuilder.addIngredient('D', scrollDownItem);
guiItemBuilder.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle())); guiItemBuilder.addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()));
guiItemBuilder.setContent(items); guiItemBuilder.setContent(items);
}); });
@ -56,6 +64,6 @@ public class CacheDetailedGUI {
} }
public void open() { public void open() {
Window.single().setGui(gui).setTitle(TITLE).open(player); Window.single().setGui(gui).setTitle(title).open(player);
} }
} }

View file

@ -7,6 +7,8 @@ import xyz.atnrch.nicko.gui.items.admin.check.PlayerInformationItem;
import xyz.atnrch.nicko.gui.items.common.GoBackItem; import xyz.atnrch.nicko.gui.items.common.GoBackItem;
import xyz.atnrch.nicko.gui.items.common.ScrollDownItem; import xyz.atnrch.nicko.gui.items.common.ScrollDownItem;
import xyz.atnrch.nicko.gui.items.common.ScrollUpItem; import xyz.atnrch.nicko.gui.items.common.ScrollUpItem;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.gui.ScrollGui; import xyz.xenondevs.invui.gui.ScrollGui;
import xyz.xenondevs.invui.gui.structure.Markers; import xyz.xenondevs.invui.gui.structure.Markers;
@ -17,18 +19,24 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class PlayerCheckGUI { public class PlayerCheckGUI {
public static final String TITLE = "Nicko > Admin... > Check";
private final Player player; private final Player player;
private final Gui gui; private final Gui gui;
private final String title;
public PlayerCheckGUI(Player player) { public PlayerCheckGUI(Player player) {
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.CHECK);
final List<Item> items = Bukkit.getOnlinePlayers().stream() final List<Item> items = Bukkit.getOnlinePlayers().stream()
.map(Entity::getUniqueId) .map(Entity::getUniqueId)
.map(PlayerInformationItem::new) .map(uuid -> new PlayerInformationItem(i18n, uuid))
.collect(Collectors.toList()); .collect(Collectors.toList());
final AdminGUI parent = new AdminGUI(player); final AdminGUI parent = new AdminGUI(player);
final GoBackItem backItem = new GoBackItem(player);
final ScrollUpItem scrollUpItem = new ScrollUpItem(i18n);
final ScrollDownItem scrollDownItem = new ScrollDownItem(i18n);
gui = ScrollGui.items(guiItemBuilder -> { gui = ScrollGui.items(guiItemBuilder -> {
guiItemBuilder.setStructure( guiItemBuilder.setStructure(
"x x x x x x x x U", "x x x x x x x x U",
@ -38,9 +46,9 @@ public class PlayerCheckGUI {
"x x x x x x x x D", "x x x x x x x x D",
"B % % % % % % % %"); "B % % % % % % % %");
guiItemBuilder.addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL); guiItemBuilder.addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL);
guiItemBuilder.addIngredient('U', new ScrollUpItem()); guiItemBuilder.addIngredient('U', scrollUpItem);
guiItemBuilder.addIngredient('D', new ScrollDownItem()); guiItemBuilder.addIngredient('D', scrollDownItem);
guiItemBuilder.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle())); guiItemBuilder.addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()));
guiItemBuilder.setContent(items); guiItemBuilder.setContent(items);
}); });
@ -48,6 +56,6 @@ public class PlayerCheckGUI {
} }
public void open() { public void open() {
Window.single().setGui(gui).setTitle(TITLE).open(player); Window.single().setGui(gui).setTitle(title).open(player);
} }
} }

View file

@ -1,17 +1,19 @@
package xyz.atnrch.nicko.gui; package xyz.atnrch.nicko.gui;
import xyz.atnrch.nicko.gui.items.common.GoBackItem; import xyz.atnrch.nicko.gui.items.common.GoBackItem;
import xyz.atnrch.nicko.gui.items.common.UnavailableItem;
import xyz.atnrch.nicko.gui.items.settings.BungeeCordCyclingItem; import xyz.atnrch.nicko.gui.items.settings.BungeeCordCyclingItem;
import xyz.atnrch.nicko.gui.items.settings.LanguageCyclingItem; import xyz.atnrch.nicko.gui.items.settings.LanguageCyclingItem;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.window.Window; import xyz.xenondevs.invui.window.Window;
public class SettingsGUI { public class SettingsGUI {
public static final String TITLE = "Nicko > Settings";
private final Player player; private final Player player;
private final Gui gui; private final Gui gui;
private final String title;
public SettingsGUI(Player player) { public SettingsGUI(Player player) {
final String[] dynamicStructure = new String[]{ final String[] dynamicStructure = new String[]{
@ -23,17 +25,26 @@ public class SettingsGUI {
// TODO: 3/6/23 Replace when Redis is not enabled // TODO: 3/6/23 Replace when Redis is not enabled
dynamicStructure[1] = dynamicStructure[1].replace("T", "U"); dynamicStructure[1] = dynamicStructure[1].replace("T", "U");
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.SETTINGS);
final HomeGUI parent = new HomeGUI(player); final HomeGUI parent = new HomeGUI(player);
final UnavailableItem unavailableItem = new UnavailableItem(player);
final LanguageCyclingItem languageItem = new LanguageCyclingItem(player);
final BungeeCordCyclingItem bungeeCordItem = new BungeeCordCyclingItem(player);
final GoBackItem backItem = new GoBackItem(player);
this.gui = Gui.normal() this.gui = Gui.normal()
.setStructure(dynamicStructure) .setStructure(dynamicStructure)
.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle())) .addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()))
.addIngredient('L', new LanguageCyclingItem().get(player)) .addIngredient('L', languageItem.get())
.addIngredient('T', new BungeeCordCyclingItem().get(player)) .addIngredient('U', unavailableItem.get())
.addIngredient('T', bungeeCordItem.get())
.build(); .build();
this.player = player; this.player = player;
} }
public void open() { public void open() {
Window.single().setGui(gui).setTitle(TITLE).open(player); Window.single().setGui(gui).setTitle(title).open(player);
} }
} }

View file

@ -1,24 +1,33 @@
package xyz.atnrch.nicko.gui.items.admin; package xyz.atnrch.nicko.gui.items.admin;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.builder.SkullBuilder;
import xyz.xenondevs.invui.item.impl.AsyncItem;
import xyz.atnrch.nicko.gui.CacheManagementGUI;
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 org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.atnrch.nicko.gui.CacheManagementGUI;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.builder.SkullBuilder;
import xyz.xenondevs.invui.item.impl.AsyncItem;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class ManageCacheItem extends AsyncItem { public class ManageCacheItem extends AsyncItem {
public ManageCacheItem() { public ManageCacheItem(I18N i18n) {
super(new ItemBuilder(Material.PAINTING) super(new SuppliedItem(() -> {
.setDisplayName("Manage §6skin §fcache...") final ItemBuilder builder = new ItemBuilder(Material.PAINTING);
.addLoreLines("§7Access the skin cache management panel."), final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.LOADING);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
}, (click -> true)).getItemProvider(),
() -> { () -> {
final SkullBuilder builder = new SkullBuilder("Notch"); final SkullBuilder builder = new SkullBuilder("Notch");
builder.setDisplayName("Manage §6skin §fcache..."); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.MANAGE_CACHE);
builder.addLoreLines("§7Access the skin cache management panel."); builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
}); });
} }

View file

@ -2,30 +2,32 @@ package xyz.atnrch.nicko.gui.items.admin;
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.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
import xyz.atnrch.nicko.gui.PlayerCheckGUI; import xyz.atnrch.nicko.gui.PlayerCheckGUI;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
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;
public class ManagePlayerItem extends SuppliedItem { public class ManagePlayerItem {
public ManagePlayerItem() { private final Player player;
super(() -> { private final I18N i18n;
final ItemBuilder builder = new ItemBuilder(Material.WRITABLE_BOOK);
builder.setDisplayName("Check a player..."); public ManagePlayerItem(I18N i18n, Player player) {
builder.addLoreLines("§7See players' disguise information."); this.i18n = i18n;
return builder; this.player = player;
},
click -> true);
} }
@Override public SuppliedItem get() {
public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent return new SuppliedItem(() -> {
event) { final ItemBuilder builder = new ItemBuilder(Material.WRITABLE_BOOK);
if (clickType.isLeftClick() || clickType.isRightClick()) { final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.MANAGE_PLAYER);
event.getView().close(); builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
}, click -> {
new PlayerCheckGUI(player).open(); new PlayerCheckGUI(player).open();
} return true;
});
} }
} }

View file

@ -6,9 +6,9 @@ import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.gui.ConfirmGUI; import xyz.atnrch.nicko.gui.ChoiceGUI;
import xyz.atnrch.nicko.gui.CacheDetailedGUI; import xyz.atnrch.nicko.gui.InvalidateSkinGUI;
import xyz.atnrch.nicko.gui.items.common.confirm.ChoiceCallback; import xyz.atnrch.nicko.gui.items.common.choice.ChoiceCallback;
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.MojangAPI; import xyz.atnrch.nicko.mojang.MojangAPI;
@ -40,7 +40,7 @@ public class CacheEntryItem extends AsyncItem {
public void handleClick(@NotNull ClickType click, @NotNull Player player, @NotNull InventoryClickEvent event) { public void handleClick(@NotNull ClickType click, @NotNull Player player, @NotNull InventoryClickEvent event) {
if (click.isLeftClick() || click.isRightClick()) { if (click.isLeftClick() || click.isRightClick()) {
event.getView().close(); event.getView().close();
new ConfirmGUI(player, new ChoiceCallback() { new ChoiceGUI(player, new ChoiceCallback() {
@Override @Override
public void onConfirm() { public void onConfirm() {
final I18N i18n = new I18N(player); final I18N i18n = new I18N(player);
@ -50,7 +50,7 @@ public class CacheEntryItem extends AsyncItem {
@Override @Override
public void onCancel() { public void onCancel() {
new CacheDetailedGUI(player).open(); new InvalidateSkinGUI(player).open();
} }
}).open(); }).open();
} }

View file

@ -2,7 +2,11 @@ package xyz.atnrch.nicko.gui.items.admin.cache;
import com.google.common.cache.CacheStats; import com.google.common.cache.CacheStats;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.atnrch.nicko.mojang.MojangSkin; import xyz.atnrch.nicko.mojang.MojangSkin;
import org.bukkit.Material; import org.bukkit.Material;
import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.builder.ItemBuilder;
@ -10,17 +14,26 @@ import xyz.xenondevs.invui.item.impl.SuppliedItem;
import java.util.Optional; import java.util.Optional;
public class CacheStatisticsItem extends SuppliedItem { public class CacheStatisticsItem {
public CacheStatisticsItem() { private final I18N i18n;
super(() -> {
public CacheStatisticsItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.BOOK); final ItemBuilder builder = new ItemBuilder(Material.BOOK);
final LoadingCache<String, Optional<MojangSkin>> cache = NickoBukkit.getInstance().getMojangAPI().getSkinCache(); final LoadingCache<String, Optional<MojangSkin>> cache = NickoBukkit.getInstance().getMojangAPI().getSkinCache();
final CacheStats stats = cache.stats(); final CacheStats stats = cache.stats();
builder.setDisplayName("Statistics");
builder.addLoreLines( final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.Cache.STATISTICS,
"Request Count: §b" + stats.requestCount(), stats.requestCount(),
"Skin Cached: §b" + Math.round(cache.size()), Math.round(cache.size())
"§8§oCache is cleared every 24 hours."); );
// TODO (Ineanto, 9/11/23): This doesn't work.
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
}, (event) -> true); }, (event) -> true);
} }

View file

@ -6,18 +6,23 @@ 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.ItemTranslation;
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;
public class InvalidateCacheItem extends SuppliedItem { public class InvalidateCacheItem {
public InvalidateCacheItem() { private final I18N i18n;
super(() -> {
public InvalidateCacheItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.TNT); final ItemBuilder builder = new ItemBuilder(Material.TNT);
builder.setDisplayName("Invalidate cache"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.Cache.INVALIDATE_CACHE);
builder.addLoreLines( builder.setDisplayName(translation.getName());
"§c§oNOT RECOMMENDED", translation.getLore().forEach(builder::addLoreLines);
"§7Invalidates every skin entry present in the cache.",
"§7Does not reset player disguises.");
return builder; return builder;
}, (click) -> { }, (click) -> {
final ClickType clickType = click.getClickType(); final ClickType clickType = click.getClickType();

View file

@ -1,28 +0,0 @@
package xyz.atnrch.nicko.gui.items.admin.cache;
import xyz.atnrch.nicko.gui.CacheDetailedGUI;
import org.bukkit.Material;
import org.bukkit.event.inventory.ClickType;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class InvalidateEntryItem extends SuppliedItem {
public InvalidateEntryItem() {
super(() -> {
final ItemBuilder builder = new ItemBuilder(Material.PAPER);
builder.setDisplayName("Invalidate specific entry");
builder.addLoreLines("§7Select a specific skin to invalidate.",
"§7Useful if a skin has been updated",
"§7recently and the cache no longer up-to-date.");
return builder;
}, (click) -> {
final ClickType clickType = click.getClickType();
if (clickType.isLeftClick() || clickType.isRightClick()) {
click.getEvent().getView().close();
new CacheDetailedGUI(click.getPlayer()).open();
return true;
}
return false;
});
}
}

View file

@ -0,0 +1,37 @@
package xyz.atnrch.nicko.gui.items.admin.cache;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import xyz.atnrch.nicko.gui.InvalidateSkinGUI;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class InvalidateSkinItem {
private final I18N i18n;
public InvalidateSkinItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.PAPER);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.Cache.INVALIDATE_SKIN);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
}, (click) -> {
final ClickType clickType = click.getClickType();
if (clickType.isLeftClick() || clickType.isRightClick()) {
click.getEvent().getView().close();
new InvalidateSkinGUI(click.getPlayer()).open();
return true;
}
return false;
});
}
}

View file

@ -4,38 +4,48 @@ 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.i18n.I18N;
import xyz.atnrch.nicko.mojang.MojangAPI; import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
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 xyz.xenondevs.invui.item.impl.SuppliedItem;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public class PlayerInformationItem extends AsyncItem { public class PlayerInformationItem extends AsyncItem {
private final MojangAPI mojangAPI = NickoBukkit.getInstance().getMojangAPI(); public PlayerInformationItem(I18N i18n, UUID uuid) {
super(new SuppliedItem(() -> {
public PlayerInformationItem(UUID uuid) { final ItemBuilder builder = new ItemBuilder(Material.PAINTING);
super(new ItemBuilder(Material.PAINTING).setDisplayName("§7§oLoading..."), () -> { final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.LOADING);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
}, (click -> true)).getItemProvider(), () -> {
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);
if (appearanceManager.hasData()) { if (optionalProfile.isPresent()) {
skull.addLoreLines( final NickoProfile profile = optionalProfile.get();
"§cNicked: §a✔", final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.CHECK, player.getName(), (profile.hasData() ? "§a✔" : "§c❌"), profile.getName(), profile.getSkin());
"§cName: §6" + appearanceManager.getName(), skull.setDisplayName("§6" + translation.getName());
"§cSkin: §6" + appearanceManager.getSkin() translation.getLore().forEach(skull::addLoreLines);
);
} else { } else {
// Default item name in case the profile is not found
skull.setDisplayName("§6§lYou should not see this!");
skull.addLoreLines( skull.addLoreLines(
"§cNicked: §c❌", "§cPlease file a bug report",
"§cName: §7N/A", "§cat https://ineanto.xyz/git/ineanto/nicko!"
"§cSkin: §7N/A"
); );
} }
skull.setDisplayName("§6" + player.getName());
return skull; return skull;
}); });
} }

View file

@ -1,17 +1,28 @@
package xyz.atnrch.nicko.gui.items.appearance; package xyz.atnrch.nicko.gui.items.appearance;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.anvil.AnvilManager; import xyz.atnrch.nicko.anvil.AnvilManager;
import org.bukkit.Material; import org.bukkit.Material;
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.i18n.ItemTranslation;
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;
public class ChangeBothItem extends SuppliedItem { public class ChangeBothItem {
public ChangeBothItem() { private final I18N i18n;
super(() -> {
public ChangeBothItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.TOTEM_OF_UNDYING); final ItemBuilder builder = new ItemBuilder(Material.TOTEM_OF_UNDYING);
builder.setDisplayName("§6Skin §fand §6name §fchange"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Home.CHANGE_BOTH);
builder.addLoreLines("§7Will open a GUI to change both your name and your skin."); builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
}, click -> { }, click -> {
final ClickType clickType = click.getClickType(); final ClickType clickType = click.getClickType();

View file

@ -1,17 +1,28 @@
package xyz.atnrch.nicko.gui.items.appearance; package xyz.atnrch.nicko.gui.items.appearance;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.anvil.AnvilManager; import xyz.atnrch.nicko.anvil.AnvilManager;
import org.bukkit.Material; import org.bukkit.Material;
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.i18n.ItemTranslation;
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;
public class ChangeNameItem extends SuppliedItem { public class ChangeNameItem {
public ChangeNameItem() { private final I18N i18n;
super(() -> {
public ChangeNameItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.NAME_TAG); final ItemBuilder builder = new ItemBuilder(Material.NAME_TAG);
builder.setDisplayName("Change §6name"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Home.CHANGE_NAME);
builder.addLoreLines("§7Will open a GUI to change your name only."); builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
}, click -> { }, click -> {
final ClickType clickType = click.getClickType(); final ClickType clickType = click.getClickType();

View file

@ -3,15 +3,27 @@ package xyz.atnrch.nicko.gui.items.appearance;
import xyz.atnrch.nicko.anvil.AnvilManager; import xyz.atnrch.nicko.anvil.AnvilManager;
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.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.builder.SkullBuilder; import xyz.xenondevs.invui.item.builder.SkullBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem; import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class ChangeSkinItem extends SuppliedItem { public class ChangeSkinItem {
private final I18N i18n;
private final Player player;
public ChangeSkinItem(Player player) { public ChangeSkinItem(Player player) {
super(() -> { this.i18n = new I18N(player);
this.player = player;
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final SkullBuilder builder = new SkullBuilder(player.getName()); final SkullBuilder builder = new SkullBuilder(player.getName());
builder.setDisplayName("Change §6skin"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Home.CHANGE_SKIN);
builder.addLoreLines("§7Will open a GUI to change your skin only."); builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
}, click -> { }, click -> {
final ClickType clickType = click.getClickType(); final ClickType clickType = click.getClickType();

View file

@ -1,17 +1,27 @@
package xyz.atnrch.nicko.gui.items.common; package xyz.atnrch.nicko.gui.items.common;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.Gui;
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 xyz.xenondevs.invui.window.Window; import xyz.xenondevs.invui.window.Window;
public class GoBackItem extends SuppliedItem { public class GoBackItem {
public GoBackItem(Gui gui, String parentTitle) { private final I18N i18n;
super(() -> {
public GoBackItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get(Gui gui, String parentTitle) {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.ARROW); final ItemBuilder builder = new ItemBuilder(Material.ARROW);
builder.setDisplayName("Go back"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.GO_BACK);
builder.addLoreLines("§7Return to the previous window."); builder.setDisplayName(translation.getName());
return builder; return builder;
}, click -> { }, click -> {
click.getEvent().getView().close(); click.getEvent().getView().close();
@ -19,4 +29,4 @@ public class GoBackItem extends SuppliedItem {
return true; return true;
}); });
} }
} }

View file

@ -1,24 +1,28 @@
package xyz.atnrch.nicko.gui.items.common; package xyz.atnrch.nicko.gui.items.common;
import org.bukkit.Material; import org.bukkit.Material;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.gui.ScrollGui; import xyz.xenondevs.invui.gui.ScrollGui;
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.controlitem.ScrollItem; import xyz.xenondevs.invui.item.impl.controlitem.ScrollItem;
public class ScrollDownItem extends ScrollItem { public class ScrollDownItem extends ScrollItem {
final I18N i18n;
public ScrollDownItem() { public ScrollDownItem(I18N i18n) {
super(1); super(1);
this.i18n = i18n;
} }
@Override @Override
public ItemProvider getItemProvider(ScrollGui gui) { public ItemProvider getItemProvider(ScrollGui gui) {
ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE); ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE);
builder.setDisplayName("Scroll down"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.SCROLL_UP);
if (!gui.canScroll(1)) builder.setDisplayName(translation.getName());
builder.addLoreLines("§7§o(You can't scroll further down.)"); if (!gui.canScroll(1)) translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
} }
} }

View file

@ -1,24 +1,28 @@
package xyz.atnrch.nicko.gui.items.common; package xyz.atnrch.nicko.gui.items.common;
import org.bukkit.Material; import org.bukkit.Material;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.gui.ScrollGui; import xyz.xenondevs.invui.gui.ScrollGui;
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.controlitem.ScrollItem; import xyz.xenondevs.invui.item.impl.controlitem.ScrollItem;
public class ScrollUpItem extends ScrollItem { public class ScrollUpItem extends ScrollItem {
final I18N i18n;
public ScrollUpItem() { public ScrollUpItem(I18N i18n) {
super(-1); super(-1);
this.i18n = i18n;
} }
@Override @Override
public ItemProvider getItemProvider(ScrollGui gui) { public ItemProvider getItemProvider(ScrollGui gui) {
ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE); final ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
builder.setDisplayName("Scroll up"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.SCROLL_UP);
if (!gui.canScroll(-1)) builder.setDisplayName(translation.getName());
builder.addLoreLines("§7§o(You've reached the top.)"); if (!gui.canScroll(-1)) translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
} }

View file

@ -1,15 +1,26 @@
package xyz.atnrch.nicko.gui.items.common; package xyz.atnrch.nicko.gui.items.common;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
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;
public class UnavailableItem extends SuppliedItem { public class UnavailableItem {
public UnavailableItem() { private final I18N i18n;
super(() -> {
public UnavailableItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.RED_TERRACOTTA); final ItemBuilder builder = new ItemBuilder(Material.RED_TERRACOTTA);
builder.setDisplayName("Unavailable"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.UNAVAILABLE);
builder.addLoreLines("§7§oThis button is disabled."); builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
}, click -> true); }, click -> true);
} }

View file

@ -0,0 +1,32 @@
package xyz.atnrch.nicko.gui.items.common.choice;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class CancelItem {
private final I18N i18n;
private final ChoiceCallback callback;
public CancelItem(Player player, ChoiceCallback callback) {
this.i18n = new I18N(player);
this.callback = callback;
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Choice.CANCEL);
builder.setDisplayName(translation.getName());
return builder;
}, click -> {
click.getEvent().getView().close();
callback.onCancel();
return true;
});
}
}

View file

@ -1,4 +1,4 @@
package xyz.atnrch.nicko.gui.items.common.confirm; package xyz.atnrch.nicko.gui.items.common.choice;
public interface ChoiceCallback { public interface ChoiceCallback {
void onConfirm(); void onConfirm();

View file

@ -0,0 +1,32 @@
package xyz.atnrch.nicko.gui.items.common.choice;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class ConfirmItem {
private final I18N i18n;
private final ChoiceCallback callback;
public ConfirmItem(Player player, ChoiceCallback callback) {
this.i18n = new I18N(player);
this.callback = callback;
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Choice.CONFIRM);
builder.setDisplayName(translation.getName());
return builder;
}, click -> {
click.getEvent().getView().close();
callback.onConfirm();
return true;
});
}
}

View file

@ -1,19 +0,0 @@
package xyz.atnrch.nicko.gui.items.common.confirm;
import org.bukkit.Material;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class CancelItem extends SuppliedItem {
public CancelItem(ChoiceCallback callback) {
super(() -> {
final ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
builder.setDisplayName("§cCancel");
return builder;
}, click -> {
click.getEvent().getView().close();
callback.onCancel();
return true;
});
}
}

View file

@ -1,19 +0,0 @@
package xyz.atnrch.nicko.gui.items.common.confirm;
import org.bukkit.Material;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class ConfirmItem extends SuppliedItem {
public ConfirmItem(ChoiceCallback callback) {
super(() -> {
final ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE);
builder.setDisplayName("§aConfirm");
return builder;
}, click -> {
click.getEvent().getView().close();
callback.onConfirm();
return true;
});
}
}

View file

@ -1,17 +1,28 @@
package xyz.atnrch.nicko.gui.items.home; package xyz.atnrch.nicko.gui.items.home;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
import xyz.atnrch.nicko.gui.AdminGUI; import xyz.atnrch.nicko.gui.AdminGUI;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
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;
public class AdminAccessItem extends SuppliedItem { public class AdminAccessItem {
public AdminAccessItem() { private final I18N i18n;
super(() -> {
public AdminAccessItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.COMMAND_BLOCK_MINECART); final ItemBuilder builder = new ItemBuilder(Material.COMMAND_BLOCK_MINECART);
builder.setDisplayName("Administration panel"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Home.ADMIN);
builder.addLoreLines("§7Configure and manage Nicko."); builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
}, click -> { }, click -> {
final ClickType clickType = click.getClickType(); final ClickType clickType = click.getClickType();

View file

@ -1,21 +1,34 @@
package xyz.atnrch.nicko.gui.items.home; package xyz.atnrch.nicko.gui.items.home;
import com.comphenix.protocol.utility.MinecraftVersion;
import org.bukkit.Material; import org.bukkit.Material;
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.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SimpleItem; import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class ExitItem extends SimpleItem { public class ExitItem {
public ExitItem() { private final I18N i18n;
super(new ItemBuilder(Material.OAK_DOOR).setDisplayName("Exit"), click -> {
if(MinecraftVersion.BEE_UPDATE.atOrAbove()) {
} public ExitItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.OAK_DOOR);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.EXIT);
builder.setDisplayName(translation.getName());
return builder;
}, click -> {
click.getEvent().getView().close();
final ClickType clickType = click.getClickType(); final ClickType clickType = click.getClickType();
if (clickType.isLeftClick() || clickType.isRightClick()) { if (clickType.isLeftClick() || clickType.isRightClick()) {
click.getEvent().getView().close(); click.getEvent().getView().close();
} }
return true;
}); });
} }
} }

View file

@ -1,42 +1,54 @@
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.appearance.AppearanceManager;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
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;
public class ResetItem extends SuppliedItem { import java.util.Optional;
public ResetItem() {
super(() -> { public class ResetItem {
private final I18N i18n;
public ResetItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.TNT); final ItemBuilder builder = new ItemBuilder(Material.TNT);
builder.setDisplayName("Reset appearance"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Home.RESET);
builder.addLoreLines("§7Completely remove your disguise."); builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
}, (event) -> { }, (event) -> {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final I18N i18n = new I18N(player);
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);
optionalProfile.ifPresent(profile -> {
if (!profile.hasData()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.MISSING));
event.getEvent().getView().close();
return;
}
if (!appearanceManager.hasData()) { final AppearanceManager appearanceManager = new AppearanceManager(player);
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.MISSING)); if (!appearanceManager.reset().isError()) {
event.getEvent().getView().close(); player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.OK));
return true; } else {
} player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.ERROR));
profile.setSkin(null);
if (!appearanceManager.reset().isError()) { profile.setName(null);
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.OK)); }
return true; });
} else { return true;
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.ERROR));
return false;
}
} }
return false; return false;
}); });

View file

@ -1,17 +1,28 @@
package xyz.atnrch.nicko.gui.items.home; package xyz.atnrch.nicko.gui.items.home;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.gui.SettingsGUI; import xyz.atnrch.nicko.gui.SettingsGUI;
import org.bukkit.Material; import org.bukkit.Material;
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.i18n.ItemTranslation;
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;
public class SettingsAccessItem extends SuppliedItem { public class SettingsAccessItem {
public SettingsAccessItem() { private final I18N i18n;
super(() -> {
public SettingsAccessItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.COMPARATOR); final ItemBuilder builder = new ItemBuilder(Material.COMPARATOR);
builder.setDisplayName("Settings"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Home.SETTINGS);
builder.addLoreLines("§7Configure your experience."); builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
}, click -> { }, click -> {
final ClickType clickType = click.getClickType(); final ClickType clickType = click.getClickType();

View file

@ -1,10 +1,14 @@
package xyz.atnrch.nicko.gui.items.settings; package xyz.atnrch.nicko.gui.items.settings;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.profile.NickoProfile;
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;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
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;
@ -14,18 +18,28 @@ import xyz.xenondevs.invui.item.impl.SimpleItem;
import java.util.Optional; import java.util.Optional;
public class BungeeCordCyclingItem { public class BungeeCordCyclingItem {
private final ItemProvider[] providers = new ItemProvider[]{ private final Player player;
getItemProviderForValue(true), private final I18N i18n;
getItemProviderForValue(false) private final ItemProvider[] providers;
};
public AbstractItem get(Player player) { public BungeeCordCyclingItem(Player player) {
final Optional<NickoProfile> profile = NickoBukkit.getInstance().getDataStore().getData(player.getUniqueId()); this.player = player;
this.i18n = new I18N(player);
this.providers = new ItemProvider[]{
getItemProviderForValue(true),
getItemProviderForValue(false)
};
}
public AbstractItem get() {
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);
} }
@ -35,15 +49,20 @@ public class BungeeCordCyclingItem {
private ItemProvider getItemProviderForValue(boolean enabled) { private ItemProvider getItemProviderForValue(boolean enabled) {
final ItemBuilder builder = new ItemBuilder(Material.COMPASS); final ItemBuilder builder = new ItemBuilder(Material.COMPASS);
builder.setDisplayName("BungeeCord transfer"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Settings.BUNGEECORD);
if (enabled) {
builder.addLoreLines("§7> §cDisabled"); builder.setDisplayName(translation.getName());
builder.addLoreLines("§6§l> §a§lEnabled"); translation.getLore().forEach(builder::addLoreLines);
} else { /*
builder.addLoreLines("§6§l> §c§lDisabled"); if (enabled) {
builder.addLoreLines("§7> §aEnabled"); builder.addLoreLines("§7> §cDisabled");
} builder.addLoreLines("§6§l> §a§lEnabled");
builder.addLoreLines("§7§oCycle through the values by", "§7§oleft and right clicking."); } else {
builder.addLoreLines("§6§l> §c§lDisabled");
builder.addLoreLines("§7> §aEnabled");
}
builder.addLoreLines("§7§oCycle through the values by", "§7§oleft and right clicking.");
*/
return builder; return builder;
} }
} }

View file

@ -4,8 +4,10 @@ import org.bukkit.Material;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import xyz.atnrch.nicko.NickoBukkit; import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.gui.SettingsGUI;
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.i18n.ItemTranslation;
import xyz.atnrch.nicko.i18n.Locale; import xyz.atnrch.nicko.i18n.Locale;
import xyz.atnrch.nicko.profile.NickoProfile; import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore; import xyz.atnrch.nicko.storage.PlayerDataStore;
@ -21,9 +23,17 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
public class LanguageCyclingItem { public class LanguageCyclingItem {
private final ItemProvider[] providers = getItems(); private final Player player;
private final ItemProvider[] providers;
private final I18N i18n;
public AbstractItem get(Player player) { public LanguageCyclingItem(Player player) {
this.player = player;
this.i18n = new I18N(player);
this.providers = getItems();
}
public AbstractItem get() {
final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore(); final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
final Optional<NickoProfile> profile = dataStore.getData(player.getUniqueId()); final Optional<NickoProfile> profile = dataStore.getData(player.getUniqueId());
if (profile.isPresent()) { if (profile.isPresent()) {
@ -32,11 +42,12 @@ public class LanguageCyclingItem {
return CycleItem.withStateChangeHandler((observer, integer) -> { return CycleItem.withStateChangeHandler((observer, integer) -> {
nickoProfile.setLocale(Locale.values()[integer]); nickoProfile.setLocale(Locale.values()[integer]);
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
player.getOpenInventory().close();
// TODO (Ineanto, 7/14/23): This checks a 2nd time for the profile. // TODO (Ineanto, 7/14/23): This checks a 2nd time for the profile.
if (dataStore.updateCache(player.getUniqueId(), nickoProfile).isError()) { if (dataStore.updateCache(player.getUniqueId(), nickoProfile).isError()) {
final I18N i18n = new I18N(player);
player.sendMessage(i18n.translate(I18NDict.Event.Settings.ERROR)); player.sendMessage(i18n.translate(I18NDict.Event.Settings.ERROR));
player.getOpenInventory().close(); } else {
new SettingsGUI(player).open();
} }
}, localeOrdinal, providers); }, localeOrdinal, providers);
} }
@ -46,7 +57,9 @@ public class LanguageCyclingItem {
private ItemProvider generateItem(Locale locale, List<Locale> locales) { private ItemProvider generateItem(Locale locale, List<Locale> locales) {
final ItemBuilder builder = new ItemBuilder(Material.OAK_SIGN); final ItemBuilder builder = new ItemBuilder(Material.OAK_SIGN);
builder.setDisplayName("Language"); final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Settings.LANGUAGE);
builder.setDisplayName(translation.getName());
for (Locale value : locales) { for (Locale value : locales) {
if (locale != value) { if (locale != value) {
builder.addLoreLines("§7> " + value.getName()); builder.addLoreLines("§7> " + value.getName());
@ -54,15 +67,15 @@ public class LanguageCyclingItem {
builder.addLoreLines("§6§l> §f" + value.getName()); builder.addLoreLines("§6§l> §f" + value.getName());
} }
} }
builder.addLoreLines("§7§oCycle through the values by", "§7§oleft and right clicking."); translation.getLore().forEach(builder::addLoreLines);
return builder; return builder;
} }
private ItemProvider[] getItems() { private ItemProvider[] getItems() {
final NickoBukkit instance = NickoBukkit.getInstance(); final NickoBukkit instance = NickoBukkit.getInstance();
final ArrayList<ItemProvider> items = new ArrayList<>(); final ArrayList<ItemProvider> items = new ArrayList<>();
final ArrayList<Locale> localesToGenerate = new ArrayList<>(); final ArrayList<Locale> localesToGenerate = new ArrayList<>();
Collections.addAll(localesToGenerate, Locale.values()); Collections.addAll(localesToGenerate, Locale.values());
if (!instance.getNickoConfig().isCustomLocale()) { if (!instance.getNickoConfig().isCustomLocale()) {
localesToGenerate.remove(Locale.CUSTOM); localesToGenerate.remove(Locale.CUSTOM);

View file

@ -3,50 +3,96 @@ 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.Collections; import java.util.Iterator;
import java.util.List; import java.util.Optional;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class I18N { public class I18N {
private final MessageFormat formatter = new MessageFormat(""); private final MessageFormat formatter = new MessageFormat("");
private final Logger logger = Logger.getLogger("I18N");
private final NickoBukkit instance = NickoBukkit.getInstance(); private final NickoBukkit instance = NickoBukkit.getInstance();
private final Pattern replacementPattern = Pattern.compile("\\{\\d+}$", Pattern.DOTALL);
private final YamlConfig yamlConfig;
private final Player player; private final Player player;
private final Locale playerLocale; private final Locale playerLocale;
public I18N(Player player) { public I18N(Player player) {
this.player = player; this.player = player;
this.playerLocale = getPlayerLocale(); this.playerLocale = getPlayerLocale();
this.yamlConfig = getYamlConfig();
} }
public I18N(Locale locale) { public I18N(Locale locale) {
this.player = null; this.player = null;
this.playerLocale = locale; this.playerLocale = locale;
this.yamlConfig = getYamlConfig();
} }
public List<String> translateItem(String key, Object... arguments) { public ItemTranslation translateItem(String key, Object... args) {
final ArrayList<String> lines = new ArrayList<>(); final String nameKey = key + ".name";
final String itemNameKey = readString(key + ".name"); final String loreKey = key + ".lore";
final ArrayList<String> itemLoreKey = readList(key + ".lore"); final String name = readString(nameKey);
try { final ArrayList<String> lore = readList(loreKey);
// Item Name
formatter.applyPattern(itemNameKey); if (name == null) {
final String itemNameTranslated = formatter.format(arguments); logger.warning(nameKey + " doesn't exists! Please translate this entry.");
lines.add(itemNameTranslated); return new ItemTranslation(nameKey, new ArrayList<String>() {{
return lines; add(loreKey);
} catch (Exception e) { }});
return Collections.singletonList(key);
} }
// Add all elements to a list
final ArrayList<String> toTranslate = new ArrayList<>();
toTranslate.add(name);
if (lore != null && !lore.isEmpty()) {
toTranslate.addAll(lore);
}
// Set starting index to 0
int lineIndex = 0;
int replacementIndex = 0;
// While iterator next value exists/isn't null
final Iterator<String> iterator = toTranslate.iterator();
while (iterator.hasNext() && iterator.next() != null) {
// Get the current line
final String currentLine = toTranslate.get(lineIndex);
// If the line doesn't contain {i}, skip it
final Matcher matcher = replacementPattern.matcher(currentLine);
if (!matcher.find()) {
lineIndex++;
continue;
}
// If it does, replace the content with the args at position replacementIndex
if (replacementIndex < args.length && args[replacementIndex] != null) {
// Replace with the corresponding varargs index
toTranslate.set(lineIndex, currentLine.replace("{" + replacementIndex + "}", args[replacementIndex].toString()));
replacementIndex++;
}
// Increment the index
lineIndex++;
}
if (lore == null || lore.isEmpty()) {
return new ItemTranslation(toTranslate.get(0), new ArrayList<>());
}
return new ItemTranslation(toTranslate.get(0), new ArrayList<>(toTranslate.subList(1, toTranslate.size())));
} }
public String translate(String key, Object... arguments) { public String translate(String key, Object... arguments) {
final String string = readString(key); final String translation = readString(key);
try { try {
formatter.applyPattern(string); formatter.applyPattern(translation);
return instance.getNickoConfig().getPrefix() + formatter.format(arguments); return instance.getNickoConfig().getPrefix() + formatter.format(arguments);
} catch (Exception e) { } catch (Exception e) {
return instance.getNickoConfig().getPrefix() + key; return instance.getNickoConfig().getPrefix() + key;
@ -64,43 +110,27 @@ public class I18N {
} }
private String readString(String key) { private String readString(String key) {
YamlConfig yamlFile; return yamlConfig.getString(key);
if (playerLocale == Locale.CUSTOM) {
yamlFile = instance.getLocaleFileManager().getYamlFile();
} else {
final InputStream resource = instance.getResource(playerLocale.getCode() + ".yml");
yamlFile = YamlConfig.load(resource);
}
return yamlFile.getString(key);
} }
private ArrayList<String> readList(String key) { private ArrayList<String> readList(String key) {
final ArrayList<String> lines = new ArrayList<>(); return yamlConfig.getStringList(key);
YamlConfig yamlFile;
if (playerLocale == Locale.CUSTOM) {
yamlFile = instance.getLocaleFileManager().getYamlFile();
} else {
final InputStream resource = instance.getResource(playerLocale.getCode() + ".yml");
yamlFile = YamlConfig.load(resource);
}
// 9 is a magic number
for (int i = 0; i < yamlFile.getInt(key + ".length"); i++) {
final String line = yamlFile.getString(key + ".content[" + i + "]");
System.out.println("line = " + line);
if (line != null && !line.equals("{" + i + "}")) {
lines.add(line);
}
}
return lines;
} }
private Locale getPlayerLocale() { private YamlConfig getYamlConfig() {
try { if (playerLocale == Locale.CUSTOM) {
final AppearanceManager appearanceManager = AppearanceManager.get(player); return instance.getLocaleFileManager().getYamlFile();
return !appearanceManager.hasData() ? Locale.FALLBACK_LOCALE : appearanceManager.getLocale(); } else {
} catch (IllegalArgumentException exception) { final InputStream resource = instance.getResource(playerLocale.getCode() + ".yml");
instance.getLogger().severe("Invalid locale provided by " + player.getName() + ", defaulting to " + Locale.FALLBACK_LOCALE.getCode() + "."); return new YamlConfig(resource);
}
}
public Locale getPlayerLocale() {
final Optional<NickoProfile> optionalProfile = NickoProfile.get(player);
if (optionalProfile.isPresent()) {
return optionalProfile.get().getLocale();
} else {
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 {
@ -64,11 +67,63 @@ public class I18NDict {
private static final String GUI_KEY = "gui."; private static final String GUI_KEY = "gui.";
public static final String EXIT = GUI_KEY + "exit"; public static final String EXIT = GUI_KEY + "exit";
public static final String GO_BACK = GUI_KEY + "go_back";
public static final String UNAVAILABLE = GUI_KEY + "unavailable";
public static final String LOADING = GUI_KEY + "loading";
public static final String SCROLL_UP = GUI_KEY + "scroll_up";
public static final String SCROLL_DOWN = GUI_KEY + "scroll_down";
public static class Titles {
public static final String TITLE_KEY = GUI_KEY + "title.";
public static final String HOME = TITLE_KEY + "home";
public static final String SETTINGS = TITLE_KEY + "settings";
public static final String ADMIN = TITLE_KEY + "admin";
public static final String CHECK = TITLE_KEY + "check";
public static final String CACHE = TITLE_KEY + "cache";
public static final String INVALIDATE_SKIN = TITLE_KEY + "invalidate_skin";
}
public static class Choice {
private static final String CHOICE_KEY = GUI_KEY + "choice.";
public static final String CONFIRM = CHOICE_KEY + "confirm";
public static final String CHOOSE = CHOICE_KEY + "choose";
public static final String CANCEL = CHOICE_KEY + "cancel";
}
public static class Home { public static class Home {
private static final String HOME_KEY = GUI_KEY + "home."; private static final String HOME_KEY = GUI_KEY + "home.";
public static final String ADMIN = HOME_KEY + "admin"; public static final String ADMIN = HOME_KEY + "admin";
public static final String CHANGE_NAME = HOME_KEY + "change_name";
public static final String CHANGE_SKIN = HOME_KEY + "change_skin";
public static final String CHANGE_BOTH = HOME_KEY + "change_both";
public static final String RESET = HOME_KEY + "reset";
public static final String SETTINGS = HOME_KEY + "settings";
}
public static class Settings {
private static final String SETTINGS_KEY = GUI_KEY + "settings.";
public static final String LANGUAGE = SETTINGS_KEY + "language";
public static final String BUNGEECORD = SETTINGS_KEY + "bungeecord";
}
public static class Admin {
private static final String ADMIN_KEY = GUI_KEY + "admin.";
public static final String MANAGE_CACHE = ADMIN_KEY + "manage_cache";
public static final String MANAGE_PLAYER = ADMIN_KEY + "manage_player";
public static final String CHECK = ADMIN_KEY + "check";
public static class Cache {
private static final String CACHE_KEY = ADMIN_KEY + "cache.";
public static final String STATISTICS = CACHE_KEY + "statistics";
public static final String INVALIDATE_CACHE = CACHE_KEY + "invalidate_cache";
public static final String INVALIDATE_SKIN = CACHE_KEY + "invalidate_skin";
}
} }
} }
} }

View file

@ -0,0 +1,21 @@
package xyz.atnrch.nicko.i18n;
import java.util.ArrayList;
public class ItemTranslation {
private final String name;
private final ArrayList<String> lore;
public ItemTranslation(String name, ArrayList<String> lore) {
this.name = name;
this.lore = lore;
}
public String getName() {
return name;
}
public ArrayList<String> getLore() {
return lore;
}
}

View file

@ -15,7 +15,7 @@ public class LocaleFileManager {
public String getString(String key) { public String getString(String key) {
if (!file.exists()) return key; if (!file.exists()) return key;
try (BufferedInputStream inputStream = new BufferedInputStream(Files.newInputStream(file.toPath()))) { try (BufferedInputStream inputStream = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
final YamlConfig yamlConfig = YamlConfig.load(inputStream); final YamlConfig yamlConfig = new YamlConfig(inputStream);
return yamlConfig.getString(key); return yamlConfig.getString(key);
} catch (IOException e) { } catch (IOException e) {
return key; return key;
@ -44,7 +44,7 @@ public class LocaleFileManager {
public YamlConfig getYamlFile() { public YamlConfig getYamlFile() {
if (yamlFile == null) { if (yamlFile == null) {
try (BufferedInputStream inputStream = new BufferedInputStream(Files.newInputStream(file.toPath()))) { try (BufferedInputStream inputStream = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
yamlFile = YamlConfig.load(inputStream); yamlFile = new YamlConfig(inputStream);
} catch (IOException ignored) { } catch (IOException ignored) {
return null; return null;
} }

View file

@ -51,20 +51,30 @@ 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()) { if (profile.hasData()) {
name = profile.getName(); if (profile.getName() != null) {
skin = profile.getSkin(); name = profile.getName();
}
if (profile.getSkin() != null) {
skin = profile.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,10 +1,20 @@
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.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 PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
public static final NickoProfile EMPTY_PROFILE = new NickoProfile(null, null, Locale.ENGLISH, true); public static final NickoProfile EMPTY_PROFILE = new NickoProfile(null, null, Locale.ENGLISH, true);
private transient final Player player;
private String name; private String name;
private String skin; private String skin;
private Locale locale; private Locale locale;
@ -15,10 +25,35 @@ public class NickoProfile implements Cloneable {
this.skin = skin; this.skin = skin;
this.locale = locale; this.locale = locale;
this.bungeecordTransfer = bungeecordTransfer; this.bungeecordTransfer = bungeecordTransfer;
this.player = null;
} }
public boolean isEmpty() { public NickoProfile(Player player, String name, String skin, Locale locale, boolean bungeecordTransfer) {
return name == null && skin == null; this.player = player;
this.name = name;
this.skin = skin;
this.locale = locale;
this.bungeecordTransfer = bungeecordTransfer;
}
public NickoProfile(UUID uuid, String name, String skin, Locale locale, boolean bungeecordTransfer) {
this.name = name;
this.skin = skin;
this.locale = locale;
this.bungeecordTransfer = bungeecordTransfer;
this.player = Bukkit.getPlayer(uuid);
}
public static Optional<NickoProfile> get(Player player) {
return dataStore.getData(player.getUniqueId());
}
public static Optional<NickoProfile> get(UUID uuid) {
return dataStore.getData(uuid);
}
public boolean hasData() {
return name != null || skin != null;
} }
public String getName() { public String getName() {
@ -37,9 +72,13 @@ public class NickoProfile implements Cloneable {
this.skin = skin; this.skin = skin;
} }
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 +91,11 @@ public class NickoProfile implements Cloneable {
@Override @Override
public String toString() { public String toString() {
return "NickoProfile{" + return "NickoProfile{" +
"name='" + name + '\'' + "name='" + name + '\'' +
", skin='" + skin + '\'' + ", skin='" + skin + '\'' +
", locale=" + locale + ", locale=" + locale +
", bungeecordTransfer=" + bungeecordTransfer + ", bungeecordTransfer=" + bungeecordTransfer +
'}'; '}';
} }
@Override @Override

View file

@ -76,12 +76,12 @@ public class PlayerDataStore {
if (storage.isError()) return ActionResult.error(I18NDict.Error.GENERIC); if (storage.isError()) return ActionResult.error(I18NDict.Error.GENERIC);
if (cache.isError()) return ActionResult.error(I18NDict.Error.CACHE); if (cache.isError()) return ActionResult.error(I18NDict.Error.CACHE);
if (!cache.isCached(player.getUniqueId())) return ActionResult.error(I18NDict.Error.GENERIC); if (!cache.isCached(player.getUniqueId())) return ActionResult.error(I18NDict.Error.GENERIC);
if (!cache.retrieve(player.getUniqueId()).isPresent())
return ActionResult.error(I18NDict.Error.GENERIC);
// TODO (Ineanto, 5/20/23): Remove value from cache final Optional<NickoProfile> cachedProfile = cache.retrieve(player.getUniqueId());
//profiles.remove(player.getUniqueId()); if (!cachedProfile.isPresent()) return ActionResult.error(I18NDict.Error.GENERIC);
return storage.store(player.getUniqueId(), cache.retrieve(player.getUniqueId()).get());
cache.delete(player.getUniqueId());
return storage.store(player.getUniqueId(), cachedProfile.get());
} }
public Storage getStorage() { public Storage getStorage() {

View file

@ -19,7 +19,6 @@ public class MapCacheProvider implements CacheProvider {
@Override @Override
public boolean close() { public boolean close() {
profiles = null;
return true; return true;
} }

View file

@ -50,6 +50,7 @@ public class RedisCache extends Cache {
@Override @Override
public Optional<NickoProfile> retrieve(UUID uuid) { public Optional<NickoProfile> retrieve(UUID uuid) {
try (Jedis jedis = provider.getJedis()) { try (Jedis jedis = provider.getJedis()) {
// 29/08/23: what the fuck was I talking about?
// TODO (Ineanto, 5/20/23): Check if cached before because Jedis returns a bulk reply so this is unsafe // TODO (Ineanto, 5/20/23): Check if cached before because Jedis returns a bulk reply so this is unsafe
final String data = jedis.get("nicko:" + uuid.toString()); final String data = jedis.get("nicko:" + uuid.toString());
final NickoProfile profile = gson.fromJson(data, NickoProfile.class); final NickoProfile profile = gson.fromJson(data, NickoProfile.class);

View file

@ -1,5 +1,6 @@
package xyz.atnrch.nicko.storage.redis; package xyz.atnrch.nicko.storage.redis;
import redis.clients.jedis.exceptions.JedisConnectionException;
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.storage.CacheProvider; import xyz.atnrch.nicko.storage.CacheProvider;
@ -18,7 +19,11 @@ public class RedisCacheProvider implements CacheProvider {
public boolean init() { public boolean init() {
final DataSourceConfiguration redisConfiguration = configuration.getRedisConfiguration(); final DataSourceConfiguration redisConfiguration = configuration.getRedisConfiguration();
pool = new JedisPool(redisConfiguration.getAddress(), redisConfiguration.getPort()); pool = new JedisPool(redisConfiguration.getAddress(), redisConfiguration.getPort());
return !pool.isClosed() && pool.getResource() != null; try {
return !pool.isClosed() && pool.getResource() != null;
} catch (JedisConnectionException exception) {
return false;
}
} }
@Override @Override

View file

@ -91,9 +91,6 @@ public class SQLStorage extends Storage {
locale = resultSet.getString("locale"); locale = resultSet.getString("locale");
bungeecord = resultSet.getBoolean("bungeecord"); bungeecord = resultSet.getBoolean("bungeecord");
} }
System.out.println("name = " + name);
System.out.println("skin = " + skin);
System.out.println("locale = " + locale);
final NickoProfile profile = new NickoProfile(name, skin, Locale.fromCode(locale), bungeecord); final NickoProfile profile = new NickoProfile(name, skin, Locale.fromCode(locale), bungeecord);
return Optional.of(profile); return Optional.of(profile);

View file

@ -40,7 +40,7 @@ public class WrapperPlayServerRespawn extends AbstractPacket {
public void setDimension(World value) { public void setDimension(World value) {
if (MinecraftVersion.WILD_UPDATE.atOrAbove()) { if (MinecraftVersion.WILD_UPDATE.atOrAbove()) {
// 1.19 to 1.19.4 // 1.19 to 1.20.1
// Thank you lukalt! // Thank you lukalt!
final InternalStructure dimensionType = handle.getStructures().read(0); final InternalStructure dimensionType = handle.getStructures().read(0);
dimensionType.getMinecraftKeys().write(0, new MinecraftKey("minecraft", "dimension_type")); dimensionType.getMinecraftKeys().write(0, new MinecraftKey("minecraft", "dimension_type"));

View file

@ -25,4 +25,102 @@ event:
admin: admin:
cache: cache:
invalidate_cache: "§fComplete cache invalidated." invalidate_cache: "§fComplete cache invalidated."
invalidate_entry: "§6{0} §fhas been invalidated." invalidate_entry: "§6{0} §fhas been invalidated."
gui:
title:
home: "Nicko - Home"
settings: "Nicko > Settings"
admin: "Nicko > Administration"
check: "Nicko > Admin... > Check"
cache: "Nicko > Admin... > Cache"
invalidate_skin: "... > Cache > Invalidate"
exit:
name: "Exit"
go_back:
name: "Back"
unavailable:
name: "Unavailable"
lore:
- "§7§oThis button is disabled."
loading:
name: "§7§oLoading..."
choice:
confirm:
name: "§aConfirm"
choose:
name: "§6§oChoose an option..."
cancel:
name: "§cCancel"
scroll_up:
name: "Scroll up"
lore:
- "§8§o(You can't scroll any higher.)"
scroll_down:
name: "Scroll down"
lore:
- "§8§o(You can't scroll any further down.)"
home:
admin:
name: "Administration panel"
lore:
- "§7Configure and manage Nicko."
settings:
name: "Settings"
lore:
- "§7Fine tune your experience with Nicko."
change_name:
name: "§6Nickname §fchange"
change_skin:
name: "§6Skin §fchange"
change_both:
name: "Change §6both"
reset:
name: "Reset appearance"
lore:
- "§7Completely remove your disguise."
admin:
manage_cache:
name: "Manage §6skin §fcache..."
lore:
- "§7View and manage the skin cache."
manage_player:
name: "Check a player..."
lore:
- "§7See players' disguise information."
check:
name: "{0}"
lore:
- "§cNicked: §a{1}"
- "§cName: §6{2}"
- "§cSkin: §6{3}"
cache:
statistics:
name: "Statistics"
lore:
- "§fRequest count: §b{0}"
- "§fNumber of skin cached: §b{1}"
- "§8§oCache is cleared every 24 hours."
invalidate_cache:
name: "Invalidate cache"
lore:
- "§c§oNOT RECOMMENDED"
- "§7Invalidate the entirety of the skin cache."
- "§7This doesn't reset player's disguises."
invalidate_skin:
name: "Invalidate a skin..."
lore:
- "§7Select a specific skin to invalidate."
- "§7Useful if a skin has been recently updated."
settings:
language:
name: "Language"
lore:
- "§7§oGet through the values"
- "§7§oby left or right clicking."
bungeecord:
name: "Bungeecord Transfer"
lore:
- "§7§oGet through the values"
- "§7§oby left or right clicking."

View file

@ -1,7 +1,7 @@
error: error:
generic: "Une erreur inconnue c'est produite." generic: "Une erreur inconnue c'est produite."
permission: "§cVous ne possédez pas la permission." permission: "§cVous ne possédez pas la permission."
invalid_username: "§cLe pseudo n''est pas un pseudo Minecraft valide." invalid_username: "§cLe pseudo n'est pas un pseudo Minecraft valide."
mojang_name: "Un compte Minecraft avec ce nom n'existe pas." mojang_name: "Un compte Minecraft avec ce nom n'existe pas."
mojang_skin: "Ce compte Minecraft n'a pas de skin." mojang_skin: "Ce compte Minecraft n'a pas de skin."
cache: "Impossible de récupérer le skin depuis le cache." cache: "Impossible de récupérer le skin depuis le cache."
@ -9,6 +9,8 @@ error:
json: "Erreur JSON" json: "Erreur JSON"
event: event:
settings:
error: "§cImpossible de mettre à jour vos paramètres. §7§o({0})"
appearance: appearance:
set: set:
error: "§cImpossible d''appliquer votre déguisement. §7§o({0})" error: "§cImpossible d''appliquer votre déguisement. §7§o({0})"
@ -26,20 +28,48 @@ event:
invalidate_entry: "§6{0} §fa été invalidé." invalidate_entry: "§6{0} §fa été invalidé."
gui: gui:
exit: "Quitter" title:
home: "Nicko - Accueil"
settings: "Nicko > Paramètres"
admin: "Nicko > Administration"
check: "Nicko > Admin... > Vérification"
cache: "Nicko > Admin... > Cache"
invalidate_skin: "... > Cache > Invalider"
exit:
name: "Quitter"
go_back:
name: "Retour"
unavailable:
name: "Indisponible"
lore:
- "§7§oCe boutton est désactivé."
loading:
name: "§7§oChargement..."
choice:
confirm:
name: "§aConfirmer"
choose:
name: "§6§oChoisissez une option..."
cancel:
name: "§cAnnuler"
scroll_up:
name: "Défiler vers le haut"
lore:
- "§8§o(Impossible de défiler plus haut.)"
scroll_down:
name: "Défiler vers le bas"
lore:
- "§8§o(Impossible de défiler plus bas.)"
home: home:
admin: admin:
name: "Panel d''administration" name: "Panel d'administration"
lore: lore:
length: 1 - "§7Configurez et gérez Nicko."
content:
- "Configurez et gérez Nicko."
settings: settings:
name: "Paramètres" name: "Paramètres"
lore: lore:
length: 1 - "§7Gérez votre expérience avec Nicko."
content:
"Configurez votre expérience."
change_name: change_name:
name: "Changer le §6pseudo" name: "Changer le §6pseudo"
change_skin: change_skin:
@ -49,12 +79,50 @@ gui:
reset: reset:
name: "Réinitialiser l'apparence" name: "Réinitialiser l'apparence"
lore: lore:
- "Supprime complètement votre déguisement." - "§7Supprime complètement votre déguisement."
admin:
manage_cache:
name: "Gérer le cache de §6skin..."
lore:
- "§7Consultez et gérez le cache de skin."
manage_player:
name: "Vérifier un joueur..."
lore:
- "§7Vérifiez les informations de déguisement d'un joueur."
check:
name: "{0}"
lore:
- "§cDéguisé: §a{1}"
- "§cNom: §6{2}"
- "§cSkin: §6{3}"
cache:
statistics:
name: "Statistiques"
lore:
- "§fNombre de requêtes: §b{0}"
- "§fNb. de skin dans le cache: §b{1}"
- "§8§oLe cache est vidé toutes les 24 heures."
invalidate_cache:
name: "Invalider le cache"
lore:
- "§c§oDÉCONSEILLÉ"
- "§7Invalide l'entièreté du cache des skin."
- "§7Ne retire pas les déguisements"
- "§7pour les joueurs en disposant."
invalidate_skin:
name: "Invalider un skin..."
lore:
- "§7Sélectionnez une apparence spécifique à"
- "§7invalider. Utile dans le cas où un skin"
- "§7a récemment été mis à jour."
settings: settings:
language: language:
name: "Language" name: "Langage"
lore:
- "§7§oParcourez les valeurs"
- "§7§oavec un clique gauche/droit."
bungeecord:
name: "Transfert Bungeecord"
lore: lore:
# The language values will be filled at {0}
- "{0}"
- "§7§oParcourez les valeurs" - "§7§oParcourez les valeurs"
- "§7§oavec un clique gauche/droit." - "§7§oavec un clique gauche/droit."

View file

@ -0,0 +1,57 @@
package xyz.atnrch.nicko.test.i18n;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.entity.PlayerMock;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.config.Configuration;
import xyz.atnrch.nicko.config.DataSourceConfiguration;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.atnrch.nicko.i18n.Locale;
import static org.junit.jupiter.api.Assertions.*;
public class ItemTranslationTest {
private static PlayerMock player;
@BeforeAll
public static void setup() {
final Configuration config = new Configuration(
DataSourceConfiguration.SQL_EMPTY,
DataSourceConfiguration.REDIS_EMPTY,
"",
false);
MockBukkit.mock();
MockBukkit.load(NickoBukkit.class, config);
}
@Test
@DisplayName("Translate Item Without Lore")
public void translateItemTranslationWithoutLore() {
final I18N i18n = new I18N(Locale.FRENCH);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.GO_BACK);
assertTrue(translation.getLore().isEmpty());
assertEquals(translation.getName(), "Retour");
}
@Test
@DisplayName("Translate Item")
public void translateItemLore() {
final I18N i18n = new I18N(Locale.FRENCH);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.Cache.STATISTICS, "1", "1");
assertFalse(translation.getLore().isEmpty());
assertEquals("§fNombre de requêtes: §b1", translation.getLore().get(0));
assertEquals("§fNb. de skin dans le cache: §b1", translation.getLore().get(1));
assertEquals("§8§oLe cache est vidé toutes les 24 heures.", translation.getLore().get(2));
}
@AfterAll
public static void shutdown() {
MockBukkit.unmock();
}
}

View file

@ -1,7 +1,6 @@
package xyz.atnrch.nicko.test.i18n; package xyz.atnrch.nicko.test.i18n;
import be.seeseemelk.mockbukkit.MockBukkit; import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import be.seeseemelk.mockbukkit.entity.PlayerMock; import be.seeseemelk.mockbukkit.entity.PlayerMock;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
@ -14,10 +13,9 @@ import xyz.atnrch.nicko.i18n.I18N;
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 java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals;
public class I18NLoreTest { public class TranslationTest {
private static NickoBukkit plugin;
private static PlayerMock player; private static PlayerMock player;
@BeforeAll @BeforeAll
@ -27,16 +25,16 @@ public class I18NLoreTest {
DataSourceConfiguration.REDIS_EMPTY, DataSourceConfiguration.REDIS_EMPTY,
"", "",
false); false);
final ServerMock server = MockBukkit.mock(); MockBukkit.mock();
plugin = MockBukkit.load(NickoBukkit.class, config); MockBukkit.load(NickoBukkit.class, config);
} }
@Test @Test
@DisplayName("Translate Item Lore") @DisplayName("Translate Line With Replacement")
public void translateItemLore() { public void translateItemTranslationWithoutLore() {
final I18N i18n = new I18N(Locale.FRENCH); final I18N i18n = new I18N(Locale.FRENCH);
List<String> strings = i18n.translateItem(I18NDict.GUI.Home.ADMIN); final String translation = i18n.translatePrefixless(I18NDict.Event.Settings.ERROR, "Test");
System.out.println("strings = " + strings); assertEquals("§cImpossible de mettre à jour vos paramètres. §7§o(Test)", translation);
} }
@AfterAll @AfterAll

View file

@ -46,7 +46,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,7 +54,9 @@ 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()); assertNull(profile.getName());
assertNull(profile.getSkin()); assertNull(profile.getSkin());
@ -74,10 +76,10 @@ 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"); assertEquals(updatedProfile.getName(), "Notch");
assertEquals(updatedProfile.getSkin(), "Notch"); assertEquals(updatedProfile.getSkin(), "Notch");
assertEquals(updatedProfile.getLocale(), Locale.FRENCH); assertEquals(updatedProfile.getLocale(), Locale.FRENCH);

View file

@ -6,7 +6,6 @@ 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.NickoProfile; import xyz.atnrch.nicko.profile.NickoProfile;
@ -46,10 +45,14 @@ 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); profile.setName("Notch");
appearanceManager.setName("Notch"); dataStore.updateCache(player.getUniqueId(), profile);
dataStore.updateCache(player.getUniqueId(), appearanceManager.getProfile());
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();