From 828297aef2d79f2ae9d11990a636b2ab677eba31 Mon Sep 17 00:00:00 2001 From: Byte Dice Date: Sat, 30 Nov 2024 17:22:20 +0100 Subject: [PATCH] moved to ItemDisplays and added support for CustomModelData --- .../bytedice/bde_particles/Bde_particles.kt | 18 +++++--- .../bytedice/bde_particles/DisplayEntity.kt | 35 +++++++++++++-- .../bde_particles/DisplayEntityProperties.kt | 6 ++- .../bde_particles/particles/EmitterParams.kt | 8 ++-- .../bde_particles/particles/Particle.kt | 44 +++++++++++++++---- .../particles/ParticleEmitter.kt | 3 +- .../particles/ParticleIdRegister.kt | 12 ++--- 7 files changed, 93 insertions(+), 33 deletions(-) diff --git a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt index 3bf4fd3..0d8dd59 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/Bde_particles.kt @@ -18,7 +18,7 @@ import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry import net.fabricmc.loader.api.FabricLoader 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.item.ItemStack import net.minecraft.nbt.NbtCompound @@ -38,7 +38,6 @@ import java.util.* // Allowing the use of regular Minecraft particles instead of just BDEs. // Better command auto-completion. (and change names of args) // force field "config" option - // blockCurve array not needing "minecraft:" // Parameters // rotWithVel / scaleWithVel (bool) @@ -70,6 +69,11 @@ class Bde_particles : ModInitializer { GameRules.Category.UPDATES, GameRuleFactory.createIntRule(3000, 0) ) + val SHOW_PARTICLE_DEBUG: GameRules.Key = GameRuleRegistry.register( + "ShowParticleDebug", + GameRules.Category.UPDATES, + GameRuleFactory.createBooleanRule(false) + ) } override fun onInitialize() { @@ -122,10 +126,10 @@ fun tick(server: MinecraftServer) { runBlocking { server.worlds.map { world -> async { - val blockDisplayEntities = world.iterateEntities() - .filter { it.type == EntityType.BLOCK_DISPLAY } - for (entity in blockDisplayEntities) { - if (displayEntityContainsTag(entity as BlockDisplayEntity, "BPS_UUID") + val displayEntities = world.iterateEntities() + .filter { it.type == EntityType.ITEM_DISPLAY } + for (entity in displayEntities) { + if (displayEntityContainsTag(entity as ItemDisplayEntity, "BPS_UUID") && !displayEntityContainsTag(entity, SESSION_UUID.toString())) { entity.kill() @@ -185,7 +189,7 @@ fun emitterParamsToJson(params: EmitterParams) : Map { // TODO: map */ -fun displayEntityContainsTag(entity: BlockDisplayEntity, tag: String) : Boolean { +fun displayEntityContainsTag(entity: ItemDisplayEntity, tag: String) : Boolean { val nbt = NbtCompound() entity.writeNbt(nbt) val tagsNbtList = nbt.getList("Tags", 8) diff --git a/src/main/kotlin/com/bytedice/bde_particles/DisplayEntity.kt b/src/main/kotlin/com/bytedice/bde_particles/DisplayEntity.kt index 315919b..554d721 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/DisplayEntity.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/DisplayEntity.kt @@ -1,21 +1,26 @@ package com.bytedice.bde_particles +import net.minecraft.component.Component +import net.minecraft.component.ComponentType 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.NbtFloat import net.minecraft.nbt.NbtList import net.minecraft.nbt.NbtString +import net.minecraft.registry.Registries +import net.minecraft.registry.Registry import net.minecraft.server.world.ServerWorld class DisplayEntity(private var properties: DisplayEntityProperties?) { private var hasSpawned = false - private var entity: BlockDisplayEntity? = null + private var entity: ItemDisplayEntity? = null fun spawn(world: ServerWorld) { if (hasSpawned || properties == null) { return } - entity = BlockDisplayEntity(EntityType.BLOCK_DISPLAY, world) + entity = ItemDisplayEntity(EntityType.ITEM_DISPLAY, world) updateProperties(properties!!) world.spawnEntity(entity) @@ -25,6 +30,21 @@ class DisplayEntity(private var 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 tagList = NbtList() @@ -34,7 +54,11 @@ class DisplayEntity(private var properties: DisplayEntityProperties?) { 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 { val offsetList = NbtList().apply { @@ -65,6 +89,9 @@ class DisplayEntity(private var properties: DisplayEntityProperties?) { put("scale", scaleList) put("right_rotation", rightRotList) }) + + put("view_range", NbtCompound().apply { properties.viewRange }) + } entity?.readNbt(nbt) diff --git a/src/main/kotlin/com/bytedice/bde_particles/DisplayEntityProperties.kt b/src/main/kotlin/com/bytedice/bde_particles/DisplayEntityProperties.kt index 857dd20..afd7782 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/DisplayEntityProperties.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/DisplayEntityProperties.kt @@ -9,11 +9,13 @@ data class DisplayEntityProperties ( val pos: Vec3d = Vec3d(0.0, 0.0, 0.0), 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 = emptyArray(), val translation: Vector3f = Vector3f(-0.5f, -0.5f, -0.5f), val leftRotation: Vector4f = Vector4f(0.0f, 0.0f, 0.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 ) diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt index 87f5ca8..309dbd1 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/EmitterParams.kt @@ -30,7 +30,7 @@ data class EmitterParams ( var offsetCurve: ParamClasses.LerpVal, var rotVelCurve: ParamClasses.LerpVal, var scaleCurve: ParamClasses.LerpVal, - var blockCurve: Pair, LerpCurves>, + var modelCurve: Pair, LerpCurves>, ) { companion object Presets { @@ -42,7 +42,7 @@ data class EmitterParams ( spawnPosOffset = Vector3f(0.0f, 0.0f, 0.0f), lifeTime = ParamClasses.PairInt(25, 40), 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), rotVel = ParamClasses.PairVec3f.NonUniform(-0.2f, -0.2f, -0.2f, 0.2f, 0.2f, 0.2f), initVel = ParamClasses.PairVec3f.Null, @@ -56,8 +56,8 @@ data class EmitterParams ( offsetCurve = ParamClasses.LerpVal.NoLerpVec3f, rotVelCurve = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt), scaleCurve = ParamClasses.LerpVal.LerpUniform(0.0f, 2.0f, LerpCurves.Linear), - blockCurve = Pair( - arrayOf("shroomlight", "orange_concrete", "orange_stained_glass", "gray_wool", "gray_stained_glass", "light_gray_stained_glass"), + modelCurve = Pair( + arrayOf("shroomlight", "orange_concrete", "orange_stained_glass", "gray_wool", "gray_stained_glass", "light_gray_stained_glass", "light_gray_stained_glass_pane"), LerpCurves.Sqrt ), ) diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt index cfe3cf1..e35061e 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/Particle.kt @@ -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 blockDisplay: DisplayEntity = DisplayEntity(DisplayEntityProperties()) private var timeAlive = 0 private var isInit = false var isDead = false @@ -56,6 +60,9 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos: private var lifeTime = emitterParams.lifeTime.randomize() + private lateinit var particleEntity: DisplayEntity + private lateinit var debugOriginEntity: DisplayEntity + private lateinit var debugVelEntity: DisplayEntity fun init() { val so = emitterParams.spawnPosOffset @@ -76,14 +83,14 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos: val properties = DisplayEntityProperties( pos = entityPos, rot = entityRot, - blockType = lerpArray(emitterParams.blockCurve.first as Array, 0.0f, emitterParams.blockCurve.second) as String, + model = lerpArray(emitterParams.modelCurve.first as Array, 0.0f, emitterParams.modelCurve.second) as String, translation = newPos.add(pos), leftRotation = quatRot, scale = scale, tags = arrayOf("BPS_Particle", "BPS_UUID", SESSION_UUID.toString()) ) - blockDisplay = DisplayEntity(properties) + particleEntity = DisplayEntity(properties) isInit = true } @@ -91,7 +98,7 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos: fun spawn(world: ServerWorld) { if (isInit) { - blockDisplay.spawn(world) + particleEntity.spawn(world) LIVING_PARTICLE_COUNT += 1 } 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() - blockDisplay.updateProperties(newProperties) + particleEntity.updateProperties(newProperties) if (timeAlive > lifeTime) { kill() } @@ -127,7 +134,7 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos: private fun calcNewProperties() : DisplayEntityProperties { val timeAliveClamped = (timeAlive.toFloat() / lifeTime.toFloat()).coerceIn(0.0f, 1.0f) - val newBlock = lerpArray(emitterParams.blockCurve.first as Array, timeAliveClamped, emitterParams.blockCurve.second) as String + val newModel = lerpArray(emitterParams.modelCurve.first as Array, timeAliveClamped, emitterParams.modelCurve.second) as String val (newVel, newPos) = calcPos() val newRot = calcRot(timeAliveClamped) val newScale = calcScale(timeAliveClamped) @@ -147,7 +154,7 @@ class Particle(private val emitterParams: EmitterParams, private var entityPos: val newProperties = DisplayEntityProperties( pos = entityPos, - blockType = newBlock, + model = newModel, translation = combinedOffset.add(newOriginOffset), leftRotation = quatRot, 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() { if (!isDead) { - blockDisplay.kill() + particleEntity.kill() LIVING_PARTICLE_COUNT -= 1 isDead = true } diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt index c066e1e..8ecb522 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleEmitter.kt @@ -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)) 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.spawn(world) diff --git a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt index 0fad576..b56fc3c 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particles/ParticleIdRegister.kt @@ -13,17 +13,17 @@ fun addToRegister(id: String, params: EmitterParams) : Pair { return Pair(newId, false) } - val newBlocks: MutableList = mutableListOf() + val newModels: MutableList = mutableListOf() - for (block in params.blockCurve.first) { - val blockModIdRegex = ".*:".toRegex() - if (blockModIdRegex.containsMatchIn(block)) { break } + for (model in params.modelCurve.first) { + val modelModIdRegex = ".*:".toRegex() + if (modelModIdRegex.containsMatchIn(model)) { break } 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 println("BPS - Registered Emitter ID \"$newId\".")