use of com.lowdragmc.multiblocked.api.capability.IO 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.capability.IO in project Multiblocked by Low-Drag-MC.
the class MultiCapabilityTrait method serialize.
@Override
public void serialize(@Nullable JsonElement jsonElement) {
if (jsonElement == null) {
jsonElement = new JsonArray();
}
JsonArray jsonArray = jsonElement.getAsJsonArray();
int size = jsonArray.size();
capabilityIO = new IO[size];
guiIO = new IO[size];
x = new int[size];
y = new int[size];
autoIO = new boolean[size];
int i = 0;
for (JsonElement element : jsonArray) {
JsonObject jsonObject = element.getAsJsonObject();
capabilityIO[i] = JsonUtil.getEnumOr(jsonObject, "cIO", IO.class, IO.BOTH);
guiIO[i] = JsonUtil.getEnumOr(jsonObject, "gIO", IO.class, IO.BOTH);
x[i] = JSONUtils.getAsInt(jsonObject, "x", 5);
y[i] = JSONUtils.getAsInt(jsonObject, "y", 5);
autoIO[i] = JSONUtils.getAsBoolean(jsonObject, "autoIO", false);
i++;
}
}
use of com.lowdragmc.multiblocked.api.capability.IO in project Multiblocked by Low-Drag-MC.
the class ControllerTileEntity method load.
@Override
public void load(@Nonnull BlockState blockState, @Nonnull CompoundNBT compound) {
try {
super.load(blockState, compound);
} catch (Exception e) {
if (definition == null) {
MultiblockWorldSavedData mwsd = MultiblockWorldSavedData.getOrCreate(level);
if (worldPosition != null && mwsd.mapping.containsKey(worldPosition)) {
mwsd.removeMapping(mwsd.mapping.get(worldPosition));
}
return;
}
}
if (compound.contains("ars")) {
asyncRecipeSearching = compound.getBoolean("ars");
}
if (compound.contains("recipeLogic")) {
recipeLogic = new RecipeLogic(this);
recipeLogic.readFromNBT(compound.getCompound("recipeLogic"));
status = recipeLogic.getStatus().name;
}
if (compound.contains("capabilities")) {
ListNBT tagList = compound.getList("capabilities", Constants.NBT.TAG_COMPOUND);
settings = new HashMap<>();
for (INBT base : tagList) {
CompoundNBT tag = (CompoundNBT) base;
settings.computeIfAbsent(tag.getLong("pos"), l -> new HashMap<>()).put(MbdCapabilities.get(tag.getString("cap")), new Tuple<>(IO.VALUES[tag.getInt("io")], Direction.values()[tag.getInt("facing")]));
}
}
}
use of com.lowdragmc.multiblocked.api.capability.IO in project Multiblocked by Low-Drag-MC.
the class ControllerTileEntity method save.
@Nonnull
@Override
public CompoundNBT save(@Nonnull CompoundNBT compound) {
super.save(compound);
if (!asyncRecipeSearching) {
compound.putBoolean("ars", false);
}
if (recipeLogic != null)
compound.put("recipeLogic", recipeLogic.writeToNBT(new CompoundNBT()));
if (capabilities != null) {
ListNBT tagList = new ListNBT();
for (Table.Cell<IO, MultiblockCapability<?>, Long2ObjectOpenHashMap<CapabilityProxy<?>>> cell : capabilities.cellSet()) {
IO io = cell.getRowKey();
MultiblockCapability<?> cap = cell.getColumnKey();
Long2ObjectOpenHashMap<CapabilityProxy<?>> value = cell.getValue();
if (io != null && cap != null && value != null) {
for (Map.Entry<Long, CapabilityProxy<?>> entry : value.entrySet()) {
CompoundNBT tag = new CompoundNBT();
tag.putInt("io", io.ordinal());
tag.putInt("facing", entry.getValue().facing.ordinal());
tag.putString("cap", cap.name);
tag.putLong("pos", entry.getKey());
tagList.add(tag);
}
}
}
compound.put("capabilities", tagList);
}
return compound;
}
use of com.lowdragmc.multiblocked.api.capability.IO 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());
}
}
Aggregations