Ejemplo: Custom Interaction¶
Ejemplo de cómo crear una interacción personalizada.
Interacción Teleport¶
package com.ejemplo.interactions;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.protocol.InteractionState;
import com.hypixel.hytale.protocol.InteractionType;
import com.hypixel.hytale.server.core.entity.InteractionContext;
import com.hypixel.hytale.server.core.entity.LivingEntity;
import com.hypixel.hytale.server.core.modules.interaction.interaction.CooldownHandler;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.SimpleInstantInteraction;
import javax.annotation.Nonnull;
/**
* Interacción que teletransporta al jugador 5 bloques hacia adelante.
*/
public class TeleportInteraction extends SimpleInstantInteraction {
private final double teleportDistance = 5.0;
public TeleportInteraction() {
super();
this.id = "custom:teleport";
this.runTime = 0.5f; // 0.5 segundos de cooldown
}
@Override
protected void firstRun(@Nonnull InteractionType type,
@Nonnull InteractionContext context,
@Nonnull CooldownHandler cooldownHandler) {
// Obtener entidad
LivingEntity entity = getEntity(context);
if (entity == null) {
failInteraction(context);
return;
}
// Calcular nueva posición
Vector3d currentPos = entity.getPosition();
Vector3d lookDir = entity.getLookDirection();
Vector3d newPos = new Vector3d(
currentPos.x + lookDir.x * teleportDistance,
currentPos.y,
currentPos.z + lookDir.z * teleportDistance
);
// Teletransportar
entity.setPosition(newPos);
// Mensaje
entity.sendMessage("¡Teletransportado!");
// Completar interacción
context.getState().state = InteractionState.Finished;
}
private LivingEntity getEntity(InteractionContext ctx) {
var ref = ctx.getEntity();
if (ref == null || !ref.isValid()) return null;
var buffer = ctx.getCommandBuffer();
if (buffer == null) return null;
var entity = buffer.getEntity(ref);
return entity instanceof LivingEntity ? (LivingEntity) entity : null;
}
private void failInteraction(InteractionContext ctx) {
ctx.getState().state = InteractionState.Failed;
}
}
Interacción con Metadatos¶
public class CounterInteraction extends SimpleInstantInteraction {
// MetaKey para contador
private static final MetaKey<Integer> USE_COUNT =
Interaction.META_REGISTRY.registerMetaObject(i -> 0);
@Override
protected void firstRun(InteractionType type,
InteractionContext context,
CooldownHandler cooldownHandler) {
// Incrementar contador
int count = context.getMetaObject(USE_COUNT);
context.putMetaObject(USE_COUNT, count + 1);
// Obtener entidad
LivingEntity entity = getEntity(context);
if (entity != null) {
entity.sendMessage("Usos: " + (count + 1));
}
context.getState().state = InteractionState.Finished;
}
}
Interacción con Target¶
public class HighlightEntityInteraction extends SimpleInstantInteraction {
@Override
protected void firstRun(InteractionType type,
InteractionContext context,
CooldownHandler cooldownHandler) {
// Obtener entidad objetivo
Ref<EntityStore> targetRef =
context.getMetaObject(Interaction.TARGET_ENTITY);
if (targetRef == null || !targetRef.isValid()) {
context.getState().state = InteractionState.Failed;
return;
}
// Obtener ubicación del impacto
Vector4d hitLocation =
context.getMetaObject(Interaction.HIT_LOCATION);
// Procesar
CommandBuffer<EntityStore> buffer = context.getCommandBuffer();
Entity target = buffer.getEntity(targetRef);
// Aplicar efecto de highlight
applyHighlight(target, hitLocation);
context.getState().state = InteractionState.Finished;
}
private void applyHighlight(Entity entity, Vector4d hitPos) {
// Lógica para destacar la entidad
System.out.println("Destacando: " + entity + " en " + hitPos);
}
}
Interacción Progresiva¶
public class ChargingBlastInteraction extends Interaction {
private float chargeTime = 2.0f; // 2 segundos para carga completa
@Override
protected void tick0(boolean firstRun, float time,
InteractionType type,
InteractionContext context,
CooldownHandler cooldownHandler) {
float progress = Math.min(time / chargeTime, 1.0f);
// Actualizar efectos según progreso
updateChargeEffects(context, progress);
if (time >= chargeTime) {
// Carga completa - disparar
fireBlast(context, progress);
context.getState().state = InteractionState.Finished;
} else {
// Aún cargando
context.getState().state = InteractionState.NotFinished;
context.getState().progress = time;
}
}
@Override
protected void simulateTick0(boolean firstRun, float time,
InteractionType type,
InteractionContext context,
CooldownHandler cooldownHandler) {
// Misma lógica para predicción cliente
tick0(firstRun, time, type, context, cooldownHandler);
}
@Override
public boolean walk(Collector collector, InteractionContext context) {
return true;
}
private void updateChargeEffects(InteractionContext ctx, float progress) {
// Actualizar partículas, sonido, etc.
}
private void fireBlast(InteractionContext ctx, float power) {
// Disparar proyectil
}
}
Registrar Interacción¶
// En tu plugin o mod
public class MyPlugin {
public static void registerInteractions() {
AssetStore<String, Interaction, ?> store =
Interaction.getAssetStore();
// Registrar interacciones
store.loadAssets("MyMod:MyMod", List.of(
new TeleportInteraction(),
new CounterInteraction(),
new HighlightEntityInteraction()
));
System.out.println("[MyPlugin] Interacciones registradas");
}
}
Ver También¶
- Interaction System: Documentación completa
- Simple Plugin: Plugin básico