improved bag seed usage

This commit is contained in:
Jottyfan
2022-02-21 19:14:20 +01:00
parent e196bded07
commit 9adb81e431
4 changed files with 173 additions and 81 deletions

View File

@ -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<BlockPos> findEqualBlock(World world, BlockPos pos, int seekLimit,
BiFunction<World, BlockPos, Boolean> checkLambda) {
Set<NeighborhoodBean> 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<BlockPos> finals = new HashSet<>();
for (NeighborhoodBean bean : found) {
finals.add(bean.getPos());
}
return finals;
}
private static final BlockPos findNextUncheckedField(Set<NeighborhoodBean> found) {
Iterator<NeighborhoodBean> 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<NeighborhoodBean> found,
BiFunction<World, BlockPos, Boolean> 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;
}
}

View File

@ -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;
}
}

View File

@ -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<BlockPos> posList, ItemUsageContext context, World world,
private Integer useItemsOfStack(ItemStack stack, Set<BlockPos> posList, ItemUsageContext context, World world,
PlayerEntity player, Item item) {
for (BlockPos pos : posList) {
Iterator<BlockPos> 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<BlockPos> 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<BlockPos> posList = findFreeFields(new ArrayList<>(), world, pos, stack.getCount());
List<BlockPos> 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<BlockPos> 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<BlockPos> findFreeFields(List<BlockPos> 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<BlockPos> hackedFindFields(World world, BlockPos pos) {
List<BlockPos> 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
*