Skip to content

Commit ea173b4

Browse files
committed
# 修复
修复了ParticleGroupStyle 在传送,旋转上的同步参数输入错误的问题 # 新增 新增了几个其他的粒子样式 使用注解更快生成粒子同步参数 支持修改单个粒子朝向(x,y,z) 修改了粒子渲染方式 (在参数中输入 faceToPlayer = false)时 多个朝向修改生效 修复了只TP一次会发生来回闪烁的BUG
1 parent 7104966 commit ea173b4

24 files changed

Lines changed: 459 additions & 89 deletions

src/main/kotlin/cn/coostack/cooparticlesapi/network/buffer/ParticleControlerDataBuffer.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,20 @@ import net.minecraft.util.Identifier
44

55
interface ParticleControlerDataBuffer<T> {
66

7-
data class Id(val value: Identifier)
7+
data class Id(val value: Identifier) {
8+
companion object {
9+
@JvmStatic
10+
fun toID(string: String): Id {
11+
val split = string.split(":")
12+
if (split.size != 2) {
13+
throw IllegalArgumentException("Invalid ID format: $string")
14+
}
15+
val namespace = split[0]
16+
val id = split[1]
17+
return Id(Identifier.of(namespace, id))
18+
}
19+
}
20+
}
821

922
var loadedValue: T?
1023
fun encode(): ByteArray?

src/main/kotlin/cn/coostack/cooparticlesapi/network/buffer/ParticleControlerDataBuffers.kt

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,16 @@ import net.minecraft.util.math.Vec3d
77
import java.util.UUID
88

99
object ParticleControlerDataBuffers {
10-
10+
private val wrapperToPrimitive = mapOf<Class<*>, Class<*>>(
11+
java.lang.Integer::class.java to Int::class.java,
12+
java.lang.Double::class.java to Double::class.java,
13+
java.lang.Long::class.java to Long::class.java,
14+
java.lang.Float::class.java to Float::class.java,
15+
java.lang.Boolean::class.java to Boolean::class.java,
16+
java.lang.Character::class.java to Char::class.java,
17+
java.lang.Byte::class.java to Byte::class.java,
18+
java.lang.Short::class.java to Short::class.java
19+
)
1120
val registerBuilder = HashMap<ParticleControlerDataBuffer.Id, Class<out ParticleControlerDataBuffer<*>>>()
1221
val registerTypes = HashMap<Class<*>, ParticleControlerDataBuffer.Id>()
1322

@@ -46,8 +55,11 @@ object ParticleControlerDataBuffers {
4655
}
4756

4857
fun fromBufferType(value: Any, clazz: Class<*>): ParticleControlerDataBuffer<*>? {
49-
val id = registerTypes[clazz]!!
50-
return withId(id, value)
58+
val targetClass = registerTypes[clazz]?.let { clazz }
59+
?: wrapperToPrimitive[clazz]?.takeIf { registerTypes.containsKey(it) }
60+
?: return null
61+
62+
return registerTypes[targetClass]?.let { withId(it, value) }
5163
}
5264

5365
fun withDecode(buf: ByteArray, clazz: Class<out ParticleControlerDataBuffer<*>>): ParticleControlerDataBuffer<*> {
@@ -145,7 +157,7 @@ object ParticleControlerDataBuffers {
145157
init {
146158
register(Boolean::class.java, BooleanControlerBuffer.id, BooleanControlerBuffer::class.java)
147159
register(Long::class.java, LongControlerBuffer.id, LongControlerBuffer::class.java)
148-
register(Int::class.java, IntControlerBuffer.id, IntControlerBuffer::class.java)
160+
register(Integer::class.java, IntControlerBuffer.id, IntControlerBuffer::class.java)
149161
register(Double::class.java, DoubleControlerBuffer.id, DoubleControlerBuffer::class.java)
150162
register(Float::class.java, FloatControlerBuffer.id, FloatControlerBuffer::class.java)
151163
register(String::class.java, StringControlerBuffer.id, StringControlerBuffer::class.java)

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ open class ParticleShapeStyle(uuid: UUID) :
2424
val scaleHelper = StyleScaleHelper(1.0, 1.0, 1)
2525
private var onDisplayInvoke: ParticleShapeStyle.() -> Unit = {}
2626
private var beforeDisplayInvoke: ParticleShapeStyle.(Map<StyleData, RelativeLocation>) -> Unit = {}
27-
private val pointBuilders = LinkedHashMap<PointsBuilder, () -> StyleData>()
27+
private val pointBuilders = LinkedHashMap<PointsBuilder, (RelativeLocation) -> StyleData>()
2828

2929
/**
3030
* 设置为true时 会利用scaleHelper 每tick增长一点
@@ -38,11 +38,18 @@ open class ParticleShapeStyle(uuid: UUID) :
3838
var scaleReversed = false
3939
private set
4040

41-
fun appendBuilder(pointsBuilder: PointsBuilder, dataBuilder: () -> StyleData): ParticleShapeStyle {
41+
fun appendBuilder(pointsBuilder: PointsBuilder, dataBuilder: (RelativeLocation) -> StyleData): ParticleShapeStyle {
4242
pointBuilders[pointsBuilder] = dataBuilder
4343
return this
4444
}
4545

46+
fun appendPoint(point: RelativeLocation, dataBuilder: (RelativeLocation) -> StyleData): ParticleShapeStyle {
47+
pointBuilders[
48+
PointsBuilder().also { it.addPoint(point) }
49+
] = dataBuilder
50+
return this
51+
}
52+
4653
/**
4754
* @param max 直接让scale从最大开始
4855
*/
@@ -87,7 +94,7 @@ open class ParticleShapeStyle(uuid: UUID) :
8794
override fun getCurrentFrames(): Map<StyleData, RelativeLocation> {
8895
val res = HashMap<StyleData, RelativeLocation>()
8996
pointBuilders.forEach { entry ->
90-
res.putAll(entry.key.createWithStyleData { entry.value() })
97+
res.putAll(entry.key.createWithStyleData { entry.value(it) })
9198
}
9299
return res
93100
}

src/main/kotlin/cn/coostack/cooparticlesapi/particles/ControlableParticle.kt

Lines changed: 152 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,39 @@ package cn.coostack.cooparticlesapi.particles
33
import cn.coostack.cooparticlesapi.particles.control.ControlParticleManager
44
import cn.coostack.cooparticlesapi.particles.control.ParticleControler
55
import cn.coostack.cooparticlesapi.utils.Math3DUtil
6-
import com.mojang.blaze3d.platform.GlStateManager
7-
import com.mojang.blaze3d.systems.RenderSystem
6+
import cn.coostack.cooparticlesapi.utils.RelativeLocation
87
import net.fabricmc.api.EnvType
98
import net.fabricmc.api.Environment
10-
import net.minecraft.client.particle.Particle
119
import net.minecraft.client.particle.ParticleTextureSheet
1210
import net.minecraft.client.particle.SpriteBillboardParticle
1311
import net.minecraft.client.render.Camera
1412
import net.minecraft.client.render.LightmapTextureManager
1513
import net.minecraft.client.render.VertexConsumer
1614
import net.minecraft.client.world.ClientWorld
17-
import net.minecraft.particle.ParticleTypes
1815
import net.minecraft.util.math.Box
16+
import net.minecraft.util.math.MathHelper
1917
import net.minecraft.util.math.Vec3d
2018
import net.minecraft.util.math.random.Random
19+
import org.joml.Matrix4f
20+
import org.joml.Quaternionf
2121
import org.joml.Vector2f
2222
import org.joml.Vector3f
23+
import org.joml.Vector4f
24+
import org.lwjgl.opengl.GL11
2325
import java.util.*
26+
import kotlin.math.PI
27+
2428

2529
@Environment(EnvType.CLIENT)
2630
abstract class ControlableParticle(
2731
world: ClientWorld,
2832
pos: Vec3d,
2933
velocity: Vec3d,
30-
val controlUUID: UUID
34+
val controlUUID: UUID,
35+
/**
36+
* 是否始终转向玩家(默认实现)
37+
*/
38+
val faceToCamera: Boolean = true
3139
) : SpriteBillboardParticle(world, pos.x, pos.y, pos.z, velocity.x, velocity.y, velocity.z) {
3240
val controler: ParticleControler = ControlParticleManager.getControl(controlUUID)!!
3341

@@ -180,10 +188,16 @@ abstract class ControlableParticle(
180188
alpha = value.coerceIn(0f, 1f)
181189
}
182190

191+
var previewAngleX: Float = 0f
192+
var currentAngleX: Float = 0f
193+
194+
var previewAngleY: Float = 0f
195+
var currentAngleY: Float = 0f
196+
183197
/**
184198
* @see prevAngle
185199
*/
186-
var previewAngle: Float
200+
var previewAngleZ: Float
187201
get() = prevAngle
188202
set(value) {
189203
prevAngle = value
@@ -192,7 +206,7 @@ abstract class ControlableParticle(
192206
/**
193207
* @see angle
194208
*/
195-
var currentAngle: Float
209+
var currentAngleZ: Float
196210
get() = angle
197211
set(value) {
198212
angle = value
@@ -238,6 +252,22 @@ abstract class ControlableParticle(
238252
controler.particleInit()
239253
}
240254

255+
var lastRotate = Vector3f(previewAngleX, previewAngleY, previewAngleZ)
256+
var updateRotate = false
257+
fun rotateParticleTo(target: RelativeLocation) {
258+
rotateParticleTo(Vector3f(target.x.toFloat(), target.y.toFloat(), target.z.toFloat()))
259+
}
260+
261+
fun rotateParticleTo(target: Vec3d) {
262+
rotateParticleTo(target.toVector3f())
263+
}
264+
265+
fun rotateParticleTo(target: Vector3f) {
266+
val (x, y, z) = Math3DUtil.calculateEulerAnglesToPoint(target)
267+
updateRotate = true
268+
lastRotate = Vector3f(x, y, z)
269+
}
270+
241271
/**
242272
* 防止频繁调用Math3DUtil (让键盘休息一会)
243273
* 也不用调用 color = Vector3f(xxx/255f,xxx/255f,xxx/255f)
@@ -264,13 +294,128 @@ abstract class ControlableParticle(
264294
super.tick()
265295
}
266296
controler.doTick()
297+
prevPos = this.pos
267298
if (update) {
268299
prevPos = this.pos
269300
this.pos = lastPreview
270301
update = false
271302
}
303+
previewAngleX = currentAngleX
304+
previewAngleY = currentAngleY
305+
previewAngleZ = currentAngleZ
306+
if (updateRotate) {
307+
currentAngleX = lastRotate.x
308+
currentAngleY = lastRotate.y
309+
currentAngleZ = lastRotate.z
310+
updateRotate = false
311+
}
272312
}
273313

314+
override fun buildGeometry(vertexConsumer: VertexConsumer, camera: Camera, tickDelta: Float) {
315+
if (faceToCamera) {
316+
super.buildGeometry(vertexConsumer, camera, tickDelta)
317+
return
318+
}
319+
// 获取摄像机位置
320+
val cameraPos = camera.pos
321+
val x = (MathHelper.lerp(tickDelta.toDouble(), this.prevPosX, this.x) - cameraPos.getX()).toFloat()
322+
val y = (MathHelper.lerp(tickDelta.toDouble(), this.prevPosY, this.y) - cameraPos.getY()).toFloat()
323+
val z = (MathHelper.lerp(tickDelta.toDouble(), this.prevPosZ, this.z) - cameraPos.getZ()).toFloat()
324+
val q = Quaternionf()
325+
q.rotateXYZ(
326+
MathHelper.lerp(tickDelta, this.previewAngleX, this.currentAngleX),
327+
MathHelper.lerp(tickDelta, this.previewAngleY, this.currentAngleY),
328+
MathHelper.lerp(tickDelta, this.previewAngleZ, this.currentAngleZ)
329+
)
330+
// 构建顶点几何
331+
val light = this.getBrightness(tickDelta)
332+
333+
334+
setParticleTexture(vertexConsumer, q, x, y, z, tickDelta, light)
335+
}
336+
337+
private fun setParticleTexture(
338+
vertexConsumer: VertexConsumer,
339+
q: Quaternionf,
340+
x: Float,
341+
y: Float,
342+
z: Float,
343+
tickDelta: Float,
344+
light: Int
345+
) {
346+
val s = getSize(tickDelta)
347+
348+
addVertex(
349+
vertexConsumer, q, x, y, z, 1f, -1f, maxU, maxV, s, light
350+
)
351+
addVertex(
352+
vertexConsumer, q, x, y, z, 1f, 1f, maxU, minV, s, light
353+
)
354+
addVertex(
355+
vertexConsumer, q, x, y, z, -1f, 1f, minU, minV, s, light
356+
)
357+
addVertex(
358+
vertexConsumer, q, x, y, z, -1f, -1f, minU, maxV, s, light
359+
)
360+
361+
// 背面
362+
addVertex(
363+
vertexConsumer, q, x, y, z,
364+
vx = -1f, // 左下角 X
365+
vy = -1f,
366+
tu = minU, // UV 镜像
367+
tv = maxV,
368+
size = s,
369+
light = light
370+
)
371+
addVertex(
372+
vertexConsumer, q, x, y, z,
373+
vx = -1f, // 左上角 X
374+
vy = 1f,
375+
tu = minU,
376+
tv = minV,
377+
size = s,
378+
light = light
379+
)
380+
addVertex(
381+
vertexConsumer, q, x, y, z,
382+
vx = 1f, // 右上角 X
383+
vy = 1f,
384+
tu = maxU, // UV 镜像
385+
tv = minV,
386+
size = s,
387+
light = light
388+
)
389+
addVertex(
390+
vertexConsumer, q, x, y, z,
391+
vx = 1f, // 右下角 X
392+
vy = -1f,
393+
tu = maxU,
394+
tv = maxV,
395+
size = s,
396+
light = light
397+
)
398+
}
399+
400+
private fun addVertex(
401+
consumer: VertexConsumer,
402+
q: Quaternionf,
403+
dx: Float,
404+
dy: Float,
405+
dz: Float,
406+
vx: Float,
407+
vy: Float,
408+
tu: Float,
409+
tv: Float,
410+
size: Float,
411+
light: Int
412+
) {
413+
val pos = Vector3f(vx, vy, 0f).rotate(q).mul(size).add(dx, dy, dz)
414+
consumer.vertex(pos.x, pos.y, pos.z)
415+
.texture(tu, tv)
416+
.color(red, green, blue, alpha)
417+
.light(light)
418+
}
274419

275420
override fun getType(): ParticleTextureSheet? {
276421
return textureSheet
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package cn.coostack.cooparticlesapi.particles
22

3+
import cn.coostack.cooparticlesapi.particles.impl.ControlableCloudEffect
4+
import com.mojang.serialization.Codec
5+
import com.mojang.serialization.MapCodec
6+
import com.mojang.serialization.codecs.RecordCodecBuilder
7+
import io.netty.buffer.Unpooled
38
import net.minecraft.particle.ParticleEffect
49
import java.util.UUID
510

6-
abstract class ControlableParticleEffect(val controlUUID: UUID) : ParticleEffect {
11+
abstract class ControlableParticleEffect(val controlUUID: UUID, val faceToPlayer: Boolean = true) : ParticleEffect {
12+
713
}

src/main/kotlin/cn/coostack/cooparticlesapi/particles/control/ParticleControler.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package cn.coostack.cooparticlesapi.particles.control
22

33
import cn.coostack.cooparticlesapi.particles.Controlable
44
import cn.coostack.cooparticlesapi.particles.ControlableParticle
5+
import cn.coostack.cooparticlesapi.utils.Math3DUtil
56
import cn.coostack.cooparticlesapi.utils.RelativeLocation
67
import net.fabricmc.api.EnvType
78
import net.fabricmc.api.Environment
89
import net.minecraft.util.math.Vec3d
10+
import org.joml.Vector3f
911
import java.util.UUID
1012
import java.util.concurrent.ConcurrentHashMap
1113

@@ -67,6 +69,18 @@ class ParticleControler(private val uuid: UUID) : Controlable<ControlableParticl
6769
}
6870
}
6971

72+
fun rotateParticleTo(target: RelativeLocation) {
73+
rotateParticleTo(Vector3f(target.x.toFloat(), target.y.toFloat(), target.z.toFloat()))
74+
}
75+
76+
fun rotateParticleTo(target: Vec3d) {
77+
rotateParticleTo(target.toVector3f())
78+
}
79+
80+
fun rotateParticleTo(target: Vector3f) {
81+
particle.rotateParticleTo(target)
82+
}
83+
7084
override fun controlUUID(): UUID {
7185
return uuid
7286
}

0 commit comments

Comments
 (0)