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

View file

@ -3,15 +3,12 @@ package xyz.atnrch.nicko;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
import xyz.atnrch.nicko.command.NickoCommand;
import xyz.atnrch.nicko.config.Configuration;
import xyz.atnrch.nicko.config.ConfigurationManager;
import xyz.atnrch.nicko.event.PlayerJoinListener;
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.LocaleFileManager;
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.impl.SimpleItem;
import java.io.File;
import java.io.IOException;
public class NickoBukkit extends JavaPlugin {
@ -44,16 +40,8 @@ public class NickoBukkit extends JavaPlugin {
/**
* Used by MockBukkit
*/
protected NickoBukkit(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
this(loader, description, dataFolder, file, null);
}
/**
* Used by MockBukkit
*/
protected NickoBukkit(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file, Configuration configuration) {
super(loader, description, dataFolder, file);
unitTesting = true;
protected NickoBukkit(Configuration configuration) {
this.unitTesting = true;
this.configuration = configuration;
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.BLACK_STAINED_GLASS_PANE).setDisplayName(" ")));
Structure.addGlobalIngredient('U', new UnavailableItem());
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
getLogger().info("Enabling PlaceHolderAPI support...");
@ -120,11 +107,12 @@ public class NickoBukkit extends JavaPlugin {
@Override
public void onDisable() {
if (!getDataStore().getStorage().isError()) {
getLogger().info("Closing persistence...");
nameStore.clearStoredNames();
Bukkit.getOnlinePlayers().forEach(player -> dataStore.saveData(player));
if (!dataStore.getStorage().getProvider().close()) {
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.I18NDict;
import xyz.atnrch.nicko.mojang.MojangUtils;
import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class AnvilManager {
private final Player player;
private final AppearanceManager appearanceManager;
private final PlayerDataStore dataStore;
private final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
private final NickoProfile profile;
public AnvilManager(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() {
@ -39,7 +44,7 @@ public class AnvilManager {
getNameAnvil().open(player);
}
public AnvilGUI.Builder getNameThenSkinAnvil() {
private AnvilGUI.Builder getNameThenSkinAnvil() {
return new AnvilGUI.Builder()
.plugin(NickoBukkit.getInstance())
.itemLeft(getLeftItem(false))
@ -49,8 +54,8 @@ public class AnvilManager {
if (MojangUtils.isUsernameInvalid(snapshot.getText())) {
return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!"));
} else {
appearanceManager.setName(snapshot.getText());
dataStore.updateCache(player.getUniqueId(), appearanceManager.getProfile());
profile.setName(snapshot.getText());
dataStore.updateCache(player.getUniqueId(), profile);
openSkinAnvil();
return Collections.singletonList(AnvilGUI.ResponseAction.close());
}
@ -60,7 +65,7 @@ public class AnvilManager {
.text("New name...");
}
public AnvilGUI.Builder getNameAnvil() {
private AnvilGUI.Builder getNameAnvil() {
return new AnvilGUI.Builder()
.plugin(NickoBukkit.getInstance())
.itemLeft(getLeftItem(false))
@ -70,8 +75,8 @@ public class AnvilManager {
if (MojangUtils.isUsernameInvalid(snapshot.getText())) {
return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!"));
} else {
appearanceManager.setName(snapshot.getText());
dataStore.updateCache(player.getUniqueId(), appearanceManager.getProfile());
profile.setName(snapshot.getText());
dataStore.updateCache(player.getUniqueId(), profile);
final ActionResult actionResult = appearanceManager.updatePlayer(false, false);
return sendResultAndClose(actionResult);
}
@ -91,8 +96,8 @@ public class AnvilManager {
if (MojangUtils.isUsernameInvalid(snapshot.getText())) {
return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!"));
} else {
appearanceManager.setSkin(snapshot.getText());
dataStore.updateCache(player.getUniqueId(), appearanceManager.getProfile());
profile.setSkin(snapshot.getText());
dataStore.updateCache(player.getUniqueId(), profile);
final ActionResult actionResult = appearanceManager.updatePlayer(true, false);
return sendResultAndClose(actionResult);
}

View file

@ -11,7 +11,6 @@ import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.Locale;
import xyz.atnrch.nicko.mojang.MojangAPI;
import xyz.atnrch.nicko.mojang.MojangSkin;
import xyz.atnrch.nicko.profile.NickoProfile;
@ -22,96 +21,36 @@ import xyz.atnrch.nicko.wrapper.*;
import java.io.IOException;
import java.util.EnumSet;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
public class AppearanceManager {
private final NickoProfile profile;
private final Player player;
private final UUID uuid;
private final NickoBukkit instance = NickoBukkit.getInstance();
private final PlayerDataStore dataStore = instance.getDataStore();
private final PlayerNameStore nameStore = instance.getNameStore();
private AppearanceManager(UUID uuid) {
this.player = Bukkit.getPlayer(uuid);
this.uuid = uuid;
this.profile = dataStore.getData(uuid).orElse(NickoProfile.EMPTY_PROFILE.clone());
}
private final Player player;
private AppearanceManager(String name) {
this.player = null;
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 AppearanceManager(Player player) {
this.player = player;
}
public ActionResult reset() {
final NickoProfile profile = getNickoProfile();
final String defaultName = nameStore.getStoredName(player);
this.profile.setName(defaultName);
this.profile.setSkin(defaultName);
profile.setName(defaultName);
profile.setSkin(defaultName);
dataStore.getCache().cache(player.getUniqueId(), profile);
final ActionResult actionResult = updatePlayer(true, true);
if (!actionResult.isError()) {
this.profile.setSkin(null);
this.profile.setName(null);
dataStore.getCache().cache(uuid, profile);
profile.setSkin(null);
profile.setName(null);
dataStore.getCache().cache(player.getUniqueId(), profile);
}
return actionResult;
}
public ActionResult updatePlayer(boolean skinChange, boolean reset) {
final NickoProfile profile = getNickoProfile();
final String displayName = profile.getName() == null ? player.getName() : profile.getName();
final WrappedGameProfile gameProfile = WrappedGameProfile.fromPlayer(player).withName(displayName);
final ActionResult result = updateGameProfileSkin(gameProfile, skinChange, reset);
@ -124,6 +63,11 @@ public class AppearanceManager {
return result;
}
private NickoProfile getNickoProfile() {
final Optional<NickoProfile> optionalProfile = dataStore.getData(player.getUniqueId());
return optionalProfile.orElse(NickoProfile.EMPTY_PROFILE.clone());
}
public void updateOthers() {
final WrapperPlayServerEntityDestroy destroy = new WrapperPlayServerEntityDestroy();
final WrapperPlayServerNamedEntitySpawn spawn = new WrapperPlayServerNamedEntitySpawn();
@ -139,15 +83,16 @@ public class AppearanceManager {
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;
try {
final MojangAPI mojang = NickoBukkit.getInstance().getMojangAPI();
final Optional<String> uuid = mojang.getUUID(profile.getSkin());
final MojangAPI mojangAPI = NickoBukkit.getInstance().getMojangAPI();
final Optional<String> uuid = mojangAPI.getUUID(profile.getSkin());
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()) {
final MojangSkin skinResult = skin.get();
final Multimap<String, WrappedSignedProperty> properties = gameProfile.getProperties();
@ -177,6 +122,7 @@ public class AppearanceManager {
private void respawnPlayer() {
final World world = player.getWorld();
final boolean wasFlying = player.isFlying();
final boolean wasAllowedToFly = player.getAllowFlight();
final WrapperPlayServerRespawn respawn = new WrapperPlayServerRespawn();
respawn.setDimension(world);
respawn.setSeed(world.getSeed());
@ -185,9 +131,10 @@ public class AppearanceManager {
respawn.setDifficulty(world.getDifficulty());
respawn.setCopyMetadata(true);
respawn.sendPacket(player);
player.setFlying(wasFlying);
player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
player.updateInventory();
player.setAllowFlight(wasAllowedToFly);
player.setFlying(wasFlying);
player.updateInventory(); // Marked as unstable.
}
@SuppressWarnings("deprecation")
@ -218,6 +165,9 @@ public class AppearanceManager {
// No, I'll not waste another day fixing their mess.
// Go cry about it to Mojang.
// (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(
player.getUniqueId(),
player.getPing(),

View file

@ -1,13 +1,12 @@
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.CommandExecutor;
import org.bukkit.command.CommandSender;
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.I18NDict;
@ -17,20 +16,14 @@ public class NickoCommand implements CommandExecutor {
"§6/nicko help §f- §7Print this help message.\n";
@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) {
final Player player = (Player) sender;
if (args.length >= 1) {
switch (args[0]) {
case "debug":
new NickoDebugSubCmd().execute(player, args);
break;
case "check":
new NickoCheckSubCmd().execute(player, args);
break;
default:
if (args[0].equals("debug")) {
new NickoDebugCmd().execute(player, args);
} else {
sendHelpMessage(sender);
break;
}
return false;
}
@ -49,7 +42,7 @@ public class NickoCommand implements CommandExecutor {
}
public void sendHelpMessage(CommandSender sender) {
helpMessage = helpMessage.replace("{version}", NickoBukkit.getInstance().getDescription().getVersion());
helpMessage = helpMessage.replace("{version}", NickoBukkit.getInstance().getPluginMeta().getVersion());
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.appearance.ActionResult;
import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.mojang.MojangUtils;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore;
public class NickoDebugSubCmd {
import java.util.Optional;
public class NickoDebugCmd {
public void execute(CommandSender sender, String[] args) {
final String prefix = NickoBukkit.getInstance().getNickoConfig().getPrefix();
Player target;
String name, skin;
String playerName = null;
if (args.length == 3) {
target = (Player) sender;
name = args[1];
@ -26,7 +31,7 @@ public class NickoDebugSubCmd {
return;
}
final String playerName = args[1];
playerName = args[1];
name = args[2];
skin = args[3];
@ -47,8 +52,14 @@ public class NickoDebugSubCmd {
return;
}
final AppearanceManager appearanceManager = AppearanceManager.get(target.getPlayer());
appearanceManager.setNameAndSkin(name, skin);
final Optional<NickoProfile> optionalProfile = NickoProfile.get(target);
if (optionalProfile.isPresent()) {
final NickoProfile profile = optionalProfile.get();
final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
profile.setName(name);
profile.setSkin(skin);
dataStore.updateCache(target.getUniqueId(), profile);
final AppearanceManager appearanceManager = new AppearanceManager(target);
final ActionResult result = appearanceManager.updatePlayer(true, false);
if (!result.isError()) {
target.sendMessage(prefix + "§aWhoosh!");
@ -59,3 +70,4 @@ public class NickoDebugSubCmd {
}
}
}
}

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.i18n.I18N;
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 java.util.Optional;
public class PlayerJoinListener implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
@ -19,19 +23,25 @@ public class PlayerJoinListener implements Listener {
final NickoBukkit instance = NickoBukkit.getInstance();
final I18N i18n = new I18N(player);
final PlayerNameStore nameStore = instance.getNameStore();
final PlayerDataStore dataStore = instance.getDataStore();
// TODO: 2/20/23 Fetch data from BungeeCord
nameStore.storeName(player);
Bukkit.getScheduler().runTaskLater(instance, () -> {
final AppearanceManager appearanceManager = AppearanceManager.get(player);
if (appearanceManager.hasData()) {
final ActionResult actionResult = appearanceManager.updatePlayer(appearanceManager.needsASkinChange(), false);
final Optional<NickoProfile> optionalProfile = dataStore.getData(player.getUniqueId());
optionalProfile.ifPresent(profile -> {
if (profile.hasData()) {
final AppearanceManager appearanceManager = new AppearanceManager(player);
final boolean needsASkinChange = profile.getSkin() != null && !profile.getSkin().equals(player.getName());
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);
}
}

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.common.GoBackItem;
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.window.Window;
public class AdminGUI {
private final String title = "Nicko > Administration";
private final Player player;
private final Gui gui;
private final String title;
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 GoBackItem backItem = new GoBackItem(player);
final UnavailableItem unavailableItem = new UnavailableItem(player);
final ManagePlayerItem managePlayerItem = new ManagePlayerItem(i18n, player);
this.gui = Gui.normal()
.setStructure(
"# # # # # # # # #",
"# # # S C U # # #",
"# # # S C X # # #",
"B # # # # # # # #"
)
.addIngredient('S', new ManageCacheItem())
.addIngredient('C', new ManagePlayerItem())
.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle()))
.addIngredient('S', new ManageCacheItem(i18n))
.addIngredient('C', managePlayerItem.get())
.addIngredient('U', unavailableItem.get())
.addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()))
.build();
this.player = player;
}

View file

@ -3,28 +3,39 @@ package xyz.atnrch.nicko.gui;
import org.bukkit.entity.Player;
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.InvalidateEntryItem;
import xyz.atnrch.nicko.gui.items.admin.cache.InvalidateSkinItem;
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.window.Window;
public class CacheManagementGUI {
private final String title = "Nicko > Admin... > Cache";
private final Player player;
private final Gui gui;
private final String title;
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 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()
.setStructure(
"# # # # # # # # #",
"# # # S A D # # #",
"# # # S C E # # #",
"B # # # # # # # #"
)
.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle()))
.addIngredient('S', new CacheStatisticsItem())
.addIngredient('A', new InvalidateCacheItem())
.addIngredient('D', new InvalidateEntryItem())
.addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()))
.addIngredient('S', cacheStatisticsItem.get())
.addIngredient('C', invalidateCacheItem.get())
.addIngredient('E', invalidateSkinItem.get())
.build();
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.ResetItem;
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.window.Window;
public class HomeGUI {
private final String title = "Nicko - Home";
private final Player player;
private final Gui gui;
private final String title;
public HomeGUI(Player player) {
final String[] dynamicStructure = new String[]{
@ -26,15 +28,26 @@ public class HomeGUI {
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()
.setStructure(dynamicStructure)
.addIngredient('E', new ExitItem())
.addIngredient('R', new ResetItem())
.addIngredient('N', new ChangeNameItem())
.addIngredient('B', new ChangeBothItem())
.addIngredient('S', new ChangeSkinItem(player))
.addIngredient('P', new SettingsAccessItem())
.addIngredient('A', new AdminAccessItem())
.addIngredient('E', exitItem.get())
.addIngredient('R', resetItem.get())
.addIngredient('N', changeNameItem.get())
.addIngredient('B', changeBothItem.get())
.addIngredient('S', changeSkinItem.get())
.addIngredient('P', settingsAccessItem.get())
.addIngredient('A', adminAccessItem.get())
.build();
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.ScrollUpItem;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.mojang.MojangSkin;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.gui.ScrollGui;
@ -19,13 +21,15 @@ import java.util.Optional;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
public class CacheDetailedGUI {
public static final String TITLE = "... > Cache > Invalidate";
public class InvalidateSkinGUI {
private final Player player;
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 List<String> loadedSkins = skins.entrySet().stream()
.filter(entry -> entry.getValue().isPresent())
@ -37,6 +41,10 @@ public class CacheDetailedGUI {
.collect(Collectors.toList());
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 -> {
guiItemBuilder.setStructure(
"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",
"B % % % % % % % %");
guiItemBuilder.addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL);
guiItemBuilder.addIngredient('U', new ScrollUpItem());
guiItemBuilder.addIngredient('D', new ScrollDownItem());
guiItemBuilder.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle()));
guiItemBuilder.addIngredient('U', scrollUpItem);
guiItemBuilder.addIngredient('D', scrollDownItem);
guiItemBuilder.addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()));
guiItemBuilder.setContent(items);
});
@ -56,6 +64,6 @@ public class CacheDetailedGUI {
}
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.ScrollDownItem;
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.ScrollGui;
import xyz.xenondevs.invui.gui.structure.Markers;
@ -17,18 +19,24 @@ import java.util.List;
import java.util.stream.Collectors;
public class PlayerCheckGUI {
public static final String TITLE = "Nicko > Admin... > Check";
private final Player player;
private final Gui gui;
private final String title;
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()
.map(Entity::getUniqueId)
.map(PlayerInformationItem::new)
.map(uuid -> new PlayerInformationItem(i18n, uuid))
.collect(Collectors.toList());
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 -> {
guiItemBuilder.setStructure(
"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",
"B % % % % % % % %");
guiItemBuilder.addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL);
guiItemBuilder.addIngredient('U', new ScrollUpItem());
guiItemBuilder.addIngredient('D', new ScrollDownItem());
guiItemBuilder.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle()));
guiItemBuilder.addIngredient('U', scrollUpItem);
guiItemBuilder.addIngredient('D', scrollDownItem);
guiItemBuilder.addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()));
guiItemBuilder.setContent(items);
});
@ -48,6 +56,6 @@ public class PlayerCheckGUI {
}
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;
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.LanguageCyclingItem;
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.window.Window;
public class SettingsGUI {
public static final String TITLE = "Nicko > Settings";
private final Player player;
private final Gui gui;
private final String title;
public SettingsGUI(Player player) {
final String[] dynamicStructure = new String[]{
@ -23,17 +25,26 @@ public class SettingsGUI {
// TODO: 3/6/23 Replace when Redis is not enabled
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 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()
.setStructure(dynamicStructure)
.addIngredient('B', new GoBackItem(parent.getGUI(), parent.getTitle()))
.addIngredient('L', new LanguageCyclingItem().get(player))
.addIngredient('T', new BungeeCordCyclingItem().get(player))
.addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()))
.addIngredient('L', languageItem.get())
.addIngredient('U', unavailableItem.get())
.addIngredient('T', bungeeCordItem.get())
.build();
this.player = player;
}
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;
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.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
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 ManageCacheItem() {
super(new ItemBuilder(Material.PAINTING)
.setDisplayName("Manage §6skin §fcache...")
.addLoreLines("§7Access the skin cache management panel."),
public ManageCacheItem(I18N i18n) {
super(new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.PAINTING);
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");
builder.setDisplayName("Manage §6skin §fcache...");
builder.addLoreLines("§7Access the skin cache management panel.");
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.MANAGE_CACHE);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
});
}

View file

@ -2,30 +2,32 @@ package xyz.atnrch.nicko.gui.items.admin;
import org.bukkit.Material;
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.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 ManagePlayerItem extends SuppliedItem {
public ManagePlayerItem() {
super(() -> {
final ItemBuilder builder = new ItemBuilder(Material.WRITABLE_BOOK);
builder.setDisplayName("Check a player...");
builder.addLoreLines("§7See players' disguise information.");
return builder;
},
click -> true);
public class ManagePlayerItem {
private final Player player;
private final I18N i18n;
public ManagePlayerItem(I18N i18n, Player player) {
this.i18n = i18n;
this.player = player;
}
@Override
public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent
event) {
if (clickType.isLeftClick() || clickType.isRightClick()) {
event.getView().close();
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.WRITABLE_BOOK);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.MANAGE_PLAYER);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
}, click -> {
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.jetbrains.annotations.NotNull;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.gui.ConfirmGUI;
import xyz.atnrch.nicko.gui.CacheDetailedGUI;
import xyz.atnrch.nicko.gui.items.common.confirm.ChoiceCallback;
import xyz.atnrch.nicko.gui.ChoiceGUI;
import xyz.atnrch.nicko.gui.InvalidateSkinGUI;
import xyz.atnrch.nicko.gui.items.common.choice.ChoiceCallback;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
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) {
if (click.isLeftClick() || click.isRightClick()) {
event.getView().close();
new ConfirmGUI(player, new ChoiceCallback() {
new ChoiceGUI(player, new ChoiceCallback() {
@Override
public void onConfirm() {
final I18N i18n = new I18N(player);
@ -50,7 +50,7 @@ public class CacheEntryItem extends AsyncItem {
@Override
public void onCancel() {
new CacheDetailedGUI(player).open();
new InvalidateSkinGUI(player).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.LoadingCache;
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.mojang.MojangSkin;
import org.bukkit.Material;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
@ -10,17 +14,26 @@ import xyz.xenondevs.invui.item.impl.SuppliedItem;
import java.util.Optional;
public class CacheStatisticsItem extends SuppliedItem {
public CacheStatisticsItem() {
super(() -> {
public class CacheStatisticsItem {
private final I18N i18n;
public CacheStatisticsItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.BOOK);
final LoadingCache<String, Optional<MojangSkin>> cache = NickoBukkit.getInstance().getMojangAPI().getSkinCache();
final CacheStats stats = cache.stats();
builder.setDisplayName("Statistics");
builder.addLoreLines(
"Request Count: §b" + stats.requestCount(),
"Skin Cached: §b" + Math.round(cache.size()),
"§8§oCache is cleared every 24 hours.");
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.Cache.STATISTICS,
stats.requestCount(),
Math.round(cache.size())
);
// TODO (Ineanto, 9/11/23): This doesn't work.
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
}, (event) -> true);
}

View file

@ -6,18 +6,23 @@ import xyz.atnrch.nicko.i18n.I18NDict;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class InvalidateCacheItem extends SuppliedItem {
public InvalidateCacheItem() {
super(() -> {
public class InvalidateCacheItem {
private final I18N i18n;
public InvalidateCacheItem(Player player) {
this.i18n = new I18N(player);
}
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.TNT);
builder.setDisplayName("Invalidate cache");
builder.addLoreLines(
"§c§oNOT RECOMMENDED",
"§7Invalidates every skin entry present in the cache.",
"§7Does not reset player disguises.");
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.Cache.INVALIDATE_CACHE);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
}, (click) -> {
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.entity.Player;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.mojang.MojangAPI;
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.builder.ItemBuilder;
import xyz.xenondevs.invui.item.builder.SkullBuilder;
import xyz.xenondevs.invui.item.impl.AsyncItem;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
import java.util.Optional;
import java.util.UUID;
public class PlayerInformationItem extends AsyncItem {
private final MojangAPI mojangAPI = NickoBukkit.getInstance().getMojangAPI();
public PlayerInformationItem(UUID uuid) {
super(new ItemBuilder(Material.PAINTING).setDisplayName("§7§oLoading..."), () -> {
public PlayerInformationItem(I18N i18n, UUID uuid) {
super(new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.PAINTING);
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 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()) {
skull.addLoreLines(
"§cNicked: §a✔",
"§cName: §6" + appearanceManager.getName(),
"§cSkin: §6" + appearanceManager.getSkin()
);
if (optionalProfile.isPresent()) {
final NickoProfile profile = optionalProfile.get();
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.CHECK, player.getName(), (profile.hasData() ? "§a✔" : "§c❌"), profile.getName(), profile.getSkin());
skull.setDisplayName("§6" + translation.getName());
translation.getLore().forEach(skull::addLoreLines);
} else {
// Default item name in case the profile is not found
skull.setDisplayName("§6§lYou should not see this!");
skull.addLoreLines(
"§cNicked: §c❌",
"§cName: §7N/A",
"§cSkin: §7N/A"
"§cPlease file a bug report",
"§cat https://ineanto.xyz/git/ineanto/nicko!"
);
}
skull.setDisplayName("§6" + player.getName());
return skull;
});
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,10 +1,14 @@
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.Sound;
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.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.AbstractItem;
@ -14,18 +18,28 @@ import xyz.xenondevs.invui.item.impl.SimpleItem;
import java.util.Optional;
public class BungeeCordCyclingItem {
private final ItemProvider[] providers = new ItemProvider[]{
private final Player player;
private final I18N i18n;
private final ItemProvider[] providers;
public BungeeCordCyclingItem(Player player) {
this.player = player;
this.i18n = new I18N(player);
this.providers = new ItemProvider[]{
getItemProviderForValue(true),
getItemProviderForValue(false)
};
}
public AbstractItem get(Player player) {
final Optional<NickoProfile> profile = NickoBukkit.getInstance().getDataStore().getData(player.getUniqueId());
public AbstractItem get() {
final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
final Optional<NickoProfile> profile = dataStore.getData(player.getUniqueId());
if (profile.isPresent()) {
final NickoProfile nickoProfile = profile.get();
int startingState = nickoProfile.isBungeecordTransfer() ? 0 : 1;
return CycleItem.withStateChangeHandler((observer, integer) -> {
nickoProfile.setBungeecordTransfer(integer != 1);
dataStore.updateCache(player.getUniqueId(), nickoProfile);
observer.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 0.707107f); // 0.707107 ~= C
}, startingState, providers);
}
@ -35,7 +49,11 @@ public class BungeeCordCyclingItem {
private ItemProvider getItemProviderForValue(boolean enabled) {
final ItemBuilder builder = new ItemBuilder(Material.COMPASS);
builder.setDisplayName("BungeeCord transfer");
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Settings.BUNGEECORD);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
/*
if (enabled) {
builder.addLoreLines("§7> §cDisabled");
builder.addLoreLines("§6§l> §a§lEnabled");
@ -44,6 +62,7 @@ public class BungeeCordCyclingItem {
builder.addLoreLines("§7> §aEnabled");
}
builder.addLoreLines("§7§oCycle through the values by", "§7§oleft and right clicking.");
*/
return builder;
}
}

View file

@ -4,8 +4,10 @@ import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.gui.SettingsGUI;
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 xyz.atnrch.nicko.profile.NickoProfile;
import xyz.atnrch.nicko.storage.PlayerDataStore;
@ -21,9 +23,17 @@ import java.util.List;
import java.util.Optional;
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 Optional<NickoProfile> profile = dataStore.getData(player.getUniqueId());
if (profile.isPresent()) {
@ -32,11 +42,12 @@ public class LanguageCyclingItem {
return CycleItem.withStateChangeHandler((observer, integer) -> {
nickoProfile.setLocale(Locale.values()[integer]);
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.
if (dataStore.updateCache(player.getUniqueId(), nickoProfile).isError()) {
final I18N i18n = new I18N(player);
player.sendMessage(i18n.translate(I18NDict.Event.Settings.ERROR));
player.getOpenInventory().close();
} else {
new SettingsGUI(player).open();
}
}, localeOrdinal, providers);
}
@ -46,7 +57,9 @@ public class LanguageCyclingItem {
private ItemProvider generateItem(Locale locale, List<Locale> locales) {
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) {
if (locale != value) {
builder.addLoreLines("§7> " + value.getName());
@ -54,15 +67,15 @@ public class LanguageCyclingItem {
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;
}
private ItemProvider[] getItems() {
final NickoBukkit instance = NickoBukkit.getInstance();
final ArrayList<ItemProvider> items = new ArrayList<>();
final ArrayList<Locale> localesToGenerate = new ArrayList<>();
Collections.addAll(localesToGenerate, Locale.values());
if (!instance.getNickoConfig().isCustomLocale()) {
localesToGenerate.remove(Locale.CUSTOM);

View file

@ -3,50 +3,96 @@ package xyz.atnrch.nicko.i18n;
import com.github.jsixface.YamlConfig;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.appearance.AppearanceManager;
import xyz.atnrch.nicko.profile.NickoProfile;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Iterator;
import java.util.Optional;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class I18N {
private final MessageFormat formatter = new MessageFormat("");
private final Logger logger = Logger.getLogger("I18N");
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 Locale playerLocale;
public I18N(Player player) {
this.player = player;
this.playerLocale = getPlayerLocale();
this.yamlConfig = getYamlConfig();
}
public I18N(Locale locale) {
this.player = null;
this.playerLocale = locale;
this.yamlConfig = getYamlConfig();
}
public List<String> translateItem(String key, Object... arguments) {
final ArrayList<String> lines = new ArrayList<>();
final String itemNameKey = readString(key + ".name");
final ArrayList<String> itemLoreKey = readList(key + ".lore");
try {
// Item Name
formatter.applyPattern(itemNameKey);
final String itemNameTranslated = formatter.format(arguments);
lines.add(itemNameTranslated);
return lines;
} catch (Exception e) {
return Collections.singletonList(key);
public ItemTranslation translateItem(String key, Object... args) {
final String nameKey = key + ".name";
final String loreKey = key + ".lore";
final String name = readString(nameKey);
final ArrayList<String> lore = readList(loreKey);
if (name == null) {
logger.warning(nameKey + " doesn't exists! Please translate this entry.");
return new ItemTranslation(nameKey, new ArrayList<String>() {{
add(loreKey);
}});
}
// 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) {
final String string = readString(key);
final String translation = readString(key);
try {
formatter.applyPattern(string);
formatter.applyPattern(translation);
return instance.getNickoConfig().getPrefix() + formatter.format(arguments);
} catch (Exception e) {
return instance.getNickoConfig().getPrefix() + key;
@ -64,43 +110,27 @@ public class I18N {
}
private String readString(String key) {
YamlConfig yamlFile;
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);
return yamlConfig.getString(key);
}
private ArrayList<String> readList(String key) {
final ArrayList<String> lines = new ArrayList<>();
YamlConfig yamlFile;
return yamlConfig.getStringList(key);
}
private YamlConfig getYamlConfig() {
if (playerLocale == Locale.CUSTOM) {
yamlFile = instance.getLocaleFileManager().getYamlFile();
return instance.getLocaleFileManager().getYamlFile();
} else {
final InputStream resource = instance.getResource(playerLocale.getCode() + ".yml");
yamlFile = YamlConfig.load(resource);
return new YamlConfig(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() {
try {
final AppearanceManager appearanceManager = AppearanceManager.get(player);
return !appearanceManager.hasData() ? Locale.FALLBACK_LOCALE : appearanceManager.getLocale();
} catch (IllegalArgumentException exception) {
instance.getLogger().severe("Invalid locale provided by " + player.getName() + ", defaulting to " + Locale.FALLBACK_LOCALE.getCode() + ".");
public Locale getPlayerLocale() {
final Optional<NickoProfile> optionalProfile = NickoProfile.get(player);
if (optionalProfile.isPresent()) {
return optionalProfile.get().getLocale();
} else {
return Locale.FALLBACK_LOCALE;
}
}

View file

@ -2,14 +2,17 @@ package xyz.atnrch.nicko.i18n;
public class I18NDict {
public static class Error {
public static final String GENERIC = "error.generic";
public static final String PERMISSION = "error.permission";
public static final String CACHE = "error.cache";
public static final String MOJANG_NAME = "error.mojang_name";
public static final String MOJANG_SKIN = "error.mojang_skin";
public static final String INVALID_USERNAME = "error.invalid_username";
public static final String SQL_ERROR = "error.sql";
public static final String JSON_ERROR = "error.json";
public static final String ERROR_KEY = "error.";
public static final String GENERIC = ERROR_KEY + "generic";
public static final String PERMISSION = ERROR_KEY + "permission";
public static final String CACHE = ERROR_KEY + "cache";
public static final String MOJANG_NAME = ERROR_KEY + "mojang_name";
public static final String MOJANG_SKIN = ERROR_KEY + "mojang_skin";
@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 {
@ -64,11 +67,63 @@ public class I18NDict {
private static final String GUI_KEY = "gui.";
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 {
private static final String HOME_KEY = GUI_KEY + "home.";
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) {
if (!file.exists()) return key;
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);
} catch (IOException e) {
return key;
@ -44,7 +44,7 @@ public class LocaleFileManager {
public YamlConfig getYamlFile() {
if (yamlFile == null) {
try (BufferedInputStream inputStream = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
yamlFile = YamlConfig.load(inputStream);
yamlFile = new YamlConfig(inputStream);
} catch (IOException ignored) {
return null;
}

View file

@ -51,20 +51,30 @@ public class NickoExpansion extends PlaceholderExpansion {
final Optional<NickoProfile> optionalProfile = instance.getDataStore().getData(player.getUniqueId());
if (optionalProfile.isPresent()) {
final NickoProfile profile = optionalProfile.get();
if (!profile.isEmpty()) {
if (profile.hasData()) {
if (profile.getName() != null) {
name = profile.getName();
}
if (profile.getSkin() != null) {
skin = profile.getSkin();
}
}
locale = profile.getLocale().getName();
bungeecord = profile.isBungeecordTransfer();
}
switch (params) {
case "name": return name;
case "skin": return skin;
case "locale": return locale;
case "bungeecord": return String.valueOf(bungeecord);
default: return null;
case "name":
return name;
case "skin":
return skin;
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;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import xyz.atnrch.nicko.NickoBukkit;
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 static final PlayerDataStore dataStore = NickoBukkit.getInstance().getDataStore();
public static final NickoProfile EMPTY_PROFILE = new NickoProfile(null, null, Locale.ENGLISH, true);
private transient final Player player;
private String name;
private String skin;
private Locale locale;
@ -15,10 +25,35 @@ public class NickoProfile implements Cloneable {
this.skin = skin;
this.locale = locale;
this.bungeecordTransfer = bungeecordTransfer;
this.player = null;
}
public boolean isEmpty() {
return name == null && skin == null;
public NickoProfile(Player player, String name, String skin, Locale locale, boolean bungeecordTransfer) {
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() {
@ -37,9 +72,13 @@ public class NickoProfile implements Cloneable {
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() {
return bungeecordTransfer;

View file

@ -76,12 +76,12 @@ public class PlayerDataStore {
if (storage.isError()) return ActionResult.error(I18NDict.Error.GENERIC);
if (cache.isError()) return ActionResult.error(I18NDict.Error.CACHE);
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
//profiles.remove(player.getUniqueId());
return storage.store(player.getUniqueId(), cache.retrieve(player.getUniqueId()).get());
final Optional<NickoProfile> cachedProfile = cache.retrieve(player.getUniqueId());
if (!cachedProfile.isPresent()) return ActionResult.error(I18NDict.Error.GENERIC);
cache.delete(player.getUniqueId());
return storage.store(player.getUniqueId(), cachedProfile.get());
}
public Storage getStorage() {

View file

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

View file

@ -50,6 +50,7 @@ public class RedisCache extends Cache {
@Override
public Optional<NickoProfile> retrieve(UUID uuid) {
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
final String data = jedis.get("nicko:" + uuid.toString());
final NickoProfile profile = gson.fromJson(data, NickoProfile.class);

View file

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

View file

@ -91,9 +91,6 @@ public class SQLStorage extends Storage {
locale = resultSet.getString("locale");
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);
return Optional.of(profile);

View file

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

View file

@ -26,3 +26,101 @@ event:
cache:
invalidate_cache: "§fComplete cache 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:
generic: "Une erreur inconnue c'est produite."
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_skin: "Ce compte Minecraft n'a pas de skin."
cache: "Impossible de récupérer le skin depuis le cache."
@ -9,6 +9,8 @@ error:
json: "Erreur JSON"
event:
settings:
error: "§cImpossible de mettre à jour vos paramètres. §7§o({0})"
appearance:
set:
error: "§cImpossible d''appliquer votre déguisement. §7§o({0})"
@ -26,20 +28,48 @@ event:
invalidate_entry: "§6{0} §fa été invalidé."
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:
admin:
name: "Panel d''administration"
name: "Panel d'administration"
lore:
length: 1
content:
- "Configurez et gérez Nicko."
- "§7Configurez et gérez Nicko."
settings:
name: "Paramètres"
lore:
length: 1
content:
"Configurez votre expérience."
- "§7Gérez votre expérience avec Nicko."
change_name:
name: "Changer le §6pseudo"
change_skin:
@ -49,12 +79,50 @@ gui:
reset:
name: "Réinitialiser l'apparence"
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:
language:
name: "Language"
name: "Langage"
lore:
- "§7§oParcourez les valeurs"
- "§7§oavec un clique gauche/droit."
bungeecord:
name: "Transfert Bungeecord"
lore:
# The language values will be filled at {0}
- "{0}"
- "§7§oParcourez les valeurs"
- "§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;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import be.seeseemelk.mockbukkit.entity.PlayerMock;
import org.junit.jupiter.api.AfterAll;
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.Locale;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class I18NLoreTest {
private static NickoBukkit plugin;
public class TranslationTest {
private static PlayerMock player;
@BeforeAll
@ -27,16 +25,16 @@ public class I18NLoreTest {
DataSourceConfiguration.REDIS_EMPTY,
"",
false);
final ServerMock server = MockBukkit.mock();
plugin = MockBukkit.load(NickoBukkit.class, config);
MockBukkit.mock();
MockBukkit.load(NickoBukkit.class, config);
}
@Test
@DisplayName("Translate Item Lore")
public void translateItemLore() {
@DisplayName("Translate Line With Replacement")
public void translateItemTranslationWithoutLore() {
final I18N i18n = new I18N(Locale.FRENCH);
List<String> strings = i18n.translateItem(I18NDict.GUI.Home.ADMIN);
System.out.println("strings = " + strings);
final String translation = i18n.translatePrefixless(I18NDict.Event.Settings.ERROR, "Test");
assertEquals("§cImpossible de mettre à jour vos paramètres. §7§o(Test)", translation);
}
@AfterAll

View file

@ -46,7 +46,7 @@ public class SQLStorageTest {
@DisplayName("Store empty profile")
@Order(2)
public void storeEmptyProfile() {
final Optional<NickoProfile> optionalProfile = dataStore.getData(uuid);
final Optional<NickoProfile> optionalProfile = NickoProfile.get(uuid);
assertTrue(optionalProfile.isPresent());
}
@ -54,7 +54,9 @@ public class SQLStorageTest {
@DisplayName("Update profile")
@Order(3)
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();
assertNull(profile.getName());
assertNull(profile.getSkin());
@ -74,10 +76,10 @@ public class SQLStorageTest {
@DisplayName("Get updated profile")
@Order(4)
public void hasProfileBeenUpdated() {
final Optional<NickoProfile> profile = dataStore.getData(uuid);
assertTrue(profile.isPresent());
final Optional<NickoProfile> optionalProfile = NickoProfile.get(uuid);
assertTrue(optionalProfile.isPresent());
final NickoProfile updatedProfile = profile.get();
final NickoProfile updatedProfile = optionalProfile.get();
assertEquals(updatedProfile.getName(), "Notch");
assertEquals(updatedProfile.getSkin(), "Notch");
assertEquals(updatedProfile.getLocale(), Locale.FRENCH);

View file

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