1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-20 03:35:51 +00:00

Player Profiles are now truly asynchronous

This commit is contained in:
TheBusyBiscuit 2020-05-08 18:47:25 +02:00
parent 643f992532
commit dc137d04bf
8 changed files with 148 additions and 146 deletions

View File

@ -10,6 +10,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.SlimefunBackpack;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.BackpackListener;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This class represents the instance of a {@link SlimefunBackpack} that is ready to
@ -74,6 +75,11 @@ public class PlayerBackpack {
return id;
}
/**
* This returns the size of this {@link PlayerBackpack}.
*
* @return The size of this {@link PlayerBackpack}
*/
public int getSize() {
return size;
}
@ -90,9 +96,11 @@ public class PlayerBackpack {
* The players who this Backpack will be shown to
*/
public void open(Player... players) {
for (Player p : players) {
p.openInventory(inventory);
}
Slimefun.runSync(() -> {
for (Player p : players) {
p.openInventory(inventory);
}
});
}
/**

View File

@ -67,10 +67,6 @@ public final class PlayerProfile {
}
}
private PlayerProfile(UUID uuid) {
this(Bukkit.getOfflinePlayer(uuid));
}
public HashedArmorpiece[] getArmor() {
return armor;
}
@ -230,62 +226,8 @@ public final class PlayerProfile {
return guideHistory;
}
/**
* This is now deprecated, use {@link #fromUUID(UUID, Consumer)} instead
*
* @param uuid
* The UUID of the profile you are trying to retrieve.
* @return The PlayerProfile of this player
*/
public static PlayerProfile fromUUID(UUID uuid) {
PlayerProfile profile = SlimefunPlugin.getRegistry().getPlayerProfiles().get(uuid);
if (profile == null) {
profile = new PlayerProfile(uuid);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, profile);
}
else {
profile.markedForDeletion = false;
}
return profile;
}
public static boolean fromUUID(UUID uuid, Consumer<PlayerProfile> callback) {
PlayerProfile profile = SlimefunPlugin.getRegistry().getPlayerProfiles().get(uuid);
if (profile != null) {
callback.accept(profile);
return true;
}
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance, () -> {
PlayerProfile pp = new PlayerProfile(uuid);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, pp);
callback.accept(pp);
});
return false;
}
/**
* This is now deprecated, use {@link #get(OfflinePlayer, Consumer)} instead
*
* @param p
* The player's profile you wish to retrieve
* @return The PlayerProfile of this player
*/
public static PlayerProfile get(OfflinePlayer p) {
PlayerProfile profile = SlimefunPlugin.getRegistry().getPlayerProfiles().get(p.getUniqueId());
if (profile == null) {
profile = new PlayerProfile(p);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(p.getUniqueId(), profile);
}
else {
profile.markedForDeletion = false;
}
return profile;
return get(Bukkit.getOfflinePlayer(uuid), callback);
}
/**
@ -299,22 +241,46 @@ public final class PlayerProfile {
* @return If the player was cached or not.
*/
public static boolean get(OfflinePlayer p, Consumer<PlayerProfile> callback) {
PlayerProfile cached = SlimefunPlugin.getRegistry().getPlayerProfiles().get(p.getUniqueId());
UUID uuid = p.getUniqueId();
PlayerProfile profile = SlimefunPlugin.getRegistry().getPlayerProfiles().get(uuid);
if (cached != null) {
callback.accept(cached);
if (profile != null) {
callback.accept(profile);
return true;
}
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance, () -> {
PlayerProfile profile = new PlayerProfile(p);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(p.getUniqueId(), profile);
callback.accept(profile);
PlayerProfile pp = new PlayerProfile(p);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, pp);
callback.accept(pp);
});
return false;
}
/**
* This requests an instance of {@link PlayerProfile} to be loaded for the given {@link OfflinePlayer}.
* This method will return true if the {@link PlayerProfile} was already found.
*
* @param p
* The {@link OfflinePlayer} to request the {@link PlayerProfile} for.
*
* @return Whether the {@link PlayerProfile} was already loaded
*/
public static boolean request(OfflinePlayer p) {
if (!SlimefunPlugin.getRegistry().getPlayerProfiles().containsKey(p.getUniqueId())) {
// Should probably prevent multiple requests for the same profile in the future
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance, () -> {
PlayerProfile pp = new PlayerProfile(p);
SlimefunPlugin.getRegistry().getPlayerProfiles().put(p.getUniqueId(), pp);
});
return false;
}
return true;
}
public static Optional<PlayerProfile> find(OfflinePlayer p) {
return Optional.ofNullable(SlimefunPlugin.getRegistry().getPlayerProfiles().get(p.getUniqueId()));
}
@ -323,8 +289,10 @@ public final class PlayerProfile {
return SlimefunPlugin.getRegistry().getPlayerProfiles().values().iterator();
}
public static PlayerBackpack getBackpack(ItemStack item) {
if (item == null || !item.hasItemMeta() || !item.getItemMeta().hasLore()) return null;
public static void getBackpack(ItemStack item, Consumer<PlayerBackpack> callback) {
if (item == null || !item.hasItemMeta() || !item.getItemMeta().hasLore()) {
return;
}
OptionalInt id = OptionalInt.empty();
String uuid = "";
@ -341,11 +309,8 @@ public final class PlayerProfile {
}
if (id.isPresent()) {
PlayerProfile profile = fromUUID(UUID.fromString(uuid));
return profile.getBackpack(id.getAsInt());
}
else {
return null;
int number = id.getAsInt();
fromUUID(UUID.fromString(uuid), profile -> callback.accept(profile.getBackpack(number)));
}
}

View File

@ -1,5 +1,6 @@
package io.github.thebusybiscuit.slimefun4.core.services.plugins;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
@ -40,27 +41,43 @@ class PlaceholderAPIHook extends PlaceholderExpansion {
@Override
public String onRequest(OfflinePlayer p, String params) {
if (params.equals("researches_total_xp_levels_spent")) {
Stream<Research> stream = PlayerProfile.get(p).getResearches().stream();
return String.valueOf(stream.mapToInt(Research::getCost).sum());
if (params.equals("researches_total_xp_levels_spent") && PlayerProfile.request(p)) {
Optional<PlayerProfile> profile = PlayerProfile.find(p);
if (profile.isPresent()) {
Stream<Research> stream = profile.get().getResearches().stream();
return String.valueOf(stream.mapToInt(Research::getCost).sum());
}
}
if (params.equals("researches_total_researches_unlocked")) {
Set<Research> set = PlayerProfile.get(p).getResearches();
return String.valueOf(set.size());
if (params.equals("researches_total_researches_unlocked") && PlayerProfile.request(p)) {
Optional<PlayerProfile> profile = PlayerProfile.find(p);
if (profile.isPresent()) {
Set<Research> set = profile.get().getResearches();
return String.valueOf(set.size());
}
}
if (params.equals("researches_total_researches")) {
return String.valueOf(SlimefunPlugin.getRegistry().getResearches().size());
}
if (params.equals("researches_percentage_researches_unlocked")) {
Set<Research> set = PlayerProfile.get(p).getResearches();
return String.valueOf(Math.round(((set.size() * 100.0F) / SlimefunPlugin.getRegistry().getResearches().size()) * 100.0F) / 100.0F);
if (params.equals("researches_percentage_researches_unlocked") && PlayerProfile.request(p)) {
Optional<PlayerProfile> profile = PlayerProfile.find(p);
if (profile.isPresent()) {
Set<Research> set = profile.get().getResearches();
return String.valueOf(Math.round(((set.size() * 100.0F) / SlimefunPlugin.getRegistry().getResearches().size()) * 100.0F) / 100.0F);
}
}
if (params.equals("researches_title")) {
return PlayerProfile.get(p).getTitle();
if (params.equals("researches_title") && PlayerProfile.request(p)) {
Optional<PlayerProfile> profile = PlayerProfile.find(p);
if (profile.isPresent()) {
return profile.get().getTitle();
}
}
if (params.equals("gps_complexity")) {

View File

@ -47,7 +47,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
return new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&aSlimefun Guide &7(Book GUI)", "", "&eRight Click &8\u21E8 &7Browse Items", "&eShift + Right Click &8\u21E8 &7Open Settings / Credits");
}
private void openBook(Player p, List<ChatComponent> lines, boolean backButton) {
private void openBook(Player p, PlayerProfile profile, List<ChatComponent> lines, boolean backButton) {
CustomBookInterface book = new CustomBookInterface(SlimefunPlugin.instance);
book.setTitle(SlimefunPlugin.getLocal().getMessage(p, "guide.title.main"));
@ -56,10 +56,10 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
ChatComponent header = new ChatComponent(ChatColors.color("&b&l- " + SlimefunPlugin.getLocal().getMessage(p, "guide.title.main") + " -\n\n"));
header.setHoverEvent(new HoverEvent(ChestMenuUtils.getSearchButton(p)));
header.setClickEvent(new ClickEvent(guideSearch, player -> PlayerProfile.get(player, profile -> Slimefun.runSync(() -> {
header.setClickEvent(new ClickEvent(guideSearch, player -> Slimefun.runSync(() -> {
SlimefunPlugin.getLocal().sendMessage(player, "guide.search.message");
ChatInput.waitForPlayer(SlimefunPlugin.instance, player, msg -> SlimefunGuide.openSearch(profile, msg, true, true));
}, 1))));
}, 1)));
page.append(header);
@ -72,7 +72,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
if (backButton) {
ChatComponent button = new ChatComponent(ChatColor.DARK_BLUE + "\u21E6 " + SlimefunPlugin.getLocal().getMessage(p, "guide.back.title"));
button.setHoverEvent(new HoverEvent(ChatColor.DARK_BLUE + "\u21E6 " + SlimefunPlugin.getLocal().getMessage(p, "guide.back.title"), "", ChatColor.GRAY + SlimefunPlugin.getLocal().getMessage(p, "guide.back.guide")));
button.setClickEvent(new ClickEvent(new NamespacedKey(SlimefunPlugin.instance, "slimefun_guide"), pl -> openMainMenu(PlayerProfile.get(pl), 1)));
button.setClickEvent(new ClickEvent(new NamespacedKey(SlimefunPlugin.instance, "slimefun_guide"), pl -> openMainMenu(profile, 1)));
page.append(button);
}
@ -132,7 +132,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
}
}
openBook(p, lines, false);
openBook(p, profile, lines, false);
}
@Override
@ -206,7 +206,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
}
}
openBook(p, lines, true);
openBook(p, profile, lines, true);
}
else {
p.sendMessage(ChatColor.RED + "That Category is too big to open :/");

View File

@ -4,7 +4,6 @@ import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
@ -12,7 +11,9 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerBackpack;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.SlimefunBackpack;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.BackpackListener;
@ -54,16 +55,21 @@ abstract class BackpackCrafter extends MultiBlockMachine {
if (id.equals("")) {
for (int line = 0; line < output.getItemMeta().getLore().size(); line++) {
if (output.getItemMeta().getLore().get(line).equals(ChatColor.translateAlternateColorCodes('&', "&7ID: <ID>"))) {
int backpackID = PlayerProfile.get(p).createBackpack(size).getID();
if (output.getItemMeta().getLore().get(line).equals(ChatColors.color("&7ID: <ID>"))) {
int target = line;
BackpackListener.setBackpackId(p, output, line, backpackID);
PlayerProfile.get(p, profile -> {
int backpackId = profile.createBackpack(size).getID();
BackpackListener.setBackpackId(p, output, target, backpackId);
});
break;
}
}
}
else {
for (int line = 0; line < output.getItemMeta().getLore().size(); line++) {
if (output.getItemMeta().getLore().get(line).equals(ChatColor.translateAlternateColorCodes('&', "&7ID: <ID>"))) {
if (output.getItemMeta().getLore().get(line).equals(ChatColors.color("&7ID: <ID>"))) {
ItemMeta im = output.getItemMeta();
List<String> lore = im.getLore();
lore.set(line, lore.get(line).replace("<ID>", id));
@ -78,15 +84,20 @@ abstract class BackpackCrafter extends MultiBlockMachine {
private String retrieveID(ItemStack backpack, int size) {
if (backpack != null) {
for (String line : backpack.getItemMeta().getLore()) {
if (line.startsWith(ChatColor.translateAlternateColorCodes('&', "&7ID: ")) && line.contains("#")) {
String id = line.replace(ChatColor.translateAlternateColorCodes('&', "&7ID: "), "");
if (line.startsWith(ChatColors.color("&7ID: ")) && line.contains("#")) {
String id = line.replace(ChatColors.color("&7ID: "), "");
String[] idSplit = PatternUtils.HASH.split(id);
PlayerProfile.fromUUID(UUID.fromString(idSplit[0])).getBackpack(Integer.parseInt(idSplit[1])).setSize(size);
PlayerProfile.fromUUID(UUID.fromString(idSplit[0]), profile -> {
PlayerBackpack bp = profile.getBackpack(Integer.parseInt(idSplit[1]));
bp.setSize(size);
});
return id;
}
}
}
return "";
}

View File

@ -53,10 +53,12 @@ public class BackpackListener implements Listener {
@EventHandler
public void onClose(InventoryCloseEvent e) {
if (backpacks.containsKey(e.getPlayer().getUniqueId())) {
((Player) e.getPlayer()).playSound(e.getPlayer().getLocation(), Sound.ENTITY_HORSE_ARMOR, 1F, 1F);
PlayerProfile.getBackpack(backpacks.get(e.getPlayer().getUniqueId())).markDirty();
backpacks.remove(e.getPlayer().getUniqueId());
Player p = ((Player) e.getPlayer());
ItemStack backpack = backpacks.remove(p.getUniqueId());
if (backpack != null) {
p.playSound(p.getLocation(), Sound.ENTITY_HORSE_ARMOR, 1F, 1F);
PlayerProfile.getBackpack(backpack, PlayerBackpack::markDirty);
}
}
@ -140,9 +142,7 @@ public class BackpackListener implements Listener {
p.playSound(p.getLocation(), Sound.ENTITY_HORSE_ARMOR, 1F, 1F);
backpacks.put(p.getUniqueId(), item);
Slimefun.runSync(() -> {
PlayerBackpack backpack = PlayerProfile.getBackpack(item);
PlayerProfile.getBackpack(item, backpack -> {
if (backpack != null) {
backpack.open(p);
}

View File

@ -39,22 +39,22 @@ public class CoolerListener implements Listener {
}
@EventHandler
public void onStarve(FoodLevelChangeEvent e) {
public void onHungerLoss(FoodLevelChangeEvent e) {
if (cooler == null || cooler.isDisabled()) {
return;
}
if (e.getFoodLevel() < ((Player) e.getEntity()).getFoodLevel()) {
Player p = (Player) e.getEntity();
Player p = (Player) e.getEntity();
if (e.getFoodLevel() < p.getFoodLevel()) {
for (ItemStack item : p.getInventory().getContents()) {
if (cooler.isItem(item)) {
if (Slimefun.hasUnlocked(p, cooler, true)) {
PlayerBackpack backpack = PlayerProfile.getBackpack(item);
if (backpack != null && consumeJuice(p, backpack)) {
break;
}
PlayerProfile.getBackpack(item, backpack -> {
if (backpack != null) {
Slimefun.runSync(() -> consumeJuice(p, backpack));
}
});
}
else {
return;

View File

@ -1,5 +1,6 @@
package me.mrCookieSlime.Slimefun.api;
import java.util.Optional;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
@ -79,28 +80,11 @@ public final class Slimefun {
SlimefunItem sfItem = SlimefunItem.getByItem(item);
if (sfItem != null) {
if (sfItem.getState() == ItemState.DISABLED) {
if (message) {
SlimefunPlugin.getLocal().sendMessage(p, "messages.disabled-item", true);
}
return false;
}
if (isEnabled(p, item, message) && hasPermission(p, sfItem, message)) {
if (sfItem.getResearch() == null) return true;
else if (PlayerProfile.get(p).hasUnlocked(sfItem.getResearch())) return true;
else {
if (message && !(sfItem instanceof VanillaItem)) {
SlimefunPlugin.getLocal().sendMessage(p, "messages.not-researched", true);
}
return false;
}
}
else return false;
return hasUnlocked(p, sfItem, message);
}
else {
return true;
}
else return true;
}
/**
@ -117,19 +101,33 @@ public final class Slimefun {
* <code>false</code> otherwise.
*/
public static boolean hasUnlocked(Player p, SlimefunItem sfItem, boolean message) {
if (sfItem.getState() == ItemState.VANILLA_FALLBACK) {
return true;
}
if (isEnabled(p, sfItem, message) && hasPermission(p, sfItem, message)) {
if (sfItem.getResearch() == null) {
return true;
}
else if (PlayerProfile.get(p).hasUnlocked(sfItem.getResearch())) {
return true;
}
else {
if (message && !(sfItem instanceof VanillaItem)) {
SlimefunPlugin.getLocal().sendMessage(p, "messages.not-researched", true);
}
Optional<PlayerProfile> profile = PlayerProfile.find(p);
return false;
if (!profile.isPresent()) {
// We will return false since we cannot know the answer yet
// But we will schedule the Profile for loading.
PlayerProfile.request(p);
return false;
}
else if (profile.get().hasUnlocked(sfItem.getResearch())) {
return true;
}
else {
if (message && !(sfItem instanceof VanillaItem)) {
SlimefunPlugin.getLocal().sendMessage(p, "messages.not-researched", true);
}
return false;
}
}
}
@ -198,7 +196,10 @@ public final class Slimefun {
* <code>false</code> otherwise.
*/
public static boolean isEnabled(Player p, SlimefunItem sfItem, boolean message) {
if (sfItem.isDisabled()) {
if (sfItem.getState() == ItemState.VANILLA_FALLBACK) {
return true;
}
else if (sfItem.isDisabled()) {
if (message) {
SlimefunPlugin.getLocal().sendMessage(p, "messages.disabled-item", true);
}