Sort recipes

This commit is contained in:
Nassim Jahnke 2024-10-16 10:26:32 +02:00
parent 16eca5f6aa
commit fd85b67a92
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F

View File

@ -29,12 +29,17 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2; import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21; import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import java.util.List; import java.util.List;
// Mostly a lost cause as the server will not send all the necessary data.
// Recipe displays can also be different from the actual recipe - at the end of the same,
// the server will still properly handle inputs, but we can't fully reconstruct the recipe book.
public final class RecipeStorage implements StorableObject { public final class RecipeStorage implements StorableObject {
// Pairs of open + filtering for: Crafting, furnace, blast furnace, smoker // Pairs of open + filtering for: Crafting, furnace, blast furnace, smoker
public static final int RECIPE_BOOK_SETTINGS = 4 * 2; public static final int RECIPE_BOOK_SETTINGS = 4 * 2;
private static final String[] EMPTY_STRINGS = new String[0];
private final List<Recipe> recipes = new ArrayList<>(); private final List<Recipe> recipes = new ArrayList<>();
private final List<Recipe> tempRecipes = new ArrayList<>(); private final List<Recipe> tempRecipes = new ArrayList<>();
private final List<StoneCutterRecipe> stoneCutterRecipes = new ArrayList<>(); private final List<StoneCutterRecipe> stoneCutterRecipes = new ArrayList<>();
@ -46,9 +51,13 @@ public final class RecipeStorage implements StorableObject {
} }
abstract static class Recipe { abstract static class Recipe {
private static final int FOOD_CRAFTING_BOOK_CATEGORY = 0;
private static final int BLOCKS_CRAFTING_BOOK_CATEGORY = 1;
private static final int MISC_CRAFTING_BOOK_CATEGORY = 2;
protected int index; protected int index;
private Integer group; private Integer group;
private int category; private int category;
private boolean highlight;
private boolean locked; private boolean locked;
abstract void write(PacketWrapper wrapper); abstract void write(PacketWrapper wrapper);
@ -77,7 +86,14 @@ public final class RecipeStorage implements StorableObject {
} }
void writeCategory(final PacketWrapper wrapper) { void writeCategory(final PacketWrapper wrapper) {
wrapper.write(Types.VAR_INT, 0); // TODO // TODO Doesn't translate exactly
final int craftingBookCategory = switch (category) {
case 4, 9, 12 -> FOOD_CRAFTING_BOOK_CATEGORY;
case 0, 5, 7, 10 -> BLOCKS_CRAFTING_BOOK_CATEGORY;
case 1, 2, 3, 6, 8, 11 -> MISC_CRAFTING_BOOK_CATEGORY;
default -> MISC_CRAFTING_BOOK_CATEGORY;
};
wrapper.write(Types.VAR_INT, craftingBookCategory);
} }
int category() { int category() {
@ -104,11 +120,14 @@ public final class RecipeStorage implements StorableObject {
recipes.add(recipe); recipes.add(recipe);
} }
// Sort by id
recipes.sort(Comparator.comparingInt(a -> a.index));
// Since the server only sends unlocked recipes, we need to re-send all recipes in UPDATE_RECIPES // Since the server only sends unlocked recipes, we need to re-send all recipes in UPDATE_RECIPES
final PacketWrapper updateRecipesPacket = PacketWrapper.create(ClientboundPackets1_21.UPDATE_RECIPES, connection); final PacketWrapper updateRecipesPacket = PacketWrapper.create(ClientboundPackets1_21.UPDATE_RECIPES, connection);
updateRecipesPacket.write(Types.VAR_INT, recipes.size()); updateRecipesPacket.write(Types.VAR_INT, recipes.size());
for (final Recipe recipe : recipes) { for (final Recipe recipe : recipes) {
updateRecipesPacket.write(Types.STRING, Integer.toString(recipe.index)); // Use index as the recipe identifier updateRecipesPacket.write(Types.STRING, identifier(recipe.index));
recipe.write(updateRecipesPacket); recipe.write(updateRecipesPacket);
} }
updateRecipesPacket.send(Protocol1_21_2To1_21.class); updateRecipesPacket.send(Protocol1_21_2To1_21.class);
@ -116,6 +135,11 @@ public final class RecipeStorage implements StorableObject {
sendUnlockedRecipes(connection, recipes); sendUnlockedRecipes(connection, recipes);
} }
private static String identifier(final int recipeIndex) {
// Use index as the recipe identifier, add leading zeros to keept it sorted
return String.format("%06d", recipeIndex);
}
public void lockRecipes(final PacketWrapper wrapper, final int[] ids) { public void lockRecipes(final PacketWrapper wrapper, final int[] ids) {
for (final int id : ids) { for (final int id : ids) {
recipes.get(id).locked = true; recipes.get(id).locked = true;
@ -128,13 +152,12 @@ public final class RecipeStorage implements StorableObject {
final String[] recipeKeys = new String[ids.length]; final String[] recipeKeys = new String[ids.length];
for (int i = 0; i < ids.length; i++) { for (int i = 0; i < ids.length; i++) {
recipeKeys[i] = Integer.toString(ids[i]); recipeKeys[i] = identifier(ids[i]);
} }
wrapper.write(Types.STRING_ARRAY, recipeKeys); wrapper.write(Types.STRING_ARRAY, recipeKeys);
} }
private void sendUnlockedRecipes(final UserConnection connection, final List<Recipe> recipes) { private void sendUnlockedRecipes(final UserConnection connection, final List<Recipe> recipes) {
// TODO Not working?
final PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_21.RECIPE, connection); final PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_21.RECIPE, connection);
wrapper.write(Types.VAR_INT, 0); // Init recipes wrapper.write(Types.VAR_INT, 0); // Init recipes
@ -144,12 +167,16 @@ public final class RecipeStorage implements StorableObject {
// Use index as the recipe identifier. We only know the unlocked ones, so send all // Use index as the recipe identifier. We only know the unlocked ones, so send all
final String[] recipeKeys = new String[recipes.size()]; final String[] recipeKeys = new String[recipes.size()];
final List<String> highlightRecipes = new ArrayList<>();
for (int i = 0; i < recipes.size(); i++) { for (int i = 0; i < recipes.size(); i++) {
recipeKeys[i] = Integer.toString(i); recipeKeys[i] = identifier(i);
if (recipes.get(i).highlight) {
highlightRecipes.add(recipeKeys[i]);
}
} }
wrapper.write(Types.STRING_ARRAY, recipeKeys); wrapper.write(Types.STRING_ARRAY, recipeKeys);
wrapper.write(Types.STRING_ARRAY, new String[0]); // Highlights // TODO wrapper.write(Types.STRING_ARRAY, highlightRecipes.toArray(EMPTY_STRINGS));
wrapper.send(Protocol1_21_2To1_21.class); wrapper.send(Protocol1_21_2To1_21.class);
} }
@ -170,7 +197,7 @@ public final class RecipeStorage implements StorableObject {
if (wrapper.read(Types.BOOLEAN)) { if (wrapper.read(Types.BOOLEAN)) {
final int ingredientsSize = wrapper.read(Types.VAR_INT); final int ingredientsSize = wrapper.read(Types.VAR_INT);
for (int j = 0; j < ingredientsSize; j++) { for (int j = 0; j < ingredientsSize; j++) {
//handleIngredient(wrapper); // Items //TODO //handleIngredient(wrapper); // Items //TODO ?
wrapper.read(Types.HOLDER_SET); wrapper.read(Types.HOLDER_SET);
} }
} }
@ -180,6 +207,7 @@ public final class RecipeStorage implements StorableObject {
recipe.index = id; recipe.index = id;
recipe.group = group; recipe.group = group;
recipe.category = category; recipe.category = category;
recipe.highlight = (flags & 2) != 0;
} }
} }
@ -268,7 +296,7 @@ public final class RecipeStorage implements StorableObject {
yield new Item[]{item}; yield new Item[]{item};
} }
case 4 -> { case 4 -> {
wrapper.read(Types.STRING); // Tag key // TODO wrapper.read(Types.STRING); // Tag key // TODO Probably not even worth the effort
yield new Item[0]; yield new Item[0];
} }
case 5 -> { case 5 -> {
@ -306,7 +334,7 @@ public final class RecipeStorage implements StorableObject {
private Item[] readHolderSet(final PacketWrapper wrapper) { private Item[] readHolderSet(final PacketWrapper wrapper) {
final HolderSet holderSet = wrapper.read(Types.HOLDER_SET); final HolderSet holderSet = wrapper.read(Types.HOLDER_SET);
if (holderSet.hasTagKey()) { if (holderSet.hasTagKey()) {
return new Item[]{new StructuredItem(1, 1)}; // TODO return new Item[]{new StructuredItem(1, 1)}; // TODO Probably not even worth the effort
} }
final int[] ids = holderSet.ids(); final int[] ids = holderSet.ids();