From 23481984dfa62c1fda7e5bce579a1319101364ef Mon Sep 17 00:00:00 2001 From: Kermina Awad Date: Thu, 31 Dec 2020 16:51:14 -0500 Subject: [PATCH 1/6] add advancements sharable --- .../share/Sharables.java | 66 ++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java index 8de6d01a..96e9bd1c 100644 --- a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java +++ b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java @@ -8,19 +8,23 @@ import com.onarandombox.multiverseinventories.profile.PlayerProfile; import com.onarandombox.multiverseinventories.util.MinecraftTools; import org.bukkit.Bukkit; +import org.bukkit.GameRule; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.World; +import org.bukkit.advancement.Advancement; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.jetbrains.annotations.NotNull; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedList; @@ -582,6 +586,65 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { }).serializer(new ProfileEntry(false, "potions"), new PotionEffectSerializer()) .altName("potion").altName("potions").build(); + /** + * Sharing Advancements. + */ + public static final Sharable ADVANCEMENTS = new Sharable.Builder("advancements", List.class, + new SharableHandler() { + @Override + public void updateProfile(PlayerProfile profile, Player player) { + Set completedAdvancements = new HashSet<>(); + Iterator advancementIterator = inventories.getServer().advancementIterator(); + + while (advancementIterator.hasNext()) { + Advancement advancement = advancementIterator.next(); + Collection awardedCriteria = player.getAdvancementProgress(advancement).getAwardedCriteria(); + completedAdvancements.addAll(awardedCriteria); + } + + profile.set(ADVANCEMENTS, new ArrayList<>(completedAdvancements)); + } + + @Override + public boolean updatePlayer(Player player, PlayerProfile profile) { + List advancements = profile.get(ADVANCEMENTS); + Set processedAdvancements = new HashSet<>(); + Set completedAdvancements = (advancements != null) ? new HashSet<>(advancements) : new HashSet<>(); + Iterator advancementIterator = inventories.getServer().advancementIterator(); + + boolean announceAdvancements = player.getWorld().getGameRuleValue(GameRule.ANNOUNCE_ADVANCEMENTS); + if (announceAdvancements) player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, false); + while (advancementIterator.hasNext()) { + Advancement advancement = advancementIterator.next(); + // the set of Advancements to revoke + Set revoke = new HashSet<>(advancement.getCriteria()); + // the set of Advancements to grant + Set intersection = new HashSet<>(advancement.getCriteria()); + + revoke.removeAll(processedAdvancements); + revoke.removeAll(completedAdvancements); + intersection.removeAll(processedAdvancements); + intersection.retainAll(completedAdvancements); + + for (String criteria: revoke) { + processedAdvancements.add(criteria); + completedAdvancements.remove(criteria); + player.getAdvancementProgress(advancement).revokeCriteria(criteria); + } + for (String criteria: intersection) { + processedAdvancements.add(criteria); + completedAdvancements.remove(criteria); + player.getAdvancementProgress(advancement).awardCriteria(criteria); + } + + // here's the idea: revoke all (criteria \ completedAdvancements), grant (criteria intersect completedAdvancements) + // also, we don't need to grant/revoke anything in processedAdvancements since they've already been granted/revoked! + } + if (announceAdvancements) player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, true); + return advancements != null; + } + }).defaultSerializer(new ProfileEntry(false, "advancements")).altName("achievements").build(); + /** * Grouping for inventory sharables. */ @@ -625,7 +688,8 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { */ public static final SharableGroup ALL_DEFAULT = new SharableGroup("all", fromSharables(HEALTH, ECONOMY, FOOD_LEVEL, SATURATION, EXHAUSTION, EXPERIENCE, TOTAL_EXPERIENCE, LEVEL, INVENTORY, ARMOR, BED_SPAWN, - MAXIMUM_AIR, REMAINING_AIR, FALL_DISTANCE, FIRE_TICKS, POTIONS, LAST_LOCATION, ENDER_CHEST, OFF_HAND), + MAXIMUM_AIR, REMAINING_AIR, FALL_DISTANCE, FIRE_TICKS, POTIONS, LAST_LOCATION, ENDER_CHEST, OFF_HAND, + ADVANCEMENTS), "*", "everything"); From fabddbd9e935704b1c3ddf4cca4ea9ec0e985fae Mon Sep 17 00:00:00 2001 From: Kermina Awad Date: Fri, 5 Jun 2020 06:18:10 -0400 Subject: [PATCH 2/6] add game stats sharable --- .../share/Sharables.java | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java index 96e9bd1c..466a81f5 100644 --- a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java +++ b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java @@ -13,6 +13,7 @@ import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.World; +import org.bukkit.Statistic; import org.bukkit.advancement.Advancement; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -645,6 +646,41 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { } }).defaultSerializer(new ProfileEntry(false, "advancements")).altName("achievements").build(); + /** + * Sharing Statistics. + */ + public static final Sharable GAME_STATISTICS = new Sharable.Builder("game_statistics", Map.class, + new SharableHandler() { + @Override + public void updateProfile(PlayerProfile profile, Player player) { + Map playerStats = new HashMap<>(); + for (Statistic stat: Statistic.values()) { + if (stat.getType() == Statistic.Type.UNTYPED) { + int val = player.getStatistic(stat); + // no need to save values of 0, that's the default! + if (val != 0) playerStats.put(stat.name(), val); + } + } + profile.set(GAME_STATISTICS, playerStats); + } + + @Override + public boolean updatePlayer(Player player, PlayerProfile profile) { + Map playerStats = profile.get(GAME_STATISTICS); + for (Statistic stat : Statistic.values()) { + if (stat.getType() == Statistic.Type.UNTYPED) player.setStatistic(stat, 0); + } + if (playerStats == null) { + return false; + } + for (String stringStat : playerStats.keySet()) { + Statistic stat = Statistic.valueOf(stringStat); + if (stat.getType() == Statistic.Type.UNTYPED) player.setStatistic(stat, playerStats.get(stat.name())); + } + return true; + } + }).defaultSerializer(new ProfileEntry(false, "game_statistics")).altName("game_stats").build(); + /** * Grouping for inventory sharables. */ @@ -680,7 +716,7 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { */ public static final SharableGroup STATS = new SharableGroup("stats", fromSharables(HEALTH, FOOD_LEVEL, SATURATION, EXHAUSTION, EXPERIENCE, TOTAL_EXPERIENCE, LEVEL, - REMAINING_AIR, MAXIMUM_AIR, FALL_DISTANCE, FIRE_TICKS, POTIONS)); + REMAINING_AIR, MAXIMUM_AIR, FALL_DISTANCE, FIRE_TICKS, POTIONS, GAME_STATISTICS)); /** * Grouping for ALL default sharables. @@ -689,7 +725,7 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { public static final SharableGroup ALL_DEFAULT = new SharableGroup("all", fromSharables(HEALTH, ECONOMY, FOOD_LEVEL, SATURATION, EXHAUSTION, EXPERIENCE, TOTAL_EXPERIENCE, LEVEL, INVENTORY, ARMOR, BED_SPAWN, MAXIMUM_AIR, REMAINING_AIR, FALL_DISTANCE, FIRE_TICKS, POTIONS, LAST_LOCATION, ENDER_CHEST, OFF_HAND, - ADVANCEMENTS), + ADVANCEMENTS, GAME_STATISTICS), "*", "everything"); From 302e120ed0cbeb8dfab4b82258748e734b565d82 Mon Sep 17 00:00:00 2001 From: Kermina Awad Date: Fri, 5 Jun 2020 06:30:08 -0400 Subject: [PATCH 3/6] add recipes sharable --- .../share/Sharables.java | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java index 466a81f5..998abea0 100644 --- a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java +++ b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java @@ -9,14 +9,17 @@ import com.onarandombox.multiverseinventories.util.MinecraftTools; import org.bukkit.Bukkit; import org.bukkit.GameRule; +import org.bukkit.Keyed; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.World; +import org.bukkit.NamespacedKey; import org.bukkit.Statistic; import org.bukkit.advancement.Advancement; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; import org.bukkit.potion.PotionEffect; import org.jetbrains.annotations.NotNull; @@ -681,6 +684,55 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { } }).defaultSerializer(new ProfileEntry(false, "game_statistics")).altName("game_stats").build(); + /** + * Sharing Recipes. + */ + public static final Sharable RECIPES = new Sharable.Builder("recipes", Map.class, + new SharableHandler() { + @Override + public void updateProfile(PlayerProfile profile, Player player) { + Set recipes = new HashSet<>(); + Iterator recipeIterator = inventories.getServer().recipeIterator(); + + while (recipeIterator.hasNext()) { + Recipe recipe = recipeIterator.next(); + if (recipe instanceof Keyed) { + NamespacedKey key = ((Keyed) recipe).getKey(); + if (player.undiscoverRecipe(key)) recipes.add(key); + } + } + + player.discoverRecipes(recipes); + + Map> recipesMap = new HashMap<>(); + for (NamespacedKey recipe: recipes) { + recipesMap.putIfAbsent(recipe.getNamespace(), new ArrayList<>()); + recipesMap.get(recipe.getNamespace()).add(recipe.getKey()); + } + + profile.set(RECIPES, recipesMap); + } + + @Override + public boolean updatePlayer(Player player, PlayerProfile profile) { + Map> recipes = profile.get(RECIPES); + if (recipes == null) recipes = new HashMap<>(); + Iterator recipeIterator = inventories.getServer().recipeIterator(); + + while (recipeIterator.hasNext()) { + Recipe recipe = recipeIterator.next(); + if (recipe instanceof Keyed) { + NamespacedKey key = ((Keyed) recipe).getKey(); + if (recipes.containsKey(key.getNamespace()) && recipes.get(key.getNamespace()).contains(key.getKey())) { + player.discoverRecipe(key); + } else player.undiscoverRecipe(key); + } + } + + return !recipes.isEmpty(); + } + }).defaultSerializer(new ProfileEntry(false, "recipes")).build(); + /** * Grouping for inventory sharables. */ @@ -725,7 +777,7 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { public static final SharableGroup ALL_DEFAULT = new SharableGroup("all", fromSharables(HEALTH, ECONOMY, FOOD_LEVEL, SATURATION, EXHAUSTION, EXPERIENCE, TOTAL_EXPERIENCE, LEVEL, INVENTORY, ARMOR, BED_SPAWN, MAXIMUM_AIR, REMAINING_AIR, FALL_DISTANCE, FIRE_TICKS, POTIONS, LAST_LOCATION, ENDER_CHEST, OFF_HAND, - ADVANCEMENTS, GAME_STATISTICS), + ADVANCEMENTS, GAME_STATISTICS, RECIPES), "*", "everything"); From 0d91d85cd4899286176d7dd9227c143cbd054625 Mon Sep 17 00:00:00 2001 From: Kermina Awad Date: Wed, 27 Jan 2021 21:36:49 -0500 Subject: [PATCH 4/6] improve efficiency and code style --- .../share/Sharables.java | 95 ++++++++++--------- 1 file changed, 52 insertions(+), 43 deletions(-) diff --git a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java index 998abea0..7a43de61 100644 --- a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java +++ b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java @@ -612,39 +612,35 @@ public void updateProfile(PlayerProfile profile, Player player) { @Override public boolean updatePlayer(Player player, PlayerProfile profile) { List advancements = profile.get(ADVANCEMENTS); - Set processedAdvancements = new HashSet<>(); - Set completedAdvancements = (advancements != null) ? new HashSet<>(advancements) : new HashSet<>(); - Iterator advancementIterator = inventories.getServer().advancementIterator(); + Set processedCriteria = new HashSet<>(); + Set completedCriteria = (advancements != null) ? new HashSet<>(advancements) : new HashSet<>(); boolean announceAdvancements = player.getWorld().getGameRuleValue(GameRule.ANNOUNCE_ADVANCEMENTS); - if (announceAdvancements) player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, false); + if (announceAdvancements) { + player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, false); + } + + Iterator advancementIterator = inventories.getServer().advancementIterator(); while (advancementIterator.hasNext()) { Advancement advancement = advancementIterator.next(); - // the set of Advancements to revoke - Set revoke = new HashSet<>(advancement.getCriteria()); - // the set of Advancements to grant - Set intersection = new HashSet<>(advancement.getCriteria()); - - revoke.removeAll(processedAdvancements); - revoke.removeAll(completedAdvancements); - intersection.removeAll(processedAdvancements); - intersection.retainAll(completedAdvancements); - - for (String criteria: revoke) { - processedAdvancements.add(criteria); - completedAdvancements.remove(criteria); - player.getAdvancementProgress(advancement).revokeCriteria(criteria); - } - for (String criteria: intersection) { - processedAdvancements.add(criteria); - completedAdvancements.remove(criteria); - player.getAdvancementProgress(advancement).awardCriteria(criteria); + + for (String criteria : advancement.getCriteria()) { + if (processedCriteria.contains(criteria)) { + continue; + } else if (completedCriteria.contains(criteria)) { + player.getAdvancementProgress(advancement).awardCriteria(criteria); + } else { + player.getAdvancementProgress(advancement).revokeCriteria(criteria); + } + + processedCriteria.add(criteria); } + } - // here's the idea: revoke all (criteria \ completedAdvancements), grant (criteria intersect completedAdvancements) - // also, we don't need to grant/revoke anything in processedAdvancements since they've already been granted/revoked! + if (announceAdvancements) { + player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, true); } - if (announceAdvancements) player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, true); + return advancements != null; } }).defaultSerializer(new ProfileEntry(false, "advancements")).altName("achievements").build(); @@ -661,9 +657,12 @@ public void updateProfile(PlayerProfile profile, Player player) { if (stat.getType() == Statistic.Type.UNTYPED) { int val = player.getStatistic(stat); // no need to save values of 0, that's the default! - if (val != 0) playerStats.put(stat.name(), val); + if (val != 0) { + playerStats.put(stat.name(), val); + } } } + profile.set(GAME_STATISTICS, playerStats); } @@ -671,15 +670,22 @@ public void updateProfile(PlayerProfile profile, Player player) { public boolean updatePlayer(Player player, PlayerProfile profile) { Map playerStats = profile.get(GAME_STATISTICS); for (Statistic stat : Statistic.values()) { - if (stat.getType() == Statistic.Type.UNTYPED) player.setStatistic(stat, 0); + if (stat.getType() == Statistic.Type.UNTYPED) { + player.setStatistic(stat, 0); + } } + if (playerStats == null) { return false; } - for (String stringStat : playerStats.keySet()) { - Statistic stat = Statistic.valueOf(stringStat); - if (stat.getType() == Statistic.Type.UNTYPED) player.setStatistic(stat, playerStats.get(stat.name())); + + for (Map.Entry statInfo : playerStats.entrySet()) { + Statistic stat = Statistic.valueOf(statInfo.getKey()); + if (stat.getType() == Statistic.Type.UNTYPED) { + player.setStatistic(stat, statInfo.getValue()); + } } + return true; } }).defaultSerializer(new ProfileEntry(false, "game_statistics")).altName("game_stats").build(); @@ -692,40 +698,43 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { @Override public void updateProfile(PlayerProfile profile, Player player) { Set recipes = new HashSet<>(); + Map> recipesMap = new HashMap<>(); Iterator recipeIterator = inventories.getServer().recipeIterator(); while (recipeIterator.hasNext()) { Recipe recipe = recipeIterator.next(); if (recipe instanceof Keyed) { NamespacedKey key = ((Keyed) recipe).getKey(); - if (player.undiscoverRecipe(key)) recipes.add(key); + if (player.undiscoverRecipe(key)) { + recipes.add(key); + recipesMap.putIfAbsent(key.getNamespace(), new ArrayList<>()); + recipesMap.get(key.getNamespace()).add(key.getKey()); + } } } player.discoverRecipes(recipes); - - Map> recipesMap = new HashMap<>(); - for (NamespacedKey recipe: recipes) { - recipesMap.putIfAbsent(recipe.getNamespace(), new ArrayList<>()); - recipesMap.get(recipe.getNamespace()).add(recipe.getKey()); - } - profile.set(RECIPES, recipesMap); } @Override public boolean updatePlayer(Player player, PlayerProfile profile) { Map> recipes = profile.get(RECIPES); - if (recipes == null) recipes = new HashMap<>(); - Iterator recipeIterator = inventories.getServer().recipeIterator(); + if (recipes == null) { + recipes = new HashMap<>(); + } + Iterator recipeIterator = inventories.getServer().recipeIterator(); while (recipeIterator.hasNext()) { Recipe recipe = recipeIterator.next(); if (recipe instanceof Keyed) { NamespacedKey key = ((Keyed) recipe).getKey(); - if (recipes.containsKey(key.getNamespace()) && recipes.get(key.getNamespace()).contains(key.getKey())) { + List namespace = recipes.get(key.getNamespace()); + if (namespace != null && namespace.contains(key.getKey())) { player.discoverRecipe(key); - } else player.undiscoverRecipe(key); + } else { + player.undiscoverRecipe(key); + } } } From c5702ec0cce1e4490d802b00a2f5b4f579817cd8 Mon Sep 17 00:00:00 2001 From: Kermina Awad Date: Wed, 27 Jan 2021 21:39:03 -0500 Subject: [PATCH 5/6] attempt at fixing xp exploit --- .../com/onarandombox/multiverseinventories/share/Sharables.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java index 7a43de61..f869dd57 100644 --- a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java +++ b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java @@ -615,6 +615,7 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { Set processedCriteria = new HashSet<>(); Set completedCriteria = (advancements != null) ? new HashSet<>(advancements) : new HashSet<>(); + float exp = player.getExp(); boolean announceAdvancements = player.getWorld().getGameRuleValue(GameRule.ANNOUNCE_ADVANCEMENTS); if (announceAdvancements) { player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, false); @@ -637,6 +638,7 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { } } + player.setExp(exp); if (announceAdvancements) { player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, true); } From 0373e9053cbb666bc99534124d2f62d76938e6cc Mon Sep 17 00:00:00 2001 From: Kermina Awad Date: Wed, 27 Jan 2021 22:03:50 -0500 Subject: [PATCH 6/6] another attempt at fixing xp exploit --- .../onarandombox/multiverseinventories/share/Sharables.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java index f869dd57..11e4cf42 100644 --- a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java +++ b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java @@ -615,7 +615,10 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { Set processedCriteria = new HashSet<>(); Set completedCriteria = (advancements != null) ? new HashSet<>(advancements) : new HashSet<>(); + int totalExperience = player.getTotalExperience(); + int level = player.getLevel(); float exp = player.getExp(); + boolean announceAdvancements = player.getWorld().getGameRuleValue(GameRule.ANNOUNCE_ADVANCEMENTS); if (announceAdvancements) { player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, false); @@ -639,6 +642,9 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { } player.setExp(exp); + player.setLevel(level); + player.setTotalExperience(totalExperience); + if (announceAdvancements) { player.getWorld().setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, true); }