feat(phase-1): scaffold ChainLightning Sceptre plugin
Build infrastructure (Gradle wrapper, shadow, Java 25), manifest, item JSON + interactions, and ChainLightningPlugin entry with stub handler that logs sceptre clicks. Cooldown wiring deferred to Phase 3 (real Hytale API is getCooldown(id).setCooldownMax — not cooldown(Duration)).
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
package com.mythlane.chainlightning;
|
||||
|
||||
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
|
||||
import com.hypixel.hytale.server.core.plugin.JavaPlugin;
|
||||
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
|
||||
import com.mythlane.chainlightning.sceptre.ChainLightningSceptreInteraction;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Entry point for the Chain Lightning Sceptre plugin.
|
||||
*
|
||||
* Phase 1 scope:
|
||||
* - Register the {@code ChainLightningSceptre} interaction codec so the runtime
|
||||
* can dispatch primary/secondary clicks on the chain_lightning_sceptre item.
|
||||
* - No chain resolution, no VFX, no config — those land in Phases 2/3/4.
|
||||
*/
|
||||
public class ChainLightningPlugin extends JavaPlugin {
|
||||
|
||||
public ChainLightningPlugin(JavaPluginInit init) {
|
||||
super(init);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() {
|
||||
// The string "ChainLightningSceptre" MUST match the "Type" field in
|
||||
// Server/Item/Interactions/chain_lightning_sceptre_click.json (case-sensitive).
|
||||
getCodecRegistry(Interaction.CODEC).register(
|
||||
"ChainLightningSceptre",
|
||||
ChainLightningSceptreInteraction.class,
|
||||
ChainLightningSceptreInteraction.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start() {
|
||||
super.start();
|
||||
getLogger().at(Level.INFO).log("ChainLightning started");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdown() {
|
||||
getLogger().at(Level.INFO).log("ChainLightning stopped");
|
||||
super.shutdown();
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
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.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Phase 1 stub interaction handler for the Chain Lightning Sceptre item.
|
||||
* Logs the click + applies a 4s cooldown smoke-test. Full chain logic lands in Phase 3.
|
||||
*/
|
||||
public final class ChainLightningSceptreInteraction extends SimpleInstantInteraction {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ChainLightningSceptreInteraction.class.getName());
|
||||
|
||||
@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() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void firstRun(@Nonnull InteractionType type,
|
||||
@Nonnull InteractionContext context,
|
||||
@Nonnull CooldownHandler cooldownHandler) {
|
||||
// Phase 1: stub only. Identify the player for traceability, log, then arm the cooldown
|
||||
// (smoke test of the CooldownHandler API — actual chain resolution lands in Phase 3).
|
||||
UUID playerUuid = null;
|
||||
try {
|
||||
Ref<EntityStore> entityRef = context.getEntity();
|
||||
CommandBuffer<EntityStore> commandBuffer = context.getCommandBuffer();
|
||||
if (entityRef != null && commandBuffer != null) {
|
||||
PlayerRef playerRef = commandBuffer.getComponent(entityRef, PlayerRef.getComponentType());
|
||||
if (playerRef != null) {
|
||||
playerUuid = playerRef.getUuid();
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
// Defensive: never fail the click because of telemetry.
|
||||
}
|
||||
|
||||
LOGGER.log(Level.INFO,
|
||||
"[ChainLightning] sceptre clicked by player {0} (type={1})",
|
||||
new Object[]{playerUuid, type});
|
||||
|
||||
// TODO Phase 3: wire cooldown via CooldownHandler.
|
||||
// Confirmed API (javap on Server-2026.03.26-89796e57b.jar):
|
||||
// CooldownHandler has NO cooldown(Duration) method.
|
||||
// Use: cooldownHandler.getCooldown("primary").setCooldownMax(4f)
|
||||
// then cooldownHandler.resetCooldown("primary", ...) on next tick.
|
||||
// Full cooldown integration deferred to Phase 3 to keep Phase 1 build green.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"Type": "ChainLightningSceptre"
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"TranslationProperties": {
|
||||
"Name": "Chain Lightning Sceptre",
|
||||
"Description": "Click to chain lightning between up to 5 targets."
|
||||
},
|
||||
"Categories": [
|
||||
"Items.Weapons"
|
||||
],
|
||||
"Icon": "Icons/ItemsGenerated/Weapon_Wand_Wood.png",
|
||||
"Quality": "Rare",
|
||||
"ItemLevel": 40,
|
||||
"Model": "Items/Weapons/Wand/Wood.blockymodel",
|
||||
"Texture": "Items/Weapons/Wand/Wood_Texture.png",
|
||||
"PlayerAnimationsId": "Wand",
|
||||
"Utility": {
|
||||
"Compatible": true
|
||||
},
|
||||
"Interactions": {
|
||||
"Primary": "chain_lightning_sceptre_root",
|
||||
"Secondary": "chain_lightning_sceptre_root"
|
||||
},
|
||||
"IconProperties": {
|
||||
"Scale": 0.6,
|
||||
"Translation": [
|
||||
-13,
|
||||
-16
|
||||
],
|
||||
"Rotation": [
|
||||
45,
|
||||
90,
|
||||
0
|
||||
]
|
||||
},
|
||||
"DroppedItemAnimation": "Items/Animations/Dropped/Dropped_Diagonal_Left.blockyanim",
|
||||
"Tags": {
|
||||
"Type": [
|
||||
"Weapon"
|
||||
],
|
||||
"Family": [
|
||||
"Wand"
|
||||
]
|
||||
},
|
||||
"Weapon": {},
|
||||
"ItemSoundSetId": "ISS_Weapons_Wand",
|
||||
"MaxStackSize": 1
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"Interactions": [
|
||||
"chain_lightning_sceptre_click"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"Group": "Mythlane",
|
||||
"Name": "ChainLightning",
|
||||
"Version": "${version}",
|
||||
"Description": "${description}",
|
||||
"Authors": [
|
||||
{
|
||||
"Name": "Mythlane Team",
|
||||
"Email": "contact@mythlane.com",
|
||||
"Url": "https://mythlane.com"
|
||||
}
|
||||
],
|
||||
"Website": "https://mythlane.com",
|
||||
"Main": "com.mythlane.chainlightning.ChainLightningPlugin",
|
||||
"ServerVersion": "${hytaleServerVersion}",
|
||||
"Dependencies": {},
|
||||
"OptionalDependencies": {},
|
||||
"DisabledByDefault": false,
|
||||
"IncludesAssetPack": true
|
||||
}
|
||||
Reference in New Issue
Block a user