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+ // register default entity converters
63+ static {
64+ registerEntityConverter (Entity .class , (entity , data , ctx ) -> {
65+ data .put ("id" , entity .getId ());
66+ data .put ("uuid" , entity .getStringUUID ());
67+ if (entity .hasCustomName ())
68+ data .put ("customName" , entity .getCustomName ().getString ());
69+ EntityType <?> type = entity .getType ();
70+ data .put ("displayName" , type .getDescription ().getString ());
71+ data .put ("name" , type .builtInRegistryHolder ().key ().location ().toString ());
72+ if (ctx .detailed ()) {
73+ data .put ("type" , type .getDescriptionId ());
74+ data .put ("category" , type .getCategory ().getName ());
75+ data .put ("canBurn" , entity .fireImmune ());
76+ data .put ("canFreeze" , entity .canFreeze ());
77+ data .put ("tags" , entity .getTags ());
78+ data .put ("isGlowing" , entity .isCurrentlyGlowing ());
79+ data .put ("isUnderWater" , entity .isUnderWater ());
80+ data .put ("isInLava" , entity .isInLava ());
81+ data .put ("isInWall" , entity .isInWall ());
82+ data .put ("team" , teamToLua (entity .getTeam ()));
83+ }
84+ });
85+ registerEntityConverter (LivingEntity .class , (entity , data , ctx ) -> {
86+ data .put ("baby" , entity .isBaby ());
87+ data .put ("health" , entity .getHealth ());
88+ data .put ("maxHealth" , entity .getMaxHealth ());
89+ if (ctx .detailed ()) {
90+ data .put ("lastDamageSource" , entity .getLastDamageSource () == null ? null : entity .getLastDamageSource ().toString ());
91+ Map <String , Object > effMap = new HashMap <>();
92+ entity .getActiveEffectsMap ().forEach ((key , value ) -> {
93+ effMap .put (key .getDescriptionId (), effectToLua (value ));
94+ });
95+ data .put ("effects" , effMap );
96+ }
97+ });
98+ registerEntityConverter (Mob .class , (entity , data , ctx ) -> {
99+ data .put ("aggressive" , entity .isAggressive ());
100+ });
101+ registerEntityConverter (Animal .class , (entity , data , ctx ) -> {
102+ data .put ("inLove" , entity .isInLove ());
103+ if (ctx .detailed () && !ctx .itemInHand ().isEmpty () && entity instanceof IForgeShearable shareable ) {
104+ data .put ("shareable" , shareable .isShearable (ctx .itemInHand (), entity .level , entity .blockPosition ()));
105+ }
106+ });
107+ registerEntityConverter (Player .class , (entity , data , ctx ) -> {
108+ data .put ("score" , entity .getScore ());
109+ data .put ("luck" , entity .getLuck ());
110+ Inventory inv = entity .getInventory ();
111+ data .put ("handSlot" , inv .selected );
112+ if (ctx .detailed ()) {
113+ Map <Integer , Object > invMap = new HashMap <>();
114+ for (int slot = 0 ; slot < inv .getContainerSize (); slot ++) {
115+ ItemStack item = inv .getItem (slot );
116+ if (!item .isEmpty ()) {
117+ invMap .put (slot , itemStackToObject (item ));
118+ }
119+ }
120+ data .put ("inventory" , invMap );
121+ }
122+ });
83123 }
84124
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- }
125+ @ FunctionalInterface
126+ public interface EntityConverter <T extends Entity > {
127+ void entityToMap (T entity , Map <String , Object > data , Context ctx );
90128
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 ;
129+ record Context (boolean detailed , ItemStack itemInHand ) {}
117130 }
118131
119132 public static Map <String , Object > completeEntityToLua (Entity entity ) {
@@ -129,11 +142,20 @@ public static Map<String, Object> completeEntityToLua(Entity entity, ItemStack i
129142 }
130143
131144 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 );
145+ if (entity == null ) {
146+ return null ;
147+ }
148+ EntityConverter .Context ctx = new EntityConverter .Context (detailed , itemInHand );
149+ Map <String , Object > data = new HashMap <>();
150+ for (Class <?> entityClass = entity .getClass (); Entity .class .isAssignableFrom (entityClass ); entityClass = entityClass .getSuperclass ()) {
151+ List <EntityConverter <? extends Entity >> converters = ENTITY_CONVERTERS .get ((Class <? extends Entity >) entityClass );
152+ if (converters != null ) {
153+ for (EntityConverter <? extends Entity > converter : converters ) {
154+ ((EntityConverter <Entity >) converter ).entityToMap (entity , data , ctx );
155+ }
156+ }
157+ }
158+ return data ;
137159 }
138160
139161 public static Map <String , Object > completeEntityWithPositionToLua (Entity entity , BlockPos pos ) {
@@ -303,14 +325,24 @@ public static BlockPos convertToBlockPos(BlockPos center, Map<?, ?> table) throw
303325 return new BlockPos (center .getX () + relative .getX (), center .getY () + relative .getY (), center .getZ () + relative .getZ ());
304326 }
305327
306- public static Object effectToObject (MobEffectInstance effect ) {
328+ public static Map < String , Object > effectToLua (MobEffectInstance effect ) {
307329 Map <String , Object > map = new HashMap <>();
308330 map .put ("name" , effect .getDescriptionId ());
309331 map .put ("duration" , effect .getDuration ());
310332 map .put ("amplifier" , effect .getAmplifier ());
311333 return map ;
312334 }
313335
336+ public static Map <String , Object > teamToLua (Team team ) {
337+ if (team == null ) {
338+ return null ;
339+ }
340+ Map <String , Object > map = new HashMap <>();
341+ map .put ("name" , team .getName ());
342+ map .put ("color" , team .getColor ());
343+ return map ;
344+ }
345+
314346 public static Map <String , Object > shipToObject (ServerShip ship ) {
315347 return shipToObject (ship , null );
316348 }
0 commit comments