Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ Opt a namespace into cube-based outlines and precise client picking with
rotated and reversed cubes, parent models, weighted variants, multipart models and resource reloads.
Optional providers describe moving BER parts using shared geometry and per-frame transforms.
Geometry, background outline work, caches and rendered line counts have explicit limits.
Reloadable blacklists can use `CubeSelection.registerTargetExclusion(id, predicate)` and
`unregisterTargetExclusion(id)` without discarding baked geometry.

### Config Module

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ AnvilLib 采用模块化设计,包含以下功能模块:
提供精确拾取和斜棱线高亮。
支持旋转、反向描边壳、父模型、随机变体、multipart 和资源重载;
可选提供器支持 BER 活动部件。几何共享、BVH 拾取和后台轮廓任务均有数量及内存预算。
支持按 ID 注册、替换和注销运行时目标排除规则,方便接入可重载黑名单,且不丢弃模型缓存。

### Config 模块

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;

/** 仅在客户端初始化时注册命名空间;注册后的模型默认同时启用精确拾取和棱线高亮。 */
public final class CubeSelection {
public static final int MAX_PARTS = 32;
private static final Set<String> NAMESPACES = ConcurrentHashMap.newKeySet();
private static final Set<Block> EXCLUDED = ConcurrentHashMap.newKeySet();
private static final Map<ResourceLocation, Predicate<BlockState>> TARGET_EXCLUSIONS = new ConcurrentHashMap<>();
private static final Map<Block, Dynamic> DYNAMIC = new ConcurrentHashMap<>();
private static final OutlineCache OUTLINES = new OutlineCache();
private static final Long2ObjectOpenHashMap<Target> FRAME = new Long2ObjectOpenHashMap<>();
Expand All @@ -50,6 +52,39 @@ public static void enableNamespace(String namespace) {

public static void exclude(Block block) { EXCLUDED.add(block); }

/**
* 注册运行时目标排除规则;同一 id 再次注册会替换旧规则,不同 id 的规则互不覆盖。
* 任意规则返回 true 时,target 返回 null,精确拾取与默认模型高亮均回退原版。
*
* <p>规则不影响模型烘焙和 modelParts,可读取接入方当前的资源包配置。
* 每次目标查询都会在帧缓存之前检查规则,因此修改配置或注销规则后即可恢复已加载的模型。
* 回调应保持轻量、无副作用,不应捕获世界或方块实体等会跨存档保留的对象。
*
* @param id 由调用模组自己的命名空间限定的规则标识
* @param exclusion 返回 true 表示该状态不使用模型目标
*/
public static void registerTargetExclusion(ResourceLocation id, Predicate<BlockState> exclusion) {
TARGET_EXCLUSIONS.put(id, exclusion);
}

/**
* 注销指定运行时规则;不会清除其他规则或 exclude(Block) 设置的永久排除。
*
* @return 是否存在并移除了该规则
*/
public static boolean unregisterTargetExclusion(ResourceLocation id) {
return TARGET_EXCLUSIONS.remove(id) != null;
}

/** 检查永久排除及当前运行时规则;不表示该状态一定存在可用的模型几何。 */
public static boolean isTargetExcluded(BlockState state) {
if (EXCLUDED.contains(state.getBlock())) return true;
for (Predicate<BlockState> exclusion : TARGET_EXCLUSIONS.values()) {
if (exclusion.test(state)) return true;
}
return false;
}

/** 部件变换须与 BER 一致;最大包围盒用于寻找越过锚点格的机械臂等部件。 */
public static void registerDynamic(Block block, AABB maximumBounds, boolean includeStaticModel, BlockSelectionProvider provider) {
if (!supportedBounds(block.defaultBlockState().hasOffsetFunction() ? maximumBounds.inflate(0.5) : maximumBounds)) {
Expand Down Expand Up @@ -125,7 +160,7 @@ public static boolean extendsBlock(BlockState state) {
}

public static @Nullable Target target(ClientLevel level, BlockPos pos, BlockState state, float fraction) {
if (EXCLUDED.contains(state.getBlock())) return null;
if (isTargetExcluded(state)) return null;
if (frameLevel != level || fraction != partialTick) beginFrame(level, fraction);
Target cached = FRAME.get(pos.asLong());
if (cached != null && cached.state == state) return cached;
Expand Down
Loading