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.world.level.block.state.BlockState;
021import net.minecraft.world.level.block.Mirror;
022
023import java.util.List;
024import java.util.stream.Collectors;
025
026public class MirroredSchematic implements ISchematic {
027
028    private final ISchematic schematic;
029    private final Mirror mirror;
030
031    public MirroredSchematic(ISchematic schematic, Mirror mirror) {
032        this.schematic = schematic;
033        this.mirror = mirror;
034    }
035
036    @Override
037    public boolean inSchematic(int x, int y, int z, BlockState currentState) {
038        return schematic.inSchematic(
039                mirrorX(x, widthX(), mirror),
040                y,
041                mirrorZ(z, lengthZ(), mirror),
042                mirror(currentState, mirror)
043        );
044    }
045
046    @Override
047    public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
048        return mirror(schematic.desiredState(
049                mirrorX(x, widthX(), mirror),
050                y,
051                mirrorZ(z, lengthZ(), mirror),
052                mirror(current, mirror),
053                mirror(approxPlaceable, mirror)
054        ), mirror);
055    }
056
057    @Override
058    public void reset() {
059        schematic.reset();
060    }
061
062    @Override
063    public int widthX() {
064        return schematic.widthX();
065    }
066
067    @Override
068    public int heightY() {
069        return schematic.heightY();
070    }
071
072    @Override
073    public int lengthZ() {
074        return schematic.lengthZ();
075    }
076
077    private static int mirrorX(int x, int sizeX, Mirror mirror) {
078        switch (mirror) {
079            case NONE:
080            case LEFT_RIGHT:
081                return x;
082            case FRONT_BACK:
083                return sizeX - x - 1;
084        }
085        throw new IllegalArgumentException("Unknown mirror");
086    }
087
088    private static int mirrorZ(int z, int sizeZ, Mirror mirror) {
089        switch (mirror) {
090            case NONE:
091            case FRONT_BACK:
092                return z;
093            case LEFT_RIGHT:
094                return sizeZ - z - 1;
095        }
096        throw new IllegalArgumentException("Unknown mirror");
097    }
098
099    private static BlockState mirror(BlockState state, Mirror mirror) {
100        if (state == null) {
101            return null;
102        }
103        return state.mirror(mirror);
104    }
105
106    private static List<BlockState> mirror(List<BlockState> states, Mirror mirror) {
107        if (states == null) {
108            return null;
109        }
110        return states.stream()
111                .map(s -> mirror(s, mirror))
112                .collect(Collectors.toList());
113    }
114}