2222import net .minecraft .world .level .block .state .properties .Property ;
2323import net .minecraft .world .level .material .Fluid ;
2424import net .minecraft .world .phys .Vec3 ;
25+ import net .minecraft .world .scores .Team ;
2526import net .minecraftforge .common .IForgeShearable ;
2627import net .minecraftforge .fluids .FluidStack ;
2728import net .minecraftforge .fluids .FluidType ;
4546public class LuaConverter {
4647
4748 private static final CompoundTag EMPTY_TAG = new CompoundTag ();
49+ private static final Map <Class <? extends Entity >, List <EntityConverter <?>>> ENTITY_CONVERTERS = new HashMap <>();
4850
49- public static Map <String , Object > entityToLua (Entity entity ) {
50- Map <String , Object > data = new HashMap <>();
51- data .put ("id" , entity .getId ());
52- data .put ("uuid" , entity .getStringUUID ());
53- if (entity .hasCustomName ())
54- data .put ("customName" , entity .getCustomName ().getString ());
55- EntityType <?> type = entity .getType ();
56- data .put ("displayName" , type .getDescription ().getString ());
57- data .put ("name" , type .builtInRegistryHolder ().key ().location ().toString ());
58- data .put ("type" , type .getDescriptionId ());
59- data .put ("category" , type .getCategory ());
60- data .put ("canBurn" , entity .fireImmune ());
61- data .put ("canFreeze" , entity .canFreeze ());
62- data .put ("isGlowing" , entity .isCurrentlyGlowing ());
63- data .put ("isUnderWater" , entity .isUnderWater ());
64- data .put ("isInLava" , entity .isInLava ());
65- data .put ("isInWall" , entity .isInWall ());
66- return data ;
51+ /**
52+ * registerEntityConverter register a converter for a type of entity.
53+ * If an old converter exists, it will invoke the old one first before invoke the new converter.
54+ *
55+ * @param clazz The entity's class
56+ * @param converter The {@link EntityConverter}
57+ */
58+ public static <T extends Entity > void registerEntityConverter (Class <T > clazz , EntityConverter <T > converter ) {
59+ ENTITY_CONVERTERS .computeIfAbsent (clazz , (k ) -> new ArrayList <>(1 )).add (converter );
6760 }
6861
69- public static Map <String , Object > livingEntityToLua (LivingEntity entity , boolean detailed ) {
70- Map <String , Object > data = entityToLua (entity );
71- data .put ("baby" , entity .isBaby ());
72- data .put ("health" , entity .getHealth ());
73- data .put ("maxHealth" , entity .getMaxHealth ());
74- data .put ("lastDamageSource" , entity .getLastDamageSource () == null ? null : entity .getLastDamageSource ().toString ());
75- if (detailed ) {
76- Map <String , Object > effMap = new HashMap <>();
77- entity .getActiveEffectsMap ().forEach ((key , value ) -> {
78- effMap .put (key .getDescriptionId (), effectToObject (value ));
79- });
80- data .put ("effects" , effMap );
81- }
82- return data ;
62+ /**
63+ * register default entity converters
64+ */
65+ static {
66+ registerEntityConverter (Entity .class , (entity , data , ctx ) -> {
67+ data .put ("id" , entity .getId ());
68+ data .put ("uuid" , entity .getStringUUID ());
69+ if (entity .hasCustomName ())
70+ data .put ("customName" , entity .getCustomName ().getString ());
71+ EntityType <?> type = entity .getType ();
72+ data .put ("displayName" , type .getDescription ().getString ());
73+ data .put ("name" , type .builtInRegistryHolder ().key ().location ().toString ());
74+ if (ctx .detailed ()) {
75+ data .put ("type" , type .getDescriptionId ());
76+ data .put ("category" , type .getCategory ());
77+ data .put ("canBurn" , entity .fireImmune ());
78+ data .put ("canFreeze" , entity .canFreeze ());
79+ data .put ("tags" , entity .getTags ());
80+ data .put ("isGlowing" , entity .isCurrentlyGlowing ());
81+ data .put ("isUnderWater" , entity .isUnderWater ());
82+ data .put ("isInLava" , entity .isInLava ());
83+ data .put ("isInWall" , entity .isInWall ());
84+ data .put ("team" , teamToLua (entity .getTeam ()));
85+ }
86+ });
87+ registerEntityConverter (LivingEntity .class , (entity , data , ctx ) -> {
88+ data .put ("baby" , entity .isBaby ());
89+ data .put ("health" , entity .getHealth ());
90+ data .put ("maxHealth" , entity .getMaxHealth ());
91+ if (ctx .detailed ()) {
92+ data .put ("lastDamageSource" , entity .getLastDamageSource () == null ? null : entity .getLastDamageSource ().toString ());
93+ Map <String , Object > effMap = new HashMap <>();
94+ entity .getActiveEffectsMap ().forEach ((key , value ) -> {
95+ effMap .put (key .getDescriptionId (), effectToLua (value ));
96+ });
97+ data .put ("effects" , effMap );
98+ }
99+ });
100+ registerEntityConverter (Mob .class , (entity , data , ctx ) -> {
101+ data .put ("aggressive" , entity .isAggressive ());
102+ });
103+ registerEntityConverter (Animal .class , (entity , data , ctx ) -> {
104+ data .put ("inLove" , entity .isInLove ());
105+ if (ctx .detailed () && !ctx .itemInHand ().isEmpty () entity instanceof IForgeShearable shareable ) {
106+ data .put ("shareable" , shareable .isShearable (ctx .itemInHand (), entity .level , entity .blockPosition ()));
107+ }
108+ });
109+ registerEntityConverter (Player .class , (entity , data , ctx ) -> {
110+ data .put ("score" , entity .getScore ());
111+ data .put ("luck" , entity .getLuck ());
112+ Inventory inv = entity .getInventory ();
113+ data .put ("handSlot" , inv .selected );
114+ if (ctx .detailed ()) {
115+ Map <Integer , Object > invMap = new HashMap <>();
116+ for (int slot = 0 ; slot < inv .getContainerSize (); slot ++) {
117+ ItemStack item = inv .getItem (slot );
118+ if (!item .isEmpty ()) {
119+ invMap .put (slot , itemStackToObject (item ));
120+ }
121+ }
122+ data .put ("inventory" , invMap );
123+ }
124+ });
83125 }
84126
85- public static Map <String , Object > mobToLua (Mob animal , boolean detailed ) {
86- Map <String , Object > data = livingEntityToLua (animal , detailed );
87- data .put ("aggressive" , animal .isAggressive ());
88- return data ;
89- }
127+ @ FunctionalInterface
128+ public interface EntityConverter <T extends Entity > {
129+ void entityToMap (T entity , Map <String , Object > data , Context ctx );
90130
91- public static Map <String , Object > animalToLua (Animal animal , ItemStack itemInHand , boolean detailed ) {
92- Map <String , Object > data = mobToLua (animal , detailed );
93- data .put ("inLove" , animal .isInLove ());
94- if (animal instanceof IForgeShearable shareable && !itemInHand .isEmpty ()) {
95- data .put ("shareable" , shareable .isShearable (itemInHand , animal .level , animal .blockPosition ()));
96- }
97- return data ;
98- }
99-
100- public static Map <String , Object > playerToLua (Player player , boolean detailed ) {
101- Map <String , Object > data = livingEntityToLua (player , detailed );
102- data .put ("score" , player .getScore ());
103- data .put ("luck" , player .getLuck ());
104- Inventory inv = player .getInventory ();
105- data .put ("handSlot" , inv .selected );
106- if (detailed ) {
107- Map <Integer , Object > invMap = new HashMap <>();
108- for (int slot = 0 ; slot < inv .getContainerSize (); slot ++) {
109- ItemStack item = inv .getItem (slot );
110- if (!item .isEmpty ()) {
111- invMap .put (slot , itemStackToObject (item ));
112- }
113- }
114- data .put ("inventory" , invMap );
115- }
116- return data ;
131+ record Context (boolean detailed , ItemStack itemInHand ) {}
117132 }
118133
119134 public static Map <String , Object > completeEntityToLua (Entity entity ) {
@@ -129,11 +144,20 @@ public static Map<String, Object> completeEntityToLua(Entity entity, ItemStack i
129144 }
130145
131146 public static Map <String , Object > completeEntityToLua (Entity entity , ItemStack itemInHand , boolean detailed ) {
132- if (entity instanceof Player player ) return playerToLua (player , detailed );
133- if (entity instanceof Animal animal ) return animalToLua (animal , itemInHand , detailed );
134- if (entity instanceof Mob mob ) return mobToLua (mob , detailed );
135- if (entity instanceof LivingEntity livingEntity ) return livingEntityToLua (livingEntity , detailed );
136- return entityToLua (entity );
147+ if (entity == null ) {
148+ return null ;
149+ }
150+ EntityConverter .Context ctx = new EntityConverter .Context (detailed , itemInHand );
151+ Map <String , Object > data = new HashMap <>();
152+ for (Class <?> entityClass = entity .getClass (); Entity .class .isAssignableFrom (entityClass ); entityClass = entityClass .getSuperclass ()) {
153+ List <EntityConverter <? extends Entity >> converters = ENTITY_CONVERTERS .get ((Class <? extends Entity >) entityClass );
154+ if (converters != null ) {
155+ for (EntityConverter <? extends Entity > converter : converters ) {
156+ converter .entityToMap (entity , data , ctx );
157+ }
158+ }
159+ }
160+ return data ;
137161 }
138162
139163 public static Map <String , Object > completeEntityWithPositionToLua (Entity entity , BlockPos pos ) {
@@ -303,14 +327,24 @@ public static BlockPos convertToBlockPos(BlockPos center, Map<?, ?> table) throw
303327 return new BlockPos (center .getX () + relative .getX (), center .getY () + relative .getY (), center .getZ () + relative .getZ ());
304328 }
305329
306- public static Object effectToObject (MobEffectInstance effect ) {
330+ public static Map < String , Object > effectToLua (MobEffectInstance effect ) {
307331 Map <String , Object > map = new HashMap <>();
308332 map .put ("name" , effect .getDescriptionId ());
309333 map .put ("duration" , effect .getDuration ());
310334 map .put ("amplifier" , effect .getAmplifier ());
311335 return map ;
312336 }
313337
338+ public static Map <String , Object > teamToLua (Team team ) {
339+ if (team == null ) {
340+ return null ;
341+ }
342+ Map <String , Object > map = new HashMap <>();
343+ map .put ("name" , team .getName ());
344+ map .put ("color" , team .getColor ());
345+ return map ;
346+ }
347+
314348 public static Map <String , Object > shipToObject (ServerShip ship ) {
315349 return shipToObject (ship , null );
316350 }
0 commit comments