夜间压暗机制
入口:全局 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 分支的"末地无天空亮度"处理,从而恢复光照。