Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-28 09:00:11 +01:00
Update crafting recipe combinations calculation
Dieser Commit ist enthalten in:
Ursprung
e7a1063ee2
Commit
8a589129f0
@ -39,6 +39,8 @@ import lombok.EqualsAndHashCode;
|
|||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
|
import org.geysermc.connector.network.translators.item.ItemEntry;
|
||||||
|
import org.geysermc.connector.utils.Toolbox;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -54,8 +56,8 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator<ServerDeclare
|
|||||||
case CRAFTING_SHAPELESS: {
|
case CRAFTING_SHAPELESS: {
|
||||||
ShapelessRecipeData shapelessRecipeData = (ShapelessRecipeData) recipe.getData();
|
ShapelessRecipeData shapelessRecipeData = (ShapelessRecipeData) recipe.getData();
|
||||||
ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapelessRecipeData.getResult());
|
ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapelessRecipeData.getResult());
|
||||||
List<ItemData[]> inputList = combinations(shapelessRecipeData.getIngredients());
|
ItemData[][] inputCombinations = combinations(shapelessRecipeData.getIngredients());
|
||||||
for (ItemData[] inputs : inputList) {
|
for (ItemData[] inputs : inputCombinations) {
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
|
craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(),
|
||||||
inputs, new ItemData[]{output}, uuid, "crafting_table", 0));
|
inputs, new ItemData[]{output}, uuid, "crafting_table", 0));
|
||||||
@ -65,8 +67,8 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator<ServerDeclare
|
|||||||
case CRAFTING_SHAPED: {
|
case CRAFTING_SHAPED: {
|
||||||
ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData();
|
ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData();
|
||||||
ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapedRecipeData.getResult());
|
ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapedRecipeData.getResult());
|
||||||
List<ItemData[]> inputList = combinations(shapedRecipeData.getIngredients());
|
ItemData[][] inputCombinations = combinations(shapedRecipeData.getIngredients());
|
||||||
for (ItemData[] inputs : inputList) {
|
for (ItemData[] inputs : inputCombinations) {
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
|
craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(),
|
||||||
shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), inputs,
|
shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), inputs,
|
||||||
@ -79,37 +81,45 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator<ServerDeclare
|
|||||||
session.getUpstream().sendPacket(craftingDataPacket);
|
session.getUpstream().sendPacket(craftingDataPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ItemData[]> combinations(Ingredient[] ingredients) {
|
private ItemData[][] combinations(Ingredient[] ingredients) {
|
||||||
ItemData[][] squashed = new ItemData[ingredients.length][];
|
Map<Set<ItemData>, Set<Integer>> squashedOptions = new HashMap<>();
|
||||||
for (int i = 0; i < ingredients.length; i++) {
|
for (int i = 0; i < ingredients.length; i++) {
|
||||||
if (ingredients[i].getOptions().length == 0) {
|
if (ingredients[i].getOptions().length == 0) {
|
||||||
squashed[i] = new ItemData[]{ItemData.AIR};
|
squashedOptions.computeIfAbsent(Collections.singleton(ItemData.AIR), k -> new HashSet<>()).add(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Ingredient ingredient = ingredients[i];
|
Ingredient ingredient = ingredients[i];
|
||||||
Map<GroupedItem, List<ItemData>> groupedByIds = Arrays.stream(ingredient.getOptions())
|
Map<GroupedItem, List<ItemData>> groupedByIds = Arrays.stream(ingredient.getOptions())
|
||||||
.map(item -> TranslatorsInit.getItemTranslator().translateToBedrock(item))
|
.map(item -> TranslatorsInit.getItemTranslator().translateToBedrock(item))
|
||||||
.collect(Collectors.groupingBy(item -> new GroupedItem(item.getId(), item.getCount(), item.getTag())));
|
.collect(Collectors.groupingBy(item -> new GroupedItem(item.getId(), item.getCount(), item.getTag())));
|
||||||
squashed[i] = new ItemData[groupedByIds.size()];
|
Set<ItemData> optionSet = new HashSet<>(groupedByIds.size());
|
||||||
int index = 0;
|
|
||||||
for (Map.Entry<GroupedItem, List<ItemData>> entry : groupedByIds.entrySet()) {
|
for (Map.Entry<GroupedItem, List<ItemData>> entry : groupedByIds.entrySet()) {
|
||||||
if (entry.getValue().size() > 1) {
|
if (entry.getValue().size() > 1) {
|
||||||
GroupedItem groupedItem = entry.getKey();
|
GroupedItem groupedItem = entry.getKey();
|
||||||
squashed[i][index++] = ItemData.of(groupedItem.id, (short) -1, groupedItem.count, groupedItem.tag);
|
int idCount = 0;
|
||||||
|
//not optimal
|
||||||
|
for (ItemEntry itemEntry : Toolbox.ITEM_ENTRIES.valueCollection()) {
|
||||||
|
if (itemEntry.getBedrockId() == groupedItem.id) {
|
||||||
|
idCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (entry.getValue().size() < idCount) {
|
||||||
|
optionSet.addAll(entry.getValue());
|
||||||
|
} else {
|
||||||
|
optionSet.add(ItemData.of(groupedItem.id, (short) -1, groupedItem.count, groupedItem.tag));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ItemData item = entry.getValue().get(0);
|
ItemData item = entry.getValue().get(0);
|
||||||
squashed[i][index++] = item;
|
optionSet.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
squashedOptions.computeIfAbsent(optionSet, k -> new HashSet<>()).add(i);
|
||||||
}
|
}
|
||||||
int[] sizeArray = new int[squashed.length];
|
int totalCombinations = 1;
|
||||||
int[] counterArray = new int[squashed.length];
|
for (Set optionSet : squashedOptions.keySet()) {
|
||||||
int totalCombinationCount = 1;
|
totalCombinations *= optionSet.size();
|
||||||
for(int i = 0; i < squashed.length; i++) {
|
|
||||||
sizeArray[i] = squashed[i].length;
|
|
||||||
totalCombinationCount *= squashed[i].length;
|
|
||||||
}
|
}
|
||||||
if (totalCombinationCount > 10000) {
|
if (totalCombinations > 500) {
|
||||||
ItemData[] translatedItems = new ItemData[ingredients.length];
|
ItemData[] translatedItems = new ItemData[ingredients.length];
|
||||||
for (int i = 0; i < ingredients.length; i++) {
|
for (int i = 0; i < ingredients.length; i++) {
|
||||||
if (ingredients[i].getOptions().length > 0) {
|
if (ingredients[i].getOptions().length > 0) {
|
||||||
@ -118,25 +128,27 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator<ServerDeclare
|
|||||||
translatedItems[i] = ItemData.AIR;
|
translatedItems[i] = ItemData.AIR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Collections.singletonList(translatedItems);
|
return new ItemData[][]{translatedItems};
|
||||||
}
|
}
|
||||||
List<ItemData[]> combinationList = new ArrayList<>(totalCombinationCount);
|
List<Set<ItemData>> sortedSets = new ArrayList<>(squashedOptions.keySet());
|
||||||
for (int countdown = totalCombinationCount; countdown > 0; --countdown) {
|
sortedSets.sort(Comparator.comparing(Set::size, Comparator.reverseOrder()));
|
||||||
ItemData[] translatedItems = new ItemData[squashed.length];
|
ItemData[][] combinations = new ItemData[totalCombinations][ingredients.length];
|
||||||
for(int i = 0; i < squashed.length; ++i) {
|
int x = 1;
|
||||||
if (squashed[i].length > 0)
|
for (Set<ItemData> set : sortedSets) {
|
||||||
translatedItems[i] = squashed[i][counterArray[i]];
|
Set<Integer> slotSet = squashedOptions.get(set);
|
||||||
}
|
int i = 0;
|
||||||
combinationList.add(translatedItems);
|
for (ItemData item : set) {
|
||||||
for(int incIndex = squashed.length - 1; incIndex >= 0; --incIndex) {
|
for (int j = 0; j < totalCombinations / set.size(); j++) {
|
||||||
if(counterArray[incIndex] + 1 < sizeArray[incIndex]) {
|
final int comboIndex = (i * x) + (j % x) + ((j / x) * set.size() * x);
|
||||||
++counterArray[incIndex];
|
for (int slot : slotSet) {
|
||||||
break;
|
combinations[comboIndex][slot] = item;
|
||||||
}
|
|
||||||
counterArray[incIndex] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return combinationList;
|
i++;
|
||||||
|
}
|
||||||
|
x *= set.size();
|
||||||
|
}
|
||||||
|
return combinations;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren