Skip to content

Commit 4d2df39

Browse files
committed
好像修正了多个RenderEntity的问题
1 parent 8603f68 commit 4d2df39

18 files changed

Lines changed: 758 additions & 150 deletions

common/src/main/kotlin/cn/coostack/cooparticlesapi/event/events/key/KeyActionEvent.kt

Lines changed: 104 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,115 @@ enum class KeyActionType(val id: Int) {
1616
}
1717
}
1818

19+
data class KeyActionData<K>(
20+
val keyId: K,
21+
val actions: List<KeyActionType>,
22+
val pressTick: Int,
23+
val released: Boolean
24+
) {
25+
init {
26+
require(actions.isNotEmpty()) { "key action entry must contain at least one action: $keyId" }
27+
}
28+
}
29+
30+
class KeyActionBatch<K>(entries: List<KeyActionData<K>>) {
31+
private val entriesByKey = LinkedHashMap<K, KeyActionData<K>>()
32+
33+
init {
34+
entries.forEach(::merge)
35+
}
36+
37+
val entries: List<KeyActionData<K>>
38+
get() = entriesByKey.values.toList()
39+
40+
fun getKeys(): List<K> {
41+
return entriesByKey.keys.toList()
42+
}
43+
44+
fun getAction(keyId: K): List<KeyActionType> {
45+
return entriesByKey[keyId]?.actions ?: emptyList()
46+
}
47+
48+
fun getPressTick(keyId: K): Int {
49+
return entriesByKey[keyId]?.pressTick ?: 0
50+
}
51+
52+
fun isReleased(keyId: K): Boolean {
53+
return entriesByKey[keyId]?.released ?: false
54+
}
55+
56+
fun isSingleClick(keyId: K): Boolean {
57+
return KeyActionType.SINGLE_CLICK in getAction(keyId)
58+
}
59+
60+
fun isDoubleClick(keyId: K): Boolean {
61+
return KeyActionType.DOUBLE_CLICK in getAction(keyId)
62+
}
63+
64+
fun isLongPress(keyId: K): Boolean {
65+
return KeyActionType.LONG_PRESS in getAction(keyId)
66+
}
67+
68+
fun isEmpty(): Boolean {
69+
return entriesByKey.isEmpty()
70+
}
71+
72+
private fun merge(entry: KeyActionData<K>) {
73+
val current = entriesByKey[entry.keyId]
74+
if (current == null) {
75+
entriesByKey[entry.keyId] = entry
76+
return
77+
}
78+
entriesByKey[entry.keyId] = KeyActionData(
79+
keyId = entry.keyId,
80+
actions = current.actions + entry.actions,
81+
pressTick = maxOf(current.pressTick, entry.pressTick),
82+
released = current.released || entry.released
83+
)
84+
}
85+
}
86+
1987
/**
2088
* Fired on client when sending a key action; fired on server when receiving the packet.
2189
*
22-
* @param pressTick 按键已按住的 tick 数(长按时每 tick 递增)
23-
* @param isRelease 是否为松开按键时的触发
2490
* @param serverSide 是否在服务端触发
2591
*/
2692
class KeyActionEvent(
2793
player: Player,
28-
val keyId: ResourceLocation,
29-
val action: KeyActionType,
30-
val pressTick: Int,
31-
val isRelease: Boolean,
94+
val keyActions: KeyActionBatch<ResourceLocation>,
3295
val serverSide: Boolean
33-
) : PlayerEvent(player)
96+
) : PlayerEvent(player) {
97+
constructor(player: Player, entries: List<KeyActionData<ResourceLocation>>, serverSide: Boolean) : this(
98+
player,
99+
KeyActionBatch(entries),
100+
serverSide
101+
)
102+
103+
fun getKeys(): List<ResourceLocation> {
104+
return keyActions.getKeys()
105+
}
106+
107+
fun getAction(keyId: ResourceLocation): List<KeyActionType> {
108+
return keyActions.getAction(keyId)
109+
}
110+
111+
fun getPressTick(keyId: ResourceLocation): Int {
112+
return keyActions.getPressTick(keyId)
113+
}
114+
115+
fun isReleased(keyId: ResourceLocation): Boolean {
116+
return keyActions.isReleased(keyId)
117+
}
118+
119+
fun isSingleClick(keyId: ResourceLocation): Boolean {
120+
return keyActions.isSingleClick(keyId)
121+
}
122+
123+
fun isDoubleClick(keyId: ResourceLocation): Boolean {
124+
return keyActions.isDoubleClick(keyId)
125+
}
126+
127+
fun isLongPress(keyId: ResourceLocation): Boolean {
128+
return keyActions.isLongPress(keyId)
129+
}
130+
}

common/src/main/kotlin/cn/coostack/cooparticlesapi/key/CooKeyBindingManager.kt

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cn.coostack.cooparticlesapi.key
22

33
import cn.coostack.cooparticlesapi.event.CooEventBus
4+
import cn.coostack.cooparticlesapi.event.events.key.KeyActionBatch
5+
import cn.coostack.cooparticlesapi.event.events.key.KeyActionData
46
import cn.coostack.cooparticlesapi.event.events.key.KeyActionEvent
57
import cn.coostack.cooparticlesapi.event.events.key.KeyActionType
68
import cn.coostack.cooparticlesapi.network.packet.client.PacketKeyActionC2S
@@ -82,6 +84,7 @@ object CooKeyBindingManager {
8284
tickCounter++
8385
val doubleInterval = doubleClickWindowTicks.coerceAtLeast(0).toLong()
8486
val states = keyStates.values.toList()
87+
val pendingActions = ArrayList<KeyActionData<ResourceLocation>>()
8588
states.forEach { state ->
8689
if (keyCountDowns.containsKey(state.id)) {
8790
val current = keyCountDowns[state.id]!!
@@ -101,18 +104,28 @@ object CooKeyBindingManager {
101104
state.pressTick = 0
102105
}
103106
state.pressTick++
104-
sendAction(state.id, KeyActionType.LONG_PRESS, state.pressTick, false)
107+
pendingActions.add(
108+
KeyActionData(state.id, listOf(KeyActionType.LONG_PRESS), state.pressTick, false)
109+
)
105110
} else if (state.wasDown) {
106-
sendAction(state.id, KeyActionType.LONG_PRESS, state.pressTick.coerceAtLeast(1), true)
111+
val capturedPressTick = state.pressTick.coerceAtLeast(1)
112+
pendingActions.add(
113+
KeyActionData(state.id, listOf(KeyActionType.LONG_PRESS), capturedPressTick, true)
114+
)
107115
val isDouble =
108116
state.lastClickTick >= 0 && tickCounter - state.lastClickTick <= doubleInterval
109117
val action = if (isDouble) KeyActionType.DOUBLE_CLICK else KeyActionType.SINGLE_CLICK
110-
sendAction(state.id, action, state.pressTick.coerceAtLeast(1), true)
118+
pendingActions.add(
119+
KeyActionData(state.id, listOf(action), capturedPressTick, true)
120+
)
111121
state.lastClickTick = tickCounter
112122
state.pressTick = 0
113123
}
114124
state.wasDown = down
115125
}
126+
if (pendingActions.isNotEmpty()) {
127+
sendActions(KeyActionBatch(pendingActions))
128+
}
116129
}
117130

118131
private fun registerIfPossible(state: KeyState) {
@@ -122,20 +135,15 @@ object CooKeyBindingManager {
122135
}
123136
}
124137

125-
private fun sendAction(
126-
keyId: ResourceLocation,
127-
action: KeyActionType,
128-
pressTick: Int,
129-
isRelease: Boolean
130-
) {
138+
private fun sendActions(keyActions: KeyActionBatch<ResourceLocation>) {
131139
val client = Minecraft.getInstance()
132140
val player = client.player
133141
if (player == null || client.level == null) {
134142
return
135143
}
136144
CooEventBus.call(
137-
KeyActionEvent(player, keyId, action, pressTick, isRelease, false)
145+
KeyActionEvent(player, keyActions, false)
138146
)
139-
CooParticlesServices.CLIENT_NETWORK.send(PacketKeyActionC2S(keyId, action, pressTick, isRelease))
147+
CooParticlesServices.CLIENT_NETWORK.send(PacketKeyActionC2S(keyActions))
140148
}
141-
}
149+
}
Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cn.coostack.cooparticlesapi.network.packet.client
22

33
import cn.coostack.cooparticlesapi.CooParticlesConstants
4+
import cn.coostack.cooparticlesapi.event.events.key.KeyActionBatch
5+
import cn.coostack.cooparticlesapi.event.events.key.KeyActionData
46
import cn.coostack.cooparticlesapi.event.events.key.KeyActionType
57
import net.minecraft.network.FriendlyByteBuf
68
import net.minecraft.network.codec.StreamCodec
@@ -9,36 +11,46 @@ import net.minecraft.resources.ResourceLocation
911

1012
/**
1113
* 客户端按键动作触发时发送给服务器
12-
*
13-
* @param pressTick 按键已按住的 tick 数(长按时每 tick 递增)
14-
* @param isRelease 是否为松开按键时的触发
1514
*/
1615
class PacketKeyActionC2S(
17-
val keyId: ResourceLocation,
18-
val action: KeyActionType,
19-
val pressTick: Int,
20-
val isRelease: Boolean
16+
val keyActions: KeyActionBatch<ResourceLocation>
2117
) : CustomPacketPayload {
2218
companion object {
2319
private val identifierID =
2420
ResourceLocation.fromNamespaceAndPath(CooParticlesConstants.MOD_ID, "key_action")
2521
val payloadID = CustomPacketPayload.Type<PacketKeyActionC2S>(identifierID)
2622
val CODEC: StreamCodec<FriendlyByteBuf, PacketKeyActionC2S> =
2723
CustomPacketPayload.codec({ packet, buf ->
28-
buf.writeResourceLocation(packet.keyId)
29-
buf.writeInt(packet.action.id)
30-
buf.writeInt(packet.pressTick)
31-
buf.writeBoolean(packet.isRelease)
24+
val entries = packet.keyActions.entries
25+
buf.writeVarInt(entries.size)
26+
entries.forEach { entry ->
27+
buf.writeResourceLocation(entry.keyId)
28+
buf.writeVarInt(entry.actions.size)
29+
entry.actions.forEach { action ->
30+
buf.writeInt(action.id)
31+
}
32+
buf.writeInt(entry.pressTick)
33+
buf.writeBoolean(entry.released)
34+
}
3235
}, { buf ->
33-
val keyId = buf.readResourceLocation()
34-
val action = KeyActionType.Companion.fromId(buf.readInt())
35-
val pressTick = buf.readInt()
36-
val isRelease = buf.readBoolean()
37-
PacketKeyActionC2S(keyId, action, pressTick, isRelease)
36+
val entryCount = buf.readVarInt()
37+
val entries = ArrayList<KeyActionData<ResourceLocation>>(entryCount)
38+
repeat(entryCount) {
39+
val keyId = buf.readResourceLocation()
40+
val actionCount = buf.readVarInt()
41+
val actions = ArrayList<KeyActionType>(actionCount)
42+
repeat(actionCount) {
43+
actions.add(KeyActionType.fromId(buf.readInt()))
44+
}
45+
val pressTick = buf.readInt()
46+
val released = buf.readBoolean()
47+
entries.add(KeyActionData(keyId, actions, pressTick, released))
48+
}
49+
PacketKeyActionC2S(KeyActionBatch(entries))
3850
})
3951
}
4052

4153
override fun type(): CustomPacketPayload.Type<out CustomPacketPayload> {
4254
return payloadID
4355
}
44-
}
56+
}

common/src/main/kotlin/cn/coostack/cooparticlesapi/network/packet/server/listener/ServerKeyActionHandler.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ object ServerKeyActionHandler {
1010
val player = context.player()
1111
context.server().execute {
1212
CooEventBus.call(
13-
KeyActionEvent(player, packet.keyId, packet.action, packet.pressTick, packet.isRelease, true)
13+
KeyActionEvent(player, packet.keyActions, true)
1414
)
1515
}
1616
}

common/src/main/kotlin/cn/coostack/cooparticlesapi/renderer/RenderEntity.kt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ abstract class RenderEntity(var world: Level?, var pos: Vec3 = Vec3.ZERO) : Serv
404404
*
405405
* 默认使用 `REPLACE`,保持旧行为。
406406
* 如果多个实体共享同一个 glow / bloom pipe,并且希望输入 mask 可以叠加,
407-
* 则应覆盖为 `ADDITIVE`,同时避免在 `render(...)` 内再次强制关闭 blend。
407+
* 通常应覆盖为 `ALPHA` 或 `ADDITIVE`,同时避免在 `render(...)` 内再次强制关闭 blend。
408408
*/
409409
open fun getInputBlendMode(): RenderEntityInputBlendMode {
410410
return RenderEntityInputBlendMode.REPLACE
@@ -476,14 +476,15 @@ abstract class RenderEntity(var world: Level?, var pos: Vec3 = Vec3.ZERO) : Serv
476476
RenderSystem.enableDepthTest()
477477
RenderSystem.depthMask(true)
478478
applyInputBlendMode()
479-
runCatching {
479+
try {
480480
render(matrices, viewMatrix, projMatrix, tickDelta)
481+
} finally {
482+
RenderSystem.defaultBlendFunc()
483+
RenderSystem.disableBlend()
484+
RenderSystem.depthMask(true)
485+
RenderSystem.enableDepthTest()
486+
RenderSystem.disableCull()
481487
}
482-
RenderSystem.defaultBlendFunc()
483-
RenderSystem.disableBlend()
484-
RenderSystem.depthMask(true)
485-
RenderSystem.enableDepthTest()
486-
RenderSystem.disableCull()
487488
}
488489

489490
private fun applyInputBlendMode() {
@@ -493,6 +494,11 @@ abstract class RenderEntity(var world: Level?, var pos: Vec3 = Vec3.ZERO) : Serv
493494
RenderSystem.disableBlend()
494495
}
495496

497+
RenderEntityInputBlendMode.ALPHA -> {
498+
RenderSystem.enableBlend()
499+
RenderSystem.defaultBlendFunc()
500+
}
501+
496502
RenderEntityInputBlendMode.ADDITIVE -> {
497503
RenderSystem.enableBlend()
498504
RenderSystem.blendFunc(GL_ONE, GL_ONE)

common/src/main/kotlin/cn/coostack/cooparticlesapi/renderer/RenderEntityInputBlendMode.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ enum class RenderEntityInputBlendMode {
1414
*/
1515
REPLACE,
1616

17+
/**
18+
* 使用标准 alpha 混合把当前实体写入共享输入 FBO。
19+
* 适合 glow / distortion mask 这类需要多实例共存,但又不能让同一实体内部片元彼此纯加法放大的效果。
20+
*/
21+
ALPHA,
22+
1723
/**
1824
* 使用加法混合把当前实体累加到共享输入 FBO。
1925
* 适合 glow / bloom / emissive mask 这类允许多个实体共同叠加的效果。

common/src/main/kotlin/cn/coostack/cooparticlesapi/renderer/glow/DistanceAdaptiveGlow.kt

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,35 @@ object DistanceAdaptiveGlow {
179179
val nearFactor = smoothstep(nearFadeStartPx, nearFadeEndPx, safeRadius)
180180

181181
return PersistentHaloProfile(
182-
haloRadiusScale = mix(2.25f, 1.45f, nearFactor).coerceIn(1.45f, 2.25f),
183-
brightnessNormalization = mix(1.10f, 0.98f, nearFactor).coerceIn(0.98f, 1.10f),
184-
softOcclusionFloor = mix(0.34f, 0.18f, nearFactor).coerceIn(0.18f, 0.34f),
185-
haloOpacity = mix(0.74f, 0.68f, nearFactor).coerceIn(0.68f, 0.74f),
186-
blurSigma = mix(4.20f, 3.20f, nearFactor).coerceIn(3.20f, 4.20f),
187-
blurRange = mix(4.00f, 3.00f, nearFactor).coerceIn(3.00f, 4.00f)
182+
haloRadiusScale = mix(1.82f, 1.34f, nearFactor).coerceIn(1.34f, 1.82f),
183+
brightnessNormalization = mix(0.92f, 0.84f, nearFactor).coerceIn(0.84f, 0.92f),
184+
softOcclusionFloor = mix(0.18f, 0.10f, nearFactor).coerceIn(0.10f, 0.18f),
185+
haloOpacity = mix(0.50f, 0.44f, nearFactor).coerceIn(0.44f, 0.50f),
186+
blurSigma = mix(3.00f, 2.30f, nearFactor).coerceIn(2.30f, 3.00f),
187+
blurRange = mix(2.60f, 1.90f, nearFactor).coerceIn(1.90f, 2.60f)
188188
)
189189
}
190190

191+
/**
192+
* 为 `PersistentBloom` 提供一个更偏向远景的权重。
193+
*
194+
* 设计目标:
195+
* - 当球体已经足够大、直接绘制层本身就很显眼时,persistent bloom 应明显收敛,避免把整屏背景洗灰。
196+
* - 当球体投影尺寸很小、直接层难以维持可读性时,再把权重逐步交给 persistent bloom。
197+
*/
198+
@JvmStatic
199+
fun persistentBloomWeightFromOrbBlend(
200+
blend: DistanceAdaptiveGlowBlend,
201+
nearFloor: Float = 0.10f,
202+
farCeiling: Float = 0.88f
203+
): Float {
204+
val farWeight = blend.screenGlowWeight.coerceIn(0.0f, 1.0f)
205+
val directWeight = blend.directWeight.coerceIn(0.0f, 1.0f)
206+
val squaredFarWeight = farWeight * farWeight
207+
val directSuppression = mix(nearFloor, farCeiling, 1.0f - directWeight)
208+
return (squaredFarWeight * directSuppression).coerceIn(0.0f, 1.0f)
209+
}
210+
191211
/**
192212
* 提供给球体本体 shader 的直接绘制 profile。
193213
*

common/src/main/kotlin/cn/coostack/cooparticlesapi/test/options/renderer/TestGlowSphereEntity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class TestGlowSphereEntity(world: Level?) : RenderEntity(world), WorldLightProvi
127127
}
128128

129129
override fun getInputBlendMode(): RenderEntityInputBlendMode {
130-
return RenderEntityInputBlendMode.ADDITIVE
130+
return RenderEntityInputBlendMode.ALPHA
131131
}
132132

133133
override fun release() {

0 commit comments

Comments
 (0)