use of com.lowdragmc.multiblocked.api.pattern.predicates.SimplePredicate in project Multiblocked by Low-Drag-MC.
the class TemplateBuilderWidget method onSelected.
@OnlyIn(Dist.CLIENT)
public void onSelected(ItemStack itemStack, int slot) {
if (this.selected != itemStack) {
this.selected = itemStack;
this.selectedSlot = slot;
if (selected != null && isRemote()) {
this.pos = null;
this.facing = null;
templateButton.setVisible(true);
if (ItemBlueprint.isRaw(itemStack)) {
BlockPos[] poses = ItemBlueprint.getPos(itemStack);
World world = table.getLevel();
sceneWidget.createScene(world);
if (poses != null && world.hasChunksAt(poses[0], poses[1])) {
Set<BlockPos> rendered = new HashSet<>();
for (int x = poses[0].getX(); x <= poses[1].getX(); x++) {
for (int y = poses[0].getY(); y <= poses[1].getY(); y++) {
for (int z = poses[0].getZ(); z <= poses[1].getZ(); z++) {
if (!world.isEmptyBlock(new BlockPos(x, y, z))) {
rendered.add(new BlockPos(x, y, z));
}
}
}
}
sceneWidget.setRenderedCore(rendered, null);
}
} else if (itemStack.getTagElement("pattern") != null) {
String json = itemStack.getTagElement("pattern").getString("json");
JsonBlockPattern pattern = Multiblocked.GSON.fromJson(json, JsonBlockPattern.class);
int[] centerOffset = pattern.getCenterOffset();
String[][] patternString = pattern.pattern;
Set<BlockPos> rendered = new HashSet<>();
TrackedDummyWorld world = new TrackedDummyWorld();
sceneWidget.createScene(world);
int offset = Math.max(patternString.length, Math.max(patternString[0].length, patternString[0][0].length()));
for (int i = 0; i < patternString.length; i++) {
for (int j = 0; j < patternString[0].length; j++) {
for (int k = 0; k < patternString[0][0].length(); k++) {
char symbol = patternString[i][j].charAt(k);
BlockPos pos = pattern.getActualPosOffset(k - centerOffset[2], j - centerOffset[1], i - centerOffset[0], Direction.NORTH).offset(offset, offset, offset);
world.addBlock(pos, BlockInfo.fromBlockState(MbdComponents.DummyComponentBlock.defaultBlockState()));
DummyComponentTileEntity tileEntity = (DummyComponentTileEntity) world.getBlockEntity(pos);
ComponentDefinition definition = null;
assert tileEntity != null;
if (pattern.symbolMap.containsKey(symbol)) {
Set<BlockInfo> candidates = new HashSet<>();
for (String s : pattern.symbolMap.get(symbol)) {
SimplePredicate predicate = pattern.predicates.get(s);
if (predicate instanceof PredicateComponent && ((PredicateComponent) predicate).definition != null) {
definition = ((PredicateComponent) predicate).definition;
break;
} else if (predicate != null && predicate.candidates != null) {
candidates.addAll(Arrays.asList(predicate.candidates.get()));
}
}
definition = getComponentDefinition(definition, candidates);
}
if (definition != null) {
tileEntity.setDefinition(definition);
}
tileEntity.isFormed = false;
tileEntity.setLevelAndPosition(world, pos);
rendered.add(pos);
}
}
}
sceneWidget.setRenderedCore(rendered, null);
}
}
}
}
use of com.lowdragmc.multiblocked.api.pattern.predicates.SimplePredicate in project Multiblocked by Low-Drag-MC.
the class PatternWidget method onPosSelected.
private void onPosSelected(BlockPos pos, Direction facing) {
if (index >= patterns.length || index < 0)
return;
TraceabilityPredicate predicate = patterns[index].predicateMap.get(pos);
if (predicate != null) {
predicates.clear();
predicates.addAll(predicate.common);
predicates.addAll(predicate.limited);
// why it happens?
predicates.removeIf(p -> p == null || p.candidates == null);
if (candidates != null) {
for (SlotWidget candidate : candidates) {
removeWidget(candidate);
}
}
List<List<ItemStack>> candidateStacks = new ArrayList<>();
List<List<String>> predicateTips = new ArrayList<>();
for (SimplePredicate simplePredicate : predicates) {
List<ItemStack> itemStacks = simplePredicate.getCandidates();
if (!itemStacks.isEmpty()) {
candidateStacks.add(itemStacks);
predicateTips.add(simplePredicate.getToolTips(predicate));
}
}
candidates = new SlotWidget[candidateStacks.size()];
CycleItemStackHandler itemHandler = new CycleItemStackHandler(candidateStacks);
for (int i = 0; i < candidateStacks.size(); i++) {
int finalI = i;
candidates[i] = new SlotWidget(itemHandler, i, 9 + (i / 6) * 18, 33 + (i % 6) * 18, false, false).setItemHook(this::itemHook).setBackgroundTexture(new ColorRectTexture(0x4fffffff)).setOnAddedTooltips((slot, list) -> predicateTips.get(finalI).forEach(tip -> list.add(new StringTextComponent(tip))));
addWidget(candidates[i]);
}
updateClientSlots();
}
}
use of com.lowdragmc.multiblocked.api.pattern.predicates.SimplePredicate in project Multiblocked by Low-Drag-MC.
the class BlockPattern method getPreview.
public BlockInfo[][][] getPreview(int[] repetition) {
Map<SimplePredicate, Integer> cacheGlobal = new HashMap<>();
Map<BlockPos, BlockInfo> blocks = new HashMap<>();
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int minZ = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
int maxZ = Integer.MIN_VALUE;
for (int l = 0, x = 0; l < this.fingerLength; l++) {
for (int r = 0; r < repetition[l]; r++) {
// Checking single slice
for (int y = 0; y < this.thumbLength; y++) {
for (int z = 0; z < this.palmLength; z++) {
TraceabilityPredicate predicate = this.blockMatches[l][y][z];
boolean find = false;
BlockInfo[] infos = null;
// check global and previewCount
for (SimplePredicate limit : predicate.limited) {
if (limit.minCount == -1 && limit.previewCount == -1)
continue;
if (cacheGlobal.getOrDefault(limit, 0) < limit.previewCount) {
if (!cacheGlobal.containsKey(limit)) {
cacheGlobal.put(limit, 1);
} else if (cacheGlobal.get(limit) < limit.previewCount) {
cacheGlobal.put(limit, cacheGlobal.get(limit) + 1);
} else {
continue;
}
} else if (limit.minCount > 0) {
if (!cacheGlobal.containsKey(limit)) {
cacheGlobal.put(limit, 1);
} else if (cacheGlobal.get(limit) < limit.minCount) {
cacheGlobal.put(limit, cacheGlobal.get(limit) + 1);
} else {
continue;
}
} else {
continue;
}
infos = limit.candidates == null ? null : limit.candidates.get();
find = true;
break;
}
if (!find) {
// check common with previewCount
for (SimplePredicate common : predicate.common) {
if (common.previewCount > 0) {
if (!cacheGlobal.containsKey(common)) {
cacheGlobal.put(common, 1);
} else if (cacheGlobal.get(common) < common.previewCount) {
cacheGlobal.put(common, cacheGlobal.get(common) + 1);
} else {
continue;
}
} else {
continue;
}
infos = common.candidates == null ? null : common.candidates.get();
find = true;
break;
}
}
if (!find) {
// check without previewCount
for (SimplePredicate common : predicate.common) {
if (common.previewCount == -1) {
infos = common.candidates == null ? null : common.candidates.get();
find = true;
break;
}
}
}
if (!find) {
// check max
for (SimplePredicate limit : predicate.limited) {
if (limit.previewCount != -1) {
continue;
} else if (limit.maxCount != -1) {
if (cacheGlobal.getOrDefault(limit, 0) < limit.maxCount) {
if (!cacheGlobal.containsKey(limit)) {
cacheGlobal.put(limit, 1);
} else {
cacheGlobal.put(limit, cacheGlobal.get(limit) + 1);
}
} else {
continue;
}
}
infos = limit.candidates == null ? null : limit.candidates.get();
break;
}
}
BlockInfo info = infos == null || infos.length == 0 ? BlockInfo.EMPTY : infos[0];
BlockPos pos = setActualRelativeOffset(z, y, x, Direction.NORTH);
blocks.put(pos, info);
minX = Math.min(pos.getX(), minX);
minY = Math.min(pos.getY(), minY);
minZ = Math.min(pos.getZ(), minZ);
maxX = Math.max(pos.getX(), maxX);
maxY = Math.max(pos.getY(), maxY);
maxZ = Math.max(pos.getZ(), maxZ);
}
}
x++;
}
}
BlockInfo[][][] result = (BlockInfo[][][]) Array.newInstance(BlockInfo.class, maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1);
int finalMinX = minX;
int finalMinY = minY;
int finalMinZ = minZ;
blocks.forEach((pos, info) -> {
TileEntity te = blocks.get(pos).getTileEntity();
resetFacing(pos, info.getBlockState(), null, (p, f) -> {
BlockInfo blockInfo = blocks.get(p.relative(f));
if (blockInfo == null || blockInfo.getBlockState().getBlock() == Blocks.AIR) {
if (te instanceof ComponentTileEntity) {
return ((ComponentTileEntity<?>) te).isValidFrontFacing(f);
}
return true;
}
return false;
}, info::setBlockState);
result[pos.getX() - finalMinX][pos.getY() - finalMinY][pos.getZ() - finalMinZ] = info;
});
return result;
}
use of com.lowdragmc.multiblocked.api.pattern.predicates.SimplePredicate 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.predicates.SimplePredicate in project Multiblocked by Low-Drag-MC.
the class MbdPredicates method createPredicate.
public static SimplePredicate createPredicate(String type, JsonObject json) {
if (type.equals("any"))
return SimplePredicate.ANY;
if (type.equals("air"))
return SimplePredicate.AIR;
Class<? extends SimplePredicate> clazz = getPredicate(type);
if (clazz != null) {
try {
SimplePredicate simplePredicate = clazz.newInstance();
if (json == null)
return simplePredicate.buildPredicate();
simplePredicate.fromJson(Multiblocked.GSON, json);
simplePredicate.buildPredicate();
return simplePredicate;
} catch (Exception ignored) {
}
}
return null;
}
Aggregations