diff --git a/src/main/java/github/kasuminova/mmce/common/helper/IMachineController.java b/src/main/java/github/kasuminova/mmce/common/helper/IMachineController.java
index dd3e1ab2..340098b7 100644
--- a/src/main/java/github/kasuminova/mmce/common/helper/IMachineController.java
+++ b/src/main/java/github/kasuminova/mmce/common/helper/IMachineController.java
@@ -308,6 +308,50 @@ public interface IMachineController {
@ZenMethod
int getBlocksInPattern(final IBlockStatePredicate predicate);
+ /**
+ * 获取控制器的结构中指定方块的所有坐标,只能在控制器成型时使用。
+ * 会过滤空气方块。
+ * 注意:此操作的性能开销稍大,通常情况下只建议在 {@link MachineStructureUpdateEvent} 事件触发时使用。
+ *
+ * @param blockStack 要判断的方块对应的物品,会被自动转换成对应的 IBlockState,如果转换出现问题会输出错误日志。
+ * @return 所有位置。
+ */
+ @ZenMethod
+ IBlockPos[] getBlockPosInPattern(final IItemStack blockStack);
+
+ /**
+ * 获取控制器的结构中指定方块的所有坐标,只能在控制器成型时使用。
+ * 会过滤空气方块。
+ * 注意:此操作的性能开销稍大,通常情况下只建议在 {@link MachineStructureUpdateEvent} 事件触发时使用。
+ *
+ * @param blockStateMatcher 要判断的方块对应的 IBlockStateMatcher
+ * @return 所有位置。
+ */
+ @ZenMethod
+ IBlockPos[] getBlockPosInPattern(final IBlockStateMatcher blockStateMatcher);
+
+ /**
+ * 获取控制器的结构中指定方块的所有坐标,只能在控制器成型时使用。
+ * 会过滤空气方块。
+ * 注意:此操作的性能开销稍大,通常情况下只建议在 {@link MachineStructureUpdateEvent} 事件触发时使用。
+ *
+ * @param blockName 要判断的方块对应的注册名,解析方式参考机械 JSON 文件的格式。
+ * @return 所有位置。
+ */
+ @ZenMethod
+ IBlockPos[] getBlockPosInPattern(final String blockName);
+
+ /**
+ * 获取控制器的结构中指定方块的所有坐标,只能在控制器成型时使用。
+ * 会过滤空气方块。
+ * 注意:此操作的性能开销稍大,通常情况下只建议在 {@link MachineStructureUpdateEvent} 事件触发时使用。
+ *
+ * @param predicate 自定义判断逻辑。
+ * @return 所有位置。
+ */
+ @ZenMethod
+ IBlockPos[] getBlockPosInPattern(final IBlockStatePredicate predicate);
+
/**
* 获取控制器的拥有者,如果玩家不在线则返回 null。
*
diff --git a/src/main/java/hellfirepvp/modularmachinery/common/machine/DynamicMachine.java b/src/main/java/hellfirepvp/modularmachinery/common/machine/DynamicMachine.java
index 52dcde75..fa047b26 100644
--- a/src/main/java/hellfirepvp/modularmachinery/common/machine/DynamicMachine.java
+++ b/src/main/java/hellfirepvp/modularmachinery/common/machine/DynamicMachine.java
@@ -139,7 +139,6 @@ public Map getFilteredType(Collection ignore
return filtered;
}
- @SuppressWarnings("unchecked")
public void addMachineEventHandler(Class hClass, IEventHandler handler) {
machineEventHandlers.putIfAbsent(hClass, new ArrayList<>());
machineEventHandlers.get(hClass).add((IEventHandler) handler);
diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileFactoryController.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileFactoryController.java
index 82969100..d743b83f 100644
--- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileFactoryController.java
+++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileFactoryController.java
@@ -66,7 +66,7 @@ public TileFactoryController(IBlockState state) {
controllerRotation = state.getValue(BlockController.FACING);
parentMachine = parentController.getParentMachine();
} else {
- ModularMachinery.log.warn("Invalid factory controller block at " + getPos() + " !");
+ ModularMachinery.log.warn("Invalid factory controller block at {} !", getPos());
controllerRotation = EnumFacing.NORTH;
}
}
@@ -569,7 +569,7 @@ protected void checkRotation() {
this.parentMachine = parentController.getParentMachine();
this.controllerRotation = state.getValue(BlockController.FACING);
} else {
- ModularMachinery.log.warn("Invalid factory controller block at " + getPos() + " !");
+ ModularMachinery.log.warn("Invalid factory controller block at {} !", getPos());
controllerRotation = EnumFacing.NORTH;
}
}
@@ -628,7 +628,7 @@ protected void readMachineNBT(NBTTagCompound compound) {
if (parentMachine != null) {
parentController = BlockFactoryController.FACTORY_CONTROLLERS.get(parentMachine);
} else {
- ModularMachinery.log.info("Couldn't find machine named " + rl + " for controller at " + getPos());
+ ModularMachinery.log.info("Couldn't find machine named {} for controller at {}", rl, getPos());
}
}
super.readMachineNBT(compound);
diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileMachineController.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileMachineController.java
index 419a3e47..2839e516 100644
--- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileMachineController.java
+++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileMachineController.java
@@ -56,7 +56,7 @@ public TileMachineController(IBlockState state) {
this.controllerRotation = state.getValue(BlockController.FACING);
} else {
// wtf, where is the controller?
- ModularMachinery.log.warn("Invalid controller block at " + getPos() + " !");
+ ModularMachinery.log.warn("Invalid controller block at {} !", getPos());
controllerRotation = EnumFacing.NORTH;
}
}
@@ -244,7 +244,7 @@ protected void checkRotation() {
this.controllerRotation = state.getValue(BlockController.FACING);
} else {
// wtf, where is the controller?
- ModularMachinery.log.warn("Invalid controller block at " + getPos() + " !");
+ ModularMachinery.log.warn("Invalid controller block at {} !", getPos());
controllerRotation = EnumFacing.NORTH;
}
}
@@ -406,7 +406,7 @@ protected void readMachineNBT(NBTTagCompound compound) {
if (parentMachine != null) {
parentController = BlockController.MACHINE_CONTROLLERS.get(parentMachine);
} else {
- ModularMachinery.log.info("Couldn't find machine named " + rl + " for controller at " + getPos());
+ ModularMachinery.log.info("Couldn't find machine named {} for controller at {}", rl, getPos());
}
}
diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileMultiblockMachineController.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileMultiblockMachineController.java
index 918a693e..f198ae26 100644
--- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileMultiblockMachineController.java
+++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileMultiblockMachineController.java
@@ -61,6 +61,7 @@
import hellfirepvp.modularmachinery.common.util.MiscUtils;
import hellfirepvp.modularmachinery.common.util.SmartInterfaceData;
import hellfirepvp.modularmachinery.common.util.SmartInterfaceType;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayerMP;
@@ -1173,6 +1174,44 @@ public int getBlocksInPattern(final IBlockStatePredicate predicate) {
return getBlocksInPatternInternal(state -> predicate.test(CraftTweakerMC.getBlockState(state)));
}
+ @Override
+ public IBlockPos[] getBlockPosInPattern(IItemStack blockStack) {
+ if (foundPattern == null || blockStack == null) {
+ return new IBlockPos[0];
+ }
+ IBlockDefinition blockDef = blockStack.asBlock().getDefinition();
+ if (blockStack.getMetadata() == OreDictionary.WILDCARD_VALUE) {
+ return getBlockPosInPattern(blockDef.getDefaultState().matchBlock());
+ } else {
+ return getBlockPosInPattern(blockDef.getStateFromMeta(blockStack.getMetadata()));
+ }
+ }
+
+ @Override
+ public IBlockPos[] getBlockPosInPattern(IBlockStateMatcher blockStateMatcher) {
+ if (foundPattern == null) {
+ return new IBlockPos[0];
+ }
+ return getBlockPossInPatternInternal(state -> blockStateMatcher.matches(CraftTweakerMC.getBlockState(state)));
+ }
+
+ @Override
+ public IBlockPos[] getBlockPosInPattern(String blockName) {
+ if (foundPattern == null) {
+ return new IBlockPos[0];
+ }
+ List applicable = BlockArray.BlockInformation.getDescriptor(blockName).getApplicable();
+ return getBlockPossInPatternInternal(applicable::contains);
+ }
+
+ @Override
+ public IBlockPos[] getBlockPosInPattern(IBlockStatePredicate predicate) {
+ if (foundPattern == null) {
+ return new IBlockPos[0];
+ }
+ return getBlockPossInPatternInternal(state -> predicate.test(CraftTweakerMC.getBlockState(state)));
+ }
+
public int getBlocksInPatternInternal(final Predicate predicate) {
if (foundPattern == null) {
return 0;
@@ -1191,6 +1230,24 @@ public int getBlocksInPatternInternal(final Predicate predicate) {
return count;
}
+ public IBlockPos[] getBlockPossInPatternInternal(final Predicate predicate) {
+ if (foundPattern == null) {
+ return new IBlockPos[0];
+ }
+ List poss = new ObjectArrayList<>();
+ for (final BlockPos pos : foundPattern.getPattern().keySet()) {
+ BlockPos realPos = getPos().add(pos.getX(), pos.getY(), pos.getZ());
+ IBlockState state = getWorld().getBlockState(realPos);
+ if (state.getBlock() == Blocks.AIR) {
+ continue;
+ }
+ if (predicate.test(state)) {
+ poss.add(CraftTweakerMC.getIBlockPos(pos));
+ }
+ }
+ return poss.toArray(new IBlockPos[0]);
+ }
+
@Nullable
@Override
@SuppressWarnings("ConstantValue")