use of com.lowdragmc.multiblocked.api.tile.part.IPartComponent 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.tile.part.IPartComponent in project Multiblocked by Low-Drag-MC.
the class ControllerTileEntity method onStructureInvalid.
public void onStructureInvalid() {
if (recipeLogic != null) {
recipeLogic.inValid();
}
recipeLogic = null;
setStatus("unformed");
// invalid parts
if (parts != null) {
for (Long pos : parts) {
TileEntity tileEntity = level.getBlockEntity(BlockPos.of(pos));
if (tileEntity instanceof IPartComponent) {
((IPartComponent) tileEntity).removedFromController(this);
}
}
parts = null;
}
capabilities = null;
writeCustomData(-1, this::writeState);
if (Multiblocked.isKubeJSLoaded()) {
new StructureInvalidEvent(this).post(ScriptType.SERVER, StructureInvalidEvent.ID, getSubID());
}
}
use of com.lowdragmc.multiblocked.api.tile.part.IPartComponent in project Multiblocked by Low-Drag-MC.
the class ControllerTileEntity method onStructureFormed.
/**
* Called when its formed, server side only.
*/
public void onStructureFormed() {
if (recipeLogic == null) {
recipeLogic = new RecipeLogic(this);
}
if (status.equals("unformed")) {
setStatus("idle");
}
// init capabilities
Map<Long, EnumMap<IO, Set<MultiblockCapability<?>>>> capabilityMap = state.getMatchContext().get("capabilities");
if (capabilityMap != null) {
capabilities = Tables.newCustomTable(new EnumMap<>(IO.class), Object2ObjectOpenHashMap::new);
for (Map.Entry<Long, EnumMap<IO, Set<MultiblockCapability<?>>>> entry : capabilityMap.entrySet()) {
TileEntity tileEntity = level.getBlockEntity(BlockPos.of(entry.getKey()));
if (tileEntity != null) {
if (settings != null) {
Map<MultiblockCapability<?>, Tuple<IO, Direction>> caps = settings.get(entry.getKey());
if (caps != null) {
for (Map.Entry<MultiblockCapability<?>, Tuple<IO, Direction>> ioEntry : caps.entrySet()) {
MultiblockCapability<?> capability = ioEntry.getKey();
Tuple<IO, Direction> tuple = ioEntry.getValue();
if (tuple == null || capability == null)
continue;
IO io = tuple.getA();
Direction facing = tuple.getB();
if (capability.isBlockHasCapability(io, tileEntity)) {
if (!capabilities.contains(io, capability)) {
capabilities.put(io, capability, new Long2ObjectOpenHashMap<>());
}
CapabilityProxy<?> proxy = capability.createProxy(io, tileEntity);
proxy.facing = facing;
capabilities.get(io, capability).put(entry.getKey().longValue(), proxy);
}
}
}
} else {
entry.getValue().forEach((io, set) -> {
for (MultiblockCapability<?> capability : set) {
if (capability.isBlockHasCapability(io, tileEntity)) {
if (!capabilities.contains(io, capability)) {
capabilities.put(io, capability, new Long2ObjectOpenHashMap<>());
}
CapabilityProxy<?> proxy = capability.createProxy(io, tileEntity);
capabilities.get(io, capability).put(entry.getKey().longValue(), proxy);
}
}
});
}
}
}
}
settings = null;
// init parts
parts = state.getMatchContext().get("parts");
if (parts != null) {
for (Long pos : parts) {
TileEntity tileEntity = level.getBlockEntity(BlockPos.of(pos));
if (tileEntity instanceof IPartComponent) {
((IPartComponent) tileEntity).addedToController(this);
}
}
}
writeCustomData(-1, this::writeState);
if (Multiblocked.isKubeJSLoaded()) {
new StructureFormedEvent(this).post(ScriptType.SERVER, StructureFormedEvent.ID, getSubID());
}
}
use of com.lowdragmc.multiblocked.api.tile.part.IPartComponent in project Multiblocked by Low-Drag-MC.
the class GTRenderer method renderModel.
@Override
@OnlyIn(Dist.CLIENT)
public List<BakedQuad> renderModel(IBlockDisplayReader level, BlockPos pos, BlockState state, Direction side, Random rand, IModelData modelData) {
TileEntity te = level.getBlockEntity(pos);
if (formedAsController && te instanceof IPartComponent) {
IPartComponent part = (IPartComponent) te;
for (IControllerComponent controller : part.getControllers()) {
if (controller.isFormed() && controller.getRenderer() instanceof GTRenderer) {
IBakedModel model = getModel(((GTRenderer) controller.getRenderer()).baseTexture).bake(ModelLoader.instance(), ModelLoader.defaultTextureGetter(), ModelFactory.getRotation(part.getFrontFacing()), modelLocation);
if (model == null)
return Collections.emptyList();
model = new CustomBakedModel(model);
if (!((CustomBakedModel) model).shouldRenderInLayer(state, rand))
return Collections.emptyList();
return model.getQuads(state, side, rand, modelData);
}
}
}
return super.renderModel(level, pos, state, side, rand, modelData);
}
Aggregations