From 34ebb48619602960e14804a2f8ec03eff6cdf276 Mon Sep 17 00:00:00 2001 From: bconlon Date: Mon, 8 May 2023 01:25:47 -0700 Subject: [PATCH] refactor!: Rewrite internal user system --- .../com/aetherteam/nitrogen/Nitrogen.java | 26 ++- .../nitrogen/api/users/Booster.java | 8 - .../aetherteam/nitrogen/api/users/Donor.java | 51 ------ .../aetherteam/nitrogen/api/users/Patron.java | 80 --------- .../aetherteam/nitrogen/api/users/Ranked.java | 69 ------- .../aetherteam/nitrogen/api/users/Role.java | 18 -- .../aetherteam/nitrogen/api/users/User.java | 169 +++++++++++------- .../nitrogen/api/users/UserData.java | 97 +++++++++- .../nitrogen/api/users/UserSavedData.java | 92 ++++++++++ 9 files changed, 303 insertions(+), 307 deletions(-) delete mode 100644 src/main/java/com/aetherteam/nitrogen/api/users/Booster.java delete mode 100644 src/main/java/com/aetherteam/nitrogen/api/users/Donor.java delete mode 100644 src/main/java/com/aetherteam/nitrogen/api/users/Patron.java delete mode 100644 src/main/java/com/aetherteam/nitrogen/api/users/Ranked.java delete mode 100644 src/main/java/com/aetherteam/nitrogen/api/users/Role.java create mode 100644 src/main/java/com/aetherteam/nitrogen/api/users/UserSavedData.java diff --git a/src/main/java/com/aetherteam/nitrogen/Nitrogen.java b/src/main/java/com/aetherteam/nitrogen/Nitrogen.java index a42e506..427c752 100644 --- a/src/main/java/com/aetherteam/nitrogen/Nitrogen.java +++ b/src/main/java/com/aetherteam/nitrogen/Nitrogen.java @@ -10,9 +10,10 @@ import net.minecraft.data.DataGenerator; import net.minecraft.data.PackOutput; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; import net.minecraftforge.data.event.GatherDataEvent; import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.event.server.ServerAboutToStartEvent; +import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @@ -51,20 +52,27 @@ public void dataSetup(GatherDataEvent event) { generator.addProvider(event.includeClient(), new NitrogenLanguageData(packOutput)); } + @SubscribeEvent + public static void serverAboutToStart(ServerStartingEvent event) { + UserData.Server.initializeFromCache(event.getServer()); + } + @SubscribeEvent public static void playerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { - if (event.getEntity() instanceof ServerPlayer serverPlayer) { - UUID uuid = serverPlayer.getUUID(); + Player player = event.getEntity(); + if (player instanceof ServerPlayer serverPlayer) { + UUID uuid = serverPlayer.getGameProfile().getId(); Map userData = UserData.Server.getStoredUsers(); + User user; if (userData.containsKey(uuid)) { - User user = userData.get(uuid); + user = userData.get(uuid); + } else { + user = UserData.Server.queryUser(serverPlayer.getServer(), uuid); + } + //todo timestamp check + if (user != null) { PacketDistributor.sendToPlayer(NitrogenPacketHandler.INSTANCE, new UpdateUserInfoPacket(user), serverPlayer); } } } - - @SubscribeEvent - public static void serverAboutToStart(ServerAboutToStartEvent event) { - UserData.Server.initializeForTesting(); - } } diff --git a/src/main/java/com/aetherteam/nitrogen/api/users/Booster.java b/src/main/java/com/aetherteam/nitrogen/api/users/Booster.java deleted file mode 100644 index 36a812f..0000000 --- a/src/main/java/com/aetherteam/nitrogen/api/users/Booster.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.aetherteam.nitrogen.api.users; - -public class Booster implements Role { - @Override - public Type getType() { - return Type.BOOSTER; - } -} diff --git a/src/main/java/com/aetherteam/nitrogen/api/users/Donor.java b/src/main/java/com/aetherteam/nitrogen/api/users/Donor.java deleted file mode 100644 index 8894521..0000000 --- a/src/main/java/com/aetherteam/nitrogen/api/users/Donor.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.aetherteam.nitrogen.api.users; - -import net.minecraft.network.FriendlyByteBuf; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class Donor implements Role { - private List lifetimeSkins; - - protected Donor(List lifetimeSkins) { - this.lifetimeSkins = lifetimeSkins; - } - - protected Donor(String... lifetimeSkins) { - this(List.of(lifetimeSkins)); - } - - public List getLifetimeSkins() { - return this.lifetimeSkins; - } - - protected void addLifetimeSkins(String... skins) { - this.getLifetimeSkins().addAll(List.of(skins)); - } - - protected void addLifetimeSkin(String skin) { - this.getLifetimeSkins().add(skin); - } - - protected void finalizeLifetimeSkins() { - this.lifetimeSkins = Collections.unmodifiableList(this.lifetimeSkins); - } - - public static Role read(FriendlyByteBuf buffer) { - List lifetimeSkins = buffer.readCollection(ArrayList::new, FriendlyByteBuf::readUtf); - return new Donor(lifetimeSkins); - } - - @Override - public void write(FriendlyByteBuf buffer) { - Role.super.write(buffer); - buffer.writeCollection(this.getLifetimeSkins(), FriendlyByteBuf::writeUtf); - } - - @Override - public Type getType() { - return Type.DONOR; - } -} diff --git a/src/main/java/com/aetherteam/nitrogen/api/users/Patron.java b/src/main/java/com/aetherteam/nitrogen/api/users/Patron.java deleted file mode 100644 index fb9d9a3..0000000 --- a/src/main/java/com/aetherteam/nitrogen/api/users/Patron.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.aetherteam.nitrogen.api.users; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; - -import java.util.ArrayList; -import java.util.List; - -public class Patron extends Donor { - private boolean pledging; - private Tier tier; - - protected Patron(boolean pledging, Tier tier, List lifetimeSkins) { - super(lifetimeSkins); - this.pledging = pledging; - this.tier = tier; - } - - protected Patron(boolean pledging, Tier tier, String... lifetimeSkins) { - this(pledging, tier, List.of(lifetimeSkins)); - } - - public boolean isPledging() { - return this.pledging; - } - - protected void updatePledging(boolean pledging) { - this.pledging = pledging; - } - - public Tier getTier() { - return this.tier; - } - - protected void updateTier(Tier tier) { - this.tier = tier; - } - - public static Role read(FriendlyByteBuf buffer) { - List lifetimeSkins = buffer.readCollection(ArrayList::new, FriendlyByteBuf::readUtf); - boolean pledging = buffer.readBoolean(); - Tier tier = Tier.valueOf(buffer.readUtf()); - return new Patron(pledging, tier, lifetimeSkins); - } - - @Override - public void write(FriendlyByteBuf buffer) { - super.write(buffer); - buffer.writeBoolean(this.isPledging()); - buffer.writeUtf(this.getTier().name()); - } - - @Override - public Type getType() { - return Type.PATRON; - } - - public enum Tier { - HUMAN(0, Component.translatable("nitrogen.patreon.tier.human")), - ASCENTAN(1, Component.translatable("nitrogen.patreon.tier.ascentan")), - VALKYRIE(2, Component.translatable("nitrogen.patreon.tier.valkyrie")), - ARKENZUS(3, Component.translatable("nitrogen.patreon.tier.arkenzus")); - - private final int level; - private final Component displayName; - - Tier(int level, Component displayName) { - this.level = level; - this.displayName = displayName; - } - - public int getLevel() { - return this.level; - } - - public Component getDisplayName() { - return this.displayName; - } - } -} diff --git a/src/main/java/com/aetherteam/nitrogen/api/users/Ranked.java b/src/main/java/com/aetherteam/nitrogen/api/users/Ranked.java deleted file mode 100644 index a1bed47..0000000 --- a/src/main/java/com/aetherteam/nitrogen/api/users/Ranked.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.aetherteam.nitrogen.api.users; - -import net.minecraft.network.FriendlyByteBuf; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class Ranked implements Role { - private List ranks = new ArrayList<>(); - - protected Ranked(List ranks) { - this.ranks.addAll(ranks); - } - - protected Ranked(Rank... ranks) { - this(List.of(ranks)); - } - - public List getRanks() { - return this.ranks; - } - - protected void addRanks(Rank... ranks) { - this.getRanks().addAll(List.of(ranks)); - } - - protected void addRank(Rank rank) { - this.getRanks().add(rank); - } - - protected void finalizeRanks() { - this.ranks = Collections.unmodifiableList(this.ranks); - } - - public static Role read(FriendlyByteBuf buffer) { - List ranks = buffer.readCollection(ArrayList::new, Rank::read); - return new Ranked(ranks); - } - - @Override - public void write(FriendlyByteBuf buffer) { - Role.super.write(buffer); - buffer.writeCollection(this.getRanks(), Rank::write); - } - - @Override - public Type getType() { - return Type.RANKED; - } - - public enum Rank { - THE_AETHER_TEAM, - MODDING_LEGACY, - CONTRIBUTOR, - LEGACY_CONTRIBUTOR, - STAFF, - CELEBRITY, - TRANSLATOR; - - private static Rank read(FriendlyByteBuf buffer) { - return Rank.valueOf(buffer.readUtf()); - } - - private static void write(FriendlyByteBuf buffer, Rank rank) { - buffer.writeUtf(rank.name()); - } - } -} diff --git a/src/main/java/com/aetherteam/nitrogen/api/users/Role.java b/src/main/java/com/aetherteam/nitrogen/api/users/Role.java deleted file mode 100644 index 36c2427..0000000 --- a/src/main/java/com/aetherteam/nitrogen/api/users/Role.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.aetherteam.nitrogen.api.users; - -import net.minecraft.network.FriendlyByteBuf; - -interface Role { - default void write(FriendlyByteBuf buffer) { - buffer.writeUtf(this.getType().name()); - } - - Type getType(); - - enum Type { - BOOSTER, - DONOR, - PATRON, - RANKED - } -} \ No newline at end of file diff --git a/src/main/java/com/aetherteam/nitrogen/api/users/User.java b/src/main/java/com/aetherteam/nitrogen/api/users/User.java index 2b2ee18..e6d8249 100644 --- a/src/main/java/com/aetherteam/nitrogen/api/users/User.java +++ b/src/main/java/com/aetherteam/nitrogen/api/users/User.java @@ -1,103 +1,144 @@ package com.aetherteam.nitrogen.api.users; import net.minecraft.network.FriendlyByteBuf; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; +import net.minecraft.network.chat.Component; public class User { - private final List roles = new ArrayList<>(); - - protected User() { } + private Tier highestPastTier; + private Tier currentTier; + private String renewalDate; + private Group highestGroup; - public List getRoles() { - return this.roles; + protected User(Tier highestPastTier, Tier currentTier, String renewalDate, Group highestGroup) { + this.highestPastTier = highestPastTier; + this.currentTier = currentTier; + this.renewalDate = renewalDate; + this.highestGroup = highestGroup; } - protected void addRoles(Role... roles) { - for (Role role : roles) { - if (!this.isRole(role.getType())) { // Makes sure this User doesn't already have a role. - this.getRoles().add(role); - } - } + public Tier getHighestPastTier() { + return this.highestPastTier; } - protected void addRole(Role role) { - if (!this.isRole(role.getType())) { // Makes sure this User doesn't already have a role. - this.getRoles().add(role); - } + protected void updateHighestPastTier(Tier highestPastTier) { + this.highestPastTier = currentTier; } - public boolean hasRank(Ranked.Rank rank) { - return this.getRoles().stream().anyMatch((role) -> role.getType() == Role.Type.RANKED && ((Ranked) role).getRanks().contains(rank)); + public int getHighestPastTierLevel() { + Tier tier = this.getHighestPastTier(); + return tier != null ? tier.getLevel() : 0; } - public boolean isPatron() { - return this.isRole(Role.Type.PATRON); + public Tier getCurrentTier() { + return this.currentTier; } - public boolean isPledging() { - return this.getRoles().stream().anyMatch((role) -> role.getType() == Role.Type.PATRON && ((Patron) role).isPledging()); + protected void updateCurrentTier(Tier currentTier) { + this.currentTier = currentTier; } - public boolean hasPatreonTier(Patron.Tier tier) { - return this.getRoles().stream().anyMatch((role) -> role.getType() == Role.Type.PATRON && ((Patron) role).getTier() == tier); + public int getCurrentTierLevel() { + Tier tier = this.getCurrentTier(); + return tier != null ? tier.getLevel() : 0; } - public Patron.Tier getPatreonTier() { - Optional roleOptional = this.getRoles().stream().filter((role) -> role.getType() == Role.Type.PATRON).findFirst(); - return roleOptional.map(roleValue -> ((Patron) roleValue).getTier()).orElse(null); + public String getRenewalDate() { + return this.renewalDate; } - public int getPatronTierLevel() { - Patron.Tier tier = this.getPatreonTier(); - return tier != null ? tier.getLevel() : 0; + protected void updateRenewalDate(String renewalDate) { + this.renewalDate = renewalDate; } - public boolean isDonor() { - return this.isRole(Role.Type.DONOR); + public Group getHighestGroup() { + return this.highestGroup; } - public List getLifetimeSkins() { - List skins = new ArrayList<>(); - this.getRoles().stream().filter((role) -> role instanceof Donor).forEach((role) -> skins.addAll(((Donor) role).getLifetimeSkins())); - return skins; + protected void updateHighestGroup(Group highestGroup) { + this.highestGroup = highestGroup; } - public boolean hasLifetimeSkin(String skin) { - return this.getRoles().stream().anyMatch((role) -> role instanceof Donor donor && donor.getLifetimeSkins().contains(skin)); + public static User read(FriendlyByteBuf buffer) { + Tier highestPastTier = Tier.valueOf(buffer.readUtf()); + Tier currentTier = Tier.valueOf(buffer.readUtf()); + String renewalDate = buffer.readUtf(); + Group highestGroup = Group.valueOf(buffer.readUtf()); + return new User(highestPastTier, currentTier, renewalDate, highestGroup); } - public boolean isBooster() { - return this.isRole(Role.Type.BOOSTER); - } + public static void write(FriendlyByteBuf buffer, User user) { + buffer.writeUtf(user.getHighestPastTier().name()); + buffer.writeUtf(user.getCurrentTier().name()); + buffer.writeUtf(user.getRenewalDate()); + buffer.writeUtf(user.getHighestGroup().name()); + } + + public enum Tier { + HUMAN(0, 2429462, Component.translatable("nitrogen.patreon.tier.human")), + ASCENTAN(1, 616325, Component.translatable("nitrogen.patreon.tier.ascentan")), + VALKYRIE(2, 616326, Component.translatable("nitrogen.patreon.tier.valkyrie")), + ARKENZUS(3, 616327, Component.translatable("nitrogen.patreon.tier.arkenzus")); + + private final int level; + private final int id; + private final Component displayName; + + Tier(int level, int id, Component displayName) { + this.level = level; + this.id = id; + this.displayName = displayName; + } - public boolean isRole(Role.Type type) { - return this.getRoles().stream().anyMatch(role -> role.getType() == type); - } + public int getLevel() { + return this.level; + } - public static User read(FriendlyByteBuf buffer) { - User user = new User(); - int size = buffer.readInt(); - for (int i = 0; i < size; i++) { - String name = buffer.readUtf(); - Role.Type type = Role.Type.valueOf(name); - switch(type) { - case BOOSTER -> user.addRole(new Booster()); - case DONOR -> user.addRole(Donor.read(buffer)); - case PATRON -> user.addRole(Patron.read(buffer)); - case RANKED -> user.addRole(Ranked.read(buffer)); + public int getId() { + return this.id; + } + + public Component getDisplayName() { + return this.displayName; + } + + public static Tier byId(int id) { + switch(id) { + case 2429462 -> { + return HUMAN; + } + case 616325 -> { + return ASCENTAN; + } + case 616326 -> { + return VALKYRIE; + } + case 616327 -> { + return ARKENZUS; + } + default -> { + return null; + } } } - return user; } - public static void write(FriendlyByteBuf buffer, User user) { - List roles = user.getRoles(); - buffer.writeInt(roles.size()); - for (Role role : roles) { - role.write(buffer); + public enum Group { + AETHER_TEAM(7), + MODDING_LEGACY(6), + CONTRIBUTOR(5), + LEGACY_CONTRIBUTOR(4), + STAFF(3), + CELEBRITY(2), + TRANSLATOR(1); + + private final int level; + + Group(int level) { + this.level = level; + } + + public int getLevel() { + return this.level; } } } diff --git a/src/main/java/com/aetherteam/nitrogen/api/users/UserData.java b/src/main/java/com/aetherteam/nitrogen/api/users/UserData.java index 389b0b9..48fa4e3 100644 --- a/src/main/java/com/aetherteam/nitrogen/api/users/UserData.java +++ b/src/main/java/com/aetherteam/nitrogen/api/users/UserData.java @@ -1,7 +1,18 @@ package com.aetherteam.nitrogen.api.users; +import com.aetherteam.nitrogen.Nitrogen; import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import net.minecraft.server.MinecraftServer; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; import java.util.*; public class UserData { @@ -20,19 +31,89 @@ public static void setClientUser(User clientUser) { public static class Server { private static final Map STORED_USERS = new HashMap<>(); - public static void initializeForTesting() { - User user1 = new User(); - user1.addRole(new Ranked(Ranked.Rank.THE_AETHER_TEAM)); - STORED_USERS.put(UUID.fromString("380df991-f603-344c-a090-369bad2a924a"), user1); + public static void initializeFromCache(MinecraftServer server) { + STORED_USERS.putAll(getSavedMap(server)); + } + + public static User queryUser(MinecraftServer server, UUID uuid) { + try { + Nitrogen.LOGGER.info(String.valueOf(uuid)); + + URL url = new URL("https://www.aether-mod.net/api/verify/" + uuid); + URLConnection connection = url.openConnection(); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String query = reader.readLine(); + reader.close(); + + Nitrogen.LOGGER.info(query); + + JsonElement jsonElement = JsonParser.parseString(query); + if (jsonElement != null) { + JsonObject json = jsonElement.getAsJsonObject(); + + int currentTierId = json.get("currentTier").getAsInt(); + User.Tier currentTier = null; + if (currentTierId != -1) { + currentTier = User.Tier.byId(currentTierId); + } + + JsonArray pastTiersArray = json.getAsJsonArray("pastTiers"); + User.Tier highestPastTier = null; + int pastTierLevel = 0; + for (int pastTierId : pastTiersArray.asList().stream().map((JsonElement::getAsInt)).toList()) { + if (pastTierId != -1) { + User.Tier pastTier = User.Tier.byId(pastTierId); + if (pastTier != null) { + if (pastTier.getLevel() > pastTierLevel) { + pastTierLevel = pastTier.getLevel(); + highestPastTier = pastTier; + } + } + } + } + + String renewalDate = json.get("renewsAt").getAsString(); + + JsonArray groupsArray = json.getAsJsonArray("groups"); + User.Group highestGroup = null; + int groupLevel = 0; + for (String groupName : groupsArray.asList().stream().map((JsonElement::getAsString)).toList()) { + User.Group group = User.Group.valueOf(groupName.toUpperCase(Locale.ROOT)); + if (group.getLevel() > groupLevel) { + groupLevel = group.getLevel(); + highestGroup = group; + } + } - User user2 = new User(); - Donor donor = new Donor("blue_moa", "natural_moa_skins", "lifetime_angel_moa_skins"); - user2.addRole(donor); - STORED_USERS.put(UUID.fromString("58a5d694-a8a6-4605-ab33-d6904107ad5f"), user2); + User user = new User(currentTier, highestPastTier, renewalDate, highestGroup); + modifySavedData(server, uuid, user); + STORED_USERS.put(uuid, user); + return user; + } + } catch (IOException e) { + Nitrogen.LOGGER.info(e.getMessage()); + } + return null; } public static Map getStoredUsers() { return ImmutableMap.copyOf(STORED_USERS); } } + + protected static Map getSavedMap(MinecraftServer server) { + return getSavedData(server).getStoredUsers(); + } + + protected static void modifySavedData(MinecraftServer server, UUID uuid, User user) { + getSavedData(server).modifyStoredUsers(uuid, user); + } + + protected static void removeSavedData(MinecraftServer server, UUID uuid) { + getSavedData(server).removeStoredUsers(uuid); + } + + protected static UserSavedData getSavedData(MinecraftServer server) { + return UserSavedData.compute(server.overworld().getDataStorage()); + } } diff --git a/src/main/java/com/aetherteam/nitrogen/api/users/UserSavedData.java b/src/main/java/com/aetherteam/nitrogen/api/users/UserSavedData.java new file mode 100644 index 0000000..127d4a7 --- /dev/null +++ b/src/main/java/com/aetherteam/nitrogen/api/users/UserSavedData.java @@ -0,0 +1,92 @@ +package com.aetherteam.nitrogen.api.users; + +import com.google.common.collect.ImmutableMap; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.saveddata.SavedData; +import net.minecraft.world.level.storage.DimensionDataStorage; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class UserSavedData extends SavedData { + public static final String FILE_NAME = "users"; + private final Map storedUsers = new HashMap<>(); + + @Override + public CompoundTag save(CompoundTag tag) { + CompoundTag storedUsersTag = new CompoundTag(); + for (Map.Entry userEntry : this.storedUsers.entrySet()) { + CompoundTag userEntryTag = new CompoundTag(); + User user = userEntry.getValue(); + if (user.getHighestPastTier() != null) { + userEntryTag.putString("HighestPastTier", user.getHighestPastTier().name()); + } + if (user.getCurrentTier() != null) { + userEntryTag.putString("CurrentTier", user.getCurrentTier().name()); + } + if (user.getRenewalDate() != null) { + userEntryTag.putString("RenewalDate", user.getRenewalDate()); + } + if (user.getHighestGroup() != null) { + userEntryTag.putString("HighestGroup", user.getHighestGroup().name()); + } + storedUsersTag.put(userEntry.getKey().toString(), userEntryTag); + } + tag.put("StoredUsers", storedUsersTag); + return tag; + } + + public static UserSavedData load(CompoundTag tag) { + UserSavedData data = UserSavedData.create(); + for (String key : tag.getAllKeys()) { + if (key.equals("StoredUsers")) { + CompoundTag storedUsersTag = tag.getCompound(key); + for (String storedUsersKey : storedUsersTag.getAllKeys()) { + CompoundTag userEntryTag = storedUsersTag.getCompound(storedUsersKey); + UUID uuid = UUID.fromString(storedUsersKey); + User.Tier highestPastTier = null; + User.Tier currentTier = null; + String renewalDate = null; + User.Group highestGroup = null; + if (userEntryTag.contains("HighestPastTier")) { + highestPastTier = User.Tier.valueOf(userEntryTag.getString("HighestPastTier")); + } + if (userEntryTag.contains("CurrentTier")) { + currentTier = User.Tier.valueOf(userEntryTag.getString("CurrentTier")); + } + if (userEntryTag.contains("RenewalDate")) { + renewalDate = userEntryTag.getString("RenewalDate"); + } + if (userEntryTag.contains("HighestGroup")) { + highestGroup = User.Group.valueOf(userEntryTag.getString("HighestGroup")); + } + data.storedUsers.put(uuid, new User(highestPastTier, currentTier, renewalDate, highestGroup)); + } + } + } + return data; + } + + public static UserSavedData create() { + return new UserSavedData(); + } + + public static UserSavedData compute(DimensionDataStorage dataStorage) { + return dataStorage.computeIfAbsent(UserSavedData::load, UserSavedData::create, FILE_NAME); + } + + Map getStoredUsers() { + return ImmutableMap.copyOf(this.storedUsers); + } + + void modifyStoredUsers(UUID uuid, User user) { + this.storedUsers.put(uuid, user); + this.setDirty(); + } + + void removeStoredUsers(UUID uuid) { + this.storedUsers.remove(uuid); + this.setDirty(); + } +}