11package org .mvplugins .multiverse .core .world .entity ;
22
33import com .dumptruckman .minecraft .util .Logging ;
4+ import io .vavr .control .Option ;
45import io .vavr .control .Try ;
56import org .bukkit .entity .EntityType ;
67import org .bukkit .entity .SpawnCategory ;
8+ import org .jetbrains .annotations .ApiStatus ;
9+ import org .jetbrains .annotations .NotNull ;
710import org .mvplugins .multiverse .core .utils .ReflectHelper ;
811
12+ import javax .annotation .Nullable ;
913import java .lang .reflect .Method ;
1014import java .util .ArrayList ;
1115import java .util .Arrays ;
1721/**
1822 * Uses reflection into nms to map entity types to spawn categories.
1923 */
20- final class SpawnCategoryMapper {
24+ @ ApiStatus .Internal
25+ public final class SpawnCategoryMapper {
2126
22- private static final Map <EntityType , SpawnCategory > entityTypeToSpawnCategoryMap ;
23- private static final Map <SpawnCategory , List <EntityType >> spawnCategoryMap ;
27+ private static final @ NotNull Map <EntityType , SpawnCategory > entityTypeToSpawnCategoryMap ;
28+ private static final @ NotNull Map <SpawnCategory , List <EntityType >> spawnCategoryMap ;
2429
2530 static {
2631 entityTypeToSpawnCategoryMap = new HashMap <>();
2732 spawnCategoryMap = new HashMap <>();
28- buildSpawnCategoryMap ();
2933 }
3034
31- private static void buildSpawnCategoryMap () {
35+ public static void buildSpawnCategoryMap () {
3236 Class <?> entityTypeClass = ReflectHelper .tryGetClass ("net.minecraft.world.entity.EntityType" ).getOrNull ();
3337 if (entityTypeClass == null ) {
3438 Logging .warning ("Failed to find EntityType class. SpawnCategoryMapper will not work." );
3539 return ;
3640 }
41+ // In 26.2, the list of static fields has been moved from EntityType to EntityTypes class.
42+ Class <?> entityTypesListClass = ReflectHelper .tryGetClass ("net.minecraft.world.entity.EntityTypes" ).getOrNull ();
43+ if (entityTypesListClass == null ) {
44+ // Assume it's the older mc versions that has list of static fields in EntityType class instead.
45+ Logging .finer ("Failed to find EntityTypes class. falling back to EntityType." );
46+ entityTypesListClass = entityTypeClass ;
47+ }
3748 Method getCategoryMethod = ReflectHelper .tryGetMethod (entityTypeClass , "getCategory" ).getOrNull ();
3849 if (getCategoryMethod == null ) {
3950 Logging .warning ("Failed to find getCategory method. SpawnCategoryMapper will not work." );
@@ -52,7 +63,10 @@ private static void buildSpawnCategoryMap() {
5263 Logging .warning ("Failed to find toBukkit method. SpawnCategoryMapper will not work." );
5364 return ;
5465 }
55- Arrays .stream (entityTypeClass .getFields ()).forEach (entityTypeField -> Try .of (() -> EntityType .valueOf (entityTypeField .getName ()))
66+
67+ Logging .finer ("Mapping entities to its spawn category..." );
68+
69+ Arrays .stream (entityTypesListClass .getFields ()).forEach (entityTypeField -> Try .of (() -> EntityType .valueOf (entityTypeField .getName ()))
5670 .peek (entityType -> ReflectHelper .tryGetStaticFieldValue (entityTypeField , entityTypeClass )
5771 .flatMap (nmsEntityType -> ReflectHelper .tryInvokeMethod (nmsEntityType , getCategoryMethod ))
5872 .flatMap (nsmMobCategory -> ReflectHelper .tryInvokeStaticMethod (toBukkitMethod , nsmMobCategory ))
@@ -61,7 +75,22 @@ private static void buildSpawnCategoryMap() {
6175 .peek (bukkitSpawnCategory -> entityTypeToSpawnCategoryMap .put (entityType , bukkitSpawnCategory ))
6276 .peek (bukkitSpawnCategory -> spawnCategoryMap
6377 .computeIfAbsent (bukkitSpawnCategory , ignore -> new ArrayList <>())
64- .add (entityType ))));
78+ .add (entityType ))
79+ .onFailure (throwable -> Logging .warning ("Failed to map entity type "
80+ + entityTypeField .getName () + " to its spawn category. " + throwable .getLocalizedMessage ())))
81+ .onFailure (throwable -> Logging .warning ("Failed to map entity type "
82+ + entityTypeField .getName () + " to its spawn category. " + throwable .getLocalizedMessage ())));
83+
84+ if (entityTypeToSpawnCategoryMap .isEmpty ()) {
85+ Logging .warning ("entityTypeToSpawnCategoryMap map is empty after building... " +
86+ "SpawnCategoryMapper will not work." );
87+ }
88+ if (spawnCategoryMap .isEmpty ()) {
89+ Logging .warning ("spawnCategoryMap map is empty after building... " +
90+ "SpawnCategoryMapper will not work." );
91+ }
92+
93+ Logging .finer ("Mapped " + entityTypeToSpawnCategoryMap .size () + " entities to its spawn category." );
6594 }
6695
6796 /**
@@ -70,8 +99,8 @@ private static void buildSpawnCategoryMap() {
7099 * @param entityType The entity type
71100 * @return The spawn category that the given entity type is in, or null if it cannot be determined
72101 */
73- static SpawnCategory getSpawnCategory (EntityType entityType ) {
74- return entityTypeToSpawnCategoryMap .get (entityType );
102+ static @ NotNull Option < SpawnCategory > getSpawnCategory (@ Nullable EntityType entityType ) {
103+ return Option . of ( entityTypeToSpawnCategoryMap .get (entityType ) );
75104 }
76105
77106 /**
@@ -80,10 +109,11 @@ static SpawnCategory getSpawnCategory(EntityType entityType) {
80109 * @param spawnCategory The spawn category
81110 * @return The entity types associated with the spawn category
82111 */
83- static List <EntityType > getEntityTypes (SpawnCategory spawnCategory ) {
84- if (spawnCategoryMap == null ) {
85- return Collections .emptyList ();
86- }
87- return spawnCategoryMap .get (spawnCategory );
112+ static @ NotNull List <EntityType > getEntityTypes (@ Nullable SpawnCategory spawnCategory ) {
113+ return spawnCategoryMap .getOrDefault (spawnCategory , Collections .emptyList ());
114+ }
115+
116+ private SpawnCategoryMapper () {
117+ throw new UnsupportedOperationException ("This is a utility class and cannot be instantiated" );
88118 }
89119}
0 commit comments