diff --git a/api/build.gradle.kts b/api/build.gradle.kts index b3c2762..29ce62f 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -23,6 +23,8 @@ dependencies { compileOnly("io.netty:netty-all:4.1.113.Final") // GSON compileOnly("com.google.code.gson:gson:${rootProject.properties["gson_version"]}") + // Fast util + compileOnly("it.unimi.dsi:fastutil:${rootProject.properties["fastutil_version"]}") } java { diff --git a/api/src/main/java/net/momirealms/customnameplates/api/AbstractCNPlayer.java b/api/src/main/java/net/momirealms/customnameplates/api/AbstractCNPlayer.java index cc9b47f..3538708 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/AbstractCNPlayer.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/AbstractCNPlayer.java @@ -18,6 +18,11 @@ package net.momirealms.customnameplates.api; import io.netty.channel.Channel; +import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenCustomHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.momirealms.customnameplates.api.feature.Feature; import net.momirealms.customnameplates.api.feature.TimeStampData; import net.momirealms.customnameplates.api.feature.tag.TeamView; @@ -51,11 +56,11 @@ public abstract class AbstractCNPlayer implements CNPlayer { private final TeamView teamView = new TeamView(); - private final Map> cachedValues = new ConcurrentHashMap<>(); - private final Map>> cachedRelationalValues = new ConcurrentHashMap<>(); + private final Int2ObjectOpenHashMap> cachedValues = new Int2ObjectOpenHashMap<>(64); + private final Int2ObjectOpenHashMap>> cachedRelationalValues = new Int2ObjectOpenHashMap<>(64); - private final Map> cachedRequirements = new ConcurrentHashMap<>(); - private final Map>> cachedRelationalRequirements = new ConcurrentHashMap<>(); + private final Int2ObjectOpenHashMap> cachedRequirements = new Int2ObjectOpenHashMap<>(128); + private final Int2ObjectOpenHashMap>> cachedRelationalRequirements = new Int2ObjectOpenHashMap<>(128); private final Set activeFeatures = new CopyOnWriteArraySet<>(); private final Map> placeholder2Features = new ConcurrentHashMap<>(); @@ -71,7 +76,7 @@ public abstract class AbstractCNPlayer implements CNPlayer { @Override public List activePlaceholdersToRefresh() { Placeholder[] activePlaceholders = activePlaceholders(); - List placeholderWithChildren = new ArrayList<>(); + List placeholderWithChildren = new ObjectArrayList<>(); for (Placeholder placeholder : activePlaceholders) { childrenFirstList(placeholder, placeholderWithChildren); } @@ -79,9 +84,9 @@ public abstract class AbstractCNPlayer implements CNPlayer { } @Override - public void forceUpdatePlaceholders(Set placeholders, Set others) { + public void forceUpdatePlaceholders(Set placeholders, Collection others) { if (placeholders.isEmpty()) return; - List placeholderWithChildren = new ArrayList<>(); + List placeholderWithChildren = new ObjectArrayList<>(); for (Placeholder placeholder : placeholders) { childrenFirstList(placeholder, placeholderWithChildren); } @@ -224,7 +229,7 @@ public abstract class AbstractCNPlayer implements CNPlayer { Set allPlaceholders = feature.allPlaceholders(); feature2Placeholders.put(feature, allPlaceholders); for (Placeholder placeholder : allPlaceholders) { - Set featureSet = placeholder2Features.computeIfAbsent(placeholder, k -> new HashSet<>()); + Set featureSet = placeholder2Features.computeIfAbsent(placeholder, k -> new ObjectOpenHashSet<>()); featureSet.add(feature); } } @@ -330,7 +335,7 @@ public abstract class AbstractCNPlayer implements CNPlayer { @Override public Placeholder[] activePlaceholders() { - HashSet placeholders = new HashSet<>(); + Set placeholders = new ObjectOpenHashSet<>(); for (Feature feature : activeFeatures) { placeholders.addAll(feature.activePlaceholders()); } @@ -341,7 +346,7 @@ public abstract class AbstractCNPlayer implements CNPlayer { public boolean isMet(Requirement[] requirements) { int currentTicks = MainTask.getTicks(); for (Requirement requirement : requirements) { - TimeStampData data = cachedRequirements.get(requirement); + TimeStampData data = cachedRequirements.get(requirement.countId()); if (data != null) { if (data.ticks() + requirement.refreshInterval() > currentTicks) { if (!data.data()) { @@ -358,7 +363,7 @@ public abstract class AbstractCNPlayer implements CNPlayer { } else { boolean satisfied = requirement.isSatisfied(this, this); data = new TimeStampData<>(satisfied, currentTicks, true); - cachedRequirements.put(requirement, data); + cachedRequirements.put(requirement.countId(), data); if (!satisfied) { return false; } @@ -371,7 +376,7 @@ public abstract class AbstractCNPlayer implements CNPlayer { public boolean isMet(CNPlayer another, Requirement[] requirements) { int currentTicks = MainTask.getTicks(); for (Requirement requirement : requirements) { - WeakHashMap> innerMap = cachedRelationalRequirements.computeIfAbsent(requirement, k -> new WeakHashMap<>()); + WeakHashMap> innerMap = cachedRelationalRequirements.computeIfAbsent(requirement.countId(), k -> new WeakHashMap<>()); TimeStampData data = innerMap.get(another); if (data != null) { if (data.ticks() + requirement.refreshInterval() > currentTicks) { @@ -421,8 +426,8 @@ public abstract class AbstractCNPlayer implements CNPlayer { } @Override - public Set nearbyPlayers() { - return new HashSet<>(trackers.keySet()); + public Collection nearbyPlayers() { + return new ObjectArrayList<>(trackers.keySet()); } @Override @@ -446,7 +451,7 @@ public abstract class AbstractCNPlayer implements CNPlayer { @Override public Set getTrackedPassengerIds(CNPlayer another) { - return Optional.ofNullable(trackers.get(another)).map(Tracker::getPassengerIDs).orElse(new HashSet<>()); + return Optional.ofNullable(trackers.get(another)).map(Tracker::getPassengerIDs).orElse(new ObjectOpenHashSet<>()); } @Override diff --git a/api/src/main/java/net/momirealms/customnameplates/api/CNPlayer.java b/api/src/main/java/net/momirealms/customnameplates/api/CNPlayer.java index 3159b73..2acf661 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/CNPlayer.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/CNPlayer.java @@ -28,6 +28,7 @@ import net.momirealms.customnameplates.api.util.Vector3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.List; import java.util.Set; import java.util.UUID; @@ -190,7 +191,7 @@ public interface CNPlayer { * @param placeholders the placeholders to update * @param another the players related to the placeholders */ - void forceUpdatePlaceholders(Set placeholders, Set another); + void forceUpdatePlaceholders(Set placeholders, Collection another); /** * Retrieves the cached data for a given placeholder. @@ -317,7 +318,7 @@ public interface CNPlayer { * * @return the set of nearby players */ - Set nearbyPlayers(); + Collection nearbyPlayers(); /** * Adds passenger entities to the tracker for another player. diff --git a/api/src/main/java/net/momirealms/customnameplates/api/CustomNameplates.java b/api/src/main/java/net/momirealms/customnameplates/api/CustomNameplates.java index 9bd5bce..f241640 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/CustomNameplates.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/CustomNameplates.java @@ -17,6 +17,8 @@ package net.momirealms.customnameplates.api; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.momirealms.customnameplates.api.feature.actionbar.ActionBarManager; import net.momirealms.customnameplates.api.feature.advance.AdvanceManager; import net.momirealms.customnameplates.api.feature.background.BackgroundManager; @@ -38,10 +40,7 @@ import net.momirealms.customnameplates.common.locale.TranslationManager; import net.momirealms.customnameplates.common.plugin.NameplatesPlugin; import net.momirealms.customnameplates.common.plugin.scheduler.SchedulerTask; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Supplier; @@ -69,7 +68,7 @@ public abstract class CustomNameplates implements NameplatesPlugin { protected MainTask mainTask; protected SchedulerTask scheduledMainTask; protected ConcurrentHashMap onlinePlayerMap = new ConcurrentHashMap<>(); - protected HashMap entityIDFastLookup = new HashMap<>(); + protected Int2ObjectOpenHashMap entityIDFastLookup = new Int2ObjectOpenHashMap<>(); protected AdvanceManager advanceManager; protected BackgroundManager backgroundManager; protected EventManager eventManager; @@ -288,7 +287,7 @@ public abstract class CustomNameplates implements NameplatesPlugin { * @return a collection of {@link CNPlayer} instances */ public Collection getOnlinePlayers() { - return new HashSet<>(onlinePlayerMap.values()); + return new ObjectArrayList<>(onlinePlayerMap.values()); } /** diff --git a/api/src/main/java/net/momirealms/customnameplates/api/MainTask.java b/api/src/main/java/net/momirealms/customnameplates/api/MainTask.java index 9612792..5183085 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/MainTask.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/MainTask.java @@ -17,6 +17,8 @@ package net.momirealms.customnameplates.api; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import java.util.Collections; import java.util.HashSet; import java.util.Map; @@ -29,7 +31,7 @@ public class MainTask implements Runnable { private static final Map TIME_1 = new ConcurrentHashMap<>(2048); private static final Map TIME_2 = new ConcurrentHashMap<>(2048); - private static final Set requestedSharedPlaceholders = Collections.synchronizedSet(new HashSet<>()); + private static final Set requestedSharedPlaceholders = Collections.synchronizedSet(new ObjectOpenHashSet<>()); private int timer; private final CustomNameplates plugin; diff --git a/api/src/main/java/net/momirealms/customnameplates/api/feature/PreParsedDynamicText.java b/api/src/main/java/net/momirealms/customnameplates/api/feature/PreParsedDynamicText.java index acf34d1..f4c4830 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/feature/PreParsedDynamicText.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/feature/PreParsedDynamicText.java @@ -17,6 +17,8 @@ package net.momirealms.customnameplates.api.feature; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.momirealms.customnameplates.api.CNPlayer; import net.momirealms.customnameplates.api.CustomNameplates; import net.momirealms.customnameplates.api.placeholder.*; @@ -27,8 +29,8 @@ import java.util.function.Function; public class PreParsedDynamicText { private final String text; - private final List>> textFunctions = new ArrayList<>(); - private final Set set = new HashSet<>(); + private final List>> textFunctions = new ObjectArrayList<>(); + private final Set set = new ObjectOpenHashSet<>(); private boolean init = false; public PreParsedDynamicText(String text) { @@ -86,12 +88,12 @@ public class PreParsedDynamicText { String remaining = original0.substring(lastIndex); textFunctions.add((owner) -> (viewer) -> remaining); } - // To optimize the tree height, call new HashSet twice here - set.addAll(new HashSet<>(placeholders)); + // To optimize the tree height + set.addAll(new ObjectArrayList<>(placeholders)); } public DynamicText fastCreate(CNPlayer player) { - List> functions = new ArrayList<>(); + List> functions = new ObjectArrayList<>(); for (Function> textFunction : textFunctions) { functions.add(textFunction.apply(player)); } diff --git a/api/src/main/java/net/momirealms/customnameplates/api/feature/advance/CharacterFontAdvanceDataImpl.java b/api/src/main/java/net/momirealms/customnameplates/api/feature/advance/CharacterFontAdvanceDataImpl.java index b1b4032..0f84a4a 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/feature/advance/CharacterFontAdvanceDataImpl.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/feature/advance/CharacterFontAdvanceDataImpl.java @@ -18,6 +18,7 @@ package net.momirealms.customnameplates.api.feature.advance; import com.google.gson.JsonObject; +import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import java.util.HashMap; import java.util.List; @@ -28,11 +29,11 @@ import static java.util.Objects.requireNonNull; public class CharacterFontAdvanceDataImpl implements CharacterFontAdvanceData { - private final HashMap data; + private final Map data; private final String id; private final Function, List> fontProviderFunction; - public CharacterFontAdvanceDataImpl(String id, HashMap data, Function, List> fontProviderFunction) { + public CharacterFontAdvanceDataImpl(String id, Map data, Function, List> fontProviderFunction) { this.data = data; this.id = requireNonNull(id); this.fontProviderFunction = requireNonNull(fontProviderFunction); @@ -65,7 +66,7 @@ public class CharacterFontAdvanceDataImpl implements CharacterFontAdvanceData { public static class BuilderImpl implements Builder { - private final HashMap data = new HashMap<>(); + private final Int2FloatOpenHashMap data = new Int2FloatOpenHashMap(); private String id; private Function, List> fontProviderFunction = (stringObjectMap -> null); diff --git a/api/src/main/java/net/momirealms/customnameplates/api/feature/advance/ConfigurableFontAdvanceDataImpl.java b/api/src/main/java/net/momirealms/customnameplates/api/feature/advance/ConfigurableFontAdvanceDataImpl.java index d54501d..00c72ff 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/feature/advance/ConfigurableFontAdvanceDataImpl.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/feature/advance/ConfigurableFontAdvanceDataImpl.java @@ -17,18 +17,18 @@ package net.momirealms.customnameplates.api.feature.advance; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; +import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import java.util.*; import static java.util.Objects.requireNonNull; public class ConfigurableFontAdvanceDataImpl implements ConfigurableFontAdvanceData { private final float defaultAdvance; - private final HashMap data = new HashMap<>(); - private final List parents = new ArrayList<>(); + private final Map data = new Int2FloatOpenHashMap(); + private final List parents = new ObjectArrayList<>(); private final String id; public ConfigurableFontAdvanceDataImpl(String id, float defaultAdvance, HashMap customData, List parentFonts) { diff --git a/api/src/main/java/net/momirealms/customnameplates/api/feature/tag/TeamView.java b/api/src/main/java/net/momirealms/customnameplates/api/feature/tag/TeamView.java index 7793107..e7dd590 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/feature/tag/TeamView.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/feature/tag/TeamView.java @@ -17,16 +17,15 @@ package net.momirealms.customnameplates.api.feature.tag; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; +import java.util.*; public class TeamView { - private final HashMap> teamMembers = new HashMap<>(); + private final Map> teamMembers = new Object2ObjectOpenHashMap<>(); @Nullable public Set getTeamMembers(String team) { @@ -34,7 +33,7 @@ public class TeamView { } public void addTeamMembers(String team, Collection members) { - teamMembers.computeIfAbsent(team, k -> new HashSet<>(members)); + teamMembers.computeIfAbsent(team, k -> new ObjectOpenHashSet<>(members)); } public void removeTeamMembers(String team, Collection members) { diff --git a/api/src/main/java/net/momirealms/customnameplates/api/network/Tracker.java b/api/src/main/java/net/momirealms/customnameplates/api/network/Tracker.java index e1a5775..360fd22 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/network/Tracker.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/network/Tracker.java @@ -17,6 +17,7 @@ package net.momirealms.customnameplates.api.network; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.momirealms.customnameplates.api.CNPlayer; import java.util.HashSet; @@ -80,7 +81,7 @@ public class Tracker { } public Set getPassengerIDs() { - return new HashSet<>(passengerIDs); + return new ObjectOpenHashSet<>(passengerIDs); } public boolean isEmpty() { diff --git a/api/src/main/java/net/momirealms/customnameplates/api/placeholder/AbstractPlaceholder.java b/api/src/main/java/net/momirealms/customnameplates/api/placeholder/AbstractPlaceholder.java index 48ff4da..7a70902 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/placeholder/AbstractPlaceholder.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/placeholder/AbstractPlaceholder.java @@ -17,6 +17,7 @@ package net.momirealms.customnameplates.api.placeholder; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.momirealms.customnameplates.api.CustomNameplates; import java.util.HashSet; @@ -29,8 +30,8 @@ public abstract class AbstractPlaceholder implements Placeholder { protected int countId = PlaceholderCounter.getAndIncrease(); protected int refreshInterval; protected PlaceholderManager manager; - protected Set children = new HashSet<>(); - protected Set parents = new HashSet<>(); + protected Set children = new ObjectOpenHashSet<>(); + protected Set parents = new ObjectOpenHashSet<>(); protected AbstractPlaceholder(PlaceholderManager manager, String id, int refreshInterval) { if (refreshInterval == 0) { diff --git a/api/src/main/java/net/momirealms/customnameplates/api/requirement/EmptyRequirement.java b/api/src/main/java/net/momirealms/customnameplates/api/requirement/EmptyRequirement.java index cf06b13..b81b479 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/requirement/EmptyRequirement.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/requirement/EmptyRequirement.java @@ -18,6 +18,7 @@ package net.momirealms.customnameplates.api.requirement; import net.momirealms.customnameplates.api.CNPlayer; +import net.momirealms.customnameplates.api.CustomNameplates; /** * A requirement that is always satisfied, representing an "empty" or default requirement. @@ -57,6 +58,11 @@ public class EmptyRequirement implements Requirement { return "empty"; } + @Override + public int countId() { + return CustomNameplates.getInstance().getRequirementManager().countId(this); + } + /** * Returns -1, indicating that this requirement does not have a refresh interval. * diff --git a/api/src/main/java/net/momirealms/customnameplates/api/requirement/Requirement.java b/api/src/main/java/net/momirealms/customnameplates/api/requirement/Requirement.java index bc9804d..8487a6c 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/requirement/Requirement.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/requirement/Requirement.java @@ -40,6 +40,13 @@ public interface Requirement { */ String type(); + /** + * Returns the int id for faster lookup + * + * @return count id + */ + int countId(); + /** * Returns the refresh interval of the requirement. * diff --git a/api/src/main/java/net/momirealms/customnameplates/api/requirement/RequirementManager.java b/api/src/main/java/net/momirealms/customnameplates/api/requirement/RequirementManager.java index 4dc1344..1863f2d 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/requirement/RequirementManager.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/requirement/RequirementManager.java @@ -87,4 +87,12 @@ public interface RequirementManager extends Reloadable { */ @NotNull Requirement parseSimpleRequirement(@NotNull String type, @NotNull Object value); + + /** + * Gets the count id for the requirement for faster lookup + * + * @param requirement requirement + * @return the id + */ + int countId(Requirement requirement); } diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 7fa4282..25613a3 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -26,4 +26,6 @@ dependencies { // TTF compileOnly("org.lwjgl:lwjgl-freetype:${rootProject.properties["lwjgl_version"]}") compileOnly("org.lwjgl:lwjgl:${rootProject.properties["lwjgl_version"]}") + // Fast util + compileOnly("it.unimi.dsi:fastutil:${rootProject.properties["fastutil_version"]}") } \ No newline at end of file diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/actionbar/ActionBarSender.java b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/actionbar/ActionBarSender.java index 9ce5fd9..32e617f 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/actionbar/ActionBarSender.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/actionbar/ActionBarSender.java @@ -17,6 +17,7 @@ package net.momirealms.customnameplates.backend.feature.actionbar; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.momirealms.customnameplates.api.CNPlayer; import net.momirealms.customnameplates.api.ConfigManager; import net.momirealms.customnameplates.api.CustomNameplates; @@ -177,7 +178,7 @@ public class ActionBarSender implements Feature { @Override public Set allPlaceholders() { - HashSet placeholders = new HashSet<>(); + Set placeholders = new ObjectOpenHashSet<>(); for (ActionBarConfig config : manager.actionBarConfigs()) { for (CarouselText text : config.carouselTexts()) { placeholders.addAll(text.preParsedDynamicText().placeholders()); diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/advance/AdvanceManagerImpl.java b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/advance/AdvanceManagerImpl.java index a6e614a..5b6e541 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/advance/AdvanceManagerImpl.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/advance/AdvanceManagerImpl.java @@ -25,6 +25,8 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import dev.dejvokep.boostedyaml.YamlDocument; import dev.dejvokep.boostedyaml.block.implementation.Section; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; @@ -292,8 +294,8 @@ public class AdvanceManagerImpl implements AdvanceManager { private final HashMap> templateConfigConsumersMap = new HashMap<>(); private final CustomNameplates plugin; - private final HashMap charFontWidthDataMap = new HashMap<>(); - private final HashMap configFontWidthDataMap = new HashMap<>(); + private final Object2ObjectOpenHashMap charFontWidthDataMap = new Object2ObjectOpenHashMap<>(); + private final Object2ObjectOpenHashMap configFontWidthDataMap = new Object2ObjectOpenHashMap<>(); private final Cache textWidthCache; @@ -1220,7 +1222,7 @@ public class AdvanceManagerImpl implements AdvanceManager { public List> miniMessageToIterable(String text) { if (AdventureHelper.legacySupport) text = AdventureHelper.legacyToMiniMessage(text); ElementNode node = (ElementNode) AdventureHelper.miniMessage().deserializeToTree(text); - ArrayList> iterableTexts = new ArrayList<>(); + List> iterableTexts = new ObjectArrayList<>(); nodeToIterableTexts(node, iterableTexts, MINECRAFT_DEFAULT_FONT, false); return iterableTexts; } diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/background/BackgroundManagerImpl.java b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/background/BackgroundManagerImpl.java index 89896b3..7e27ec3 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/background/BackgroundManagerImpl.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/background/BackgroundManagerImpl.java @@ -18,6 +18,7 @@ package net.momirealms.customnameplates.backend.feature.background; import dev.dejvokep.boostedyaml.YamlDocument; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.momirealms.customnameplates.api.ConfigManager; import net.momirealms.customnameplates.api.CustomNameplates; import net.momirealms.customnameplates.api.feature.ConfiguredCharacter; @@ -57,7 +58,7 @@ public class BackgroundManagerImpl implements BackgroundManager { @Override public Collection getBackgrounds() { - return new HashSet<>(backgrounds.values()); + return new ObjectArrayList<>(backgrounds.values()); } private void loadConfigs() { diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/bossbar/BossBarSender.java b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/bossbar/BossBarSender.java index 51b82f6..26e33d7 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/bossbar/BossBarSender.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/bossbar/BossBarSender.java @@ -17,6 +17,7 @@ package net.momirealms.customnameplates.backend.feature.bossbar; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.momirealms.customnameplates.api.CNPlayer; import net.momirealms.customnameplates.api.CustomNameplates; import net.momirealms.customnameplates.api.feature.CarouselText; @@ -163,7 +164,7 @@ public class BossBarSender implements Feature, BossBar { @Override public Set allPlaceholders() { - HashSet placeholders = new HashSet<>(); + Set placeholders = new ObjectOpenHashSet<>(); for (CarouselText text : config.carouselTexts()) { placeholders.addAll(text.preParsedDynamicText().placeholders()); } diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/bubble/BubbleManagerImpl.java b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/bubble/BubbleManagerImpl.java index 090de46..0e4364a 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/bubble/BubbleManagerImpl.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/bubble/BubbleManagerImpl.java @@ -27,6 +27,8 @@ import dev.dejvokep.boostedyaml.settings.general.GeneralSettings; import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings; import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; import dev.dejvokep.boostedyaml.utils.format.NodeRole; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.momirealms.customnameplates.api.CNPlayer; import net.momirealms.customnameplates.api.ConfigManager; import net.momirealms.customnameplates.api.CustomNameplates; @@ -51,7 +53,7 @@ import java.util.concurrent.TimeUnit; public class BubbleManagerImpl implements BubbleManager, ChatListener { private final CustomNameplates plugin; - private final Map bubbles = new HashMap<>(); + private final Map bubbles = new Object2ObjectOpenHashMap<>(); private Requirement[] sendBubbleRequirements; private Requirement[] viewBubbleRequirements; private String defaultBubbleId; @@ -62,7 +64,7 @@ public class BubbleManagerImpl implements BubbleManager, ChatListener { private float viewRange; private Set blacklistChannels; private ChannelMode channelMode; - private final HashMap bubbleConfigs = new HashMap<>(); + private final Map bubbleConfigs = new Object2ObjectOpenHashMap<>(); public BubbleManagerImpl(CustomNameplates plugin) { this.plugin = plugin; @@ -94,12 +96,12 @@ public class BubbleManagerImpl implements BubbleManager, ChatListener { @Override public Collection bubbles() { - return new HashSet<>(bubbles.values()); + return new ObjectArrayList<>(bubbles.values()); } @Override public Collection bubbleConfigs() { - return new HashSet<>(bubbleConfigs.values()); + return new ObjectArrayList<>(bubbleConfigs.values()); } @Override diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/image/ImageManagerImpl.java b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/image/ImageManagerImpl.java index 470068b..2eb83e8 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/image/ImageManagerImpl.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/image/ImageManagerImpl.java @@ -18,6 +18,7 @@ package net.momirealms.customnameplates.backend.feature.image; import dev.dejvokep.boostedyaml.YamlDocument; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.momirealms.customnameplates.api.ConfigManager; import net.momirealms.customnameplates.api.CustomNameplates; import net.momirealms.customnameplates.api.feature.ConfiguredCharacter; @@ -60,7 +61,7 @@ public class ImageManagerImpl implements ImageManager { @Override public Collection images() { - return new HashSet<>(images.values()); + return new ObjectArrayList<>(images.values()); } private void loadConfigs() { diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/nameplate/NameplateManagerImpl.java b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/nameplate/NameplateManagerImpl.java index 082489d..392532f 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/nameplate/NameplateManagerImpl.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/nameplate/NameplateManagerImpl.java @@ -18,6 +18,7 @@ package net.momirealms.customnameplates.backend.feature.nameplate; import dev.dejvokep.boostedyaml.YamlDocument; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.momirealms.customnameplates.api.CNPlayer; import net.momirealms.customnameplates.api.ConfigManager; import net.momirealms.customnameplates.api.CustomNameplates; @@ -61,7 +62,7 @@ public class NameplateManagerImpl implements NameplateManager { @Override public Collection nameplates() { - return new HashSet<>(nameplates.values()); + return new ObjectArrayList<>(nameplates.values()); } @Override diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/tag/NameTag.java b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/tag/NameTag.java index e664e70..991a0b1 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/tag/NameTag.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/tag/NameTag.java @@ -17,6 +17,7 @@ package net.momirealms.customnameplates.backend.feature.tag; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.momirealms.customnameplates.api.CNPlayer; import net.momirealms.customnameplates.api.CustomNameplates; import net.momirealms.customnameplates.api.feature.CarouselText; @@ -195,7 +196,7 @@ public class NameTag extends AbstractTag implements RelationalFeature { @Override public Set allPlaceholders() { - HashSet placeholders = new HashSet<>(); + Set placeholders = new ObjectOpenHashSet<>(); for (CarouselText text : config.carouselTexts()) { placeholders.addAll(text.preParsedDynamicText().placeholders()); } diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/tag/TagRendererImpl.java b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/tag/TagRendererImpl.java index 5a07c6f..8df2892 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/feature/tag/TagRendererImpl.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/feature/tag/TagRendererImpl.java @@ -17,6 +17,7 @@ package net.momirealms.customnameplates.backend.feature.tag; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.momirealms.customnameplates.api.CNPlayer; import net.momirealms.customnameplates.api.CustomNameplates; import net.momirealms.customnameplates.api.feature.Feature; @@ -69,14 +70,15 @@ public class TagRendererImpl implements TagRenderer { @Override public void onTick() { - HashSet playersToUpdatePassengers = new HashSet<>(); - HashSet tagTranslationUpdates = new HashSet<>(); + Set playersToUpdatePassengers = new ObjectOpenHashSet<>(); + Set tagTranslationUpdates = new ObjectOpenHashSet<>(); + Collection nearbyPlayers = owner.nearbyPlayers(); for (Tag tag : tagArray) { boolean canShow = tag.canShow(); if (canShow) { if (tag.isShown()) { - for (CNPlayer nearby : owner.nearbyPlayers()) { + for (CNPlayer nearby : nearbyPlayers) { if (tag.isShown(nearby)) { if (!tag.canShow(nearby)) { tag.hide(nearby); @@ -97,7 +99,7 @@ public class TagRendererImpl implements TagRenderer { tag.init(); tag.tick(); tag.show(); - for (CNPlayer nearby : owner.nearbyPlayers()) { + for (CNPlayer nearby : nearbyPlayers) { if (tag.canShow(nearby) && !tag.isShown(nearby)) { tag.show(nearby); playersToUpdatePassengers.add(nearby); @@ -110,7 +112,7 @@ public class TagRendererImpl implements TagRenderer { if (tag.isShown()) { tag.hide(); if (!tag.relativeTranslation()) - tagTranslationUpdates.addAll(owner.nearbyPlayers()); + tagTranslationUpdates.addAll(nearbyPlayers); } } } diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java b/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java index 8e3af59..274fe51 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java @@ -19,6 +19,10 @@ package net.momirealms.customnameplates.backend.placeholder; import dev.dejvokep.boostedyaml.YamlDocument; import dev.dejvokep.boostedyaml.block.implementation.Section; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.momirealms.customnameplates.api.CNPlayer; import net.momirealms.customnameplates.api.ConfigManager; import net.momirealms.customnameplates.api.CustomNameplates; @@ -51,7 +55,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager { private final CustomNameplates plugin; private final HashMap refreshIntervals = new HashMap<>(); - private final HashMap fasterRefreshIntervals = new HashMap<>(); + private final Int2IntOpenHashMap fasterRefreshIntervals = new Int2IntOpenHashMap(); private final Map registeredPlaceholders = new HashMap<>(); private final HashMap> childrenText = new HashMap<>(); private final HashMap nestedPlaceholders = new HashMap<>(); @@ -575,9 +579,9 @@ public class PlaceholderManagerImpl implements PlaceholderManager { public void refreshPlaceholders() { for (CNPlayer player : plugin.getOnlinePlayers()) { if (!player.isOnline()) continue; - Set featuresToNotifyUpdates = new HashSet<>(); - Map> relationalFeaturesToNotifyUpdates = new HashMap<>(); - List delayedPlaceholdersToUpdate = new ArrayList<>(); + Set featuresToNotifyUpdates = new ObjectOpenHashSet<>(); + Map> relationalFeaturesToNotifyUpdates = new Object2ObjectOpenHashMap<>(); + List delayedPlaceholdersToUpdate = new ObjectArrayList<>(); for (Placeholder placeholder : player.activePlaceholdersToRefresh()) { if (placeholder instanceof PlayerPlaceholder playerPlaceholder) { TimeStampData previous = player.getValue(placeholder); @@ -652,7 +656,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager { for (Feature feature : player.activeFeatures(placeholder)) { // Filter features that will not be updated for all players if (!featuresToNotifyUpdates.contains(feature)) { - List players = relationalFeaturesToNotifyUpdates.computeIfAbsent(feature, k -> new ArrayList<>()); + List players = relationalFeaturesToNotifyUpdates.computeIfAbsent(feature, k -> new ObjectArrayList<>()); players.add(nearby); } } @@ -663,7 +667,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager { for (Feature feature : player.activeFeatures(placeholder)) { // Filter features that will not be updated for all players if (!featuresToNotifyUpdates.contains(feature)) { - List players = relationalFeaturesToNotifyUpdates.computeIfAbsent(feature, k -> new ArrayList<>()); + List players = relationalFeaturesToNotifyUpdates.computeIfAbsent(feature, k -> new ObjectArrayList<>()); players.add(nearby); } } @@ -677,7 +681,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager { for (Feature feature : player.activeFeatures(placeholder)) { // Filter features that will not be updated for all players if (!featuresToNotifyUpdates.contains(feature)) { - List players = relationalFeaturesToNotifyUpdates.computeIfAbsent(feature, k -> new ArrayList<>()); + List players = relationalFeaturesToNotifyUpdates.computeIfAbsent(feature, k -> new ObjectArrayList<>()); players.add(nearby); } } @@ -773,7 +777,7 @@ public class PlaceholderManagerImpl implements PlaceholderManager { if (firstPercent == 0 && text.charAt(text.length() - 1) == '%' && text.indexOf('%', 1) == text.length() - 1) { return Collections.singletonList(text); } - List placeholders = new ArrayList<>(); + List placeholders = new ObjectArrayList<>(); Matcher m = PATTERN.matcher(text); while (m.find()) { placeholders.add(m.group()); diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/AbstractRequirement.java b/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/AbstractRequirement.java index 2966113..62e4f9b 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/AbstractRequirement.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/AbstractRequirement.java @@ -17,16 +17,29 @@ package net.momirealms.customnameplates.backend.requirement; +import net.momirealms.customnameplates.api.CustomNameplates; import net.momirealms.customnameplates.api.requirement.Requirement; +import org.jetbrains.annotations.Nullable; public abstract class AbstractRequirement implements Requirement { protected final int refreshInterval; + @Nullable + protected Integer countId; public AbstractRequirement(int refreshInterval) { this.refreshInterval = refreshInterval; } + @Override + public int countId() { + // lazy init + if (countId == null) { + countId = CustomNameplates.getInstance().getRequirementManager().countId(this); + } + return countId; + } + @Override public int refreshInterval() { return refreshInterval; diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/AbstractRequirementManager.java b/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/AbstractRequirementManager.java index 04e5a83..e300a31 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/AbstractRequirementManager.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/AbstractRequirementManager.java @@ -18,6 +18,8 @@ package net.momirealms.customnameplates.backend.requirement; import dev.dejvokep.boostedyaml.block.implementation.Section; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.momirealms.customnameplates.api.ConfigManager; import net.momirealms.customnameplates.api.CustomNameplates; import net.momirealms.customnameplates.api.feature.PreParsedDynamicText; @@ -35,7 +37,9 @@ import java.util.*; public abstract class AbstractRequirementManager implements RequirementManager { protected final CustomNameplates plugin; - private final HashMap requirementFactoryMap = new HashMap<>(); + private final Object2ObjectOpenHashMap requirementFactoryMap = new Object2ObjectOpenHashMap<>(128); + private int countId = 0; + private final Map registeredRequirements = new Object2IntOpenHashMap<>(128); public AbstractRequirementManager(CustomNameplates plugin) { this.plugin = plugin; @@ -43,6 +47,21 @@ public abstract class AbstractRequirementManager implements RequirementManager { this.registerPlatformRequirements(); } + @Override + public void reload() { + this.countId = 0; + this.registeredRequirements.clear(); + } + + @Override + public int countId(Requirement requirement) { + if (requirement == null) return -1; + if (this.registeredRequirements.containsKey(requirement)) return this.registeredRequirements.get(requirement); + this.countId++; + this.registeredRequirements.put(requirement, countId); + return this.countId; + } + private void registerInternalRequirements() { this.registerRequirement((args, interval) -> { Section section = ConfigUtils.safeCast(args, Section.class); diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/builtin/PlaceholdersRequirement.java b/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/builtin/PlaceholdersRequirement.java index 37856d8..7ff7805 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/builtin/PlaceholdersRequirement.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/requirement/builtin/PlaceholdersRequirement.java @@ -37,8 +37,9 @@ public abstract class PlaceholdersRequirement extends AbstractRequirement { @Override public boolean isSatisfied(CNPlayer p1, CNPlayer p2) { - p1.forceUpdatePlaceholders(t1.placeholders(), Set.of(p2)); - p1.forceUpdatePlaceholders(t2.placeholders(), Set.of(p2)); + Set set = Set.of(p2); + p1.forceUpdatePlaceholders(t1.placeholders(), set); + p1.forceUpdatePlaceholders(t2.placeholders(), set); String a1 = t1.fastCreate(p1).render(p2); String a2 = t2.fastCreate(p1).render(p2); return checkArgument(a1, a2); diff --git a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitCustomNameplates.java b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitCustomNameplates.java index d8c4476..d6cbefb 100644 --- a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitCustomNameplates.java +++ b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitCustomNameplates.java @@ -309,6 +309,8 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener for (CNPlayer player : getOnlinePlayers()) { ((AbstractCNPlayer) player).reload(); } + // clear requirement ids + this.requirementManager.reload(); // load basics this.configManager.reload(); this.storageManager.reload(); @@ -321,8 +323,6 @@ public class BukkitCustomNameplates extends CustomNameplates implements Listener this.advanceManager.reload(); // set up placeholders this.placeholderManager.reload(); - // set up requirements - this.requirementManager.reload(); // use the placeholders this.actionBarManager.reload(); this.bossBarManager.reload(); diff --git a/compatibility/src/main/java/net/momirealms/customnameplates/bukkit/compatibility/region/RegionRequirement.java b/compatibility/src/main/java/net/momirealms/customnameplates/bukkit/compatibility/region/RegionRequirement.java index f4acd49..0ebf34e 100644 --- a/compatibility/src/main/java/net/momirealms/customnameplates/bukkit/compatibility/region/RegionRequirement.java +++ b/compatibility/src/main/java/net/momirealms/customnameplates/bukkit/compatibility/region/RegionRequirement.java @@ -17,6 +17,7 @@ package net.momirealms.customnameplates.bukkit.compatibility.region; +import com.google.common.base.Objects; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldguard.WorldGuard; @@ -76,4 +77,16 @@ public class RegionRequirement extends AbstractRequirement { public String type() { return "region"; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof RegionRequirement that)) return false; + return mode == that.mode && Objects.equal(regions, that.regions); + } + + @Override + public int hashCode() { + return Objects.hashCode(regions, mode); + } } diff --git a/gradle.properties b/gradle.properties index 4bce444..2635c71 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=3.0.9 +project_version=3.0.10 config_version=32 project_group=net.momirealms @@ -44,6 +44,7 @@ vault_version=1.7 guava_version=33.3.1-jre commons_io_version=2.17.0 lwjgl_version=3.3.4 +fastutil_version=8.5.15 # Proxy settings #systemProp.socks.proxyHost=127.0.0.1