moved to ItemDisplays and added support for CustomModelData
This commit is contained in:
@@ -18,7 +18,7 @@ import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory
|
|||||||
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry
|
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry
|
||||||
import net.fabricmc.loader.api.FabricLoader
|
import net.fabricmc.loader.api.FabricLoader
|
||||||
import net.minecraft.entity.EntityType
|
import net.minecraft.entity.EntityType
|
||||||
import net.minecraft.entity.decoration.DisplayEntity.BlockDisplayEntity
|
import net.minecraft.entity.decoration.DisplayEntity.ItemDisplayEntity
|
||||||
import net.minecraft.entity.player.PlayerEntity
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NbtCompound
|
import net.minecraft.nbt.NbtCompound
|
||||||
@@ -38,7 +38,6 @@ import java.util.*
|
|||||||
// Allowing the use of regular Minecraft particles instead of just BDEs.
|
// Allowing the use of regular Minecraft particles instead of just BDEs.
|
||||||
// Better command auto-completion. (and change names of args)
|
// Better command auto-completion. (and change names of args)
|
||||||
// force field "config" option
|
// force field "config" option
|
||||||
// blockCurve array not needing "minecraft:"
|
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
// rotWithVel / scaleWithVel (bool)
|
// rotWithVel / scaleWithVel (bool)
|
||||||
@@ -70,6 +69,11 @@ class Bde_particles : ModInitializer {
|
|||||||
GameRules.Category.UPDATES,
|
GameRules.Category.UPDATES,
|
||||||
GameRuleFactory.createIntRule(3000, 0)
|
GameRuleFactory.createIntRule(3000, 0)
|
||||||
)
|
)
|
||||||
|
val SHOW_PARTICLE_DEBUG: GameRules.Key<GameRules.BooleanRule> = GameRuleRegistry.register(
|
||||||
|
"ShowParticleDebug",
|
||||||
|
GameRules.Category.UPDATES,
|
||||||
|
GameRuleFactory.createBooleanRule(false)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInitialize() {
|
override fun onInitialize() {
|
||||||
@@ -122,10 +126,10 @@ fun tick(server: MinecraftServer) {
|
|||||||
runBlocking {
|
runBlocking {
|
||||||
server.worlds.map { world ->
|
server.worlds.map { world ->
|
||||||
async {
|
async {
|
||||||
val blockDisplayEntities = world.iterateEntities()
|
val displayEntities = world.iterateEntities()
|
||||||
.filter { it.type == EntityType.BLOCK_DISPLAY }
|
.filter { it.type == EntityType.ITEM_DISPLAY }
|
||||||
for (entity in blockDisplayEntities) {
|
for (entity in displayEntities) {
|
||||||
if (displayEntityContainsTag(entity as BlockDisplayEntity, "BPS_UUID")
|
if (displayEntityContainsTag(entity as ItemDisplayEntity, "BPS_UUID")
|
||||||
&& !displayEntityContainsTag(entity, SESSION_UUID.toString())) {
|
&& !displayEntityContainsTag(entity, SESSION_UUID.toString())) {
|
||||||
|
|
||||||
entity.kill()
|
entity.kill()
|
||||||
@@ -185,7 +189,7 @@ fun emitterParamsToJson(params: EmitterParams) : Map<String, Any> { // TODO: map
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
fun displayEntityContainsTag(entity: BlockDisplayEntity, tag: String) : Boolean {
|
fun displayEntityContainsTag(entity: ItemDisplayEntity, tag: String) : Boolean {
|
||||||
val nbt = NbtCompound()
|
val nbt = NbtCompound()
|
||||||
entity.writeNbt(nbt)
|
entity.writeNbt(nbt)
|
||||||
val tagsNbtList = nbt.getList("Tags", 8)
|
val tagsNbtList = nbt.getList("Tags", 8)
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
package com.bytedice.bde_particles
|
package com.bytedice.bde_particles
|
||||||
|
|
||||||
|
import net.minecraft.component.Component
|
||||||
|
import net.minecraft.component.ComponentType
|
||||||
import net.minecraft.entity.EntityType
|
import net.minecraft.entity.EntityType
|
||||||
import net.minecraft.entity.decoration.DisplayEntity.BlockDisplayEntity
|
import net.minecraft.entity.decoration.DisplayEntity.ItemDisplayEntity
|
||||||
|
import net.minecraft.item.Item
|
||||||
import net.minecraft.nbt.NbtCompound
|
import net.minecraft.nbt.NbtCompound
|
||||||
import net.minecraft.nbt.NbtFloat
|
import net.minecraft.nbt.NbtFloat
|
||||||
import net.minecraft.nbt.NbtList
|
import net.minecraft.nbt.NbtList
|
||||||
import net.minecraft.nbt.NbtString
|
import net.minecraft.nbt.NbtString
|
||||||
|
import net.minecraft.registry.Registries
|
||||||
|
import net.minecraft.registry.Registry
|
||||||
import net.minecraft.server.world.ServerWorld
|
import net.minecraft.server.world.ServerWorld
|
||||||
|
|
||||||
class DisplayEntity(private var properties: DisplayEntityProperties?) {
|
class DisplayEntity(private var properties: DisplayEntityProperties?) {
|
||||||
private var hasSpawned = false
|
private var hasSpawned = false
|
||||||
private var entity: BlockDisplayEntity? = null
|
private var entity: ItemDisplayEntity? = null
|
||||||
|
|
||||||
fun spawn(world: ServerWorld) {
|
fun spawn(world: ServerWorld) {
|
||||||
if (hasSpawned || properties == null) { return }
|
if (hasSpawned || properties == null) { return }
|
||||||
|
|
||||||
entity = BlockDisplayEntity(EntityType.BLOCK_DISPLAY, world)
|
entity = ItemDisplayEntity(EntityType.ITEM_DISPLAY, world)
|
||||||
updateProperties(properties!!)
|
updateProperties(properties!!)
|
||||||
|
|
||||||
world.spawnEntity(entity)
|
world.spawnEntity(entity)
|
||||||
@@ -25,6 +30,21 @@ class DisplayEntity(private var properties: DisplayEntityProperties?) {
|
|||||||
|
|
||||||
|
|
||||||
fun updateProperties(properties: DisplayEntityProperties) {
|
fun updateProperties(properties: DisplayEntityProperties) {
|
||||||
|
val customModelRegex = "^([^/]+)(?:/([0-9]+))?$".toRegex()
|
||||||
|
val matchResult = customModelRegex.find(properties.model)
|
||||||
|
|
||||||
|
val modelName: String
|
||||||
|
val customModelNum: Int
|
||||||
|
|
||||||
|
if (matchResult != null) {
|
||||||
|
modelName = matchResult.groupValues[1]
|
||||||
|
customModelNum = matchResult.groupValues[2].toInt()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
modelName = properties.model
|
||||||
|
customModelNum = 0
|
||||||
|
}
|
||||||
|
|
||||||
val nbt = NbtCompound().apply {
|
val nbt = NbtCompound().apply {
|
||||||
val tagList = NbtList()
|
val tagList = NbtList()
|
||||||
|
|
||||||
@@ -34,7 +54,11 @@ class DisplayEntity(private var properties: DisplayEntityProperties?) {
|
|||||||
|
|
||||||
put("Tags", tagList)
|
put("Tags", tagList)
|
||||||
|
|
||||||
put("block_state", NbtCompound().apply { putString("Name", properties.blockType) })
|
put("item", NbtCompound().apply {
|
||||||
|
putString("id", modelName)
|
||||||
|
putInt("count", 1)
|
||||||
|
put("components", NbtCompound().apply { putInt("minecraft:custom_model_data", customModelNum) })
|
||||||
|
})
|
||||||
|
|
||||||
put("transformation", NbtCompound().apply {
|
put("transformation", NbtCompound().apply {
|
||||||
val offsetList = NbtList().apply {
|
val offsetList = NbtList().apply {
|
||||||
@@ -65,6 +89,9 @@ class DisplayEntity(private var properties: DisplayEntityProperties?) {
|
|||||||
put("scale", scaleList)
|
put("scale", scaleList)
|
||||||
put("right_rotation", rightRotList)
|
put("right_rotation", rightRotList)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
put("view_range", NbtCompound().apply { properties.viewRange })
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entity?.readNbt(nbt)
|
entity?.readNbt(nbt)
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ data class DisplayEntityProperties (
|
|||||||
val pos: Vec3d = Vec3d(0.0, 0.0, 0.0),
|
val pos: Vec3d = Vec3d(0.0, 0.0, 0.0),
|
||||||
val rot: Vector2f = Vector2f(0.0f, 0.0f),
|
val rot: Vector2f = Vector2f(0.0f, 0.0f),
|
||||||
|
|
||||||
val blockType: String = "minecraft:purple_concrete",
|
val model: String = "minecraft:purple_concrete", // end with "/{num}" for custom model
|
||||||
val tags: Array<String> = emptyArray(),
|
val tags: Array<String> = emptyArray(),
|
||||||
|
|
||||||
val translation: Vector3f = Vector3f(-0.5f, -0.5f, -0.5f),
|
val translation: Vector3f = Vector3f(-0.5f, -0.5f, -0.5f),
|
||||||
val leftRotation: Vector4f = Vector4f(0.0f, 0.0f, 0.0f, 1.0f),
|
val leftRotation: Vector4f = Vector4f(0.0f, 0.0f, 0.0f, 1.0f),
|
||||||
val scale: Vector3f = Vector3f(1.0f, 1.0f, 1.0f),
|
val scale: Vector3f = Vector3f(1.0f, 1.0f, 1.0f),
|
||||||
val rightRotation: Vector4f = Vector4f(0.0f, 0.0f, 0.0f, 1.0f)
|
val rightRotation: Vector4f = Vector4f(0.0f, 0.0f, 0.0f, 1.0f),
|
||||||
|
|
||||||
|
val viewRange: Float = 2.0f
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ data class EmitterParams (
|
|||||||
var offsetCurve: ParamClasses.LerpVal,
|
var offsetCurve: ParamClasses.LerpVal,
|
||||||
var rotVelCurve: ParamClasses.LerpVal,
|
var rotVelCurve: ParamClasses.LerpVal,
|
||||||
var scaleCurve: ParamClasses.LerpVal,
|
var scaleCurve: ParamClasses.LerpVal,
|
||||||
var blockCurve: Pair<Array<String>, LerpCurves>,
|
var modelCurve: Pair<Array<String>, LerpCurves>,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
companion object Presets {
|
companion object Presets {
|
||||||
@@ -42,7 +42,7 @@ data class EmitterParams (
|
|||||||
spawnPosOffset = Vector3f(0.0f, 0.0f, 0.0f),
|
spawnPosOffset = Vector3f(0.0f, 0.0f, 0.0f),
|
||||||
lifeTime = ParamClasses.PairInt(25, 40),
|
lifeTime = ParamClasses.PairInt(25, 40),
|
||||||
shape = SpawningShape.Sphere(1.0f, true),
|
shape = SpawningShape.Sphere(1.0f, true),
|
||||||
offset = ParamClasses.PairVec3f.Uniform(-0.5f, -0.5f),
|
offset = ParamClasses.PairVec3f.Uniform(0.0f, 0.0f),
|
||||||
initRot = ParamClasses.PairVec3f.NonUniform(0.0f, 0.0f, 0.0f, 360.0f, 360.0f, 360.0f),
|
initRot = ParamClasses.PairVec3f.NonUniform(0.0f, 0.0f, 0.0f, 360.0f, 360.0f, 360.0f),
|
||||||
rotVel = ParamClasses.PairVec3f.NonUniform(-0.2f, -0.2f, -0.2f, 0.2f, 0.2f, 0.2f),
|
rotVel = ParamClasses.PairVec3f.NonUniform(-0.2f, -0.2f, -0.2f, 0.2f, 0.2f, 0.2f),
|
||||||
initVel = ParamClasses.PairVec3f.Null,
|
initVel = ParamClasses.PairVec3f.Null,
|
||||||
@@ -56,8 +56,8 @@ data class EmitterParams (
|
|||||||
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
offsetCurve = ParamClasses.LerpVal.NoLerpVec3f,
|
||||||
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt),
|
rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt),
|
||||||
scaleCurve = ParamClasses.LerpVal.LerpUniform(0.0f, 2.0f, LerpCurves.Linear),
|
scaleCurve = ParamClasses.LerpVal.LerpUniform(0.0f, 2.0f, LerpCurves.Linear),
|
||||||
blockCurve = Pair(
|
modelCurve = Pair(
|
||||||
arrayOf("shroomlight", "orange_concrete", "orange_stained_glass", "gray_wool", "gray_stained_glass", "light_gray_stained_glass"),
|
arrayOf("shroomlight", "orange_concrete", "orange_stained_glass", "gray_wool", "gray_stained_glass", "light_gray_stained_glass", "light_gray_stained_glass_pane"),
|
||||||
LerpCurves.Sqrt
|
LerpCurves.Sqrt
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,9 +16,13 @@ scaleWithVel: Boolean (NEW)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
class Particle(private val emitterParams: EmitterParams, private var entityPos: Vec3d, private val entityRot: Vector2f) {
|
class Particle(
|
||||||
|
private val emitterParams: EmitterParams,
|
||||||
|
private var entityPos: Vec3d,
|
||||||
|
private val entityRot: Vector2f,
|
||||||
|
private var debug: Boolean
|
||||||
|
) {
|
||||||
private var pos = Vector3f(0.0f, 0.0f, 0.0f)
|
private var pos = Vector3f(0.0f, 0.0f, 0.0f)
|
||||||
private var blockDisplay: DisplayEntity = DisplayEntity(DisplayEntityProperties())
|
|
||||||
private var timeAlive = 0
|
private var timeAlive = 0
|
||||||
private var isInit = false
|
private var isInit = false
|
||||||
var isDead = false
|
var isDead = false
|
||||||
@@ -56,6 +60,9 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
|
|||||||
|
|
||||||
private var lifeTime = emitterParams.lifeTime.randomize()
|
private var lifeTime = emitterParams.lifeTime.randomize()
|
||||||
|
|
||||||
|
private lateinit var particleEntity: DisplayEntity
|
||||||
|
private lateinit var debugOriginEntity: DisplayEntity
|
||||||
|
private lateinit var debugVelEntity: DisplayEntity
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
val so = emitterParams.spawnPosOffset
|
val so = emitterParams.spawnPosOffset
|
||||||
@@ -76,14 +83,14 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
|
|||||||
val properties = DisplayEntityProperties(
|
val properties = DisplayEntityProperties(
|
||||||
pos = entityPos,
|
pos = entityPos,
|
||||||
rot = entityRot,
|
rot = entityRot,
|
||||||
blockType = lerpArray(emitterParams.blockCurve.first as Array<Any>, 0.0f, emitterParams.blockCurve.second) as String,
|
model = lerpArray(emitterParams.modelCurve.first as Array<Any>, 0.0f, emitterParams.modelCurve.second) as String,
|
||||||
translation = newPos.add(pos),
|
translation = newPos.add(pos),
|
||||||
leftRotation = quatRot,
|
leftRotation = quatRot,
|
||||||
scale = scale,
|
scale = scale,
|
||||||
tags = arrayOf("BPS_Particle", "BPS_UUID", SESSION_UUID.toString())
|
tags = arrayOf("BPS_Particle", "BPS_UUID", SESSION_UUID.toString())
|
||||||
)
|
)
|
||||||
|
|
||||||
blockDisplay = DisplayEntity(properties)
|
particleEntity = DisplayEntity(properties)
|
||||||
|
|
||||||
isInit = true
|
isInit = true
|
||||||
}
|
}
|
||||||
@@ -91,7 +98,7 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
|
|||||||
|
|
||||||
fun spawn(world: ServerWorld) {
|
fun spawn(world: ServerWorld) {
|
||||||
if (isInit) {
|
if (isInit) {
|
||||||
blockDisplay.spawn(world)
|
particleEntity.spawn(world)
|
||||||
LIVING_PARTICLE_COUNT += 1
|
LIVING_PARTICLE_COUNT += 1
|
||||||
}
|
}
|
||||||
else { error("Particle is not initialized before being spawned. Please use Particle.init() to initialize it.") }
|
else { error("Particle is not initialized before being spawned. Please use Particle.init() to initialize it.") }
|
||||||
@@ -103,7 +110,7 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
|
|||||||
|
|
||||||
val newProperties = calcNewProperties()
|
val newProperties = calcNewProperties()
|
||||||
|
|
||||||
blockDisplay.updateProperties(newProperties)
|
particleEntity.updateProperties(newProperties)
|
||||||
|
|
||||||
if (timeAlive > lifeTime) { kill() }
|
if (timeAlive > lifeTime) { kill() }
|
||||||
|
|
||||||
@@ -127,7 +134,7 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
|
|||||||
private fun calcNewProperties() : DisplayEntityProperties {
|
private fun calcNewProperties() : DisplayEntityProperties {
|
||||||
val timeAliveClamped = (timeAlive.toFloat() / lifeTime.toFloat()).coerceIn(0.0f, 1.0f)
|
val timeAliveClamped = (timeAlive.toFloat() / lifeTime.toFloat()).coerceIn(0.0f, 1.0f)
|
||||||
|
|
||||||
val newBlock = lerpArray(emitterParams.blockCurve.first as Array<Any>, timeAliveClamped, emitterParams.blockCurve.second) as String
|
val newModel = lerpArray(emitterParams.modelCurve.first as Array<Any>, timeAliveClamped, emitterParams.modelCurve.second) as String
|
||||||
val (newVel, newPos) = calcPos()
|
val (newVel, newPos) = calcPos()
|
||||||
val newRot = calcRot(timeAliveClamped)
|
val newRot = calcRot(timeAliveClamped)
|
||||||
val newScale = calcScale(timeAliveClamped)
|
val newScale = calcScale(timeAliveClamped)
|
||||||
@@ -147,7 +154,7 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
|
|||||||
|
|
||||||
val newProperties = DisplayEntityProperties(
|
val newProperties = DisplayEntityProperties(
|
||||||
pos = entityPos,
|
pos = entityPos,
|
||||||
blockType = newBlock,
|
model = newModel,
|
||||||
translation = combinedOffset.add(newOriginOffset),
|
translation = combinedOffset.add(newOriginOffset),
|
||||||
leftRotation = quatRot,
|
leftRotation = quatRot,
|
||||||
scale = newScale,
|
scale = newScale,
|
||||||
@@ -223,9 +230,28 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun spawnDebug() {
|
||||||
|
// spawn cube at particle origin
|
||||||
|
// show arrow pointing toward particle direction
|
||||||
|
// name-tag its data
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun updateDebug() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun calcDebug() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun kill() {
|
fun kill() {
|
||||||
if (!isDead) {
|
if (!isDead) {
|
||||||
blockDisplay.kill()
|
particleEntity.kill()
|
||||||
LIVING_PARTICLE_COUNT -= 1
|
LIVING_PARTICLE_COUNT -= 1
|
||||||
isDead = true
|
isDead = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ class ParticleEmitter(private val pos: Vec3d, private val rot: Vector2f, private
|
|||||||
val randomSpawnChance = randomFloatBetween(0.0f, params.spawnChance.coerceIn(0.0f, 1.0f))
|
val randomSpawnChance = randomFloatBetween(0.0f, params.spawnChance.coerceIn(0.0f, 1.0f))
|
||||||
if (randomSpawnChance > params.spawnChance) { return }
|
if (randomSpawnChance > params.spawnChance) { return }
|
||||||
|
|
||||||
val particle = Particle(params, pos, rot)
|
val debug = world.gameRules.getBoolean(Bde_particles.SHOW_PARTICLE_DEBUG)
|
||||||
|
val particle = Particle(params, pos, rot, debug)
|
||||||
particle.init()
|
particle.init()
|
||||||
particle.spawn(world)
|
particle.spawn(world)
|
||||||
|
|
||||||
|
|||||||
@@ -13,17 +13,17 @@ fun addToRegister(id: String, params: EmitterParams) : Pair<String, Boolean> {
|
|||||||
return Pair(newId, false)
|
return Pair(newId, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val newBlocks: MutableList<String> = mutableListOf()
|
val newModels: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
for (block in params.blockCurve.first) {
|
for (model in params.modelCurve.first) {
|
||||||
val blockModIdRegex = ".*:".toRegex()
|
val modelModIdRegex = ".*:".toRegex()
|
||||||
if (blockModIdRegex.containsMatchIn(block)) { break }
|
if (modelModIdRegex.containsMatchIn(model)) { break }
|
||||||
else {
|
else {
|
||||||
newBlocks.add("minecraft:$block")
|
newModels.add("minecraft:$model")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
params.blockCurve = Pair(newBlocks.toTypedArray(), params.blockCurve.second)
|
params.modelCurve = Pair(newModels.toTypedArray(), params.modelCurve.second)
|
||||||
|
|
||||||
idRegister[id] = params
|
idRegister[id] = params
|
||||||
println("BPS - Registered Emitter ID \"$newId\".")
|
println("BPS - Registered Emitter ID \"$newId\".")
|
||||||
|
|||||||
Reference in New Issue
Block a user