expose what blocks this element might place

This commit is contained in:
Glease committed 2022-09-16 18:57:04 +08:00
1 parent 0ac8908b37
commit 7d74a65ec0
4 files changed
+358 -488

No files matched your search

@@ -4,10 +4,18 @@ import static com.gtnewhorizon.structurelib.StructureLib.LOGGER;
import static com.gtnewhorizon.structurelib.StructureLib.PANIC_MODE;
import com.gtnewhorizon.structurelib.StructureLibAPI;
import com.gtnewhorizon.structurelib.util.ItemStackPredicate;
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.Consumer;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IChatComponent;
import net.minecraft.world.World;
@@ -58,6 +66,30 @@ public interface IStructureElement<T> {
return PlaceResult.SKIP;
}
/**
* A simplified version of survivalPlaceBlock. Return null if not implemented.
* <p>
* <b>BY OVERRIDING THIS TO NULL, YOU ACKNOWLEDGE THAT THE {@link #check(Object, World, int, int, int)} OF THIS
* CLASS IS SIDE EFFECT FREE AND CAN HAVE ITS CHECK CALLED WITHOUT BREAKING ANYTHING. OTHERWISE OVERRIDE THE
* {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)} TO PROVIDE A SIDEEFFECT
* FREE {@link PlaceResult#SKIP}.</b>
* <p>
* It should be noticed that this filter is only advisory and the actual {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
* or {@link #check(Object, World, int, int, int)} are free to reject/accept/place blocks not contained in this list,
* e.g. when the element can be placed anywhere in the structure, but no more than 3 overall; when the structure
* element cannot know all blocks it will accept at the time of calling; when this is backed by a legacy
* {@link IStructureElement} that just didn't implement this API.
*
* @param trigger trigger item
* @param env autoplacing environment
* @return null if not implemented, otherwise an instance describing what kind of blocks will be placed by {@link #survivalPlaceBlock(Object, World, int, int, int, ItemStack, AutoPlaceEnvironment)}
*/
@Nullable
default BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return null;
}
/**
* Try place the block by taking resource from given IItemSource.
* <p>
@@ -69,10 +101,26 @@ public interface IStructureElement<T> {
*/
default PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
BlocksToPlace e = getBlocksToPlace(t, world, x, y, z, trigger, env);
IItemSource source = env.getSource();
EntityPlayer actor = env.getActor();
Consumer<IChatComponent> chatter = env.getChatter();
if (e != null) {
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
if (e.getStacks() == null) {
ItemStack taken = source.takeOne(e.getPredicate(), true);
return StructureUtility.survivalPlaceBlock(
taken, NBTMode.EXACT, taken.stackTagCompound, true, world, x, y, z, source, actor, chatter);
}
for (ItemStack stack : e.getStacks()) {
if (!source.takeOne(stack, true)) continue;
return StructureUtility.survivalPlaceBlock(
stack, NBTMode.EXACT, stack.stackTagCompound, true, world, x, y, z, source, actor, chatter);
}
return PlaceResult.REJECT;
}
if (actor instanceof EntityPlayerMP)
return survivalPlaceBlock(
t, world, x, y, z, trigger, env.getSource(), (EntityPlayerMP) actor, env.getChatter());
return survivalPlaceBlock(t, world, x, y, z, trigger, source, (EntityPlayerMP) actor, chatter);
if (PANIC_MODE) throw new RuntimeException("Panic Tripwire hit");
if (StructureLibAPI.isDebugEnabled())
LOGGER.info(
@@ -154,4 +202,81 @@ public interface IStructureElement<T> {
*/
ACCEPT_STOP;
}
final class BlocksToPlace {
public static final BlocksToPlace errored = createEmpty();
private final Predicate<ItemStack> predicate;
private final Iterable<ItemStack> stacks;
public static BlocksToPlace createEmpty() {
return new BlocksToPlace(s -> false, Collections.emptyList());
}
public static BlocksToPlace create(ItemStack... stacks) {
return create(Arrays.asList(stacks));
}
public static BlocksToPlace create(Iterable<ItemStack> stacks) {
Predicate<ItemStack> predicate = null;
for (ItemStack stack : stacks) {
ItemStackPredicate p = ItemStackPredicate.from(stack, NBTMode.EXACT);
if (predicate == null) predicate = p;
else predicate = predicate.or(p);
}
return new BlocksToPlace(predicate, stacks);
}
public static BlocksToPlace create(Block block, int meta) {
Item itemBlock = Item.getItemFromBlock(block);
if (itemBlock instanceof ISpecialItemBlock) {
meta = ((ISpecialItemBlock) itemBlock).getItemMetaFromBlockMeta(block, meta);
}
return create(itemBlock, meta);
}
public static BlocksToPlace create(Item item, int meta) {
return new BlocksToPlace(
ItemStackPredicate.from(item).setMeta(meta),
Collections.singletonList(new ItemStack(item, 1, meta)));
}
public static BlocksToPlace create(ItemStack itemStack) {
return new BlocksToPlace(ItemStackPredicate.from(itemStack), Collections.singletonList(itemStack));
}
public static BlocksToPlace create(Predicate<ItemStack> predicate) {
return new BlocksToPlace(predicate, null);
}
BlocksToPlace(Predicate<ItemStack> predicate, Iterable<ItemStack> stacks) {
this.predicate = predicate;
this.stacks = stacks;
}
/**
* Get the blocks to place filter. This is usually slower as it requires walking through inventories one by one.
* <p>
* Suitable for use with {@link IItemSource#takeOne(Predicate, boolean)}
* @return a predicate. never null.
*/
@Nonnull
public Predicate<ItemStack> getPredicate() {
return predicate;
}
/**
* Get the ItemStacks that this one is known to accept. Can be null if this info is not available at the time
* this instance is constructed.
* <p>
* Suitable for use with {@link IItemSource#takeOne(ItemStack, boolean)}.
* <p>
* This should be equivalent to the predicate returned from {@link #getPredicate()}
*/
@Nullable
public Iterable<ItemStack> getStacks() {
return stacks;
}
}
}
@@ -1,8 +1,11 @@
package com.gtnewhorizon.structurelib.structure;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IChatComponent;
@@ -44,6 +47,23 @@ public interface IStructureElementChain<T> extends IStructureElement<T> {
return false;
}
@Nullable
@Override
default BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
Predicate<ItemStack> predicate = null;
List<Iterable<ItemStack>> is = new ArrayList<>();
for (IStructureElement<T> fallback : fallbacks()) {
BlocksToPlace e = fallback.getBlocksToPlace(t, world, x, y, z, trigger, env);
if (e == null) continue;
if (predicate == null) predicate = e.getPredicate();
else predicate = predicate.or(e.getPredicate());
is.add(e.getStacks());
}
if (predicate == null) return null;
return new BlocksToPlace(predicate, Iterables.concat(is));
}
@Override
default PlaceResult survivalPlaceBlock(
T t,
@@ -2,6 +2,7 @@ package com.gtnewhorizon.structurelib.structure;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.annotation.Nullable;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IChatComponent;
@@ -38,6 +39,13 @@ class LazyStructureElement<T> implements IStructureElementDeferred<T> {
return get(t).spawnHint(t, world, x, y, z, trigger);
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return get(t).getBlocksToPlace(t, world, x, y, z, trigger, env);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
@@ -2,6 +2,7 @@ package com.gtnewhorizon.structurelib.structure;
import static java.lang.Integer.MIN_VALUE;
import com.google.common.collect.ImmutableList;
import com.gtnewhorizon.structurelib.StructureLib;
import com.gtnewhorizon.structurelib.StructureLibAPI;
import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
@@ -9,10 +10,12 @@ import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import com.gtnewhorizon.structurelib.structure.IStructureElement.PlaceResult;
import com.gtnewhorizon.structurelib.structure.adders.IBlockAdder;
import com.gtnewhorizon.structurelib.structure.adders.ITileAdder;
import com.gtnewhorizon.structurelib.util.ItemStackPredicate;
import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
import com.gtnewhorizon.structurelib.util.Vec3Impl;
import cpw.mods.fml.common.registry.GameRegistry;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.*;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
@@ -128,7 +131,7 @@ public class StructureUtility {
private static final Map<Vec3Impl, IStructureNavigate> STEP = new HashMap<>();
@SuppressWarnings("rawtypes")
private static final IStructureElement AIR = new IStructureElement() {
private static final IStructureElement AIR = new StructureElement_Bridge() {
@Override
public boolean check(Object t, World world, int x, int y, int z) {
return world.isAirBlock(x, y, z);
@@ -149,24 +152,16 @@ public class StructureUtility {
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
Object o,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer chatter) {
Object o, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(o, world, x, y, z)) return PlaceResult.SKIP;
if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, actor)) return PlaceResult.REJECT;
if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, env.getActor())) return PlaceResult.REJECT;
world.setBlock(x, y, z, Blocks.air, 0, 2);
return PlaceResult.ACCEPT;
}
};
@SuppressWarnings("rawtypes")
private static final IStructureElement NOT_AIR = new IStructureElement() {
private static final IStructureElement NOT_AIR = new StructureElement_Bridge() {
@Override
public boolean check(Object t, World world, int x, int y, int z) {
return !world.isAirBlock(x, y, z);
@@ -184,21 +179,19 @@ public class StructureUtility {
return true;
}
@Override
public BlocksToPlace getBlocksToPlace(
Object o, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return BlocksToPlace.create(Objects::nonNull);
}
@Override
public PlaceResult survivalPlaceBlock(
Object o,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer chatter) {
Object o, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(o, world, x, y, z)) return PlaceResult.SKIP;
// user should place anything here.
// maybe make this configurable, but for now we try to take some cobble from user
if (s.takeOne(new ItemStack(Blocks.cobblestone), false)) {
if (env.getSource().takeOne(new ItemStack(Blocks.cobblestone), false)) {
world.setBlock(x, y, z, Blocks.cobblestone, 0, 2);
}
return PlaceResult.REJECT;
@@ -206,7 +199,7 @@ public class StructureUtility {
};
@SuppressWarnings("rawtypes")
private static final IStructureElement ERROR = new IStructureElement() {
private static final IStructureElement ERROR = new StructureElement_Bridge() {
@Override
public boolean check(Object t, World world, int x, int y, int z) {
return false;
@@ -225,15 +218,7 @@ public class StructureUtility {
@Override
public PlaceResult survivalPlaceBlock(
Object o,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer chatter) {
Object o, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return PlaceResult.REJECT;
}
};
@@ -723,6 +708,14 @@ public class StructureUtility {
return true;
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
Pair<Block, Integer> hint = getHint(trigger);
return BlocksToPlace.create(hint.getKey(), hint.getValue());
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
@@ -802,6 +795,14 @@ public class StructureUtility {
return true;
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (getBlock() == null) return error().getBlocksToPlace(t, world, x, y, z, trigger, env);
return BlocksToPlace.create(getBlock(), meta);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
@@ -864,6 +865,14 @@ public class StructureUtility {
} else return fallback.placeBlock(t, world, x, y, z, trigger);
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (init()) return BlocksToPlace.create(block, meta);
return fallback.getBlocksToPlace(t, world, x, y, z, trigger, env);
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
@@ -1031,7 +1040,9 @@ public class StructureUtility {
throw new IllegalArgumentException();
}
if (defaultBlock instanceof ICustomBlockSetting) {
return new StructureElement_Bridge<T>() {
return new IStructureElement<T>() {
private BlocksToPlace blocksToPlace;
@Override
public boolean check(T t, World world, int x, int y, int z) {
Block worldBlock = world.getBlock(x, y, z);
@@ -1050,25 +1061,31 @@ public class StructureUtility {
return true;
}
@Nullable
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
return StructureUtility.survivalPlaceBlock(
defaultBlock,
defaultMeta,
world,
x,
y,
z,
env.getSource(),
env.getActor(),
env.getChatter());
if (blocksToPlace == null) {
ImmutableList.Builder<ItemStack> blocks = ImmutableList.builder();
Predicate<ItemStack> predicate = s -> true;
for (Entry<Block, Integer> e : blocsMap.entrySet()) {
Item i = Item.getItemFromBlock(e.getKey());
int meta = e.getValue();
if (i instanceof ISpecialItemBlock)
meta = ((ISpecialItemBlock) i).getItemMetaFromBlockMeta(e.getKey(), meta);
ItemStack stack = new ItemStack(i, 1, meta);
blocks.add(stack);
predicate = predicate.and(ItemStackPredicate.from(stack));
}
blocksToPlace = new BlocksToPlace(predicate, blocks.build());
}
return blocksToPlace;
}
};
} else {
return new StructureElement_Bridge<T>() {
return new IStructureElement<T>() {
private BlocksToPlace blocksToPlace;
@Override
public boolean check(T t, World world, int x, int y, int z) {
Block worldBlock = world.getBlock(x, y, z);
@@ -1088,20 +1105,23 @@ public class StructureUtility {
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
return StructureUtility.survivalPlaceBlock(
defaultBlock,
defaultMeta,
world,
x,
y,
z,
env.getSource(),
env.getActor(),
env.getChatter());
if (blocksToPlace == null) {
ImmutableList.Builder<ItemStack> blocks = ImmutableList.builder();
Predicate<ItemStack> predicate = s -> true;
for (Entry<Block, Integer> e : blocsMap.entrySet()) {
Item i = Item.getItemFromBlock(e.getKey());
int meta = e.getValue();
if (i instanceof ISpecialItemBlock)
meta = ((ISpecialItemBlock) i).getItemMetaFromBlockMeta(e.getKey(), meta);
ItemStack stack = new ItemStack(i, 1, meta);
blocks.add(stack);
predicate = predicate.and(ItemStackPredicate.from(stack));
}
blocksToPlace = new BlocksToPlace(predicate, blocks.build());
}
return blocksToPlace;
}
};
}
@@ -1126,7 +1146,9 @@ public class StructureUtility {
}
}
if (defaultBlock instanceof ICustomBlockSetting) {
return new StructureElement_Bridge<T>() {
return new IStructureElement<T>() {
private BlocksToPlace blocksToPlace;
@Override
public boolean check(T t, World world, int x, int y, int z) {
Block worldBlock = world.getBlock(x, y, z);
@@ -1147,24 +1169,30 @@ public class StructureUtility {
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
return StructureUtility.survivalPlaceBlock(
defaultBlock,
defaultMeta,
world,
x,
y,
z,
env.getSource(),
env.getActor(),
env.getChatter());
if (blocksToPlace == null) {
ImmutableList.Builder<ItemStack> blocks = ImmutableList.builder();
Predicate<ItemStack> predicate = s -> true;
for (Entry<Block, Collection<Integer>> e : blocsMap.entrySet()) {
Item i = Item.getItemFromBlock(e.getKey());
for (int meta : e.getValue()) {
if (i instanceof ISpecialItemBlock)
meta = ((ISpecialItemBlock) i).getItemMetaFromBlockMeta(e.getKey(), meta);
ItemStack stack = new ItemStack(i, 1, meta);
blocks.add(stack);
predicate = predicate.and(ItemStackPredicate.from(stack));
}
}
blocksToPlace = new BlocksToPlace(predicate, blocks.build());
}
return blocksToPlace;
}
};
} else {
return new StructureElement_Bridge<T>() {
return new IStructureElement<T>() {
private BlocksToPlace blocksToPlace;
@Override
public boolean check(T t, World world, int x, int y, int z) {
Block worldBlock = world.getBlock(x, y, z);
@@ -1185,20 +1213,24 @@ public class StructureUtility {
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
return StructureUtility.survivalPlaceBlock(
defaultBlock,
defaultMeta,
world,
x,
y,
z,
env.getSource(),
env.getActor(),
env.getChatter());
if (blocksToPlace == null) {
ImmutableList.Builder<ItemStack> blocks = ImmutableList.builder();
Predicate<ItemStack> predicate = s -> true;
for (Entry<Block, Collection<Integer>> e : blocsMap.entrySet()) {
Item i = Item.getItemFromBlock(e.getKey());
for (int meta : e.getValue()) {
if (i instanceof ISpecialItemBlock)
meta = ((ISpecialItemBlock) i).getItemMetaFromBlockMeta(e.getKey(), meta);
ItemStack stack = new ItemStack(i, 1, meta);
blocks.add(stack);
predicate = predicate.and(ItemStackPredicate.from(stack));
}
}
blocksToPlace = new BlocksToPlace(predicate, blocks.build());
}
return blocksToPlace;
}
};
}
@@ -1217,7 +1249,7 @@ public class StructureUtility {
throw new IllegalArgumentException();
}
if (block instanceof ICustomBlockSetting) {
return new StructureElement_Bridge<T>() {
return new IStructureElement<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
Block worldBlock = world.getBlock(x, y, z);
@@ -1237,24 +1269,13 @@ public class StructureUtility {
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
return StructureUtility.survivalPlaceBlock(
defaultBlock,
defaultMeta,
world,
x,
y,
z,
env.getSource(),
env.getActor(),
env.getChatter());
return BlocksToPlace.create(block, meta);
}
};
} else {
return new StructureElement_Bridge<T>() {
return new IStructureElement<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
Block worldBlock = world.getBlock(x, y, z);
@@ -1274,20 +1295,9 @@ public class StructureUtility {
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
return StructureUtility.survivalPlaceBlock(
defaultBlock,
defaultMeta,
world,
x,
y,
z,
env.getSource(),
env.getActor(),
env.getChatter());
return BlocksToPlace.create(block, meta);
}
};
}
@@ -1301,7 +1311,7 @@ public class StructureUtility {
throw new IllegalArgumentException();
}
if (block instanceof ICustomBlockSetting) {
return new StructureElement_Bridge<T>() {
return new IStructureElement<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return block == world.getBlock(x, y, z);
@@ -1320,24 +1330,14 @@ public class StructureUtility {
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
return StructureUtility.survivalPlaceBlock(
defaultBlock,
defaultMeta,
world,
x,
y,
z,
env.getSource(),
env.getActor(),
env.getChatter());
// there is getSubItems on ItemBlock, but it's client only
return BlocksToPlace.create(defaultBlock, defaultMeta);
}
};
} else {
return new StructureElement_Bridge<T>() {
return new IStructureElement<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return block == world.getBlock(x, y, z);
@@ -1356,20 +1356,10 @@ public class StructureUtility {
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (check(t, world, x, y, z)) return PlaceResult.SKIP;
return StructureUtility.survivalPlaceBlock(
defaultBlock,
defaultMeta,
world,
x,
y,
z,
env.getSource(),
env.getActor(),
env.getChatter());
// there is getSubItems on ItemBlock, but it's client only
return BlocksToPlace.create(defaultBlock, defaultMeta);
}
};
}
@@ -1577,6 +1567,13 @@ public class StructureUtility {
return element.spawnHint(t, world, x, y, z, trigger);
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return element.getBlocksToPlace(t, world, x, y, z, trigger, env);
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
@@ -1628,6 +1625,13 @@ public class StructureUtility {
return element.spawnHint(t, world, x, y, z, trigger);
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return element.getBlocksToPlace(t, world, x, y, z, trigger, env);
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
@@ -1688,6 +1692,14 @@ public class StructureUtility {
return predicate.test(t) && downstream.placeBlock(t, world, x, y, z, trigger);
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
if (predicate.test(t)) return downstream.getBlocksToPlace(t, world, x, y, z, trigger, env);
return BlocksToPlace.createEmpty();
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
@@ -1784,6 +1796,13 @@ public class StructureUtility {
return elem.placeBlock(t.getCurrentContext(), world, x, y, z, trigger);
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return elem.getBlocksToPlace(t.getCurrentContext(), world, x, y, z, trigger, env);
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
@@ -1873,6 +1892,13 @@ public class StructureUtility {
return to.get().spawnHint(t, world, x, y, z, trigger);
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return to.get().getBlocksToPlace(t, world, x, y, z, trigger, env);
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
@@ -1927,6 +1953,13 @@ public class StructureUtility {
return to.apply(t).spawnHint(t, world, x, y, z, trigger);
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return to.apply(t).getBlocksToPlace(t, world, x, y, z, trigger, env);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
@@ -1983,42 +2016,7 @@ public class StructureUtility {
if (keyExtractor == null || map == null) {
throw new IllegalArgumentException();
}
return new IStructureElementDeferred<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return map.get(keyExtractor.apply(t)).check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.get(keyExtractor.apply(t)).placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.get(keyExtractor.apply(t)).spawnHint(t, world, x, y, z, trigger);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer<IChatComponent> chatter) {
return map.get(keyExtractor.apply(t)).survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return map.get(keyExtractor.apply(t)).survivalPlaceBlock(t, world, x, y, z, trigger, env);
}
};
return defer(keyExtractor.andThen(map::get));
}
/**
@@ -2061,44 +2059,7 @@ public class StructureUtility {
if (keyExtractor == null || map == null) {
throw new IllegalArgumentException();
}
return new IStructureElementDeferred<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return map.getOrDefault(keyExtractor.apply(t), defaultElem).check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.getOrDefault(keyExtractor.apply(t), defaultElem).placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.getOrDefault(keyExtractor.apply(t), defaultElem).spawnHint(t, world, x, y, z, trigger);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer<IChatComponent> chatter) {
return map.getOrDefault(keyExtractor.apply(t), defaultElem)
.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return map.getOrDefault(keyExtractor.apply(t), defaultElem)
.survivalPlaceBlock(t, world, x, y, z, trigger, env);
}
};
return defer(keyExtractor.andThen(key -> map.getOrDefault(key, defaultElem)));
}
/**
@@ -2139,42 +2100,7 @@ public class StructureUtility {
if (keyExtractor == null || array == null) {
throw new IllegalArgumentException();
}
return new IStructureElementDeferred<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return array[keyExtractor.apply(t)].check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return array[keyExtractor.apply(t)].placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return array[keyExtractor.apply(t)].spawnHint(t, world, x, y, z, trigger);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer<IChatComponent> chatter) {
return array[keyExtractor.apply(t)].survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return array[keyExtractor.apply(t)].survivalPlaceBlock(t, world, x, y, z, trigger, env);
}
};
return defer(keyExtractor.andThen(i -> array[i]));
}
/**
@@ -2247,6 +2173,13 @@ public class StructureUtility {
return to.apply(t, trigger).spawnHint(t, world, x, y, z, trigger);
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return to.apply(t, trigger).getBlocksToPlace(t, world, x, y, z, trigger, env);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
@@ -2311,43 +2244,7 @@ public class StructureUtility {
if (keyExtractor == null || map == null) {
throw new IllegalArgumentException();
}
return new IStructureElementDeferred<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return map.get(keyExtractor.apply(t, null)).check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.get(keyExtractor.apply(t, trigger)).placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.get(keyExtractor.apply(t, trigger)).spawnHint(t, world, x, y, z, trigger);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer<IChatComponent> chatter) {
return map.get(keyExtractor.apply(t, trigger))
.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return map.get(keyExtractor.apply(t, trigger)).survivalPlaceBlock(t, world, x, y, z, trigger, env);
}
};
return defer(keyExtractor.andThen(map::get));
}
/**
@@ -2398,47 +2295,7 @@ public class StructureUtility {
if (keyExtractor == null || map == null) {
throw new IllegalArgumentException();
}
return new IStructureElementDeferred<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return map.getOrDefault(keyExtractor.apply(t, null), defaultElem)
.check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.getOrDefault(keyExtractor.apply(t, trigger), defaultElem)
.placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.getOrDefault(keyExtractor.apply(t, trigger), defaultElem)
.spawnHint(t, world, x, y, z, trigger);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer<IChatComponent> chatter) {
return map.getOrDefault(keyExtractor.apply(t, trigger), defaultElem)
.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return map.getOrDefault(keyExtractor.apply(t, trigger), defaultElem)
.survivalPlaceBlock(t, world, x, y, z, trigger, env);
}
};
return defer(keyExtractor.andThen(key -> map.getOrDefault(key, defaultElem)));
}
/**
@@ -2461,43 +2318,7 @@ public class StructureUtility {
if (keyExtractor == null || array == null) {
throw new IllegalArgumentException();
}
return new IStructureElementDeferred<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return array[keyExtractor.apply(t, null)].check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return array[keyExtractor.apply(t, trigger)].placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return array[keyExtractor.apply(t, trigger)].spawnHint(t, world, x, y, z, trigger);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer<IChatComponent> chatter) {
return array[keyExtractor.apply(t, trigger)].survivalPlaceBlock(
t, world, x, y, z, trigger, s, actor, chatter);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return array[keyExtractor.apply(t, trigger)].survivalPlaceBlock(t, world, x, y, z, trigger, env);
}
};
return defer(keyExtractor.andThen(i -> array[i]));
}
/**
@@ -2514,10 +2335,9 @@ public class StructureUtility {
* @param keyExtractor extract a key from the context object and trigger item
* @param array all possible structure element
*/
@SuppressWarnings("unchecked")
public static <T> IStructureElementDeferred<T> defer(
BiFunction<T, ItemStack, Integer> keyExtractor, List<IStructureElement<T>> array) {
return defer(keyExtractor, array.toArray(new IStructureElement[0]));
return defer(keyExtractor.andThen(array::get));
}
/**
@@ -2632,43 +2452,7 @@ public class StructureUtility {
if (keyExtractor == null || map == null) {
throw new IllegalArgumentException();
}
return new IStructureElementDeferred<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return map.get(keyExtractorCheck.apply(t)).check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.get(keyExtractor.apply(t, trigger)).placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.get(keyExtractor.apply(t, trigger)).spawnHint(t, world, x, y, z, trigger);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer<IChatComponent> chatter) {
return map.get(keyExtractor.apply(t, trigger))
.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return map.get(keyExtractor.apply(t, trigger)).survivalPlaceBlock(t, world, x, y, z, trigger, env);
}
};
return defer(keyExtractorCheck.andThen(map::get), keyExtractor.<IStructureElement<T>>andThen(map::get));
}
/**
@@ -2725,46 +2509,9 @@ public class StructureUtility {
if (keyExtractor == null || map == null) {
throw new IllegalArgumentException();
}
return new IStructureElementDeferred<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return map.getOrDefault(keyExtractorCheck.apply(t), defaultElem).check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.getOrDefault(keyExtractor.apply(t, trigger), defaultElem)
.placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return map.getOrDefault(keyExtractor.apply(t, trigger), defaultElem)
.spawnHint(t, world, x, y, z, trigger);
}
@Override
public PlaceResult survivalPlaceBlock(
T t,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer<IChatComponent> chatter) {
return map.getOrDefault(keyExtractor.apply(t, trigger), defaultElem)
.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, chatter);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return map.getOrDefault(keyExtractor.apply(t, trigger), defaultElem)
.survivalPlaceBlock(t, world, x, y, z, trigger, env);
}
};
return defer(
keyExtractorCheck.andThen(k -> map.getOrDefault(k, defaultElem)),
keyExtractor.andThen(k -> map.getOrDefault(k, defaultElem)));
}
/**
@@ -2821,44 +2568,7 @@ public class StructureUtility {
if (keyExtractor == null || array == null) {
throw new IllegalArgumentException();
}
return new IStructureElementDeferred<T>() {
@Override
public boolean check(T t, World world, int x, int y, int z) {
return array[keyExtractorCheck.apply(t)].check(t, world, x, y, z);
}
@Override
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
return array[keyExtractor.apply(t, trigger)].placeBlock(t, world, x, y, z, trigger);
}
@Override
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
return array[keyExtractor.apply(t, trigger)].spawnHint(t, world, x, y, z, trigger);
}
@Override
@Deprecated
public PlaceResult survivalPlaceBlock(
T t,
World world,
int x,
int y,
int z,
ItemStack trigger,
IItemSource s,
EntityPlayerMP actor,
Consumer<IChatComponent> chatter) {
return array[keyExtractor.apply(t, trigger)].survivalPlaceBlock(
t, world, x, y, z, trigger, s, actor, chatter);
}
@Override
public PlaceResult survivalPlaceBlock(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return array[keyExtractor.apply(t, trigger)].survivalPlaceBlock(t, world, x, y, z, trigger, env);
}
};
return defer(keyExtractorCheck.andThen(i -> array[i]), keyExtractor.andThen(i -> array[i]));
}
/**
@@ -2948,6 +2658,13 @@ public class StructureUtility {
return backing.placeBlock(t, world, x, y, z, ChannelDataAccessor.withChannel(trigger, channel));
}
@Nullable
@Override
public BlocksToPlace getBlocksToPlace(
T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) {
return backing.getBlocksToPlace(t, world, x, y, z, trigger, env);
}
@Deprecated
public PlaceResult survivalPlaceBlock(
T t,