use of com.lowdragmc.multiblocked.api.pattern.util.PatternMatchContext in project Multiblocked by Low-Drag-MC.
the class BlockPattern method checkPatternAt.
private boolean checkPatternAt(MultiblockState worldState, BlockPos centerPos, Direction facing, boolean savePredicate, Set<MultiblockCapability<?>> inputCapabilities, Set<MultiblockCapability<?>> outputCapabilities) {
boolean findFirstAisle = false;
int minZ = -centerOffset[4];
worldState.clean();
PatternMatchContext matchContext = worldState.matchContext;
Map<SimplePredicate, Integer> globalCount = worldState.globalCount;
// Checking aisles
for (int c = 0, z = minZ++, r; c < this.fingerLength; c++) {
// Checking repeatable slices
loop: for (r = 0; (findFirstAisle ? r < aisleRepetitions[c][1] : z <= -centerOffset[3]); r++) {
// Checking single slice
for (int b = 0, y = -centerOffset[1]; b < this.thumbLength; b++, y++) {
for (int a = 0, x = -centerOffset[0]; a < this.palmLength; a++, x++) {
worldState.setError(null);
TraceabilityPredicate predicate = this.blockMatches[c][b][a];
BlockPos pos = setActualRelativeOffset(x, y, z, facing).offset(centerPos.getX(), centerPos.getY(), centerPos.getZ());
if (!worldState.update(pos, predicate)) {
return false;
}
if (!predicate.isAny()) {
worldState.addPosCache(pos);
if (savePredicate) {
worldState.getMatchContext().getOrCreate("predicates", (Supplier<HashMap<BlockPos, TraceabilityPredicate>>) HashMap::new).put(pos, predicate);
}
}
boolean canPartShared = true;
TileEntity tileEntity = worldState.getTileEntity();
if (tileEntity instanceof IPartComponent) {
// add detected parts
if (!predicate.isAny()) {
IPartComponent part = (IPartComponent) tileEntity;
if (part.isFormed() && !part.canShared() && !part.hasController(worldState.controllerPos)) {
// check part can be shared
canPartShared = false;
worldState.setError(new PatternStringError("multiblocked.pattern.error.share"));
} else {
worldState.getMatchContext().getOrCreate("parts", LongOpenHashSet::new).add(worldState.getPos().asLong());
}
}
}
if (!predicate.test(worldState) || !canPartShared) {
// matching failed
if (findFirstAisle) {
if (r < aisleRepetitions[c][0]) {
// retreat to see if the first aisle can start later
r = c = 0;
z = minZ++;
matchContext.reset();
findFirstAisle = false;
}
} else {
// continue searching for the first aisle
z++;
}
continue loop;
}
if (tileEntity != null && !predicate.isAny()) {
Map<Long, EnumMap<IO, Set<MultiblockCapability<?>>>> capabilities = worldState.getMatchContext().getOrCreate("capabilities", Long2ObjectOpenHashMap::new);
if (!capabilities.containsKey(worldState.getPos().asLong()) && worldState.io != null) {
// if predicate has no specific capability requirements. we will check abilities of every blocks
Set<MultiblockCapability<?>> bothFound = new HashSet<>();
for (MultiblockCapability<?> capability : inputCapabilities) {
// IN
if (worldState.io == IO.BOTH && outputCapabilities.contains(capability) && capability.isBlockHasCapability(IO.BOTH, tileEntity)) {
bothFound.add(capability);
capabilities.computeIfAbsent(worldState.getPos().asLong(), l -> new EnumMap<>(IO.class)).computeIfAbsent(IO.BOTH, xx -> new HashSet<>()).add(capability);
} else if (worldState.io != IO.OUT && capability.isBlockHasCapability(IO.IN, tileEntity)) {
capabilities.computeIfAbsent(worldState.getPos().asLong(), l -> new EnumMap<>(IO.class)).computeIfAbsent(IO.IN, xx -> new HashSet<>()).add(capability);
}
}
if (worldState.io != IO.IN) {
for (MultiblockCapability<?> capability : outputCapabilities) {
// OUT
if (!bothFound.contains(capability) && capability.isBlockHasCapability(IO.OUT, tileEntity)) {
capabilities.computeIfAbsent(worldState.getPos().asLong(), l -> new EnumMap<>(IO.class)).computeIfAbsent(IO.OUT, xx -> new HashSet<>()).add(capability);
}
}
}
}
}
}
}
findFirstAisle = true;
z++;
}
// Repetitions out of range
if (r < aisleRepetitions[c][0] || !worldState.isFormed() || !findFirstAisle) {
if (worldState.isFormed()) {
worldState.setError(new PatternError());
}
return false;
}
}
// Check count matches amount
for (Map.Entry<SimplePredicate, Integer> entry : globalCount.entrySet()) {
if (entry.getValue() < entry.getKey().minCount) {
worldState.setError(new SinglePredicateError(entry.getKey(), 1));
return false;
}
}
worldState.setError(null);
return true;
}
use of com.lowdragmc.multiblocked.api.pattern.util.PatternMatchContext in project Multiblocked by Low-Drag-MC.
the class MultiblockState method clean.
public void clean() {
this.matchContext = new PatternMatchContext();
this.globalCount = new HashMap<>();
cache = new LongOpenHashSet();
}
Aggregations