1+ package cn.coostack.cooparticlesapi.network.particle.style
2+
3+ import cn.coostack.cooparticlesapi.network.buffer.ParticleControlerDataBuffer
4+ import cn.coostack.cooparticlesapi.particles.ParticleDisplayer
5+ import cn.coostack.cooparticlesapi.utils.RelativeLocation
6+ import cn.coostack.cooparticlesapi.utils.builder.PointsBuilder
7+ import cn.coostack.cooparticlesapi.utils.helper.ScaleHelper
8+ import cn.coostack.cooparticlesapi.utils.helper.impl.StyleBezierValueScaleHelper
9+ import cn.coostack.cooparticlesapi.utils.helper.impl.StyleScaleHelper
10+ import cn.coostack.cooparticlesapi.utils.helper.impl.StyleStatusHelper
11+ import net.minecraft.client.particle.ParticleTextureSheet
12+ import net.minecraft.entity.player.PlayerEntity
13+ import net.minecraft.util.math.Vec3d
14+ import java.util.SortedMap
15+ import java.util.TreeMap
16+ import java.util.UUID
17+ import java.util.function.Predicate
18+
19+ /* *
20+ * 为了方便制作子图形作用于父图形 (进行不同方向的旋转, rotate)
21+ * 专门创建此类
22+ *
23+ * 无法单独生成
24+ * 继承此类的目的是为这个类创建一个专属形状的子类
25+ * client属性始终为true
26+ */
27+ class SequencedParticleShapeStyle (uuid : UUID ) :
28+ SequencedParticleStyle (64.0 , uuid) {
29+ var scaleHelper: ScaleHelper ? = null
30+ private var onDisplayInvoke: SequencedParticleShapeStyle .() -> Unit = {}
31+ private var beforeDisplayInvoke: SequencedParticleShapeStyle .(SortedMap <SortedStyleData , RelativeLocation >) -> Unit =
32+ {}
33+ private val pointBuilders = LinkedHashMap <PointsBuilder , (RelativeLocation ) - > SortedStyleData > ()
34+
35+ /* *
36+ * 用于控制粒子的播放顺序
37+ * 如果满足 animationConditions[animationIndex].first的条件
38+ * 则会执行 addMultiple(second (second > 0))
39+ * 或者 removeMultiple(second (second < 0)
40+ * 符合条件后 animationIndex 会递增
41+ * 直到到达边界
42+ */
43+ private val animationConditions = ArrayList <Pair <Predicate <SequencedParticleStyle >, Int >> ()
44+ var animationIndex = 0
45+ private set
46+
47+ /* *
48+ * 通过判断(外层) 提供的状态工具来决定是否反转缩放
49+ * 在toggleDisplay执行这个方法
50+ */
51+ val reverseFunctionFromStatus: (SequencedParticleShapeStyle , StyleStatusHelper ) -> Unit =
52+ function@{ it, displayStatus ->
53+ // 必须设置缩放工具
54+ if (scaleHelper == null ) return @function
55+ it.addPreTickAction {
56+ if (it.scaleReversed && it.scaleHelper!! .isZero()) {
57+ it.remove()
58+ return @addPreTickAction
59+ }
60+ if (displayStatus.displayStatus != 2 ) {
61+ return @addPreTickAction
62+ }
63+ if (! it.scaleReversed) {
64+ it.scaleReversed(false )
65+ }
66+ }
67+ }
68+
69+ /* *
70+ * 设置为true时 会利用scaleHelper 每tick增长一点
71+ */
72+ var scalePreTick = false
73+ private set
74+
75+ /* *
76+ * 设置为true时 利用scaleHelper 每tick减弱一点
77+ */
78+ var scaleReversed = false
79+ private set
80+
81+ fun appendBuilder (
82+ pointsBuilder : PointsBuilder ,
83+ dataBuilder : (RelativeLocation ) -> SortedStyleData
84+ ): SequencedParticleShapeStyle {
85+ pointBuilders[pointsBuilder] = dataBuilder
86+ return this
87+ }
88+
89+ fun appendPoint (
90+ point : RelativeLocation ,
91+ dataBuilder : (RelativeLocation ) -> SortedStyleData
92+ ): SequencedParticleShapeStyle {
93+ pointBuilders[
94+ PointsBuilder ().also { it.addPoint(point) }
95+ ] = dataBuilder
96+ return this
97+ }
98+
99+ /* *
100+ * @param predicate 设置添加/删除动画的要求
101+ * @param add 向下的个数
102+ */
103+ fun appendAnimateCondition (predicate : Predicate <SequencedParticleStyle >, add : Int ): SequencedParticleShapeStyle {
104+ animationConditions.add(predicate to add)
105+ return this
106+ }
107+
108+ /* *
109+ * @param max 直接让scale从最大开始
110+ */
111+ fun scaleReversed (max : Boolean ): SequencedParticleShapeStyle {
112+ scaleHelper ? : return this
113+ scaleReversed = true
114+ if (max) {
115+ scaleHelper!! .toggleScale(scaleHelper!! .maxScale)
116+ }
117+ return this
118+ }
119+
120+ fun loadScaleHelper (minScale : Double , maxScale : Double , scaleTick : Int ): SequencedParticleShapeStyle {
121+ scaleHelper = StyleScaleHelper (minScale, maxScale, scaleTick)
122+ scalePreTick = true
123+ scaleHelper!! .loadControler(this )
124+ return this
125+ }
126+
127+ fun loadScaleHelperBezierValue (
128+ minScale : Double ,
129+ maxScale : Double ,
130+ scaleTick : Int ,
131+ c1 : RelativeLocation ,
132+ c2 : RelativeLocation
133+ ): SequencedParticleShapeStyle {
134+ scaleHelper = StyleBezierValueScaleHelper (scaleTick, minScale, maxScale, c1, c2)
135+ scalePreTick = true
136+ scaleHelper!! .loadControler(this )
137+ return this
138+ }
139+
140+ /* *
141+ * 在display之前执行
142+ */
143+ fun toggleOnDisplay (toggleMethod : SequencedParticleShapeStyle .() -> Unit ): SequencedParticleShapeStyle {
144+ onDisplayInvoke = toggleMethod
145+ return this
146+ }
147+
148+ /* *
149+ * 在生成粒子之前执行
150+ */
151+ fun toggleBeforeDisplay (toggleMethod : SequencedParticleShapeStyle .(Map <SortedStyleData , RelativeLocation >) -> Unit ): SequencedParticleShapeStyle {
152+ beforeDisplayInvoke = toggleMethod
153+ return this
154+ }
155+
156+
157+ override fun beforeDisplay (styles : SortedMap <SortedStyleData , RelativeLocation >) {
158+ beforeDisplayInvoke(styles)
159+ }
160+
161+
162+ override fun onDisplay () {
163+ onDisplayInvoke()
164+ addPreTickAction {
165+ if (animationIndex >= animationConditions.size) {
166+ return @addPreTickAction
167+ }
168+ val (predicate, add) = animationConditions[animationIndex]
169+ if (predicate.test(this @SequencedParticleShapeStyle)) {
170+ if (add > 0 ) {
171+ addMultiple(add)
172+ } else {
173+ removeMultiple(add)
174+ }
175+ animationIndex++
176+ }
177+ }
178+ addPreTickAction {
179+ if (! scalePreTick || scaleHelper == null ) {
180+ return @addPreTickAction
181+ }
182+
183+ if (scaleReversed) {
184+ scaleHelper!! .doScaleReversed()
185+ } else {
186+ scaleHelper!! .doScale()
187+ }
188+ }
189+ }
190+
191+ private val bufferFrame: SortedMap <SortedStyleData , RelativeLocation > = TreeMap ()
192+ override fun getParticlesCount (): Int {
193+ return bufferFrame.size
194+ }
195+
196+ override fun getCurrentFramesSequenced (): SortedMap <SortedStyleData , RelativeLocation > {
197+ val res = TreeMap <SortedStyleData , RelativeLocation >()
198+ pointBuilders.forEach { entry ->
199+ res.putAll(entry.key.createWithSequencedStyleData { it, order ->
200+ entry.value(it)
201+ })
202+ }
203+ return res
204+ }
205+
206+ override fun writePacketArgsSequenced (): Map <String , ParticleControlerDataBuffer <* >> {
207+ return mapOf ()
208+ }
209+
210+ override fun readPacketArgsSequenced (args : Map <String , ParticleControlerDataBuffer <* >>) {
211+ }
212+
213+
214+ fun fastRotateToPlayerView (player : PlayerEntity ) {
215+ rotateParticlesToPoint(RelativeLocation .of(player.rotationVector))
216+ }
217+
218+ fun fastStyleData (order : Int , color : Vec3d , displayer : (UUID ) -> ParticleDisplayer ): SortedStyleData {
219+ return SortedStyleData (displayer, order).withParticleHandler {
220+ this .colorOfRGB(color.x.toInt(), color.y.toInt(), color.z.toInt())
221+ } as SortedStyleData
222+ }
223+
224+ fun fastStyleData (
225+ order : Int ,
226+ color : Vec3d ,
227+ sheet : ParticleTextureSheet ,
228+ displayer : (UUID ) -> ParticleDisplayer
229+ ): SortedStyleData {
230+ return SortedStyleData (displayer, order).withParticleHandler {
231+ this .colorOfRGB(color.x.toInt(), color.y.toInt(), color.z.toInt())
232+ this .textureSheet = sheet
233+ } as SortedStyleData
234+ }
235+
236+ fun fastStyleData (
237+ order : Int ,
238+ color : Vec3d ,
239+ sheet : ParticleTextureSheet ,
240+ size : Float ,
241+ displayer : (UUID ) -> ParticleDisplayer
242+ ): SortedStyleData {
243+ return SortedStyleData (displayer, order).withParticleHandler {
244+ this .colorOfRGB(color.x.toInt(), color.y.toInt(), color.z.toInt())
245+ this .textureSheet = sheet
246+ this .size = size
247+ } as SortedStyleData
248+ }
249+
250+ fun fastStyleData (
251+ order : Int ,
252+ color : Vec3d ,
253+ sheet : ParticleTextureSheet ,
254+ size : Float ,
255+ alpha : Float ,
256+ displayer : (UUID ) -> ParticleDisplayer
257+ ): SortedStyleData {
258+ return SortedStyleData (displayer, order).withParticleHandler {
259+ this .colorOfRGB(color.x.toInt(), color.y.toInt(), color.z.toInt())
260+ this .textureSheet = sheet
261+ this .size = size
262+ this .particleAlpha = alpha
263+ } as SortedStyleData
264+ }
265+
266+ fun fastStyleData (
267+ order : Int ,
268+ sheet : ParticleTextureSheet ,
269+ displayer : (UUID ) -> ParticleDisplayer
270+ ): SortedStyleData {
271+ return SortedStyleData (displayer, order).withParticleHandler {
272+ this .textureSheet = sheet
273+ } as SortedStyleData
274+ }
275+ }
0 commit comments