1+ package io.github.pylonmc.rebar.nms.recipe
2+
3+ import net.minecraft.core.registries.Registries
4+ import net.minecraft.world.item.crafting.AbstractCookingRecipe
5+ import net.minecraft.world.item.crafting.CampfireCookingRecipe
6+ import net.minecraft.world.item.crafting.CraftingRecipe
7+ import net.minecraft.world.item.crafting.RecipeHolder
8+ import net.minecraft.world.item.crafting.ShapedRecipePattern
9+ import net.minecraft.world.item.crafting.SmeltingRecipe
10+ import net.minecraft.world.item.crafting.StonecutterRecipe
11+ import org.bukkit.craftbukkit.CraftServer
12+ import org.bukkit.craftbukkit.inventory.CraftItemStack
13+ import org.bukkit.craftbukkit.inventory.CraftRecipe
14+ import org.bukkit.craftbukkit.inventory.trim.CraftTrimPattern
15+ import org.bukkit.craftbukkit.util.CraftNamespacedKey
16+ import org.bukkit.inventory.BlastingRecipe
17+ import org.bukkit.inventory.CampfireRecipe
18+ import org.bukkit.inventory.FurnaceRecipe
19+ import org.bukkit.inventory.Recipe
20+ import org.bukkit.inventory.ShapedRecipe
21+ import org.bukkit.inventory.ShapelessRecipe
22+ import org.bukkit.inventory.SmithingTransformRecipe
23+ import org.bukkit.inventory.SmithingTrimRecipe
24+ import org.bukkit.inventory.SmokingRecipe
25+ import org.bukkit.inventory.StonecuttingRecipe
26+ import org.bukkit.inventory.TransmuteRecipe
27+ import java.util.Objects
28+ import net.minecraft.world.item.crafting.BlastingRecipe as NmsBlastingRecipe
29+ import net.minecraft.world.item.crafting.Recipe as NmsRecipe
30+ import net.minecraft.world.item.crafting.ShapedRecipe as NmsShapedRecipe
31+ import net.minecraft.world.item.crafting.ShapelessRecipe as NmsShapelessRecipe
32+ import net.minecraft.world.item.crafting.SmithingTransformRecipe as NmsSmithingTransformRecipe
33+ import net.minecraft.world.item.crafting.SmithingTrimRecipe as NmsSmithingTrimRecipe
34+ import net.minecraft.world.item.crafting.SmokingRecipe as NmsSmokingRecipe
35+ import net.minecraft.world.item.crafting.TransmuteRecipe as NmsTransmuteRecipe
36+
37+ /* *
38+ * Handles the conversion of bukkit recipes to nms recipes
39+ * This has to be done manually because any existing conversion will individually
40+ * convert and automatically register the recipe to the nms recipe manager and reload it.
41+ *
42+ * This is a problem because reloading the recipe manager is an expensive operation and
43+ * doing it for every single recipe will cause a lot of lag.
44+ *
45+ * By manually converting the recipes we can register them all at once and reload
46+ * the recipe manager only once saving up a LOT of tick time.
47+ *
48+ * Reference [CraftServer.addRecipe] to keep this up to date w/ version changes
49+ */
50+ object RecipeMapper {
51+ fun convertBukkitRecipe (recipe : Recipe ): RecipeHolder <NmsRecipe <* >> {
52+ val nmsRecipe = when (recipe) {
53+ is ShapedRecipe -> convertShapedRecipe(recipe)
54+ is ShapelessRecipe -> convertShapelessRecipe(recipe)
55+ is FurnaceRecipe -> convertFurnaceRecipe(recipe)
56+ is BlastingRecipe -> convertBlastingRecipe(recipe)
57+ is CampfireRecipe -> convertCampfireRecipe(recipe)
58+ is SmokingRecipe -> convertSmokingRecipe(recipe)
59+ is StonecuttingRecipe -> convertStonecuttingRecipe(recipe)
60+ is SmithingTransformRecipe -> convertSmithingTransformRecipe(recipe)
61+ is SmithingTrimRecipe -> convertSmithingTrimRecipe(recipe)
62+ is TransmuteRecipe -> convertTransmuteRecipe(recipe)
63+ else -> {
64+ throw IllegalArgumentException (" Unknown recipe type ${recipe.javaClass.canonicalName} , cannot convert to NMS type" )
65+ }
66+ }
67+ return RecipeHolder (CraftNamespacedKey .toResourceKey(Registries .RECIPE , recipe.key), nmsRecipe)
68+ }
69+
70+ private fun commonInfo () = NmsRecipe .CommonInfo (true )
71+
72+ private fun convertShapedRecipe (recipe : ShapedRecipe ): NmsRecipe <* > {
73+ val ingredients = recipe.choiceMap.filterValues(Objects ::nonNull)
74+ .mapValues { CraftRecipe .toIngredient(it.value, false ) }
75+ val shape = recipe.shape
76+ for (i in shape.indices) {
77+ val row = shape[i]
78+ shape[i] = row.toCharArray().map { if (it in ingredients) it else ' ' }.joinToString(" " )
79+ }
80+ return NmsShapedRecipe (
81+ commonInfo(),
82+ CraftingRecipe .CraftingBookInfo (
83+ CraftRecipe .getCategory(recipe.category),
84+ recipe.group
85+ ),
86+ ShapedRecipePattern .of(ingredients, * shape),
87+ CraftItemStack .asTemplate(recipe.result)
88+ )
89+ }
90+
91+ private fun convertShapelessRecipe (recipe : ShapelessRecipe ): NmsRecipe <* > {
92+ val ingredients = recipe.choiceList.map { CraftRecipe .toIngredient(it, false ) }
93+ return NmsShapelessRecipe (
94+ commonInfo(),
95+ CraftingRecipe .CraftingBookInfo (
96+ CraftRecipe .getCategory(recipe.category),
97+ recipe.group
98+ ),
99+ CraftItemStack .asTemplate(recipe.result),
100+ ingredients
101+ )
102+ }
103+
104+ private fun convertFurnaceRecipe (recipe : FurnaceRecipe ): NmsRecipe <* > {
105+ return SmeltingRecipe (
106+ commonInfo(),
107+ AbstractCookingRecipe .CookingBookInfo (
108+ CraftRecipe .getCategory(recipe.category),
109+ recipe.group
110+ ),
111+ CraftRecipe .toIngredient(recipe.inputChoice, true ),
112+ CraftItemStack .asTemplate(recipe.result),
113+ recipe.experience,
114+ recipe.cookingTime
115+ )
116+ }
117+
118+ private fun convertBlastingRecipe (recipe : BlastingRecipe ): NmsRecipe <* > {
119+ return NmsBlastingRecipe (
120+ commonInfo(),
121+ AbstractCookingRecipe .CookingBookInfo (
122+ CraftRecipe .getCategory(recipe.category),
123+ recipe.group
124+ ),
125+ CraftRecipe .toIngredient(recipe.inputChoice, true ),
126+ CraftItemStack .asTemplate(recipe.result),
127+ recipe.experience,
128+ recipe.cookingTime
129+ )
130+ }
131+
132+ private fun convertCampfireRecipe (recipe : CampfireRecipe ): NmsRecipe <* > {
133+ return CampfireCookingRecipe (
134+ commonInfo(),
135+ AbstractCookingRecipe .CookingBookInfo (
136+ CraftRecipe .getCategory(recipe.category),
137+ recipe.group
138+ ),
139+ CraftRecipe .toIngredient(recipe.inputChoice, true ),
140+ CraftItemStack .asTemplate(recipe.result),
141+ recipe.experience,
142+ recipe.cookingTime
143+ )
144+ }
145+
146+ private fun convertSmokingRecipe (recipe : SmokingRecipe ): NmsRecipe <* > {
147+ return NmsSmokingRecipe (
148+ commonInfo(),
149+ AbstractCookingRecipe .CookingBookInfo (
150+ CraftRecipe .getCategory(recipe.category),
151+ recipe.group
152+ ),
153+ CraftRecipe .toIngredient(recipe.inputChoice, true ),
154+ CraftItemStack .asTemplate(recipe.result),
155+ recipe.experience,
156+ recipe.cookingTime
157+ )
158+ }
159+
160+ private fun convertStonecuttingRecipe (recipe : StonecuttingRecipe ): NmsRecipe <* > {
161+ return StonecutterRecipe (
162+ commonInfo(),
163+ CraftRecipe .toIngredient(recipe.inputChoice, true ),
164+ CraftItemStack .asTemplate(recipe.result)
165+ )
166+ }
167+
168+ private fun convertSmithingTransformRecipe (recipe : SmithingTransformRecipe ): NmsRecipe <* > {
169+ return NmsSmithingTransformRecipe (
170+ commonInfo(),
171+ CraftRecipe .toPossibleIngredient(recipe.template, false ),
172+ CraftRecipe .toIngredient(recipe.base, false ),
173+ CraftRecipe .toPossibleIngredient(recipe.addition, false ),
174+ CraftItemStack .asTemplate(recipe.result),
175+ recipe.willCopyDataComponents()
176+ )
177+ }
178+
179+ private fun convertSmithingTrimRecipe (recipe : SmithingTrimRecipe ): NmsRecipe <* > {
180+ return NmsSmithingTrimRecipe (
181+ commonInfo(),
182+ CraftRecipe .toIngredient(recipe.template, false ),
183+ CraftRecipe .toIngredient(recipe.base, false ),
184+ CraftRecipe .toIngredient(recipe.addition, false ),
185+ CraftTrimPattern .bukkitToMinecraftHolder(recipe.trimPattern),
186+ recipe.willCopyDataComponents()
187+ )
188+ }
189+
190+ private fun convertTransmuteRecipe (recipe : TransmuteRecipe ): NmsRecipe <* > {
191+ return NmsTransmuteRecipe (
192+ commonInfo(),
193+ CraftingRecipe .CraftingBookInfo (
194+ CraftRecipe .getCategory(recipe.category),
195+ recipe.group
196+ ),
197+ CraftRecipe .toIngredient(recipe.input, true ),
198+ CraftRecipe .toIngredient(recipe.material, true ),
199+ NmsTransmuteRecipe .DEFAULT_MATERIAL_COUNT ,
200+ CraftItemStack .asTemplate(recipe.result),
201+ false
202+ )
203+ }
204+
205+ }
0 commit comments