NaturesAura/src/main/java/de/ellpeck/naturesaura/blocks/multi/Multiblock.java

183 lines
5.6 KiB
Java
Raw Normal View History

2018-11-07 13:33:49 +01:00
package de.ellpeck.naturesaura.blocks.multi;
import de.ellpeck.naturesaura.api.NaturesAuraAPI;
import de.ellpeck.naturesaura.api.multiblock.IMultiblock;
import de.ellpeck.naturesaura.api.multiblock.Matcher;
import de.ellpeck.naturesaura.compat.patchouli.PatchouliCompat;
2021-12-08 00:31:29 +01:00
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
2018-11-07 13:33:49 +01:00
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
public class Multiblock implements IMultiblock {
2018-11-07 13:33:49 +01:00
private final ResourceLocation name;
2019-01-26 00:34:05 +01:00
private final Map<BlockPos, Matcher> matchers = new HashMap<>();
private final int width;
private final int height;
private final int depth;
private final int xOffset;
private final int yOffset;
private final int zOffset;
private final char[][][] rawPattern;
2018-11-07 13:33:49 +01:00
public Multiblock(ResourceLocation name, String[][] pattern, Object... rawMatchers) {
this.name = name;
2021-12-15 16:30:22 +01:00
var width = -1;
2018-11-07 13:33:49 +01:00
this.height = pattern.length;
2021-12-15 16:30:22 +01:00
var depth = -1;
var xOff = 0;
var yOff = 0;
var zOff = 0;
2018-11-07 13:33:49 +01:00
char[][][] raw = null;
2021-12-15 16:30:22 +01:00
for (var i = 0; i < pattern.length; i++) {
var row = pattern[i];
2018-11-07 13:33:49 +01:00
if (width < 0)
width = row.length;
else if (row.length != width)
throw new IllegalArgumentException();
2021-12-15 16:30:22 +01:00
for (var j = 0; j < row.length; j++) {
var column = row[j];
2018-11-07 13:33:49 +01:00
if (depth < 0)
depth = column.length();
else if (column.length() != depth)
throw new IllegalArgumentException();
if (raw == null)
raw = new char[width][this.height][depth];
2021-12-15 16:30:22 +01:00
for (var k = 0; k < column.length(); k++) {
var c = column.charAt(k);
2018-11-07 13:33:49 +01:00
raw[k][this.height - 1 - i][j] = c;
if (c == '0') {
xOff = k;
yOff = this.height - 1 - i;
zOff = j;
}
}
}
}
this.depth = depth;
this.width = width;
this.xOffset = xOff;
this.yOffset = yOff;
this.zOffset = zOff;
this.rawPattern = raw;
Map<Character, Matcher> matchers = new HashMap<>();
2021-12-15 16:30:22 +01:00
for (var i = 0; i < rawMatchers.length; i += 2) {
var c = (char) rawMatchers[i];
2018-11-07 13:33:49 +01:00
if (matchers.containsKey(c))
continue;
2021-12-15 16:30:22 +01:00
var value = rawMatchers[i + 1];
2021-12-08 00:31:29 +01:00
if (value instanceof BlockState state) {
matchers.put(c, new Matcher(state,
2021-12-04 15:40:09 +01:00
(level, start, offset, pos, other, otherC) -> other == state));
2021-12-08 00:31:29 +01:00
} else if (value instanceof Block block) {
matchers.put(c, new Matcher(block.defaultBlockState(),
2021-12-04 15:40:09 +01:00
(level, start, offset, pos, state, otherC) -> state.getBlock() == block));
} else
2018-11-07 13:33:49 +01:00
matchers.put(c, (Matcher) value);
}
2021-12-15 16:30:22 +01:00
for (var x = 0; x < this.width; x++)
for (var y = 0; y < this.height; y++)
for (var z = 0; z < this.depth; z++) {
var matcher = matchers.get(this.rawPattern[x][y][z]);
2018-11-07 13:33:49 +01:00
if (matcher == null)
throw new IllegalStateException();
2021-12-15 16:24:53 +01:00
if (matcher.check() != null)
2018-11-07 13:33:49 +01:00
this.matchers.put(new BlockPos(x, y, z), matcher);
}
PatchouliCompat.addPatchouliMultiblock(name, pattern, rawMatchers);
NaturesAuraAPI.MULTIBLOCKS.put(this.name, this);
2018-11-07 13:33:49 +01:00
}
@Override
2021-12-04 15:40:09 +01:00
public boolean isComplete(Level level, BlockPos center) {
2021-12-15 16:30:22 +01:00
var start = this.getStart(center);
2018-11-07 13:33:49 +01:00
return this.forEach(center, (char) 0, (pos, matcher) -> {
2021-12-15 16:30:22 +01:00
var offset = pos.subtract(start);
2021-12-15 16:24:53 +01:00
return matcher.check().matches(level, start, offset, pos, level.getBlockState(pos), this.getChar(offset));
2018-11-07 13:33:49 +01:00
});
}
@Override
2019-01-26 00:34:05 +01:00
public boolean forEach(BlockPos center, char c, BiFunction<BlockPos, Matcher, Boolean> function) {
2021-12-15 16:30:22 +01:00
var start = this.getStart(center);
for (var entry : this.matchers.entrySet()) {
var offset = entry.getKey();
2018-11-07 13:33:49 +01:00
if (c == 0 || this.getChar(offset) == c)
2021-12-08 00:31:29 +01:00
if (!function.apply(start.offset(offset), entry.getValue()))
2018-11-07 13:33:49 +01:00
return false;
}
return true;
}
@Override
2018-11-07 13:33:49 +01:00
public BlockPos getStart(BlockPos center) {
2021-12-08 00:31:29 +01:00
return center.offset(-this.xOffset, -this.yOffset, -this.zOffset);
2018-11-07 13:33:49 +01:00
}
@Override
2018-11-07 13:33:49 +01:00
public char getChar(BlockPos offset) {
return this.rawPattern[offset.getX()][offset.getY()][offset.getZ()];
}
@Override
public ResourceLocation getName() {
return this.name;
}
2018-11-07 13:33:49 +01:00
@Override
2019-01-26 00:34:05 +01:00
public Map<BlockPos, Matcher> getMatchers() {
return this.matchers;
}
2018-11-07 13:33:49 +01:00
@Override
public int getWidth() {
return this.width;
}
2018-11-07 13:33:49 +01:00
@Override
public int getHeight() {
return this.height;
}
2018-11-07 13:33:49 +01:00
@Override
public int getDepth() {
return this.depth;
}
2018-11-07 13:33:49 +01:00
@Override
public int getXOffset() {
return this.xOffset;
}
@Override
public int getYOffset() {
return this.yOffset;
}
@Override
public int getZOffset() {
return this.zOffset;
2018-11-07 13:33:49 +01:00
}
@Override
public char[][][] getRawPattern() {
return this.rawPattern;
2018-11-07 13:33:49 +01:00
}
}