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 java.util.ArrayList;
021import java.util.List;
022import net.minecraft.world.level.block.state.BlockState;
023
024public class CompositeSchematic extends AbstractSchematic {
025
026    private final List<CompositeSchematicEntry> schematics;
027    private CompositeSchematicEntry[] schematicArr;
028
029    private void recalcArr() {
030        schematicArr = schematics.toArray(new CompositeSchematicEntry[0]);
031        for (CompositeSchematicEntry entry : schematicArr) {
032            this.x = Math.max(x, entry.x + entry.schematic.widthX());
033            this.y = Math.max(y, entry.y + entry.schematic.heightY());
034            this.z = Math.max(z, entry.z + entry.schematic.lengthZ());
035        }
036    }
037
038    public CompositeSchematic(int x, int y, int z) {
039        super(x, y, z);
040        schematics = new ArrayList<>();
041        recalcArr();
042    }
043
044    public void put(ISchematic extra, int x, int y, int z) {
045        schematics.add(new CompositeSchematicEntry(extra, x, y, z));
046        recalcArr();
047    }
048
049    private CompositeSchematicEntry getSchematic(int x, int y, int z, BlockState currentState) {
050        for (CompositeSchematicEntry entry : schematicArr) {
051            if (x >= entry.x && y >= entry.y && z >= entry.z &&
052                    entry.schematic.inSchematic(x - entry.x, y - entry.y, z - entry.z, currentState)) {
053                return entry;
054            }
055        }
056        return null;
057    }
058
059    @Override
060    public boolean inSchematic(int x, int y, int z, BlockState currentState) {
061        CompositeSchematicEntry entry = getSchematic(x, y, z, currentState);
062        return entry != null && entry.schematic.inSchematic(x - entry.x, y - entry.y, z - entry.z, currentState);
063    }
064
065    @Override
066    public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
067        CompositeSchematicEntry entry = getSchematic(x, y, z, current);
068        if (entry == null) {
069            throw new IllegalStateException("couldn't find schematic for this position");
070        }
071        return entry.schematic.desiredState(x - entry.x, y - entry.y, z - entry.z, current, approxPlaceable);
072    }
073
074    @Override
075    public void reset() {
076        for (CompositeSchematicEntry entry : schematicArr) {
077            entry.schematic.reset();
078        }
079    }
080}