2018-11-07 13:33:49 +01:00
|
|
|
package de.ellpeck.naturesaura.blocks.multi;
|
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
import de.ellpeck.naturesaura.api.NaturesAuraAPI;
|
|
|
|
import de.ellpeck.naturesaura.api.multiblock.IMultiblock;
|
|
|
|
import de.ellpeck.naturesaura.api.multiblock.Matcher;
|
2019-03-01 18:27:24 +01:00
|
|
|
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;
|
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
public class Multiblock implements IMultiblock {
|
2018-11-07 13:33:49 +01:00
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
private final ResourceLocation name;
|
2019-01-26 00:34:05 +01:00
|
|
|
private final Map<BlockPos, Matcher> matchers = new HashMap<>();
|
2018-11-23 19:21:52 +01:00
|
|
|
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) {
|
2018-11-23 19:21:52 +01:00
|
|
|
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));
|
2018-11-23 19:21:52 +01:00
|
|
|
} 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);
|
|
|
|
}
|
|
|
|
|
2019-03-01 18:27:24 +01:00
|
|
|
PatchouliCompat.addPatchouliMultiblock(name, pattern, rawMatchers);
|
2018-11-23 19:21:52 +01:00
|
|
|
NaturesAuraAPI.MULTIBLOCKS.put(this.name, this);
|
2018-11-07 13:33:49 +01:00
|
|
|
}
|
|
|
|
|
2018-11-23 19:21:52 +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
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-11-23 19:21:52 +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;
|
|
|
|
}
|
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@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
|
|
|
}
|
|
|
|
|
2018-11-23 19:21:52 +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()];
|
|
|
|
}
|
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@Override
|
|
|
|
public ResourceLocation getName() {
|
|
|
|
return this.name;
|
|
|
|
}
|
2018-11-07 13:33:49 +01:00
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@Override
|
2019-01-26 00:34:05 +01:00
|
|
|
public Map<BlockPos, Matcher> getMatchers() {
|
2018-11-23 19:21:52 +01:00
|
|
|
return this.matchers;
|
|
|
|
}
|
2018-11-07 13:33:49 +01:00
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@Override
|
|
|
|
public int getWidth() {
|
|
|
|
return this.width;
|
|
|
|
}
|
2018-11-07 13:33:49 +01:00
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@Override
|
|
|
|
public int getHeight() {
|
|
|
|
return this.height;
|
|
|
|
}
|
2018-11-07 13:33:49 +01:00
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@Override
|
|
|
|
public int getDepth() {
|
|
|
|
return this.depth;
|
|
|
|
}
|
2018-11-07 13:33:49 +01:00
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@Override
|
|
|
|
public int getXOffset() {
|
|
|
|
return this.xOffset;
|
|
|
|
}
|
2018-11-17 21:31:57 +01:00
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@Override
|
|
|
|
public int getYOffset() {
|
|
|
|
return this.yOffset;
|
|
|
|
}
|
2018-11-17 21:31:57 +01:00
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@Override
|
|
|
|
public int getZOffset() {
|
|
|
|
return this.zOffset;
|
2018-11-07 13:33:49 +01:00
|
|
|
}
|
|
|
|
|
2018-11-23 19:21:52 +01:00
|
|
|
@Override
|
|
|
|
public char[][][] getRawPattern() {
|
|
|
|
return this.rawPattern;
|
2018-11-07 13:33:49 +01:00
|
|
|
}
|
|
|
|
}
|