Releases: CooStack/CooParticlesAPI
V1.5
V1.42
修复BUGS
- EmptyControlerBuffer在编码时产生StackOverFlowError
- 修复Barrier距离玩家过远时(bindGroup.visibaleRange > particleVisible > 玩家到barrier的距离)使得barrier不可见,然后玩家靠近barrier,让barrier重新生成 导致 Kotlin未实例化异常
增加内容
Math3DUtil
- 新增生成球体函数 Math3DUtil.getBallLocations
- 新增生成圆面函数 Math3DUtil.getRoundScapeLocations
- 新增生成圆柱的函数 Math3DUtil.getCylinderLocations
ServerParticleUtil
由于 serverworld.spawnParticles 功能太鸡肋
无法通过该方法生成带指定方向的粒子
为了更方便在玩家面前展示粒子
于是创建此类
- ServerParticleUtil.spawnSingle
V1.4
新增
- Barrier (攻击性弹幕)框架 (类比CooLib的Barrier)
- ParticleControlerDataBuffers支持创建空类型
ParticleControlerDataBuffers.empty() 现在输入操作args时无需多余传入参数 - 新增一个物品 用于测试Barrier框架
更改了用于测试的ParticleGroup的位置
使用Barrier时 只需要创建类 继承AbstractBarrier
实现对应方法
然后生成Barrier只需要 使用BarrierManager.spawn()即可
Barrier需要绑定一个ServerParticleGroup 作为这个弹幕的显示层
这个ParticleGroup的位置由Barrier控制(teleport)
所以你无需在ControlableParticleGroup(Client)处对位置进行同步
Barrier是一个服务端模块 意味着 world entities 均代表服务端的 ServerWorld
重写tick方法时务必加上super.tick() 除非你想让大多数功能失效
Barrier示例请查阅:
SwordBarrier
BarrierSwordGroupServer
BarrierSwordGroupClient
修正
- 修复mod id的错误 (cooparticleapi -> cooparticlesapi)
- ServerParticleGroup 现在需要实现一个新的方法 getClientType() 用于返回对应的客户端类型(旧版本addParticleGroup的第一个参数)
意味着该版本不再兼容基于1.3的模组 - ServerParticleGroupManager.addParticleGroup()参数修改现在只需要输入group, pos, world 三个参数 (删除了4个参数的版本)
V1.3
案例添加
ScaleCircleGroupClient
class ScaleCircleGroupClient(uuid: UUID, val bindPlayer: UUID) : ControlableParticleGroup(uuid) {
internal var anTick = 0
internal var anMaxTick = 30
class Provider : ControlableParticleGroupProvider {
override fun createGroup(
uuid: UUID,
args: Map<String, ParticleControlerDataBuffer<*>>
): ControlableParticleGroup {
val bindPlayer = args["bind_player"]!!.loadedValue as UUID
val group = ScaleCircleGroupClient(uuid, bindPlayer)
group.anTick = args["an_tick"]!!.loadedValue as Int
group.maxTick = args["max_tick"]!!.loadedValue as Int
group.tick = args["tick"]!!.loadedValue as Int
return group
}
override fun changeGroup(group: ControlableParticleGroup, args: Map<String, ParticleControlerDataBuffer<*>>) {
}
}
override fun loadParticleLocations(): Map<ParticleRelativeData, RelativeLocation> {
val res = mutableMapOf<ParticleRelativeData, RelativeLocation>()
val points = Math3DUtil.getCycloidGraphic(3.0, 5.0, -2, 3, 720, .5)
points.forEach {
val withData = withEffect({ ParticleDisplayer.withSingle(TestEndRodEffect(it)) }) {
color = Vector3f(100 / 255f, 100 / 255f, 255 / 255f)
maxAge = 120
}.withControler { c ->
c.addPreTickAction {
currentAge++
if (currentAge >= maxAge) {
this@ScaleCircleGroupClient.canceled = true
}
}
}
res[withData] = it.multiply(1.0 / anMaxTick)
}
return res
}
override fun onGroupDisplay() {
// 保存最初始的长度
// 用于做稳定的长度添加
val firstClone = particlesLocations.map {
it.key to it.value.length()
}.toMap()
addPreTickAction {
val player = world!!.getPlayerByUuid(bindPlayer) ?: return@addPreTickAction
// 同步位置
teleportTo(player.pos)
// 在变大的过程中也能旋转
rotateParticlesAsAxis(Math.toRadians(10.0))
if (tick++ >= maxTick - anMaxTick) {
particlesLocations.forEach {
val cloneLength = firstClone[it.key]!!
// 确保添加的方向和长度正确
it.value.remove(it.value.normalize().multiply(cloneLength))
}
return@addPreTickAction
}
// 旋转时间设定
if (anTick++ >= anMaxTick) {
anTick = anMaxTick
return@addPreTickAction
}
particlesLocations.forEach {
val cloneLength = firstClone[it.key]!!
// 确保添加的方向和长度正确
it.value.add(it.value.normalize().multiply(cloneLength))
}
}
}
}ParticleRelativeData修改
新增方法 withControler(controler: (ParticleControler) -> Unit): ParticleRelativeData
此方法会在粒子生成在世界中时执行,ParticleControler是 ControlableParticle的控制器 用于控制单个粒子行为
#ServerParticleGroup 修改
增加change方法
用例
group.change({
this.your_param = your_value // 假设your_value是int类型
}, mapOf("your_param" to ParticleControlerDataBuffers.int(your_value)))ControlableParticleGroupProvider修改
ControlableParticleGroupProvider新增一个需要实现的方法
changeGroup 用于应用ServerParticleGroup的change方法
用例(以ServerParticleGroup的change输入为例)
override fun changeGroup(group: ControlableParticleGroup, args: Map<String, ParticleControlerDataBuffer<*>>) {
group.your_param = args["your_param"]!!.loadedValue as Int // loadedValue需要强制转型 注意NPE
}V1.2
API变更
ControlableParticleGroup使用变更
现在ControlableParticleGroup支持在生成粒子时输入一个子ParticleGroup
但是ParticleRelativeData由原先的
data class ParticleRelativeData(
val effect: (UUID) -> ParticleEffect,
val invoker: ControlableParticle.() -> Unit
)更改为
class ParticleRelativeData(
val effect: (UUID) -> ParticleDisplayer,
val invoker: ControlableParticle.() -> Unit
)现在ControlableParticleGroup输入粒子类型必须采用
ControlableParticleEffect
子ParticleGroup无需注册Provider
优化了粒子传送时的移动, 现在进行复杂运动(例如旋转+位移)
更加流畅
V1.1
Math3DUtil更新
Math3DUtil支持计算获取由 getCycloidGraphic方法生成的图像的顶点(点速度最小时)坐标集合
Math3DUtil.computeCycloidVertices()
重命名方法参数名字radiusPrecision 为 scale
ControlableParticleGroup更改
由于考虑到多个不同的粒子可能会出现在同一个位置上,为了适配这个,故将
ControlableParticleGroup.loadParticleLocations() 方法的返回值
由
Map<RelativeLocation, ParticleRelativeData>更改为
Map<ParticleRelativeData, RelativeLocation>