package com.gtnewhorizon.structurelib.structure; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; 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; import net.minecraft.world.World; import com.google.common.collect.Iterables; /** * Use StructureUtility to instantiate */ public interface IStructureElementChain extends IStructureElement { IStructureElement[] fallbacks(); @Override default boolean check(T t, World world, int x, int y, int z) { for (IStructureElement fallback : fallbacks()) { if (fallback.check(t, world, x, y, z)) { return true; } } return false; } @Override default boolean couldBeValid(T t, World world, int x, int y, int z, ItemStack trigger) { for (IStructureElement fallback : fallbacks()) { if (fallback.couldBeValid(t, world, x, y, z, trigger)) { return true; } } return false; } @Override default boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) { for (IStructureElement fallback : fallbacks()) { if (fallback.spawnHint(t, world, x, y, z, trigger)) { return true; } } return false; } @Override default boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) { for (IStructureElement fallback : fallbacks()) { if (fallback.placeBlock(t, world, x, y, z, trigger)) { return true; } } return false; } @Nullable @Override default List getDescription(T context) { Set descriptions = new LinkedHashSet<>(); for (IStructureElement fallback : fallbacks()) { List desc = fallback.getDescription(context); if (desc != null) { descriptions.addAll(desc); } } return descriptions.isEmpty() ? null : new ArrayList<>(descriptions); } @Nullable @Override default BlocksToPlace getBlocksToPlace(T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) { Predicate predicate = null; List> is = new ArrayList<>(); for (IStructureElement 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()); Iterable stacks = e.getStacks(); if (stacks != null) is.add(stacks); } if (predicate == null) return null; return new BlocksToPlace(predicate, Iterables.concat(is)); } @Override default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, IItemSource s, EntityPlayerMP actor, Consumer chatter) { boolean allContinue = true; List bufferedNoise = new ArrayList<>(); for (IStructureElement fallback : fallbacks()) { PlaceResult result = fallback.survivalPlaceBlock(t, world, x, y, z, trigger, s, actor, bufferedNoise::add); switch (result) { case REJECT_CONTINUE: break; case REJECT: allContinue = false; break; case SKIP: bufferedNoise.forEach(chatter); return PlaceResult.SKIP; default: return result; } } // dump all that noise back into upstream bufferedNoise.forEach(chatter); return allContinue ? PlaceResult.REJECT_CONTINUE : PlaceResult.REJECT; } @Override default PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger, AutoPlaceEnvironment env) { boolean allContinue = true; List bufferedNoise = new ArrayList<>(); for (IStructureElement fallback : fallbacks()) { PlaceResult result = fallback .survivalPlaceBlock(t, world, x, y, z, trigger, env.withChatter(bufferedNoise::add)); switch (result) { case REJECT_CONTINUE: break; case REJECT: allContinue = false; break; case SKIP: bufferedNoise.forEach(env.getChatter()); return PlaceResult.SKIP; default: return result; } } // dump all that noise back into upstream bufferedNoise.forEach(env.getChatter()); return allContinue ? PlaceResult.REJECT_CONTINUE : PlaceResult.REJECT; } }