Skip to content

Commit ba8eabb

Browse files
valapheeCopilot
andauthored
Fix stonecutter recipes being registered multiple times (#6150)
* Fix stonecutter recipes being registered multiple times * Rebuild crafting data packet from existing data * Remove the need for RecipeUtil::clearCache * Print when there is a potential bug, fixes * Make recipeNetId assignment "visible", ignore duplicate recipes * Update core/src/main/java/org/geysermc/geyser/translator/protocol/java/inventory/JavaContainerSetSlotTranslator.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * reset lastRecipeNetId properly * re-add skip for demo slot display --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 4abe649 commit ba8eabb

File tree

9 files changed

+541
-443
lines changed

9 files changed

+541
-443
lines changed

core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserRecipe.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@
2525

2626
package org.geysermc.geyser.inventory.recipe;
2727

28+
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData;
29+
import org.geysermc.geyser.session.GeyserSession;
2830
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
2931

32+
import java.util.List;
33+
3034
/**
3135
* A more compact version of {@link org.geysermc.mcprotocollib.protocol.data.game.recipe.display.RecipeDisplay}.
3236
*/
@@ -37,4 +41,6 @@ public interface GeyserRecipe {
3741
boolean isShaped();
3842

3943
SlotDisplay result();
44+
45+
List<RecipeData> asRecipeData(GeyserSession session);
4046
}

core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapedRecipe.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,53 @@
2525

2626
package org.geysermc.geyser.inventory.recipe;
2727

28+
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
29+
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.RecipeUnlockingRequirement;
30+
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData;
31+
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapedRecipeData;
32+
import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
33+
import org.geysermc.geyser.session.GeyserSession;
2834
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.ShapedCraftingRecipeDisplay;
2935
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
3036

37+
import java.util.ArrayList;
38+
import java.util.Collections;
3139
import java.util.List;
40+
import java.util.UUID;
3241

33-
public record GeyserShapedRecipe(int width, int height, List<SlotDisplay> ingredients, SlotDisplay result) implements GeyserRecipe {
42+
public record GeyserShapedRecipe(int id,
43+
int netId,
44+
int width,
45+
int height,
46+
List<SlotDisplay> ingredients,
47+
SlotDisplay result) implements GeyserRecipe {
3448

35-
public GeyserShapedRecipe(ShapedCraftingRecipeDisplay data) {
36-
this(data.width(), data.height(), data.ingredients(), data.result());
49+
public GeyserShapedRecipe(int id, int netId, ShapedCraftingRecipeDisplay data) {
50+
this(id, netId, data.width(), data.height(), data.ingredients(), data.result());
3751
}
3852

3953
@Override
4054
public boolean isShaped() {
4155
return true;
4256
}
57+
58+
@Override
59+
public List<RecipeData> asRecipeData(GeyserSession session) {
60+
var bedrockRecipes = RecipeUtil.combinations(session, result, ingredients);
61+
if (bedrockRecipes == null) {
62+
return List.of();
63+
}
64+
65+
List<RecipeData> recipeData = new ArrayList<>();
66+
ItemData output = bedrockRecipes.right();
67+
List<List<ItemDescriptorWithCount>> left = bedrockRecipes.left();
68+
int i = 0;
69+
for (List<ItemDescriptorWithCount> inputs : left) {
70+
recipeData.add(ShapedRecipeData.shaped(id + "_" + i, width, height, inputs,
71+
Collections.singletonList(output), UUID.randomUUID(), "crafting_table", 0,
72+
netId + i, false, RecipeUnlockingRequirement.INVALID));
73+
i++;
74+
}
75+
return recipeData;
76+
}
4377
}

core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserShapelessRecipe.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,51 @@
2525

2626
package org.geysermc.geyser.inventory.recipe;
2727

28+
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
29+
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.RecipeUnlockingRequirement;
30+
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData;
31+
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.ShapelessRecipeData;
32+
import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
33+
import org.geysermc.geyser.session.GeyserSession;
2834
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.ShapelessCraftingRecipeDisplay;
2935
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
3036

37+
import java.util.ArrayList;
38+
import java.util.Collections;
3139
import java.util.List;
40+
import java.util.UUID;
3241

33-
public record GeyserShapelessRecipe(List<SlotDisplay> ingredients, SlotDisplay result) implements GeyserRecipe {
42+
public record GeyserShapelessRecipe(int id,
43+
int netId,
44+
List<SlotDisplay> ingredients,
45+
SlotDisplay result) implements GeyserRecipe {
3446

35-
public GeyserShapelessRecipe(ShapelessCraftingRecipeDisplay data) {
36-
this(data.ingredients(), data.result());
47+
public GeyserShapelessRecipe(int id, int netId, ShapelessCraftingRecipeDisplay data) {
48+
this(id, netId, data.ingredients(), data.result());
3749
}
3850

3951
@Override
4052
public boolean isShaped() {
4153
return false;
4254
}
55+
56+
@Override
57+
public List<RecipeData> asRecipeData(GeyserSession session) {
58+
var bedrockRecipes = RecipeUtil.combinations(session, result, ingredients);
59+
if (bedrockRecipes == null) {
60+
return List.of();
61+
}
62+
63+
List<RecipeData> recipeData = new ArrayList<>();
64+
ItemData output = bedrockRecipes.right();
65+
List<List<ItemDescriptorWithCount>> left = bedrockRecipes.left();
66+
int i = 0;
67+
for (List<ItemDescriptorWithCount> inputs : left) {
68+
recipeData.add(ShapelessRecipeData.shapeless(id + "_" + i, inputs,
69+
Collections.singletonList(output), UUID.randomUUID(), "crafting_table", 0,
70+
netId + i, RecipeUnlockingRequirement.INVALID));
71+
i++;
72+
}
73+
return recipeData;
74+
}
4375
}

core/src/main/java/org/geysermc/geyser/inventory/recipe/GeyserSmithingRecipe.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,60 @@
2525

2626
package org.geysermc.geyser.inventory.recipe;
2727

28+
import it.unimi.dsi.fastutil.Pair;
29+
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
30+
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData;
31+
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.SmithingTransformRecipeData;
32+
import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
33+
import org.geysermc.geyser.item.type.Item;
34+
import org.geysermc.geyser.session.GeyserSession;
2835
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.SmithingRecipeDisplay;
2936
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
3037

31-
public record GeyserSmithingRecipe(SlotDisplay template,
38+
import java.util.ArrayList;
39+
import java.util.List;
40+
41+
public record GeyserSmithingRecipe(int id,
42+
int netId,
43+
SlotDisplay template,
3244
SlotDisplay base,
3345
SlotDisplay addition,
3446
SlotDisplay result) implements GeyserRecipe {
35-
public GeyserSmithingRecipe(SmithingRecipeDisplay display) {
36-
this(display.template(), display.base(), display.addition(), display.result());
47+
public GeyserSmithingRecipe(int id, int netId, SmithingRecipeDisplay display) {
48+
this(id, netId, display.template(), display.base(), display.addition(), display.result());
3749
}
3850

3951
@Override
4052
public boolean isShaped() {
4153
return false;
4254
}
55+
56+
@Override
57+
public List<RecipeData> asRecipeData(GeyserSession session) {
58+
Pair<Item, ItemData> output = RecipeUtil.translateToOutput(session, result);
59+
if (output == null) {
60+
return List.of();
61+
}
62+
63+
List<ItemDescriptorWithCount> bases = RecipeUtil.translateToInput(session, base);
64+
List<ItemDescriptorWithCount> templates = RecipeUtil.translateToInput(session, template);
65+
List<ItemDescriptorWithCount> additions = RecipeUtil.translateToInput(session, addition);
66+
if (bases == null || templates == null || additions == null) {
67+
return List.of();
68+
}
69+
70+
List<RecipeData> recipeData = new ArrayList<>();
71+
int i = 0;
72+
for (ItemDescriptorWithCount template : templates) {
73+
for (ItemDescriptorWithCount base : bases) {
74+
for (ItemDescriptorWithCount addition : additions) {
75+
// Note: vanilla inputs use aux value of Short.MAX_VALUE
76+
recipeData.add(SmithingTransformRecipeData.of(id + "_" + i, template, base, addition,
77+
output.right(), "smithing_table", netId + i));
78+
i++;
79+
}
80+
}
81+
}
82+
return recipeData;
83+
}
4384
}

0 commit comments

Comments
 (0)