diff --git a/xplat/src/main/java/fzzyhmstrs/emi_loot/client/AbstractTextKeyParsingClientLootTable.java b/xplat/src/main/java/fzzyhmstrs/emi_loot/client/AbstractTextKeyParsingClientLootTable.java index 711ae633..5d5b96ee 100644 --- a/xplat/src/main/java/fzzyhmstrs/emi_loot/client/AbstractTextKeyParsingClientLootTable.java +++ b/xplat/src/main/java/fzzyhmstrs/emi_loot/client/AbstractTextKeyParsingClientLootTable.java @@ -3,18 +3,18 @@ import dev.emi.emi.api.stack.EmiStack; import fzzyhmstrs.emi_loot.EMILoot; import fzzyhmstrs.emi_loot.util.ConditionalStack; -import fzzyhmstrs.emi_loot.util.LText; import fzzyhmstrs.emi_loot.util.TextKey; import io.netty.handler.codec.DecoderException; -import io.netty.handler.codec.EncoderException; import it.unimi.dsi.fastutil.floats.Float2ObjectArrayMap; import it.unimi.dsi.fastutil.floats.Float2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2FloatMap; import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap; import net.minecraft.block.Block; +import net.minecraft.block.BlockTypes; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; import net.minecraft.registry.Registries; +import net.minecraft.registry.tag.BlockTags; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Pair; @@ -23,10 +23,9 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; -import java.util.LinkedList; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; abstract public class AbstractTextKeyParsingClientLootTable implements LootReceiver { @@ -41,6 +40,7 @@ public AbstractTextKeyParsingClientLootTable(Map, ClientRawPool> m private final Map, ClientRawPool> rawItems; public List builtItems; + static Identifier getIdFromBuf(PacketByteBuf buf) { String idToParse = buf.readString(); if (idToParse.contains(":")) { @@ -60,74 +60,87 @@ static Identifier getIdFromBuf(PacketByteBuf buf) { } } - abstract List> getSpecialTextKeyList(World world, Block block); + abstract void getSpecialTextKeyList(World world, Block block, List> inputList); public void build(World world, Block block) { - Map>, Object2FloatMap> builderItems = new HashMap<>(); + boolean bl = Registries.BLOCK.getEntry(block).isIn(BlockTags.SLABS); + Map>, Object2FloatMap> builderItems = new LinkedHashMap<>(); rawItems.forEach((list, pool)-> { - List> applyToAllList = new ArrayList<>(getSpecialTextKeyList(world, block)); - list.forEach((textKey) -> { - Text text = textKey.process(ItemStack.EMPTY, world).text(); + List> applyToAllList = new ArrayList<>(); + getSpecialTextKeyList(world, block, applyToAllList); + for (TextKey textKey: list) { + Text text = textKey.processText(); applyToAllList.add(new Pair<>(textKey.index(), text)); - }); + } + if (bl) System.out.println(applyToAllList); + if (bl) System.out.println(); pool.map().forEach((poolList, poolItemMap)-> { + if (bl) System.out.println(poolList); + if (bl) System.out.println(poolItemMap); + if (bl) System.out.println(); List> newPoolList = new ArrayList<>(); Object2FloatMap itemsToAdd = new Object2FloatOpenHashMap<>(); List itemsToRemove = new ArrayList<>(); - poolList.forEach((textKey) -> { + for (TextKey textKey : poolList) { poolItemMap.forEach((poolStack, weight)-> { - List stacks = textKey.process(poolStack, world).stacks(); - AtomicReference toAddWeight = new AtomicReference<>(1.0f); + List stacks = textKey.processStack(poolStack, world); + if (bl) System.out.println(stacks); + float toAddWeight = 1.0f; if (!stacks.contains(poolStack)) { itemsToRemove.add(poolStack); - toAddWeight.set(poolItemMap.getFloat(poolStack)); + toAddWeight = weight; } - stacks.forEach(stack-> { + for (ItemStack stack: stacks) { if(poolItemMap.containsKey(stack)) { - toAddWeight.set(poolItemMap.getFloat(stack)); + toAddWeight = poolItemMap.getFloat(stack); } - }); - stacks.forEach(stack-> { + } + for (ItemStack stack: stacks) { if(!poolItemMap.containsKey(stack)) { - itemsToAdd.put(stack, (float)toAddWeight.get()); + itemsToAdd.put(stack, toAddWeight); } - }); + } }); - Text text = textKey.process(ItemStack.EMPTY, world).text(); + Text text = textKey.processText(); newPoolList.add(new Pair<>(textKey.index(), text)); + } - }); - list.forEach((textKey) -> { - poolItemMap.forEach((poolStack, weight)-> { - List stacks = textKey.process(poolStack, world).stacks(); - AtomicReference toAddWeight = new AtomicReference<>(1.0f); + for (TextKey textKey: list) { + poolItemMap.forEach((poolStack, weight) -> { + List stacks = textKey.processStack(poolStack, world); + float toAddWeight = 1.0f; if (!stacks.contains(poolStack)) { itemsToRemove.add(poolStack); - toAddWeight.set(poolItemMap.getFloat(poolStack)); + toAddWeight = weight; } - stacks.forEach(stack-> { + for (ItemStack stack: stacks) { if(poolItemMap.containsKey(stack)) { - toAddWeight.set(poolItemMap.getFloat(stack)); + toAddWeight = poolItemMap.getFloat(stack); } - }); - stacks.forEach(stack-> { + } + for (ItemStack stack: stacks) { if(!poolItemMap.containsKey(stack)) { - itemsToAdd.put(stack, (float)toAddWeight.get()); + itemsToAdd.put(stack, toAddWeight); } - }); - + } }); - - }); - List> summedList = new ArrayList<>(applyToAllList); - summedList.addAll(newPoolList); - if (summedList.isEmpty() && (!EMILoot.config.skippedKeys.contains("emi_loot.no_conditions") || !EMILoot.config.isTooltipStyle())) { - summedList.add(new Pair<>(TextKey.getIndex("emi_loot.no_conditions"), LText.translatable("emi_loot.no_conditions"))); } + List> summedList; + if (applyToAllList.isEmpty()) { + if (newPoolList.isEmpty() && (!EMILoot.config.skippedKeys.contains("emi_loot.no_conditions") || !EMILoot.config.isTooltipStyle())) { + summedList = TextKey.noConditionsList.get(); + } else { + summedList = newPoolList; + } + } else { + summedList = new ArrayList<>(applyToAllList); + summedList.addAll(newPoolList); + } + Object2FloatMap builderPoolMap = builderItems.getOrDefault(summedList, poolItemMap); builderPoolMap.putAll(itemsToAdd); itemsToRemove.forEach(builderPoolMap::removeFloat); @@ -135,11 +148,11 @@ public void build(World world, Block block) { }); }); - List finalList = new LinkedList<>(); + List finalList = new ArrayList<>(); builderItems.forEach((builtList, builtMap)-> { Float2ObjectMap> consolidatedMap = new Float2ObjectArrayMap<>(); builtMap.forEach((stack, weight)-> { - List consolidatedList = consolidatedMap.getOrDefault((float)weight, new LinkedList<>()); + List consolidatedList = consolidatedMap.getOrDefault((float)weight, new ArrayList<>()); if (!consolidatedList.contains(stack)) { consolidatedList.add(stack); } @@ -147,7 +160,7 @@ public void build(World world, Block block) { }); Float2ObjectMap> emiConsolidatedMap = new Float2ObjectArrayMap<>(); consolidatedMap.forEach((consolidatedWeight, consolidatedList)-> { - List emiStacks = new LinkedList<>(); + List emiStacks = new ArrayList<>(); for (ItemStack i : consolidatedList) { emiStacks.add(EmiStack.of(i)); } @@ -187,20 +200,21 @@ public LootReceiver fromBuf(PacketByteBuf buf, World world) { return simpleTableToReturn(ids, buf); } - Map, ClientRawPool> itemMap = new HashMap<>(); + Map, ClientRawPool> itemMap = new LinkedHashMap<>(); //shortcut -1 means a simple table. One guaranteed drop of quantity 1 with no conditions. for (int b = 0; b < builderCount; b++) { - List qualifierList = new LinkedList<>(); - int conditionSize = buf.readShort(); + + List qualifierList = new ArrayList<>(conditionSize + 1); + for (int i = 0; i < conditionSize; i++) { try { TextKey key = TextKey.fromBuf(buf); qualifierList.add(key); } catch (DecoderException e) { - EMILoot.LOGGER.error("Client table " + id + " had a TextKey decoding error while reading a loot condition!"); + EMILoot.LOGGER.error("Client table {} had a TextKey decoding error while reading a loot condition!", id); } } @@ -210,24 +224,25 @@ public LootReceiver fromBuf(PacketByteBuf buf, World world) { TextKey key = TextKey.fromBuf(buf); qualifierList.add(key); } catch (DecoderException e) { - EMILoot.LOGGER.error("Client table " + id + " had a TextKey decoding error while reading a loot function!"); + EMILoot.LOGGER.error("Client table {} had a TextKey decoding error while reading a loot function!", id); } } - ClientRawPool pool = itemMap.getOrDefault(qualifierList, new ClientRawPool(new HashMap<>())); + ClientRawPool pool = itemMap.getOrDefault(qualifierList, new ClientRawPool(new LinkedHashMap<>())); int pileSize = buf.readShort(); for (int i = 0; i < pileSize; i++) { - List pileQualifierList = new LinkedList<>(); - int pileQualifierSize = buf.readShort(); + + List pileQualifierList = new ArrayList<>(pileQualifierSize); + for (int j = 0; j < pileQualifierSize; j++) { try { TextKey key = TextKey.fromBuf(buf); pileQualifierList.add(key); } catch (DecoderException e) { - EMILoot.LOGGER.error("Client table " + id + " had a TextKey decoding error while reading an item pile qualifier!"); + EMILoot.LOGGER.error("Client table {} had a TextKey decoding error while reading an item pile qualifier!", id); } } diff --git a/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientBlockLootTable.java b/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientBlockLootTable.java index 61d24e74..6ddf0a31 100644 --- a/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientBlockLootTable.java +++ b/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientBlockLootTable.java @@ -31,11 +31,13 @@ public class ClientBlockLootTable extends AbstractTextKeyParsingClientLootTable< private static final Identifier EMPTY = Identifier.of("blocks/empty"); public final Identifier id; public final Identifier blockId; + public final boolean isSimple; public ClientBlockLootTable() { super(); this.id = EMPTY; this.blockId = Identifier.of("air"); + this.isSimple = false; } public ClientBlockLootTable(Identifier id, Map, ClientRawPool> map) { @@ -49,6 +51,21 @@ public ClientBlockLootTable(Identifier id, Map, ClientRawPool> map } else { blockId = Identifier.of(ns, pth.substring(Math.min(lastSlashIndex + 1, pth.length()))); } + this.isSimple = false; + } + + public ClientBlockLootTable(Identifier id, Map, ClientRawPool> map, boolean isSimple) { + super(map); + this.id = id; + String ns = id.getNamespace(); + String pth = id.getPath(); + int lastSlashIndex = pth.lastIndexOf('/'); + if (lastSlashIndex == -1) { + blockId = Identifier.of(ns, pth); + } else { + blockId = Identifier.of(ns, pth.substring(Math.min(lastSlashIndex + 1, pth.length()))); + } + this.isSimple = true; } @Override @@ -62,7 +79,7 @@ public boolean isEmpty() { } @Override - List> getSpecialTextKeyList(World world, Block block) { + void getSpecialTextKeyList(World world, Block block, List> inputList) { String tool = ""; if (block.getRegistryEntry().isIn(BlockTags.PICKAXE_MINEABLE)) { tool = "pickaxe"; @@ -73,7 +90,6 @@ List> getSpecialTextKeyList(World world, Block block) { } else if (block.getRegistryEntry().isIn(BlockTags.HOE_MINEABLE)) { tool = "hoe"; } - List> toolNeededList = new LinkedList<>(); if (!Objects.equals(tool, "")) { String type; if (block.getRegistryEntry().isIn(BlockTags.NEEDS_STONE_TOOL)) { @@ -88,10 +104,9 @@ List> getSpecialTextKeyList(World world, Block block) { String keyString = "emi_loot." + tool + "." + type; int keyIndex = TextKey.getIndex(keyString); if (keyIndex != -1) { - toolNeededList.add(new Pair<>(keyIndex, LText.translatable(keyString))); + inputList.add(new Pair<>(keyIndex, LText.translatable(keyString))); } } - return toolNeededList; } @Override @@ -108,7 +123,7 @@ ClientBlockLootTable simpleTableToReturn(Pair ids, Packe simplePool.map().put(new ArrayList<>(), simpleMap); Map, ClientRawPool> itemMap = new HashMap<>(); itemMap.put(new ArrayList<>(), simplePool); - return new ClientBlockLootTable(ids.getLeft(), itemMap); + return new ClientBlockLootTable(ids.getLeft(), itemMap, true); } @Override diff --git a/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientGameplayLootTable.java b/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientGameplayLootTable.java index b70e1166..bbd6aa64 100644 --- a/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientGameplayLootTable.java +++ b/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientGameplayLootTable.java @@ -62,36 +62,7 @@ public boolean isEmpty() { } @Override - List> getSpecialTextKeyList(World world, Block block) { - String tool = ""; - if (block.getRegistryEntry().isIn(BlockTags.PICKAXE_MINEABLE)) { - tool = "pickaxe"; - } else if (block.getRegistryEntry().isIn(BlockTags.AXE_MINEABLE)) { - tool = "axe"; - } else if (block.getRegistryEntry().isIn(BlockTags.SHOVEL_MINEABLE)) { - tool = "shovel"; - } else if (block.getRegistryEntry().isIn(BlockTags.HOE_MINEABLE)) { - tool = "hoe"; - } - List> toolNeededList = new LinkedList<>(); - if (!Objects.equals(tool, "")) { - String type; - if (block.getRegistryEntry().isIn(BlockTags.NEEDS_STONE_TOOL)) { - type = "stone"; - } else if (block.getRegistryEntry().isIn(BlockTags.NEEDS_IRON_TOOL)) { - type = "iron"; - } else if (block.getRegistryEntry().isIn(BlockTags.NEEDS_DIAMOND_TOOL)) { - type = "diamond"; - } else { - type = "wood"; - } - String keyString = "emi_loot." + tool + "." + type; - int keyIndex = TextKey.getIndex(keyString); - if (keyIndex != -1) { - toolNeededList.add(new Pair<>(keyIndex, LText.translatable(keyString))); - } - } - return toolNeededList; + void getSpecialTextKeyList(World world, Block block, List> inputList) { } @Override diff --git a/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientMobLootTable.java b/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientMobLootTable.java index 06f978da..14813071 100644 --- a/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientMobLootTable.java +++ b/xplat/src/main/java/fzzyhmstrs/emi_loot/client/ClientMobLootTable.java @@ -65,8 +65,7 @@ public boolean isEmpty() { } @Override - List> getSpecialTextKeyList(World world, Block block) { - return List.of(); + void getSpecialTextKeyList(World world, Block block, List> inputList) { } @Override diff --git a/xplat/src/main/java/fzzyhmstrs/emi_loot/emi/BlockLootRecipe.java b/xplat/src/main/java/fzzyhmstrs/emi_loot/emi/BlockLootRecipe.java index 639dd166..838ad5e4 100644 --- a/xplat/src/main/java/fzzyhmstrs/emi_loot/emi/BlockLootRecipe.java +++ b/xplat/src/main/java/fzzyhmstrs/emi_loot/emi/BlockLootRecipe.java @@ -42,23 +42,27 @@ public BlockLootRecipe(ClientBlockLootTable loot) { Block block = Registries.BLOCK.get(blockId); loot.build(MinecraftClient.getInstance().world, block); inputStack = block.asItem() == Items.AIR ? new BlockStateEmiStack(block.getDefaultState(), blockId) : EmiStack.of(block); - List list = new LinkedList<>(); - loot.builtItems.forEach((builtPool)-> { - builtPool.stacks().forEach(stack -> { - /*if (weight < 100f) { + List list = new ArrayList<>(); + boolean allStacksGuaranteed = true; + for (ClientBuiltPool builtPool : loot.builtItems) { + for (ConditionalStack stack : builtPool.stacks()) { + if (stack.weight() < 100f) { allStacksGuaranteed = false; - }*/ + } list.addAll(stack.ingredient()); - }); + } addWidgetBuilders(builtPool, false); - }); + } + + this.isSimple = loot.isSimple || allStacksGuaranteed; outputStacks = list; } private final ClientBlockLootTable loot; private final EmiStack inputStack; private final List outputStacks; - private final List rowBuilderList = new LinkedList<>(); + private final List rowBuilderList = new ArrayList<>(); + private final boolean isSimple; private void addWidgetBuilders(ClientBuiltPool newPool, boolean recursive) { WidgetRowBuilder builder; @@ -177,7 +181,7 @@ public void addWidgets(WidgetHolder widgets) { //may revisit later @Override public boolean supportsRecipeTree() { - return false; + return isSimple; } @Override diff --git a/xplat/src/main/java/fzzyhmstrs/emi_loot/emi/LootSimplifiedRenderer.java b/xplat/src/main/java/fzzyhmstrs/emi_loot/emi/LootSimplifiedRenderer.java index 0a65407b..946ba97f 100644 --- a/xplat/src/main/java/fzzyhmstrs/emi_loot/emi/LootSimplifiedRenderer.java +++ b/xplat/src/main/java/fzzyhmstrs/emi_loot/emi/LootSimplifiedRenderer.java @@ -19,6 +19,6 @@ public LootSimplifiedRenderer(int u, int v) { @Override public void render(DrawContext draw, int x, int y, float delta) { - draw.drawTexture(SPRITE_SHEET, x, y, u, v, 16, 16, 32, 16); + draw.drawTexture(SPRITE_SHEET, x, y, u, v, 16, 16, 32, 32); } } \ No newline at end of file diff --git a/xplat/src/main/java/fzzyhmstrs/emi_loot/parser/EnchantmentPredicateParser.java b/xplat/src/main/java/fzzyhmstrs/emi_loot/parser/EnchantmentPredicateParser.java index d802faf0..d9f516cf 100644 --- a/xplat/src/main/java/fzzyhmstrs/emi_loot/parser/EnchantmentPredicateParser.java +++ b/xplat/src/main/java/fzzyhmstrs/emi_loot/parser/EnchantmentPredicateParser.java @@ -11,6 +11,7 @@ import net.minecraft.text.MutableText; import net.minecraft.text.Text; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Optional; @@ -18,7 +19,7 @@ public class EnchantmentPredicateParser { public static Text parseEnchantmentPredicates(List list) { - List list2 = new LinkedList<>(); + List list2 = new ArrayList<>(); for (EnchantmentPredicate predicate : list) { Optional> enchant = predicate.enchantments(); if (enchant.isPresent() && enchant.get().getTagKey().isPresent()) { diff --git a/xplat/src/main/java/fzzyhmstrs/emi_loot/parser/condition/BlockStatePropertyConditionParser.java b/xplat/src/main/java/fzzyhmstrs/emi_loot/parser/condition/BlockStatePropertyConditionParser.java index 1b35f648..4fe8f651 100644 --- a/xplat/src/main/java/fzzyhmstrs/emi_loot/parser/condition/BlockStatePropertyConditionParser.java +++ b/xplat/src/main/java/fzzyhmstrs/emi_loot/parser/condition/BlockStatePropertyConditionParser.java @@ -21,7 +21,7 @@ public List parseCondition(LootCondition co MutableText bsText; Block block = ((BlockStatePropertyLootCondition)condition).block().value(); if (block != null) { - bsText = LText.translatable("emi_loot.condition.blockstate.block",block.getName().getString()); + bsText = LText.translatable("emi_loot.condition.blockstate.block", block.getName().getString()); } else { StatePredicate predicate = ((BlockStatePropertyLootCondition)condition).properties().orElseThrow(); // TODO? bsText = (MutableText) StatePredicateParser.parseStatePredicate(predicate); diff --git a/xplat/src/main/java/fzzyhmstrs/emi_loot/util/TextKey.java b/xplat/src/main/java/fzzyhmstrs/emi_loot/util/TextKey.java index d3da6143..060f448d 100644 --- a/xplat/src/main/java/fzzyhmstrs/emi_loot/util/TextKey.java +++ b/xplat/src/main/java/fzzyhmstrs/emi_loot/util/TextKey.java @@ -1,5 +1,6 @@ package fzzyhmstrs.emi_loot.util; +import com.google.common.base.Suppliers; import fzzyhmstrs.emi_loot.EMILoot; import net.minecraft.component.DataComponentTypes; import net.minecraft.item.ItemStack; @@ -13,10 +14,12 @@ import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; import net.minecraft.village.raid.Raid; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -28,6 +31,7 @@ import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; +import java.util.function.Supplier; public record TextKey(int index, List args) { @@ -41,6 +45,12 @@ public record TextKey(int index, List args) { static final Identifier EMPTY = Identifier.of(EMILoot.MOD_ID, "textures/gui/empty.png"); static int curDynamicIndex = 1000; + public static final Supplier>> noConditionsList = Suppliers.memoize(() -> { + List> list = new ArrayList<>(); + list.add(new Pair<>(TextKey.getIndex("emi_loot.no_conditions"), LText.translatable("emi_loot.no_conditions"))); + return list; + }); + public static final Set defaultSkips = Set.of("emi_loot.function.set_count_add", "emi_loot.function.set_count_set", "emi_loot.function.fill_player_head", "emi_loot.function.limit_count", "emi_loot.no_conditions"); static { @@ -400,6 +410,15 @@ public static String symbolKey(int index) { return String.valueOf((char)(0xe700 + index)); } + public Text processText() { + return keyTextBuilderMap.getOrDefault(this.index, DEFAULT_FUNCTION).apply(this); + } + + public List processStack(ItemStack stack, @Nullable World world) { + BiFunction> processor = processorMap.getOrDefault(this.index, DEFAULT_PROCESSOR); + return processor.apply(stack, world); + } + public TextKeyResult process(ItemStack stack, @Nullable World world) { BiFunction> processor = processorMap.getOrDefault(this.index, DEFAULT_PROCESSOR); List finalStacks = processor.apply(stack, world);