001/*
002 * This file is part of Baritone.
003 *
004 * Baritone is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU Lesser General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * Baritone is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public License
015 * along with Baritone.  If not, see <https://www.gnu.org/licenses/>.
016 */
017
018package baritone.api.schematic;
019
020import net.minecraft.block.state.IBlockState;
021
022import java.util.ArrayList;
023import java.util.List;
024
025public class CompositeSchematic extends AbstractSchematic {
026
027    private final List<CompositeSchematicEntry> schematics;
028    private CompositeSchematicEntry[] schematicArr;
029
030    private void recalcArr() {
031        schematicArr = schematics.toArray(new CompositeSchematicEntry[0]);
032        for (CompositeSchematicEntry entry : schematicArr) {
033            this.x = Math.max(x, entry.x + entry.schematic.widthX());
034            this.y = Math.max(y, entry.y + entry.schematic.heightY());
035            this.z = Math.max(z, entry.z + entry.schematic.lengthZ());
036        }
037    }
038
039    public CompositeSchematic(int x, int y, int z) {
040        super(x, y, z);
041        schematics = new ArrayList<>();
042        recalcArr();
043    }
044
045    public void put(ISchematic extra, int x, int y, int z) {
046        schematics.add(new CompositeSchematicEntry(extra, x, y, z));
047        recalcArr();
048    }
049
050    private CompositeSchematicEntry getSchematic(int x, int y, int z, IBlockState currentState) {
051        for (CompositeSchematicEntry entry : schematicArr) {
052            if (x >= entry.x && y >= entry.y && z >= entry.z &&
053                    entry.schematic.inSchematic(x - entry.x, y - entry.y, z - entry.z, currentState)) {
054                return entry;
055            }
056        }
057        return null;
058    }
059
060    @Override
061    public boolean inSchematic(int x, int y, int z, IBlockState currentState) {
062        CompositeSchematicEntry entry = getSchematic(x, y, z, currentState);
063        return entry != null && entry.schematic.inSchematic(x - entry.x, y - entry.y, z - entry.z, currentState);
064    }
065
066    @Override
067    public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) {
068        CompositeSchematicEntry entry = getSchematic(x, y, z, current);
069        if (entry == null) {
070            throw new IllegalStateException("couldn't find schematic for this position");
071        }
072        return entry.schematic.desiredState(x - entry.x, y - entry.y, z - entry.z, current, approxPlaceable);
073    }
074
075    @Override
076    public void reset() {
077        for (CompositeSchematicEntry entry : schematicArr) {
078            entry.schematic.reset();
079        }
080    }
081}