Files
hytale-chain-lightning/src/main/java/com/mythlane/chainlightning/sceptre/ChainLightningSceptreInteraction.java
T
kayjaydee 03754a0646 refactor: drop unused VFX scaffolding, single-line English doc, reduce debug logs
- Remove unused chain/ParticleTrail and chain/VolumeCurve (dead since the EntityEffect
  pivot replaced the per-particle emit path) plus their test suites.
- Drop Vec3.lerp (only consumer was ParticleTrail).
- Strip step-by-step "[N/9]" debug logs from the orchestrator and per-entity logs
  from HytaleEntitySource / HytalePlayerRayCaster / ChainDamageApplier; keep one
  summary log per click and warnings on failure.
- Extract resolveChain and tryEmitVfx helpers in ChainLightningSceptreInteraction
  so firstRun reads top-down (cooldown gate -> resolve -> damage -> vfx -> deduct).
- Translate every Java doc/comment to single-line English.

Tests: 30/30 green (29 baseline kept + 1 chain damage adapter test).
Build: ./gradlew shadowJar clean.
2026-04-27 19:17:47 +02:00

101 lines
4.6 KiB
Java

package com.mythlane.chainlightning.sceptre;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.protocol.InteractionType;
import com.hypixel.hytale.server.core.entity.InteractionContext;
import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInstantInteraction;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.mythlane.chainlightning.chain.ChainHit;
import com.mythlane.chainlightning.chain.ChainParameters;
import com.mythlane.chainlightning.chain.ChainResolver;
import com.mythlane.chainlightning.chain.Vec3;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/** Runtime orchestrator: cooldown gate, chain resolution, damage, VFX emit, charge deduct. */
public final class ChainLightningSceptreInteraction extends SimpleInstantInteraction {
private static final Logger LOGGER = Logger.getLogger(ChainLightningSceptreInteraction.class.getName());
private static final String COOLDOWN_ID = "chain_lightning_sceptre";
private static final float COOLDOWN_TIME = 4.0f;
private static final float[] CHARGE_TIMES = { 4.0f };
private static final boolean FORCE_CREATE = true;
private static final boolean INTERRUPT_RECHARGE = false;
private static final double RAY_MAX_BLOCKS = 25.0;
@Nonnull
public static final BuilderCodec<ChainLightningSceptreInteraction> CODEC =
((BuilderCodec.Builder) BuilderCodec
.builder(ChainLightningSceptreInteraction.class,
ChainLightningSceptreInteraction::new,
SimpleInstantInteraction.CODEC)
.documentation(
"Chain Lightning sceptre: primary/secondary click chains lightning to up to 5 targets."))
.build();
public ChainLightningSceptreInteraction() {
}
/** Runs the chain pipeline once per click; silently no-ops while on cooldown. */
@Override
protected void firstRun(@Nonnull InteractionType type,
@Nonnull InteractionContext context,
@Nonnull CooldownHandler cooldownHandler) {
CooldownHandler.Cooldown cooldown = cooldownHandler.getCooldown(
COOLDOWN_ID, COOLDOWN_TIME, CHARGE_TIMES, FORCE_CREATE, INTERRUPT_RECHARGE);
if (cooldown == null || cooldown.hasCooldown(false)) {
return;
}
Ref<EntityStore> playerRef = context.getEntity();
CommandBuffer<EntityStore> commandBuffer = context.getCommandBuffer();
if (playerRef == null || commandBuffer == null) {
return;
}
try {
List<ChainHit> hits = resolveChain(playerRef, commandBuffer);
if (hits.isEmpty()) {
return;
}
ChainDamageApplier.apply(hits, playerRef, commandBuffer, commandBuffer);
tryEmitVfx(hits, playerRef, commandBuffer);
cooldown.deductCharge();
LOGGER.info(String.format("[ChainLightning] ref:%d chained %d targets",
playerRef.getIndex(), hits.size()));
} catch (Throwable t) {
LOGGER.log(Level.WARNING, "[ChainLightning] chain pipeline failed", t);
}
}
/** Builds the Hytale-bound adapters and runs the pure resolver against the live world. */
private static List<ChainHit> resolveChain(@Nonnull Ref<EntityStore> playerRef,
@Nonnull CommandBuffer<EntityStore> commandBuffer) {
HytalePlayerRayCaster ray = new HytalePlayerRayCaster(playerRef, commandBuffer);
HytaleEntitySource neighbors = new HytaleEntitySource(commandBuffer);
return ChainResolver.resolve(
Vec3.ZERO, Vec3.ZERO, RAY_MAX_BLOCKS,
ray, neighbors, ChainParameters.DEFAULT
);
}
/** VFX emit is best-effort: damage is already applied so a failure must not abort the cooldown step. */
private static void tryEmitVfx(@Nonnull List<ChainHit> hits,
@Nonnull Ref<EntityStore> playerRef,
@Nonnull CommandBuffer<EntityStore> commandBuffer) {
try {
HytaleVfxEmitter.playChainEffects(hits, playerRef, commandBuffer);
} catch (Throwable t) {
LOGGER.log(Level.WARNING, "[ChainLightning] vfx emit failed (damage already applied)", t);
}
}
}