From 9adb81e431c965f8233bed04bf1aa5fe5ac8bd79 Mon Sep 17 00:00:00 2001 From: Jottyfan Date: Mon, 21 Feb 2022 19:14:20 +0100 Subject: [PATCH] improved bag seed usage --- gradle.properties | 2 +- .../quickiefabric/api/Neighborhood.java | 84 +++++++++++++++++ .../quickiefabric/api/NeighborhoodBean.java | 77 ++++++++++++++++ .../quickiefabric/items/ItemBag.java | 91 +++---------------- 4 files changed, 173 insertions(+), 81 deletions(-) create mode 100644 src/main/java/de/jottyfan/minecraft/quickiefabric/api/Neighborhood.java create mode 100644 src/main/java/de/jottyfan/minecraft/quickiefabric/api/NeighborhoodBean.java diff --git a/gradle.properties b/gradle.properties index 82eaba6..ddfeac6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ loader_version=0.12.12 # Mod Properties - mod_version = 1.18.1.5 + mod_version = 1.18.1.6 maven_group = de.jottyfan.minecraft archives_base_name = quickiefabric diff --git a/src/main/java/de/jottyfan/minecraft/quickiefabric/api/Neighborhood.java b/src/main/java/de/jottyfan/minecraft/quickiefabric/api/Neighborhood.java new file mode 100644 index 0000000..a69401a --- /dev/null +++ b/src/main/java/de/jottyfan/minecraft/quickiefabric/api/Neighborhood.java @@ -0,0 +1,84 @@ +package de.jottyfan.minecraft.quickiefabric.api; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.function.BiFunction; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +/** + * + * @author jotty + * + */ +public class Neighborhood { + + /** + * find the same blocks that is next to the current position pos + * + * @param world the world to look for the blocks + * @param pos the starting position + * @param seekLimit the limit of seek operations + * @param checkLambda check functionality + * @return a set of found block positions + */ + public static final Set findEqualBlock(World world, BlockPos pos, int seekLimit, + BiFunction checkLambda) { + Set found = new HashSet<>(); + found.add(new NeighborhoodBean(pos, true)); + + while (pos != null && found.size() < seekLimit) { + findNewNeihgbor(world, pos.east(), found, checkLambda); + findNewNeihgbor(world, pos.south(), found, checkLambda); + findNewNeihgbor(world, pos.west(), found, checkLambda); + findNewNeihgbor(world, pos.north(), found, checkLambda); + pos = findNextUncheckedField(found); + } + + Set finals = new HashSet<>(); + for (NeighborhoodBean bean : found) { + finals.add(bean.getPos()); + } + return finals; + } + + private static final BlockPos findNextUncheckedField(Set found) { + Iterator i = found.iterator(); + while (i.hasNext()) { + NeighborhoodBean bean = i.next(); + if (!bean.isChecked()) { + bean.setChecked(true); + return bean.getPos(); + } + } + return null; + } + + /** + * find new neighbor at pos + * + * @param world the world + * @param pos the position + * @param found the set with all already found positions + * @return true or false + */ + private static final boolean findNewNeihgbor(World world, BlockPos pos, Set found, + BiFunction checkLambda) { + NeighborhoodBean bean = new NeighborhoodBean(pos); + if (found.contains(bean) || found.contains(bean.over()) || found.contains(bean.below())) { + return false; + } else if (checkLambda.apply(world, pos).booleanValue()) { + found.add(bean); + return true; + } else if (checkLambda.apply(world, pos.up()).booleanValue()) { + found.add(new NeighborhoodBean(pos.up())); + return true; + } else if (checkLambda.apply(world, pos.down()).booleanValue()) { + found.add(new NeighborhoodBean(pos.down())); + return true; + } + return false; + } +} diff --git a/src/main/java/de/jottyfan/minecraft/quickiefabric/api/NeighborhoodBean.java b/src/main/java/de/jottyfan/minecraft/quickiefabric/api/NeighborhoodBean.java new file mode 100644 index 0000000..b7929fb --- /dev/null +++ b/src/main/java/de/jottyfan/minecraft/quickiefabric/api/NeighborhoodBean.java @@ -0,0 +1,77 @@ +package de.jottyfan.minecraft.quickiefabric.api; + +import java.util.Objects; + +import net.minecraft.util.math.BlockPos; + +/** + * + * @author jotty + * + */ +public class NeighborhoodBean { + private final BlockPos pos; + private boolean checked; + + public NeighborhoodBean(BlockPos pos, boolean checked) { + super(); + this.pos = pos; + this.checked = checked; + } + + public NeighborhoodBean(BlockPos pos) { + super(); + this.pos = pos; + this.checked = false; + } + + public NeighborhoodBean over() { + return new NeighborhoodBean(pos.up(), checked); + } + + public NeighborhoodBean below() { + return new NeighborhoodBean(pos.down(), checked); + } + + @Override + public int hashCode() { + return Objects.hash(pos); + } + + @Override + public boolean equals(Object obj) { + Boolean result = null; + if (this == obj) { + result = true; + } else if (obj == null) { + result = false; + } else if (getClass() != obj.getClass()) { + result = false; + } else { + NeighborhoodBean other = (NeighborhoodBean) obj; + result = Objects.equals(pos, other.pos); + } + return result; + } + + /** + * @return the checked + */ + public boolean isChecked() { + return checked; + } + + /** + * @param checked the checked to set + */ + public void setChecked(boolean checked) { + this.checked = checked; + } + + /** + * @return the pos + */ + public BlockPos getPos() { + return pos; + } +} diff --git a/src/main/java/de/jottyfan/minecraft/quickiefabric/items/ItemBag.java b/src/main/java/de/jottyfan/minecraft/quickiefabric/items/ItemBag.java index 2634a19..2d606b8 100644 --- a/src/main/java/de/jottyfan/minecraft/quickiefabric/items/ItemBag.java +++ b/src/main/java/de/jottyfan/minecraft/quickiefabric/items/ItemBag.java @@ -1,8 +1,9 @@ package de.jottyfan.minecraft.quickiefabric.items; -import java.util.ArrayList; -import java.util.List; +import java.util.Iterator; +import java.util.Set; +import de.jottyfan.minecraft.quickiefabric.api.Neighborhood; import de.jottyfan.minecraft.quickiefabric.container.BackpackInventory; import de.jottyfan.minecraft.quickiefabric.item.ModdedItemUsageContext; import net.minecraft.block.Blocks; @@ -10,7 +11,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; -import net.minecraft.text.TranslatableText; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; @@ -24,16 +24,16 @@ import net.minecraft.world.World; */ public class ItemBag extends ItemBackpack { - private Integer useItemsOfStack(ItemStack stack, List posList, ItemUsageContext context, World world, + private Integer useItemsOfStack(ItemStack stack, Set posList, ItemUsageContext context, World world, PlayerEntity player, Item item) { - for (BlockPos pos : posList) { + Iterator iterator = posList.iterator(); + while (iterator.hasNext() && stack.getCount() > 0) { + BlockPos pos = iterator.next(); BlockHitResult hit = new BlockHitResult(context.getHitPos(), context.getSide(), pos, context.hitsInsideBlock()); ModdedItemUsageContext iuc = new ModdedItemUsageContext(world, player, Hand.MAIN_HAND, stack, hit); item.useOnBlock(iuc); stack.decrement(1); - if (stack.getCount() < 1) { // interrupt if stack is empty - break; - } + iterator.remove(); } return stack.getCount(); } @@ -44,16 +44,13 @@ public class ItemBag extends ItemBackpack { World world = context.getWorld(); PlayerEntity player = context.getPlayer(); if (isFreeFarmland(world, pos)) { - if (!world.isClient) { - player.sendMessage(new TranslatableText("msg.notyetimplemented"), false); - } BackpackInventory bi = new BackpackInventory(context.getStack()); + Set posList = Neighborhood.findEqualBlock(world, pos, 4096, (w, p) -> { + return Blocks.FARMLAND.equals(w.getBlockState(p).getBlock()) && w.getBlockState(p.up()).isAir(); + }); for (int slot = 0; slot < ItemBackpack.SLOTSIZE; slot++) { ItemStack stack = bi.getStack(slot); if (stack.getCount() > 0) { - // not yet working recursive calls of findFreeFields; do not use this now! -// List posList = findFreeFields(new ArrayList<>(), world, pos, stack.getCount()); - List posList = hackedFindFields(world, pos); for (int i = stack.getCount(); i > 0; i--) { int beforeUsage = stack.getCount(); int afterUsage = useItemsOfStack(stack, posList, context, world, player, stack.getItem()); @@ -75,72 +72,6 @@ public class ItemBag extends ItemBackpack { } } - /** - * add pos to list if it is farmland - * - * @param list the list - * @param world the world - * @param pos the pos - * @return the added pos; might be up or down also; if null, no farmland was - * found or the element has been already added or there are more - * farmland fields than seed - */ - private BlockPos addToListIfNotYetDone(List list, World world, BlockPos pos, Integer limit) { - if (limit < list.size()) { - return null; // interrupt here to reduce calculation time - } else if (!list.contains(pos) && isFreeFarmland(world, pos)) { - list.add(pos); - return pos; - } else if (!list.contains(pos.up()) && isFreeFarmland(world, pos.up())) { - list.add(pos.up()); - return pos.up(); - } else if (!list.contains(pos.down()) && isFreeFarmland(world, pos.down())) { - list.add(pos.down()); - return pos.down(); - } else { - return null; - } - } - - /** - * find the next free fields that can be used to set a sapling to... - * - * @param world the world - * @param start the starting position - * @return the next free blocks of farmland - might be even the one on start - * @deprecated not yet safe abort condition; do not use it in the game - */ - @Deprecated - private final List findFreeFields(List list, World world, BlockPos start, Integer limit) { - addToListIfNotYetDone(list, world, start, limit); - BlockPos east = addToListIfNotYetDone(list, world, start.east(), limit); - if (east != null) { - list.addAll(findFreeFields(list, world, east, limit)); - } - BlockPos west = addToListIfNotYetDone(list, world, start.west(), limit); - if (west != null) { - list.addAll(findFreeFields(list, world, west, limit)); - } - BlockPos south = addToListIfNotYetDone(list, world, start.south(), limit); - if (south != null) { - list.addAll(findFreeFields(list, world, south, limit)); - } - BlockPos north = addToListIfNotYetDone(list, world, start.north(), limit); - if (north != null) { - list.addAll(findFreeFields(list, world, north, limit)); - } - return list; - } - - @Deprecated - private final List hackedFindFields(World world, BlockPos pos) { - List list = new ArrayList<>(); - if (isFreeFarmland(world, pos)) { - list.add(pos); - } - return list; - } - /** * check if the block on pos is farmland and the one above is air *