夜间压暗机制

入口:全局 enabled 开关

DarkererCore.enabled 是唯一的总开关(DarkererCore.java:25),由 DarkererEventHandler.onClientTick 在 TickEvent.ClientTickEvent 的 END 阶段每帧重算:

DarkererCore.enabled = player != null && !ArrayUtils.contains(DarkererConfig.dimBlocklist, player.dimension)
    && DarkererConfig.mode != Mode.DISABLED;

(DarkererEventHandler.java:19-27)

所有 mixin 注入点第一件事都是 if (!DarkererCore.enabled) return original;—— 因此 mode = DISABLED 或玩家所在维度在 dimBlocklist 里,效果等同原版。

三层压暗

本 mod 的全部效果由 3 个 early mixin 叠加而成(DarkererCore.getMixins 在客户端返回 MixinEntityRenderer、MixinWorld、MixinWorldProviderHell,DarkererCore.java:66-71)。

第 1 层:World.getSunBrightnessBody —— 天光上下限

mixins/MixinWorld.java:19-58,两处 @ModifyExpressionValue,常量定位方式:

注入点 定位 注入数 EVERYWHERE 返回 MOON_PHASE 返回
modifyMin @At(args = "floatValue=0.2", ordinal = 1) expect = 1 0.0f min.get()(由 modifyMax 反向算出)
modifyMax @At(args = "floatValue=0.8") expect = 1 1.0f 见下方公式

MOON_PHASE 的计算(MixinWorld.java:51-54):

int phase = (int) (Minecraft.getMinecraft().theWorld.getCurrentMoonPhaseFactorBody() * 10.0f);
float max = 0.7f + (10 - phase) * 0.03f;
min.set(1.0f - max);

即夜间天光上限 max = 0.7 + (10 - phase) * 0.03,范围 0.7 ~ 0.97(phase 取 0~9); 下限由 1.0f - max 得到 0.03 ~ 0.3。两个月相互补,呼应"随月相变化"。

ONLY_INSIDE 与 DISABLED 走 default: return original,天光数值完全不变。

第 2 层:EntityRenderer.updateLightmap —— 夜间亮度区间压缩

mixins/MixinEntityRenderer.java:27-43,两组常量替换,两组各 expect = 9:

注入点 定位的常量 enabled 时返回
modifyMin floatValue=0.03、0.05、0.35 0.0f
modifyMax floatValue=0.96、0.95、0.65 1.0f

效果是把原版 updateLightmap 里 9 处夜间亮度插值的下界全部归零、上界全部归一, 使夜间 lightmap 变成一个硬过渡:除方块光源附近外,亮度完全为 0。

⚠️ 这两处注入不区分 mode——只要 enabled 为真就生效,包括 ONLY_INSIDE 和 MOON_PHASE。也就是说"地表留一点光"并非来自这两处,而来自下面第 3 层的 天光红色分量补偿。

第 3 层:removeBlueSkyLight —— 去蓝天光

mixins/MixinEntityRenderer.java:71-92 的 @Inject modifyLightmap,在写入 lightmap 贴图前 逐项改色:

  • 生效前提:enabled && removeBlueSkyLight && mode != EVERYWHERE (MixinEntityRenderer.java:79-81)
  • 只处理 height = i / 16 落在 1..15 的项,即跳过 0 与 16(MixinEntityRenderer.java:83-84)
  • 取出红分量 red,若 mode == ONLY_INSIDE 则 red = Math.min(0xFF, red + 25) (MixinEntityRenderer.java:86-88)
  • 写回 alpha | red<<16 | red<<8 | red,即 RGB 三通道强制置为同一红色分量 (MixinEntityRenderer.java:89)

ONLY_INSIDE 的"留一点光"就来自这里的 +25:最多把天光提到不透明度 25/255。

夜视药水颜色修正

mixins/MixinEntityRenderer.java:56-69 的 @Inject adjustNightVisionColor,对 r / g / b(@Local(ordinal = 8/9/10))各执行 c * 0.9f + 0.1f。

⚠️ 这处注入没有 DarkererCore.enabled 判断——只要本 mod 的 mixin 加载了, 夜视颜色就会被压缩到约 10% 底噪的黑,即使 mode = DISABLED 或维度被屏蔽。 这是本 mod 最明显的副作用泄漏点。

维度专属处理

维度 手段 默认开关 源码
下界(Nether) MixinWorldProviderHell.generateLightBrightnessTable @Inject(HEAD, cancellable),调用 super 后 ci.cancel(),即完全禁用下界的光照亮度表 darkNether = true MixinWorldProviderHell.java:17-23
末地(End) MixinEntityRenderer.darkenEnd,把 WorldProvider.dimensionId 的读取结果改为 0(即让末地被当作非末地分支处理) darkEnd = false MixinEntityRenderer.java:45-54
暮色森林(Twilight Forest) MixinWorldProviderTwilightForest.modifyCelestialAngle,把 calculateCelestialAngle 中的 0.225 改为 0.5f darkTwilightForest = false MixinWorldProviderTwilightForest.java:15-18

暮色森林 mixin 是 late mixin,仅当 TwilightForest 在已加载 mod 集合中才注册 (DarkererLateMixins.java:19-24)。其 config 为 devOnlyNonPublishable(dependencies.gradle), 说明该依赖不随 mod 发布,需要玩家自行安装暮色森林。

darkenEnd 用 expect = 1 精确定位 WorldProvider.dimensionId 的唯一一次读取 (MixinEntityRenderer.java:46-51)。改成 0 而不是别的值,效果是让末地跳过原版 按 dimensionId 分支的"末地无天空亮度"处理,从而恢复光照。