package com.mythlane.chainlightning.sceptre; import com.hypixel.hytale.component.CommandBuffer; import com.hypixel.hytale.component.ComponentAccessor; import com.hypixel.hytale.component.Ref; import com.hypixel.hytale.server.core.asset.type.entityeffect.config.EntityEffect; import com.hypixel.hytale.server.core.entity.effect.EffectControllerComponent; import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; import com.mythlane.chainlightning.chain.ChainHit; import javax.annotation.Nonnull; import java.util.List; import java.util.logging.Logger; /** Applies a custom EntityEffect to each chain target so the visual replicates via ECS sync. */ public final class HytaleVfxEmitter { private static final Logger LOGGER = Logger.getLogger(HytaleVfxEmitter.class.getName()); private static final String EFFECT_ID = "Chain_Hit_Effect"; private HytaleVfxEmitter() {} /** Resolves the EntityEffect once and adds it to every valid target via EffectControllerComponent. */ public static void playChainEffects(@Nonnull List hits, @Nonnull Ref playerRef, @Nonnull CommandBuffer commandBuffer) { if (hits.isEmpty()) return; EntityEffect entityEffect = EntityEffect.getAssetMap().getAsset(EFFECT_ID); if (entityEffect == null) { LOGGER.warning(String.format( "[ChainLightning][Vfx] EntityEffect '%s' not registered -- VFX skipped (damage already applied)", EFFECT_ID)); return; } ComponentAccessor accessor = commandBuffer; int applied = 0; for (ChainHit hit : hits) { Ref targetRef = HytaleEntityAdapter.from(hit).ref(); if (!targetRef.isValid()) continue; EffectControllerComponent ecc = accessor.getComponent(targetRef, EffectControllerComponent.getComponentType()); if (ecc != null && ecc.addEffect(targetRef, entityEffect, accessor)) { applied++; } } LOGGER.info(String.format( "[ChainLightning][Vfx] EntityEffect '%s' applied to %d/%d targets (caster=%s)", EFFECT_ID, applied, hits.size(), playerRef)); } }