Fix crafting and some other bugs

This commit is contained in:
Bruno Rybársky 2024-07-04 16:19:50 +02:00
parent c6b94b2716
commit c1f238c928
8 changed files with 131 additions and 163 deletions

@ -11,7 +11,7 @@ loader_version=0.15.11
fabric_version=0.100.4+1.21
# Mod Properties
mod_version=2.6.2
mod_version=3.0.0
maven_group=systems.brn
archives_base_name=Server_storage

@ -56,9 +56,6 @@ public class ServerStorage implements ModInitializer {
public static List<Item> DRIVES;
public static List<Item> HEADS;
public static final GameRules.Key<GameRules.BooleanRule> ServerStorage_Crafting_Enable =
GameRuleRegistry.register("enableServerStorageCrafting", GameRules.Category.MISC, GameRuleFactory.createBooleanRule(false));
public static Identifier id(String path) {
return Identifier.of(MOD_ID, path);

@ -6,6 +6,7 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.math.BlockPos;
import systems.brn.server_storage.lib.StorageNetwork;
import systems.brn.server_storage.screens.CraftingScreen;
import systems.brn.server_storage.screens.StorageScreen;
import java.util.ArrayList;
@ -14,22 +15,19 @@ import static systems.brn.server_storage.ServerStorage.STORAGE_INTERFACE_BLOCK_E
public class StorageInterfaceBlockEntity extends BlockEntity {
public void removeScreen(StorageScreen storageScreenToDelete) {
openStorageScreens.remove(storageScreenToDelete);
}
public Boolean sortAlphabetically = false;
public String searchString = "";
public int page = 0;
public StorageNetwork network;
public final ArrayList<StorageScreen> openStorageScreens = new ArrayList<>();
public final ArrayList<CraftingScreen> openCraftingScreens = new ArrayList<>();
public StorageInterfaceBlockEntity(BlockPos pos, BlockState state) {
super(STORAGE_INTERFACE_BLOCK_ENTITY, pos, state);
}
public void justReindexDrives() {
public void reindexDrives() {
if (this.network != null) {
this.network.reindexNetwork(world, this.pos, sortAlphabetically, searchString);
} else {
@ -37,8 +35,8 @@ public class StorageInterfaceBlockEntity extends BlockEntity {
}
}
public void reindexDrives() {
justReindexDrives();
public void refreshTerminals() {
reindexDrives();
this.network.updateDisplays();
}
@ -46,6 +44,9 @@ public class StorageInterfaceBlockEntity extends BlockEntity {
for (StorageScreen screen : openStorageScreens) {
screen.updateDisplay();
}
for (CraftingScreen screen : openCraftingScreens) {
screen.updateDisplay();
}
}
// Serialize the BlockEntity

@ -180,7 +180,7 @@ public class StorageNetwork {
}
public boolean canRemove(ItemStack stackToRemove) {
return canRemoveCount(stackToRemove, itemStackMap) == 0;
return canRemoveRemainingCount(stackToRemove, itemStackMap) == 0;
}
public ItemStack removeItemStack(ItemStack stackToRemove) {

@ -159,7 +159,7 @@ public class StorageOperations {
return out;
}
public static int canRemoveCount(ItemStack stackToRemove, Map<ItemStack, Integer> itemsMap) {
public static int canRemoveRemainingCount(ItemStack stackToRemove, Map<ItemStack, Integer> itemsMap) {
int remainingToRemove = stackToRemove.getCount();
for (Map.Entry<ItemStack, Integer> entry : itemsMap.entrySet()) {

@ -112,95 +112,58 @@ public class Util {
ArrayList<CraftingEntry> craftingEntries = new ArrayList<>();
for (RecipeEntry<CraftingRecipe> recipe : allRecipes) {
int maxAmount = -1;
int maxAmount = Integer.MAX_VALUE;
boolean canMake = true;
boolean needToAdd = true;
CraftingEntry finalEntry;
HashMap<ItemStack, Integer> finalInputs = new HashMap<>();
Map<Item, Integer> ingredientCounts = new HashMap<>();
// Count the occurrences of each ingredient in the recipe
for (Ingredient ingredient : recipe.value().getIngredients()) {
HashMap<ItemStack, Integer> inputsTemp = new HashMap<>();
for (ItemStack stack : ingredient.getMatchingStacks()) {
if (stack.isEmpty()) {
break;
} else {
//if inventory contains stack
boolean foundUsableStack = false;
for (Map.Entry<ItemStack, Integer> entry : inputsTemp.entrySet()) {
ItemStack stackIn = entry.getKey();
Integer count = entry.getValue();
if (stackIn.getItem() == stack.getItem()) {
count += stack.getCount();
entry.setValue(count); // Update the value in the map
foundUsableStack = true;
break;
if (stack.isEmpty()) continue;
ingredientCounts.put(stack.getItem(), ingredientCounts.getOrDefault(stack.getItem(), 0) + 1);
}
}
if (!foundUsableStack) {
inputsTemp.put(stack, stack.getCount());
boolean usesAnyIngredient = false;
for (Ingredient ingredient : recipe.value().getIngredients()) {
int totalAvailable = 0;
HashMap<ItemStack, Integer> inputsTemp = new HashMap<>();
for (ItemStack stack : ingredient.getMatchingStacks()) {
if (stack.isEmpty()) continue;
for (Map.Entry<ItemStack, Integer> entry : itemStackMap.entrySet()) {
ItemStack inventoryStack = entry.getKey();
int inventoryCount = entry.getValue();
if (ItemStack.areItemsEqual(stack, inventoryStack)) {
totalAvailable += inventoryCount;
inputsTemp.put(stack, inventoryCount);
usesAnyIngredient = true;
}
}
}
HashMap<ItemStack, Integer> inputs = new HashMap<>();
for (Map.Entry<ItemStack, Integer> entry : inputsTemp.entrySet()) {
ItemStack stackIn = entry.getKey();
Integer count = entry.getValue();
stackIn.setCount(count);
inputs.put(stackIn, stackIn.getCount());
}
for (Map.Entry<ItemStack, Integer> entry : inputs.entrySet()) {
ItemStack stackIn = entry.getKey();
Integer count = entry.getValue();
boolean itemFound = false;
for (Map.Entry<ItemStack, Integer> itemEntry : itemStackMap.entrySet()){
Item slotItem = itemEntry.getKey().getItem();
int slotCount = itemEntry.getValue();
if (stackIn.getItem() == slotItem) {
count -= slotCount;
entry.setValue(count);
itemFound = true;
}
}
if (!itemFound) {
maxAmount = 0;
}
}
for (Map.Entry<ItemStack, Integer> entry : inputs.entrySet()) {
ItemStack stackIn = entry.getKey();
Integer count = entry.getValue();
if (count > 0) {
if (totalAvailable == 0) {
canMake = false;
} else {
int thisMaxAmount = Math.floorDivExact(Math.abs(count), stackIn.getCount());
if (maxAmount == -1) {
maxAmount = thisMaxAmount;
} else {
maxAmount = Math.min(maxAmount, thisMaxAmount);
}
}
}
if (maxAmount > 0 && canMake && needToAdd) {
ItemStack outputItem = recipe.value().getResult(server.getRegistryManager()).copy();
finalEntry = new CraftingEntry(outputItem, recipe, inputs, maxAmount);
finalInputs.putAll(inputs);
for (int i = 0; i < craftingEntries.size(); i++) {
CraftingEntry entryLoop = craftingEntries.get(i);
for (ItemStack outputStack : entryLoop.outputStacks) {
if (ItemStack.areItemsAndComponentsEqual(outputStack, outputItem)) {
needToAdd = false;
if (maxAmount > outputStack.getCount()) {
craftingEntries.set(i, finalEntry);
break;
}
int requiredCount = ingredient.getMatchingStacks()[0].getCount();
int occurrences = ingredientCounts.get(ingredient.getMatchingStacks()[0].getItem());
maxAmount = Math.min(maxAmount, totalAvailable / (requiredCount * occurrences));
for (Map.Entry<ItemStack, Integer> entry : inputsTemp.entrySet()) {
ItemStack stackIn = entry.getKey();
int count = entry.getValue();
finalInputs.put(stackIn, count);
}
}
}
} else {
break;
}
}
if (needToAdd && maxAmount > 0) {
if (canMake && maxAmount > 0 && usesAnyIngredient) {
ItemStack outputItem = recipe.value().getResult(server.getRegistryManager()).copy();
finalEntry = new CraftingEntry(outputItem, recipe, finalInputs, maxAmount);
CraftingEntry finalEntry = new CraftingEntry(outputItem, recipe, finalInputs, maxAmount);
craftingEntries.add(finalEntry);
}
}

@ -23,11 +23,8 @@ import static systems.brn.server_storage.lib.Util.getCraftableRecipes;
public class CraftingScreen extends PagedGui {
private final StorageScreen storageScreen;
private ArrayList<CraftingEntry> craftingEntries;
private final StorageInterfaceBlockEntity blockEntity;
private ArrayList<DisplayElement> recipesList;
public CraftingScreen(StorageScreen storageScreen) {
@ -39,8 +36,8 @@ public class CraftingScreen extends PagedGui {
}
@Override
public void updateDisplay(){
blockEntity.reindexDrives();
public void updateDisplay() {
blockEntity.reindexDrives(); // Use justReindexDrives to avoid looping
Map<ItemStack, Integer> itemStackMap = new HashMap<>();
addInventoryToMap(storageScreen.getPlayer().getInventory(), itemStackMap);
itemStackMap.putAll(blockEntity.network.itemStackMap);
@ -54,7 +51,7 @@ public class CraftingScreen extends PagedGui {
ArrayList<DisplayElement> recipes = new ArrayList<>();
for (CraftingEntry craftingEntry : craftingEntries) {
ItemStack stackWithCount = craftingEntry.outputStacks.getFirst().copy();
ItemStack stackWithCount = craftingEntry.outputStacks.get(0).copy();
if (stackWithCount.getCount() > stackWithCount.getMaxCount()) {
stackWithCount.setCount(stackWithCount.getMaxCount());
}
@ -68,14 +65,14 @@ public class CraftingScreen extends PagedGui {
if (clickType.isLeft) { // put into player inventory
if (clickType.shift) { // craft all
craftAll(player, recipeEntry, true);
} else { // craft one stack
craftOneStack(player, recipeEntry, true);
} else { // craft one
craftOne(player, recipeEntry, true);
}
} else if (clickType.isRight) { // put back into storage
if (clickType.shift) { // craft all
craftAll(player, recipeEntry, false);
} else { // craft one stack
craftOneStack(player, recipeEntry, false);
} else { // craft one
craftOne(player, recipeEntry, false);
}
}
updateDisplay();
@ -88,7 +85,7 @@ public class CraftingScreen extends PagedGui {
private void craftAll(PlayerEntity player, RecipeEntry<CraftingRecipe> recipeEntry, boolean toPlayerInventory) {
while (canCraft(recipeEntry)) {
if (craftOneStack(player, recipeEntry, toPlayerInventory)) {
if (craftOne(player, recipeEntry, toPlayerInventory)) {
return;
}
}
@ -96,94 +93,109 @@ public class CraftingScreen extends PagedGui {
private boolean canCraft(RecipeEntry<CraftingRecipe> recipeEntry) {
for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
ItemStack stackToRemove = findMatchingStack(ingredient);
if (stackToRemove == null) {
return false;
}
int requiredCount = canRemoveCount(stackToRemove, this.blockEntity.network.itemStackMap);
Map<ItemStack, Integer> playerInventory = new HashMap<>();
addInventoryToMap(this.storageScreen.getPlayer().getInventory(), playerInventory);
if (requiredCount > 0 && canRemoveCount(stackToRemove, playerInventory) < requiredCount) {
if (findMatchingStack(ingredient) == null) {
return false;
}
}
return true;
}
private boolean craftOneStack(PlayerEntity player, RecipeEntry<CraftingRecipe> recipeEntry, boolean toPlayerInventory) {
if (!canCraft(recipeEntry)) {
return true; //stop
}
private boolean craftOne(PlayerEntity player, RecipeEntry<CraftingRecipe> recipeEntry, boolean toPlayerInventory) {
ArrayList<ItemStack> stacksToRemove = new ArrayList<>();
// Check and remove ingredients
if (!canCraft(recipeEntry)) {
return true;
}
// Check and remove ingredients for one crafting operation
for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
ItemStack stackToRemove = findMatchingStack(ingredient);
if (stackToRemove == null) {
return false; // Unable to find required ingredient
}
stacksToRemove.add(stackToRemove);
}
// Remove ingredients from inventory and network
for (ItemStack stack : stacksToRemove) {
removeItems(stack);
}
// Add the result to the appropriate inventory
// Add crafted item to the appropriate inventory
ItemStack outputStack = recipeEntry.value().getResult(storageScreen.getPlayer().getRegistryManager()).copy();
int maxStackSize = outputStack.getMaxCount();
if (toPlayerInventory) {
PlayerInventory playerInventory = player.getInventory();
if (canInsertItemIntoInventory(playerInventory, outputStack) == outputStack.getCount()) {
playerInventory.insertStack(outputStack);
ItemStack insertStack = outputStack.copy();
if (canInsertItemIntoInventory(playerInventory, insertStack) == insertStack.getCount()) {
playerInventory.insertStack(insertStack);
} else {
return true;
return true; // Inventory full or unable to insert all items
}
} else {
if (this.blockEntity.network.canAddItemStack(outputStack)) {
this.blockEntity.network.putItemStackRemainder(outputStack);
ItemStack insertStack = outputStack.copy();
if (this.blockEntity.network.canAddItemStack(insertStack)) {
this.blockEntity.network.putItemStackRemainder(insertStack);
} else {
return true;
return true; // Storage full or unable to insert all items
}
}
// Remove ingredients
for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
ItemStack stackToRemove = findMatchingStack(ingredient);
if (stackToRemove == null){
return false;
}
removeItems(stackToRemove);
}
return false;
return false; // Crafted one item successfully
}
private ItemStack findMatchingStack(Ingredient ingredient) {
// Check player's inventory first
PlayerInventory playerInventory = storageScreen.getPlayer().getInventory();
for (int i = 0; i < playerInventory.size(); i++) {
ItemStack playerStack = playerInventory.getStack(i);
if (ingredient.test(playerStack)) {
ItemStack stackToRemove = playerStack.copy();
for (ItemStack matchingStack : ingredient.getMatchingStacks()){
if (matchingStack.getItem() == stackToRemove.getItem()) {
stackToRemove.setCount(matchingStack.getCount()); // Set count to ingredient requirement
break;
}
}
return stackToRemove;
}
}
// Check storage network
for (ItemStack stack : ingredient.getMatchingStacks()) {
if (this.blockEntity.network.canRemove(stack)) {
return stack;
ItemStack stackToRemove = stack.copy();
stackToRemove.setCount(ingredient.getMatchingStacks()[0].getCount()); // Set count to ingredient requirement
return stackToRemove;
}
}
return null;
}
private void removeItems(ItemStack stack) {
// Logic to remove items from the storage
ItemStack fromPlayer = this.blockEntity.network.removeItemStack(stack);
if (fromPlayer != null && fromPlayer.getCount() > 0) {
ItemStack removedFromStorage = this.blockEntity.network.removeItemStack(stack);
ItemStack fromPlayer = stack.copy();
fromPlayer.setCount(stack.getCount() - removedFromStorage.getCount());
if (fromPlayer.getCount() > 0) {
Inventory playerInventory = player.getInventory();
for (int i = 0; i < playerInventory.size(); i++) {
if (playerInventory.getStack(i).equals(fromPlayer)) {
playerInventory.removeStack(i);
if (ItemStack.areItemsEqual(playerInventory.getStack(i), fromPlayer)) {
playerInventory.removeStack(i, fromPlayer.getCount());
break; // Only remove one stack per crafting iteration
}
}
}
}
@Override
public boolean open() {
page = blockEntity.page;
this.blockEntity.openCraftingScreens.add(this);
blockEntity.updateDisplays();
return super.open();
}
@Override
public void onClose() {
super.onClose();
this.blockEntity.openCraftingScreens.remove(this);
storageScreen.open();
}
@ -194,10 +206,9 @@ public class CraftingScreen extends PagedGui {
@Override
protected DisplayElement getElement(int id) {
if (id >=0 && id < recipesList.size()) {
if (id >= 0 && id < recipesList.size()) {
return recipesList.get(id);
}
else {
} else {
return DisplayElement.empty();
}
}

@ -15,7 +15,6 @@ import org.jetbrains.annotations.Nullable;
import systems.brn.server_storage.blockentities.StorageInterfaceBlockEntity;
import systems.brn.server_storage.lib.PagedGui;
import static systems.brn.server_storage.ServerStorage.ServerStorage_Crafting_Enable;
import static systems.brn.server_storage.lib.StorageOperations.*;
import static systems.brn.server_storage.lib.Util.addCountToLore;
import static systems.brn.server_storage.lib.Util.removeCountFromLore;
@ -42,7 +41,7 @@ public class StorageScreen extends PagedGui {
@Override
public void updateDisplay() {
blockEntity.justReindexDrives();
blockEntity.reindexDrives();
String title = blockEntity.network.driveUsedSlots +
"u/" +
blockEntity.network.driveTotalSlots +
@ -71,7 +70,7 @@ public class StorageScreen extends PagedGui {
ItemStack itemStackKey = (ItemStack) blockEntity.network.itemStackMap.keySet().toArray()[id];
ItemStack aestheticStack = itemStackKey.copy();
int count = blockEntity.network.itemStackMap.get(itemStackKey);
aestheticStack.setCount(Math.max(aestheticStack.getMaxCount(), count));
aestheticStack.setCount(Math.min(aestheticStack.getMaxCount(), count));
ItemStack newStack = addCountToLore(count, aestheticStack, null);
GuiElementBuilder guiElement = new GuiElementBuilder(newStack);
return DisplayElement.of(guiElement);
@ -108,11 +107,11 @@ public class StorageScreen extends PagedGui {
int insertCount = canInsertItemIntoInventory(playerInventory, noLoreStack);
ItemStack insertingStack = noLoreStack.copy();
insertingStack.setCount(insertCount);
blockEntity.reindexDrives();
blockEntity.refreshTerminals();
if (blockEntity.network.canRemove(noLoreStack) && insertCount > 0) {
playerInventory.insertStack(insertingStack.copy());
blockEntity.network.removeItemStack(insertingStack);
blockEntity.reindexDrives();
blockEntity.refreshTerminals();
}
}
} else if (!cursorStack.isEmpty()) {
@ -125,13 +124,13 @@ public class StorageScreen extends PagedGui {
int canPutIn = stack.getCount() - blockEntity.network.putItemStackRemainder(stack);
if (canPutIn > 0) {
removeFromInventory(player.getInventory(), stack, canPutIn);
blockEntity.reindexDrives();
blockEntity.refreshTerminals();
}
}
@Override
public boolean insertItem(ItemStack stack, int startIndex, int endIndex, boolean fromLast) {
blockEntity.reindexDrives();
blockEntity.refreshTerminals();
insertItem(stack);
return super.insertItem(stack, startIndex, endIndex, fromLast);
}
@ -167,7 +166,7 @@ public class StorageScreen extends PagedGui {
.setCallback((x, y, z) -> {
this.blockEntity.sortAlphabetically ^= true;
playClickSound(getPlayer());
this.blockEntity.reindexDrives();
this.blockEntity.refreshTerminals();
})
);
}
@ -192,9 +191,6 @@ public class StorageScreen extends PagedGui {
@Override
protected DisplayElement crafting() {
if (!this.getPlayer().getWorld().getGameRules().getBoolean(ServerStorage_Crafting_Enable)) {
return DisplayElement.filler();
}
return DisplayElement.of(
new GuiElementBuilder(Items.PLAYER_HEAD)
.setName(Text.translatable("container.crafting").formatted(Formatting.WHITE))
@ -211,7 +207,7 @@ public class StorageScreen extends PagedGui {
public void doSearch(String query) {
this.blockEntity.searchString = query;
this.blockEntity.reindexDrives();
this.blockEntity.refreshTerminals();
this.page = 0;
}
@ -226,7 +222,7 @@ public class StorageScreen extends PagedGui {
playClickSound(player);
this.page = 0;
this.blockEntity.searchString = "";
this.blockEntity.reindexDrives();
this.blockEntity.refreshTerminals();
})
);
}
@ -235,7 +231,7 @@ public class StorageScreen extends PagedGui {
public void onClose() {
this.blockEntity.page = page;
this.blockEntity.markDirty();
this.blockEntity.removeScreen(this);
this.blockEntity.openStorageScreens.remove(this);
super.onClose();
}
}