Interaction System - Visión General¶
El Interaction System de Hytale es un sistema complejo y flexible para definir todas las interacciones que pueden ocurrir en el juego: desde destruir bloques hasta usar items, atacar entidades y más.
¿Qué es una Interaction?¶
Una Interaction es una operación que define qué sucede cuando un jugador o entidad interactúa con el mundo. Las interacciones pueden ser:
- Instantáneas (destruir un bloque)
- Progresivas (cargar un arco)
- En cadena (combo de ataques)
- Condicionales (solo si se cumple X condición)
- Paralelas (múltiples efectos simultáneos)
Arquitectura¶
graph TB
A[Interaction] -->|hereda| B[Subclases Específicas]
B --> C[SimpleInstantInteraction]
B --> D[ChargingInteraction]
B --> E[ChainingInteraction]
A -->|implementa| F[Operation]
A -->|usa| G[InteractionContext]
A -->|define| H[InteractionEffects]
A -->|registra en| I[MetaRegistry]
Clase Base: Interaction¶
Ubicación: com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction.java
public abstract class Interaction implements Operation {
// ID única de la interacción
protected String id;
// Tiempo de ejecución en segundos
protected float runTime;
// Efectos visuales y de sonido
protected InteractionEffects effects;
// Multiplicador de velocidad horizontal
protected float horizontalSpeedMultiplier = 1.0f;
// Cancelar si cambia el item
protected boolean cancelOnItemChange = true;
// Configuración por modo de juego
protected Map<GameMode, InteractionSettings> settings;
// Reglas de la interacción
protected InteractionRules rules;
// Configuración de cámara
@Nullable
protected InteractionCameraSettings camera;
// Método principal: ejecutar un tick de la interacción
protected abstract void tick0(
boolean firstRun,
float time,
InteractionType type,
InteractionContext context,
CooldownHandler cooldownHandler
);
// Versión simulada (para predicción cliente)
protected abstract void simulateTick0(...);
}
Componentes Principales¶
1. InteractionContext¶
Almacena el contexto de ejecución de una interacción.
public class InteractionContext {
// Entidad que ejecuta la interacción
Ref<EntityStore> entity;
// Item sostenido
ItemStack heldItem;
// Estado de sincronización
InteractionSyncData state;
// Cadena de interacciones
InteractionChain chain;
// CommandBuffer para modificar el mundo
CommandBuffer<EntityStore> commandBuffer;
// Meta store para datos temporales
IMetaStore instanceStore;
}
2. InteractionEffects¶
Define efectos visuales, sonoros y de animación.
public class InteractionEffects {
// Animación del item
String itemAnimationId;
// ID de animaciones del jugador
String itemPlayerAnimationsId;
// Esperar a que termine la animación
boolean waitForAnimationToFinish;
// Efectos de partículas, sonidos, etc.
// ...
}
3. InteractionType¶
Tipo de interacción que se está ejecutando.
public enum InteractionType {
LeftClick, // Click izquierdo
RightClick, // Click derecho
Equipped, // Item equipado
// ... más tipos
}
Flujo de Ejecución¶
sequenceDiagram
participant P as Player
participant IM as InteractionManager
participant IC as InteractionChain
participant I as Interaction
participant CTX as InteractionContext
participant W as World
P->>IM: Presiona botón (ej: click)
IM->>IC: Iniciar cadena de interacciones
IC->>I: tick(firstRun=true, time=0)
loop Cada tick mientras esté activa
I->>CTX: Verificar condiciones
I->>I: tick0() - Lógica personalizada
I->>W: Aplicar cambios al mundo
I->>CTX: Actualizar estado
alt Interacción completada
I->>IC: state = Finished
IC->>IM: Siguiente interacción
else Interacción continúa
I->>IC: state = NotFinished
else Interacción fallida
I->>IC: state = Failed
IC->>IM: Cancelar cadena
end
end
Tipos de Interacciones¶
Interacciones Cliente (Client Interactions)¶
Ejecutadas y verificadas por el cliente, sincronizadas con el servidor.
Ejemplos:
- DestroyBlockInteraction - Destruir un bloque
- PlaceBlockInteraction - Colocar un bloque
- UseEntityInteraction - Usar una entidad
- ChangeBlockInteraction - Modificar un bloque
Interacciones de Servidor (Server Interactions)¶
Solo ejecutadas en el servidor.
Ejemplos:
- SendMessageInteraction - Enviar mensaje al jugador
- ApplyEffectInteraction - Aplicar efecto a entidad
- RemoveEntityInteraction - Eliminar entidad
Interacciones Compuestas¶
Combinan múltiples interacciones.
Ejemplos:
- SerialInteraction - Ejecutar interacciones en secuencia
- ParallelInteraction - Ejecutar interacciones simultáneamente
- ConditionalInteraction - Ejecutar solo si se cumple condición
- RepeatInteraction - Repetir interacción N veces
MetaKeys de Interacción¶
El sistema de interacciones usa el Meta System extensivamente:
// Interaction.java:568-591
// Entidad objetivo de la interacción
public static final MetaKey<Ref<EntityStore>> TARGET_ENTITY =
CONTEXT_META_REGISTRY.registerMetaObject(data -> null);
// Ubicación del impacto (rayo)
public static final MetaKey<Vector4d> HIT_LOCATION =
CONTEXT_META_REGISTRY.registerMetaObject(data -> null);
// Detalle del impacto (parte del modelo)
public static final MetaKey<String> HIT_DETAIL =
CONTEXT_META_REGISTRY.registerMetaObject(data -> null);
// Bloque objetivo
public static final MetaKey<BlockPosition> TARGET_BLOCK =
CONTEXT_META_REGISTRY.registerMetaObject(data -> null);
// Bloque objetivo sin modificación
public static final MetaKey<BlockPosition> TARGET_BLOCK_RAW =
CONTEXT_META_REGISTRY.registerMetaObject(data -> null);
// Slot objetivo
public static final MetaKey<Integer> TARGET_SLOT =
CONTEXT_META_REGISTRY.registerMetaObject(data -> 0);
// Desplazamiento de tiempo
public static final MetaKey<Float> TIME_SHIFT =
META_REGISTRY.registerMetaObject(data -> null);
// Daño de la interacción
public static final MetaKey<Damage> DAMAGE =
CONTEXT_META_REGISTRY.registerMetaObject(data -> null);
Uso Básico¶
Obtener Datos de Interacción¶
public void onInteraction(InteractionContext ctx) {
// Obtener entidad objetivo
Ref<EntityStore> target = ctx.getMetaObject(Interaction.TARGET_ENTITY);
// Obtener posición del impacto
Vector4d hitPos = ctx.getMetaObject(Interaction.HIT_LOCATION);
// Obtener bloque objetivo
BlockPosition block = ctx.getMetaObject(Interaction.TARGET_BLOCK);
// Verificar si tiene objetivo
if (target != null && target.isValid()) {
Entity entity = commandBuffer.getEntity(target);
// Procesar entidad
}
}
Crear Interacción Personalizada¶
public class MiInteraccion extends SimpleInstantInteraction {
@Override
protected void firstRun(InteractionType type,
InteractionContext context,
CooldownHandler cooldownHandler) {
// Obtener entidad que ejecuta
Ref<EntityStore> entityRef = context.getEntity();
// Obtener objetivo
BlockPosition block = context.getTargetBlock();
if (block != null) {
// Hacer algo con el bloque
System.out.println("Interactuando con bloque: " + block);
}
// Aplicar efecto
InteractionSyncData state = context.getState();
state.state = InteractionState.Finished;
}
}
InteractionChain¶
Las interacciones pueden encadenarse para crear combos o secuencias:
public class InteractionChain {
// ID de la cadena
int chainId;
// Lista de operaciones (interacciones)
List<Operation> operations;
// Índice de operación actual
int operationIndex;
// Profundidad de llamadas
int callDepth;
// Datos de la cadena
InteractionChainData chainData;
}
Ejemplo de cadena:
Combo de espada:
1. SwingInteraction (0.3s)
2. DamageInteraction (instantáneo)
3. CooldownInteraction (1.0s)
Registro de Interacciones¶
Las interacciones se registran en el AssetStore:
// Interaction.java:115
public static AssetStore<String, Interaction, IndexedLookupTableAssetMap<String, Interaction>>
getAssetStore() {
if (ASSET_STORE == null) {
ASSET_STORE = AssetRegistry.getAssetStore(Interaction.class);
}
return ASSET_STORE;
}
// Obtener interacción por ID
Interaction interaction = Interaction.getAssetMap().getAsset("sword_attack");
Estados de Interacción¶
public enum InteractionState {
NotFinished, // Aún ejecutándose
Finished, // Completada exitosamente
Failed, // Falló
Skip, // Saltada por el usuario
ItemChanged // Cancelada por cambio de item
}
Ejemplos de Uso¶
Destruir Bloque¶
// DestroyBlockInteraction.java:26
protected void firstRun(InteractionType type,
InteractionContext context,
CooldownHandler cooldownHandler) {
BlockPosition blockPosition = context.getTargetBlock();
if (blockPosition != null) {
// Obtener mundo y chunk
World world = entityStore.getWorld();
ChunkStore chunkStore = world.getChunkStore();
// Destruir bloque
BlockHarvestUtils.performBlockBreak(
entityRef,
null, // item usado
position,
chunkRef,
commandBuffer,
chunkStoreStore
);
}
}
Mejores Prácticas¶
✅ Hacer¶
-
Verificar nulls antes de usar
-
Actualizar estado correctamente
-
Usar MetaKeys predefinidas
❌ No Hacer¶
- No modificar el mundo sin CommandBuffer
- No olvidar actualizar el estado
- No asumir que siempre hay objetivo
Siguiente¶
- Base Interaction: Clase base detallada
- Client Interactions: Interacciones de cliente
- Block Interactions: Interacciones con bloques
- Entity Interactions: Interacciones con entidades
¿Preguntas? Consulta FAQ