@@ -1110,6 +1110,71 @@ private List<Object> preprocessTeleportArgs(Entity entity, List<Object> args) {
11101110 return args ;
11111111 }
11121112
1113+ private Map <String , Object > serializeMerchantRecipe (org .bukkit .inventory .MerchantRecipe recipe ) {
1114+ Map <String , Object > map = new java .util .LinkedHashMap <>();
1115+ map .put ("result" , recipe .getResult ().serialize ());
1116+ List <Map <String , Object >> ingredients = new ArrayList <>();
1117+ for (ItemStack ingredient : recipe .getIngredients ()) {
1118+ ingredients .add (ingredient .serialize ());
1119+ }
1120+ map .put ("ingredients" , ingredients );
1121+ map .put ("maxUses" , recipe .getMaxUses ());
1122+ map .put ("uses" , recipe .getUses ());
1123+ map .put ("experienceReward" , recipe .hasExperienceReward ());
1124+ map .put ("villagerExperience" , recipe .getVillagerExperience ());
1125+ map .put ("priceMultiplier" , recipe .getPriceMultiplier ());
1126+ map .put ("demand" , recipe .getDemand ());
1127+ map .put ("specialPrice" , recipe .getSpecialPrice ());
1128+ return map ;
1129+ }
1130+
1131+ @ SuppressWarnings ("unchecked" )
1132+ private org .bukkit .inventory .MerchantRecipe deserializeMerchantRecipe (Map <String , Object > map ) {
1133+ if (map == null ) return null ;
1134+ // Deserialize result item
1135+ Object resultObj = map .get ("result" );
1136+ ItemStack result ;
1137+ if (resultObj instanceof Map <?, ?> resultMap ) {
1138+ result = ItemStack .deserialize (toStringKeyMap (resultMap ));
1139+ } else {
1140+ return null ;
1141+ }
1142+ int maxUses = map .containsKey ("maxUses" ) ? ((Number ) map .get ("maxUses" )).intValue () : 1 ;
1143+ boolean experienceReward = map .containsKey ("experienceReward" ) ? Boolean .TRUE .equals (map .get ("experienceReward" )) : true ;
1144+ int villagerExperience = map .containsKey ("villagerExperience" ) ? ((Number ) map .get ("villagerExperience" )).intValue () : 0 ;
1145+ float priceMultiplier = map .containsKey ("priceMultiplier" ) ? ((Number ) map .get ("priceMultiplier" )).floatValue () : 0.0f ;
1146+ int demand = map .containsKey ("demand" ) ? ((Number ) map .get ("demand" )).intValue () : 0 ;
1147+ int specialPrice = map .containsKey ("specialPrice" ) ? ((Number ) map .get ("specialPrice" )).intValue () : 0 ;
1148+ int uses = map .containsKey ("uses" ) ? ((Number ) map .get ("uses" )).intValue () : 0 ;
1149+
1150+ org .bukkit .inventory .MerchantRecipe recipe = new org .bukkit .inventory .MerchantRecipe (
1151+ result , uses , maxUses , experienceReward , villagerExperience , priceMultiplier , demand , specialPrice
1152+ );
1153+
1154+ // Deserialize ingredients
1155+ Object ingredientsObj = map .get ("ingredients" );
1156+ if (ingredientsObj instanceof List <?> ingredientsList ) {
1157+ List <ItemStack > ingredients = new ArrayList <>();
1158+ for (Object ingObj : ingredientsList ) {
1159+ if (ingObj instanceof Map <?, ?> ingMap ) {
1160+ ItemStack ing = ItemStack .deserialize (toStringKeyMap (ingMap ));
1161+ ingredients .add (ing );
1162+ }
1163+ }
1164+ recipe .setIngredients (ingredients );
1165+ }
1166+
1167+ return recipe ;
1168+ }
1169+
1170+ private Map <String , Object > toStringKeyMap (Map <?, ?> map ) {
1171+ Map <String , Object > result = new java .util .LinkedHashMap <>();
1172+ for (Map .Entry <?, ?> entry : map .entrySet ()) {
1173+ result .put (String .valueOf (entry .getKey ()), entry .getValue ());
1174+ }
1175+ return result ;
1176+ }
1177+
11131178 private Location toLocation (Object arg , Entity context ) {
11141179 if (arg instanceof Location loc ) return loc ;
11151180 if (arg instanceof List <?> list && list .size () >= 3 ) {
@@ -1885,6 +1950,51 @@ private Object invokeMobMethod(Entity entity, String method, List<Object> args)
18851950 goals .removeAllGoals (mob );
18861951 return null ;
18871952 }
1953+ // ── Villager trades ──────────────────────────────────────
1954+ case "getRecipes" -> {
1955+ if (!(mob instanceof org .bukkit .entity .AbstractVillager villager )) return UNHANDLED ;
1956+ List <org .bukkit .inventory .MerchantRecipe > recipes = villager .getRecipes ();
1957+ List <Map <String , Object >> result = new ArrayList <>();
1958+ for (org .bukkit .inventory .MerchantRecipe recipe : recipes ) {
1959+ result .add (serializeMerchantRecipe (recipe ));
1960+ }
1961+ return result ;
1962+ }
1963+ case "getRecipeCount" -> {
1964+ if (!(mob instanceof org .bukkit .entity .AbstractVillager villager )) return UNHANDLED ;
1965+ return villager .getRecipeCount ();
1966+ }
1967+ case "setRecipes" -> {
1968+ if (!(mob instanceof org .bukkit .entity .AbstractVillager villager )) return UNHANDLED ;
1969+ if (args .isEmpty ()) return null ;
1970+ @ SuppressWarnings ("unchecked" )
1971+ List <Map <String , Object >> recipeMaps = (List <Map <String , Object >>) args .get (0 );
1972+ List <org .bukkit .inventory .MerchantRecipe > recipes = new ArrayList <>();
1973+ for (Map <String , Object > map : recipeMaps ) {
1974+ org .bukkit .inventory .MerchantRecipe recipe = deserializeMerchantRecipe (map );
1975+ if (recipe != null ) recipes .add (recipe );
1976+ }
1977+ villager .setRecipes (recipes );
1978+ return null ;
1979+ }
1980+ case "addRecipe" -> {
1981+ if (!(mob instanceof org .bukkit .entity .AbstractVillager villager )) return UNHANDLED ;
1982+ if (args .isEmpty ()) return null ;
1983+ @ SuppressWarnings ("unchecked" )
1984+ Map <String , Object > recipeMap = (Map <String , Object >) args .get (0 );
1985+ org .bukkit .inventory .MerchantRecipe recipe = deserializeMerchantRecipe (recipeMap );
1986+ if (recipe != null ) {
1987+ List <org .bukkit .inventory .MerchantRecipe > recipes = new ArrayList <>(villager .getRecipes ());
1988+ recipes .add (recipe );
1989+ villager .setRecipes (recipes );
1990+ }
1991+ return null ;
1992+ }
1993+ case "clearRecipes" -> {
1994+ if (!(mob instanceof org .bukkit .entity .AbstractVillager villager )) return UNHANDLED ;
1995+ villager .setRecipes (new ArrayList <>());
1996+ return null ;
1997+ }
18881998 }
18891999 return UNHANDLED ;
18902000 }
0 commit comments