Skip to content

Commit af6b1ac

Browse files
committed
# 修复
修复了ParticleStyleManager clientView不删除已经失效的style的问题 修复了当联机施展魔法时, 玩家退出会导致服务器或者主机崩溃的问题
1 parent cbffb3f commit af6b1ac

14 files changed

Lines changed: 504 additions & 14 deletions

src/main/kotlin/cn/coostack/cooparticlesapi/network/particle/style/ParticleGroupStyle.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ abstract class ParticleGroupStyle(var visibleRange: Double = 32.0, val uuid: UUI
180180
if (!client) {
181181
// 同步到其他客户端
182182
ParticleStyleManager.filterVisiblePlayer(this).forEach {
183-
val player = world!!.getPlayerByUuid(it) as ServerPlayerEntity
183+
val player = world!!.getPlayerByUuid(it) as? ServerPlayerEntity
184+
player ?: return@forEach
184185
ServerPlayNetworking.send(
185186
player, PacketParticleStyleS2C(
186187
uuid, ControlType.REMOVE, mapOf()
@@ -331,7 +332,7 @@ abstract class ParticleGroupStyle(var visibleRange: Double = 32.0, val uuid: UUI
331332
val uuid = it.key.controlUUID()
332333
val len = particleDefaultLength[uuid]!!
333334
val value = it.value
334-
if (len in -1e-3 .. 1e-3) return@forEach
335+
if (len in -1e-3..1e-3) return@forEach
335336
value.multiply(len * scale / value.length())
336337
}
337338
}

src/main/kotlin/cn/coostack/cooparticlesapi/network/particle/style/ParticleShapeStyle.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import cn.coostack.cooparticlesapi.network.buffer.ParticleControlerDataBuffer
44
import cn.coostack.cooparticlesapi.particles.ParticleDisplayer
55
import cn.coostack.cooparticlesapi.utils.RelativeLocation
66
import cn.coostack.cooparticlesapi.utils.builder.PointsBuilder
7-
import cn.coostack.cooparticlesapi.utils.helper.StyleScaleHelper
7+
import cn.coostack.cooparticlesapi.utils.helper.impl.StyleScaleHelper
88
import net.minecraft.client.particle.ParticleTextureSheet
99
import net.minecraft.entity.player.PlayerEntity
1010
import net.minecraft.util.math.Vec3d

src/main/kotlin/cn/coostack/cooparticlesapi/network/particle/style/ParticleStyleManager.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import cn.coostack.cooparticlesapi.network.packet.PacketParticleStyleS2C
66
import cn.coostack.cooparticlesapi.particles.control.ControlType
77
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
88
import net.minecraft.server.network.ServerPlayerEntity
9+
import net.minecraft.text.Text
910
import net.minecraft.util.math.Vec3d
1011
import net.minecraft.world.World
1112
import java.util.HashSet
@@ -53,7 +54,7 @@ object ParticleStyleManager {
5354
style.display(pos, world)
5455
serverViewStyles[style.uuid] = style
5556
// 发送数据包 -> 包括type
56-
world.players.forEach {
57+
world.players.filter { style.pos.distanceTo(it.pos) <= style.visibleRange }.forEach {
5758
addStylePlayerView(it as ServerPlayerEntity, style)
5859
}
5960
}
@@ -91,9 +92,23 @@ object ParticleStyleManager {
9192
}
9293
}
9394
if (!style.valid) {
95+
filterVisiblePlayer(style).forEach {
96+
val player = style.world!!.getPlayerByUuid(it) ?: return@forEach
97+
removeGroupPlayerView(player as ServerPlayerEntity, style)
98+
visible[it]?.remove(style)
99+
}
94100
iterator.remove()
95101
}
96102
}
103+
val playerVisibleIterator = visible.iterator()
104+
while (playerVisibleIterator.hasNext()) {
105+
val playerUUID = playerVisibleIterator.next().key
106+
// 判断玩家是否在线
107+
val player = CooParticleAPI.server.playerManager.getPlayer(playerUUID)
108+
if (player == null) {
109+
playerVisibleIterator.remove()
110+
}
111+
}
97112
}
98113

99114
fun filterVisiblePlayer(group: ParticleGroupStyle): Set<UUID> {

src/main/kotlin/cn/coostack/cooparticlesapi/utils/Math3DUtil.kt

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,7 @@ object Math3DUtil {
9898
require(edgeCount >= 1) { "edgeCount must be at least 1" }
9999

100100
// 生成正n边形的顶点列表(xz平面,圆心在原点)
101-
val vertices = List(n) { i ->
102-
val theta = 2 * PI * i / n
103-
Vec3d(r * cos(theta), 0.0, r * sin(theta))
104-
}
101+
val vertices = getPolygonInCircleVertices(n, r)
105102

106103
val result = mutableListOf<RelativeLocation>()
107104

@@ -118,13 +115,28 @@ object Math3DUtil {
118115
val step = if (edgeCount > 1) length / (edgeCount - 1) else 0.0
119116

120117
// 生成当前边的点集
121-
val lineLocations = getLineLocations(vi, direction, step, edgeCount)
118+
val lineLocations = getLineLocations(vi.toVector(), direction, step, edgeCount)
122119
result.addAll(lineLocations)
123120
}
124121

125122
return result
126123
}
127124

125+
/**
126+
* 生成以 r为半径的圆的 内接正n边形的每个顶点
127+
* @param n 多边形的边数 必须大于等于3
128+
* @param r 半径
129+
*/
130+
fun getPolygonInCircleVertices(n: Int, r: Double): List<RelativeLocation> {
131+
require(n >= 3) { "n must be at least 3" }
132+
// 生成正n边形的顶点列表(xz平面,圆心在原点)
133+
val vertices = List(n) { i ->
134+
val theta = 2 * PI * i / n
135+
RelativeLocation(r * cos(theta), 0.0, r * sin(theta))
136+
}
137+
return vertices
138+
}
139+
128140
/**
129141
* 让两个点集合
130142
* 连线规则如下
@@ -588,6 +600,64 @@ object Math3DUtil {
588600
return res
589601
}
590602

603+
/**
604+
* 生成爆炸曲线点
605+
* @param power 爆炸威力
606+
* @param maxHeight 爆炸点的最高高度
607+
* @param handleRadius 处理爆炸的最大范围
608+
* @param step 处理圆环的步长
609+
* @param minCircleCount 圆环的最小点个数
610+
* @param maxCircleCount 圆环的最大点个数
611+
*/
612+
fun generateExplosionCurve(
613+
power: Double,
614+
maxHeight: Double,
615+
handleRadius: Double,
616+
step: Double = 1.0,
617+
minCircleCount: Int = 8,
618+
maxCircleCount: Int = 24
619+
): List<RelativeLocation> {
620+
// 参数有效性校验
621+
if (handleRadius <= 0 || maxHeight <= 0 || step <= 0) return emptyList()
622+
if (minCircleCount <= 0 || maxCircleCount < minCircleCount) return emptyList()
623+
624+
val points = mutableListOf<RelativeLocation>().apply {
625+
// 添加爆炸中心点
626+
add(RelativeLocation(0.0, maxHeight, 0.0))
627+
}
628+
629+
val maxRadius = handleRadius.coerceAtLeast(step)
630+
val totalCircles = (maxRadius / step).toInt()
631+
632+
// 计算粒子数增量步长
633+
val countStep = if (totalCircles > 0) {
634+
(maxCircleCount - minCircleCount).toDouble() / totalCircles
635+
} else 0.0
636+
637+
var currentRadius = step
638+
repeat(totalCircles) { circleIndex ->
639+
// 计算当前圆环粒子数量
640+
val particleCount = minCircleCount + (countStep * circleIndex).toInt()
641+
642+
// 环形坐标生成
643+
val angleStep = 2 * Math.PI / particleCount
644+
repeat(particleCount) { particleIndex ->
645+
val angle = angleStep * particleIndex
646+
val x = currentRadius * cos(angle)
647+
val z = currentRadius * sin(angle)
648+
649+
// 计算破坏强度
650+
val normalized = currentRadius / handleRadius
651+
val intensity = maxHeight * (1 - normalized).pow(power)
652+
653+
points.add(RelativeLocation(x, intensity, z))
654+
}
655+
currentRadius += step
656+
}
657+
658+
return points
659+
}
660+
591661
/**
592662
* 旋转是通过旋转x/z 轴来坐标值的
593663
* 由于sqrt pow 是恒大于0的值因此不能用于坐标求值

src/main/kotlin/cn/coostack/cooparticlesapi/utils/builder/PointsBuilder.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,19 @@ class PointsBuilder {
104104
)
105105
)
106106

107+
fun addBuilder(origin: RelativeLocation, builder: PointsBuilder): PointsBuilder {
108+
points.addAll(builder.create().onEach { it.add(origin) })
109+
return this
110+
}
107111

108112
fun addPolygonInCircle(n: Int, edgeCount: Int, r: Double): PointsBuilder = addPoints(
109113
Math3DUtil.getPolygonInCircleLocations(n, edgeCount, r)
110114
)
111115

116+
fun addPolygonInCircleVertices(n: Int, edgeCount: Int, r: Double): PointsBuilder = addPoints(
117+
Math3DUtil.getPolygonInCircleVertices(n, r)
118+
)
119+
112120

113121
fun addRoundShape(r: Double, step: Double, preCircleCount: Int): PointsBuilder = addPoints(
114122
Math3DUtil.getRoundScapeLocations(r, step, preCircleCount)
@@ -198,7 +206,7 @@ class PointsBuilder {
198206
return this
199207
}
200208

201-
fun create(): List<RelativeLocation> = points
209+
fun create(): List<RelativeLocation> = points.asSequence().map { it.clone() }.toList()
202210

203211
fun createWithParticleEffects(
204212
dataBuilder: (relative: RelativeLocation) -> ControlableParticleGroup.ParticleRelativeData
@@ -241,8 +249,11 @@ class PointsBuilder {
241249
)
242250
}
243251

244-
245252
fun createAsBlockPos(): Set<BlockPos> = points.asSequence().map {
246253
BlockPos.ofFloored(it.toVector())
247254
}.toMutableSet()
255+
256+
fun cloneBuilder(): PointsBuilder {
257+
return of(axis, create())
258+
}
248259
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package cn.coostack.cooparticlesapi.utils.helper
2+
3+
import cn.coostack.cooparticlesapi.particles.Controlable
4+
import kotlin.math.*
5+
6+
abstract class AlphaHelper(var minAlpha: Double, var maxAlpha: Double, var alphaTick: Int) : ParticleHelper {
7+
var current = 0
8+
protected set
9+
protected var step = abs(maxAlpha - minAlpha) / alphaTick
10+
11+
init {
12+
// 确保数值范围正确
13+
val temp = min(minAlpha, maxAlpha)
14+
maxAlpha = max(minAlpha, maxAlpha)
15+
minAlpha = temp
16+
}
17+
18+
// 重新计算步长(当参数变化时调用)
19+
fun recalculateStep(): AlphaHelper {
20+
val temp = min(minAlpha, maxAlpha)
21+
maxAlpha = max(minAlpha, maxAlpha)
22+
minAlpha = temp
23+
step = abs(maxAlpha - minAlpha) / alphaTick
24+
return this
25+
}
26+
27+
// 直接设置透明度时同步更新状态
28+
fun toggleAlpha(alpha: Double) {
29+
when {
30+
alpha <= minAlpha -> resetAlphaMin()
31+
alpha >= maxAlpha -> {
32+
current = alphaTick
33+
resetAlphaMax()
34+
}
35+
36+
else -> {
37+
val point = alpha - minAlpha
38+
val tick = (point / step).roundToInt()
39+
current = tick
40+
doAlphaTo(current)
41+
}
42+
}
43+
}
44+
45+
// 重置到最小透明度
46+
fun resetAlphaMin() {
47+
getLoadedGroup()?.let {
48+
current = 0
49+
setAlpha(minAlpha)
50+
}
51+
}
52+
53+
// 重置到最大透明度
54+
fun resetAlphaMax() {
55+
getLoadedGroup()?.let {
56+
current = alphaTick
57+
setAlpha(maxAlpha)
58+
}
59+
}
60+
61+
// 按刻度步进设置透明度
62+
fun doAlphaTo(current: Int) {
63+
getLoadedGroup()?.let {
64+
val enter = current.coerceAtLeast(0)
65+
this.current = enter
66+
when {
67+
current >= alphaTick -> resetAlphaMax()
68+
current <= 0 -> resetAlphaMin()
69+
else -> setAlpha(minAlpha + step * enter)
70+
}
71+
}
72+
}
73+
74+
// 正向逐步增加透明度(更不透明)
75+
fun increaseAlpha() {
76+
getLoadedGroup()?.takeUnless { over() }?.let {
77+
current++
78+
setAlpha(getCurrentAlpha() + step)
79+
}
80+
}
81+
82+
// 反向逐步降低透明度(更透明)
83+
fun decreaseAlpha() {
84+
getLoadedGroup()?.takeUnless { isZero() }?.let {
85+
current--
86+
setAlpha(getCurrentAlpha() - step)
87+
}
88+
}
89+
90+
// 状态判断
91+
fun over(): Boolean = alphaTick <= current
92+
fun isZero(): Boolean = current <= 0
93+
94+
/* 需要子类实现的抽象方法 */
95+
// 获取关联的可控对象
96+
abstract fun getLoadedGroup(): Controlable<*>?
97+
98+
// 获取当前实际透明度值
99+
abstract fun getCurrentAlpha(): Double
100+
101+
// 执行透明度设置操作
102+
abstract fun setAlpha(alpha: Double)
103+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package cn.coostack.cooparticlesapi.utils.helper
2+
3+
import cn.coostack.cooparticlesapi.utils.helper.impl.GroupProgressSequencedHelper
4+
import cn.coostack.cooparticlesapi.utils.helper.impl.GroupScaleHelper
5+
import cn.coostack.cooparticlesapi.utils.helper.impl.ParticleAlphaHelper
6+
import cn.coostack.cooparticlesapi.utils.helper.impl.StyleProgressSequencedHelper
7+
import cn.coostack.cooparticlesapi.utils.helper.impl.StyleScaleHelper
8+
9+
object HelperUtil {
10+
11+
fun sequencedStyle(maxCount: Int, progressMaxTick: Int): StyleProgressSequencedHelper {
12+
return StyleProgressSequencedHelper(
13+
maxCount, progressMaxTick,
14+
)
15+
}
16+
17+
fun sequencedGroup(maxCount: Int, progressMaxTick: Int): GroupProgressSequencedHelper {
18+
return GroupProgressSequencedHelper(
19+
maxCount, progressMaxTick,
20+
)
21+
}
22+
23+
fun scaleStyle(minScale: Double, maxScale: Double, scaleTick: Int): StyleScaleHelper =
24+
StyleScaleHelper(minScale, maxScale, scaleTick)
25+
26+
fun scaleGroup(minScale: Double, maxScale: Double, scaleTick: Int): GroupScaleHelper =
27+
GroupScaleHelper(minScale, maxScale, scaleTick)
28+
29+
fun particleAlpha(minAlpha: Double, maxAlpha: Double, alphaTick: Int): ParticleAlphaHelper {
30+
return ParticleAlphaHelper(minAlpha, maxAlpha, alphaTick)
31+
}
32+
33+
}

0 commit comments

Comments
 (0)