From 5f778862879c7e63663f8bfc6d70d97e352f85ed Mon Sep 17 00:00:00 2001 From: Kermina Awad Date: Wed, 13 May 2020 19:35:55 -0400 Subject: [PATCH] add advancement and game stats sharables --- .../share/SharableSerializer.java | 10 +- .../share/Sharables.java | 106 ++++++++++-------- .../share/StringArraySerializer.java | 24 ++++ 3 files changed, 88 insertions(+), 52 deletions(-) create mode 100644 src/main/java/com/onarandombox/multiverseinventories/share/StringArraySerializer.java diff --git a/src/main/java/com/onarandombox/multiverseinventories/share/SharableSerializer.java b/src/main/java/com/onarandombox/multiverseinventories/share/SharableSerializer.java index d3488fd9..86c34d11 100644 --- a/src/main/java/com/onarandombox/multiverseinventories/share/SharableSerializer.java +++ b/src/main/java/com/onarandombox/multiverseinventories/share/SharableSerializer.java @@ -8,8 +8,8 @@ public interface SharableSerializer { /** - * This deserializes the data for a Sharable. You must be expecting the type of data coming in in order to process - * this. That type will generally be the type that this serializes as with {@link #serialize(Object)}. + * This deserializes the data for a Sharable. You must be expecting the type of data coming in in order to process + * this. That type will generally be the type that this serializes as with {@link #serialize(Object)}. * * @param obj The incoming (serialized) data to be deserialized. * @return The data represented by the Sharable this object represents in deserialized form. @@ -17,9 +17,9 @@ public interface SharableSerializer { T deserialize(Object obj); /** - * This serializes the data for a Sharable. The output is an Object but what you return is up to you, however, - * this is limited by the constraints of the persistence method. Generally, returning a String is the safest way - * to serialize your data. Most boxed primitives are accepted as well as Lists of boxed primitives and + * This serializes the data for a Sharable. The output is an Object but what you return is up to you, however, + * this is limited by the constraints of the persistence method. Generally, returning a String is the safest way + * to serialize your data. Most boxed primitives are accepted as well as Lists of boxed primitives and * Map. * * @param t The value of the data represented by the Sharable. diff --git a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java index 4f071382..3a177526 100644 --- a/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java +++ b/src/main/java/com/onarandombox/multiverseinventories/share/Sharables.java @@ -680,8 +680,8 @@ public static void setPlayerSpawnLocation(Player player, Location spawnLocation) /** * Sharing Advancements. */ - public static final Sharable ADVANCEMENTS = new Sharable.Builder("advancements", HashSet.class, - new SharableHandler() { + public static final Sharable ADVANCEMENTS = new Sharable.Builder("advancements", String[].class, + new SharableHandler() { @Override public void updateProfile(PlayerProfile profile, Player player) { HashSet completedAdvancements = new HashSet<>(); @@ -693,13 +693,14 @@ public void updateProfile(PlayerProfile profile, Player player) { completedAdvancements.addAll(awardedCriteria); } - profile.set(ADVANCEMENTS, completedAdvancements); + profile.set(ADVANCEMENTS, completedAdvancements.toArray(new String[completedAdvancements.size()])); } @Override public boolean updatePlayer(Player player, PlayerProfile profile) { - HashSet completedAdvancements = profile.get(ADVANCEMENTS); - completedAdvancements = (completedAdvancements != null) ? completedAdvancements : new HashSet<>(); + String[] advancements = profile.get(ADVANCEMENTS); + HashSet processedAdvancements = new HashSet<>(); + HashSet completedAdvancements = (advancements != null) ? new HashSet<>(Arrays.asList(advancements)) : new HashSet<>(); Iterator advancementIterator = inventories.getServer().advancementIterator(); while (advancementIterator.hasNext()) { @@ -709,53 +710,64 @@ public boolean updatePlayer(Player player, PlayerProfile profile) { // the set of Advancements to grant Set intersection = new HashSet<>(advancement.getCriteria()); + revoke.removeAll(processedAdvancements); revoke.removeAll(completedAdvancements); + intersection.removeAll(processedAdvancements); intersection.retainAll(completedAdvancements); - // completedAdvancements.removeAll(intersection); - // above line was an attempt at efficiency - for (String criteria: revoke) player.getAdvancementProgress(advancement).revokeCriteria(criteria); - for (String criteria: intersection) player.getAdvancementProgress(advancement).awardCriteria(criteria); + 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! + } + return advancements != null; + } + }).serializer(new ProfileEntry(false, "advancements"), new StringArraySerializer()) + .altName("achievements").build(); - // here's the idea: revoke all (criteria - completedAdvancements), grant (criteria intersect completedAdvancements) + /** + * Sharing Statistics. + */ + public static final Sharable GAME_STATISTICS = new Sharable.Builder("game_statistics", HashMap.class, + new SharableHandler() { + @Override + public void updateProfile(PlayerProfile profile, Player player) { + HashMap 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); + } } - return !completedAdvancements.isEmpty(); + profile.set(GAME_STATISTICS, playerStats); + } + + @Override + public boolean updatePlayer(Player player, PlayerProfile profile) { + HashMap 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, "advancements")).altName("achievements").build(); - -// /** -// * Sharing Statistics. -// */ -// public static final Sharable GAME_STATISTICS = new Sharable.Builder("game_statistics", HashMap.class, -// new SharableHandler() { -// @Override -// public void updateProfile(PlayerProfile profile, Player player) { -// HashMap playerStats = new HashMap<>(); -// for (Statistic stat: Statistic.values()) { -// if (stat.getType() == Statistic.Type.UNTYPED) { -// int val = player.getStatistic(stat); -// if (val != 0) playerStats.put(stat.name(), val); -// } -// } -// profile.set(GAME_STATISTICS, playerStats); -// } -// -// @Override -// public boolean updatePlayer(Player player, PlayerProfile profile) { -// HashMap 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(); + }).defaultSerializer(new ProfileEntry(false, "game_statistics")).altName("game_stats").build(); /** * Grouping for inventory sharables. @@ -801,7 +813,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"); diff --git a/src/main/java/com/onarandombox/multiverseinventories/share/StringArraySerializer.java b/src/main/java/com/onarandombox/multiverseinventories/share/StringArraySerializer.java new file mode 100644 index 00000000..b71d58d3 --- /dev/null +++ b/src/main/java/com/onarandombox/multiverseinventories/share/StringArraySerializer.java @@ -0,0 +1,24 @@ +package com.onarandombox.multiverseinventories.share; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class StringArraySerializer implements SharableSerializer { + @Override + public String[] deserialize(Object obj) { + List list = (List) obj; + List resultList = new ArrayList<>(list.size()); + for (Object o : list) { + if (o instanceof String) { + resultList.add((String) o); + } + } + return resultList.toArray(new String[resultList.size()]); + } + + @Override + public Object serialize(String[] strings) { + return Arrays.asList(strings); + } +}