Interceptando al Enemigo: Código y Estrategia

02/02/2023

Valoración: 4.73 (13682 votos)

En el complejo universo del desarrollo de videojuegos, cada acción, cada evento y cada interacción se rige por un código meticulosamente diseñado. A menudo pensamos en la acción principal: el héroe que lanza un hechizo, el enemigo que ataca, el personaje que abre un cofre. Pero, ¿qué sucede en los milisegundos previos a esa acción? Al igual que un estratega consumado prepara el campo de batalla antes del choque de espadas, un buen programador prepara el entorno de ejecución antes de que se invoque la lógica principal. Hoy exploraremos dos poderosas técnicas que actúan como la primera línea de defensa y preparación en el código de un juego: las anotaciones que preparan el contexto y los filtros que actúan como guardianes implacables.

How to execute code before controller?
Spring Aspect is also a good option to execute code before controller. @Before("execution(* com.test.myMethod(..)))") public void doSomethingBefore(JoinPoint jp) throws Exception { //code Here myMethod() will execute before controller. Expanding on Sai Prateek answer, I'v created a custom annotation: String clientId(); String userId();
Índice de Contenido

La Magia de las Anotaciones: Preparando el Campo de Batalla

Imagina que estás diseñando un sistema de combate para un RPG. Tu mago tiene un hechizo llamado "Tormenta Ígnea". La lógica principal del hechizo calcula el daño base, el área de efecto y los gráficos. Pero quieres que sea más dinámico. Quieres que, justo antes de lanzar la "Tormenta Ígnea", el juego compruebe si el objetivo está mojado para duplicar el daño por vaporización, o si lleva una armadura de hielo para aplicar un estado de "derretido". Aquí es donde entran en juego las anotaciones.

En programación, una anotación es como una etiqueta mágica o una runa que colocamos sobre un método (una habilidad, en nuestra analogía). Esta runa no ejecuta la habilidad por sí misma, pero le dice al sistema del juego: "¡Oye! Antes de ejecutar esto, haz esta otra cosa primero".

Pensemos en el siguiente seudocódigo inspirado en un controlador de acciones de un juego:

@RestController public class ControladorDeHabilidades { @PrepararContexto("aplicar_debilidad_fuego(objetivo.id)") public RespuestaDelJuego lanzarBolaDeFuego(PeticionDeHabilidad peticion) { // Lógica principal para lanzar la bola de fuego... // El daño se calculará teniendo en cuenta la debilidad } @PrepararContexto("verificar_mana_suficiente(jugador.id, 50)") public RespuestaDelJuego invocarGolem(PeticionDeHabilidad peticion) { // Lógica principal para invocar al golem... } }

En este ejemplo, `@PrepararContexto` es nuestra anotación mágica. Antes de que se ejecute la lógica de `lanzarBolaDeFuego`, el sistema invoca una función que aplica una debilidad al fuego sobre el objetivo. De manera similar, antes de `invocarGolem`, se verifica si el jugador tiene los 50 puntos de maná necesarios. Lo brillante de esto es que la lógica principal de la habilidad no se ensucia con estas comprobaciones previas. Se mantiene limpia y centrada en su propósito. El sistema que gestiona los efectos de estado o los errores (nuestro `ExceptionHandler` en la vida real) puede luego leer este contexto preparado ("el enemigo ahora es débil al fuego") y actuar en consecuencia, aplicando el daño extra o mostrando el mensaje de error apropiado.

How do I bypass a call to a controller?
You can also add logic to bypass the call to the controller if needed. For example if you have an authentication filter and you see that the request is not authenticated you can directly reply with a 401 code without calling the controller. I want to bypass the call to the controllers if needed. Thanks, it works very good.

El Guardián Silencioso: Filtros para Detener Amenazas

Si las anotaciones son preparativos tácticos para una acción específica, los filtros son los guardianes que vigilan las puertas de todo el reino. Un filtro no se preocupa por si vas a lanzar una bola de fuego o a bailar la macarena; su trabajo es inspeccionar a *todo* el que intenta entrar en el castillo (es decir, cada solicitud que llega al servidor del juego).

Un filtro es una pieza de código que se interpone entre la solicitud del jugador y el controlador que la maneja. Tiene la capacidad de examinar la solicitud, modificarla, registrarla y, lo más importante, decidir si puede continuar su camino o si debe ser rechazada en la puerta.

Veamos cómo se vería un filtro de registro de actividad en nuestro juego:

@Component public class FiltroDeRegistroDeMazmorra implements Filter { public void doFilter(Solicitud req, Respuesta res, CadenaDeFiltros chain) { System.out.println("Un aventurero se acerca a la entrada de la mazmorra..."); // Permite que el aventurero continúe hacia el controlador de la mazmorra chain.doFilter(req, res); System.out.println("El aventurero ha salido de la mazmorra. Registrando resultado..."); } }

Este filtro es como un cronista. Anota cuándo un jugador intenta entrar en una zona (`doFilter` se llama antes del controlador) y cuándo sale (`doFilter` ha terminado su ejecución). Es increíblemente útil para monitorizar la actividad del servidor, depurar problemas o simplemente para tener un registro de todo lo que ocurre.

¡No Puedes Pasar! Bloqueando el Acceso con Filtros

La verdadera fuerza de un filtro, sin embargo, reside en su poder de veto. No es solo un observador pasivo; es un guardia de seguridad con autoridad. Imagina que tienes una zona PvP de alto nivel en tu juego. No quieres que jugadores por debajo del nivel 50 puedan entrar. Un filtro es la herramienta perfecta para esta tarea.

How to execute code before controller?
Spring Aspect is also a good option to execute code before controller. @Before("execution(* com.test.myMethod(..)))") public void doSomethingBefore(JoinPoint jp) throws Exception { //code Here myMethod() will execute before controller. Expanding on Sai Prateek answer, I'v created a custom annotation: String clientId(); String userId();

El filtro interceptaría la solicitud del jugador para entrar en la zona. Comprobaría su nivel. Si el nivel es 49 o inferior, el filtro ni siquiera se molesta en pasar la solicitud al controlador de la zona. Simplemente le devuelve un mensaje al jugador: "No tienes el nivel suficiente para entrar aquí" y detiene el proceso. Esto es una estrategia de programación sumamente eficiente. ¿Para qué cargar la lógica compleja de la zona, los monstruos y los tesoros, si el jugador ni siquiera cumple el requisito básico para entrar? El jefe final de la mazmorra (el controlador) nunca es molestado por aspirantes no cualificados.

Este mismo principio se aplica a la seguridad. Si un jugador intenta realizar una acción de administrador sin tener los permisos necesarios, el filtro de autenticación lo detendrá en seco, protegiendo el juego de posibles trampas o hackeos antes de que la solicitud maliciosa llegue a tocar cualquier lógica importante.

Tabla Comparativa de Estrategias

Para entender mejor cuándo usar cada herramienta, aquí tienes una tabla comparativa con nuestra analogía de videojuegos:

TécnicaAnalogía en VideojuegosUso Principal
Anotaciones Específicas (ej. @PreAuthorize)Aplicar un buff o debuff justo antes de usar una habilidad concreta.Preparar el contexto o realizar una validación específica para una única acción o método.
Filtros (Filters)Un guardián en la entrada de una ciudad o mazmorra que revisa a todos los que entran.Interceptar y procesar *todas* las solicitudes de forma global. Ideal para seguridad, logs y validaciones generales.

Preguntas Frecuentes (FAQ)

¿Cuál es la diferencia principal entre un Filtro y una Anotación de este tipo?
La principal diferencia es el alcance. Un Filtro es global por naturaleza; se aplica a un conjunto amplio de solicitudes, a menudo a todas. Una Anotación es específica; se aplica únicamente al método o clase donde la coloques. El filtro es el guardia de la ciudad, la anotación es el requisito para usar un altar mágico específico dentro de esa ciudad.
¿Usar estas técnicas puede hacer mi juego más lento?
Como cualquier herramienta, su impacto depende de cómo se use. Una lógica de filtro o anotación mal escrita y pesada puede ralentizar las cosas. Sin embargo, cuando se usan correctamente, los beneficios en organización, seguridad y eficiencia superan con creces cualquier sobrecarga mínima. De hecho, un filtro que bloquea solicitudes no válidas tempranamente puede hacer que el sistema general sea mucho más rápido y robusto.
¿Esto solo se aplica al desarrollo de juegos de servidor (backend)?
Los conceptos de interceptar y preparar acciones son universales en programación. Sin embargo, los ejemplos específicos como `Filter` y `@RestController` provienen del mundo del desarrollo backend (servidores), que es el cerebro detrás de la mayoría de los juegos en línea, gestionando desde la autenticación de jugadores hasta la lógica de las partidas. La misma filosofía se puede aplicar en el código del cliente (el juego que se ejecuta en tu PC o consola) con diferentes herramientas.

En conclusión, la próxima vez que juegues y veas cómo un enemigo recibe daño extra por estar mojado, o cuando el juego te impida entrar en una zona restringida, recuerda que detrás de esa experiencia fluida hay capas de código estratégico. Las anotaciones y los filtros son los héroes anónimos que preparan el escenario, vigilan las puertas y se aseguran de que la lógica principal solo tenga que preocuparse de lo verdaderamente importante: la acción. Son la prueba de que en el desarrollo, como en la guerra, la preparación y la defensa son tan cruciales como el ataque.

Si quieres conocer otros artículos parecidos a Interceptando al Enemigo: Código y Estrategia puedes visitar la categoría Juegos.

Subir