inmensia |
Blog
Juan Mellado, 28 Agosto, 2010 - 08:07
Una característica específica de la implementación de Lua en Allods es que sólo están disponibles las librerías string, math, table y coroutine. Es decir, las que permiten manipular cadenas de texto, realizar operaciones matemáticas, gestionar tablas (arrays, lists, ...) e implementar multitarea. Y no se encuentran disponibles otras como file, io, os, ... que dan libre acceso a los recursos del sistema. Otra característica de la implementación de Lua que utiliza el juego es que no se permite el uso de las variables globales por defecto. Es decir, en Lua las variables automáticamente son globales, pero dentro de Allods esto no se permite, es necesario declararlas explícitamente de la forma "Global(nombre, valor)", como en el siguiente ejemplo: Global("counter", 0)En lineas más generales, comentar que los scripts de los addons se inicializan en el mismo orden que se encuentran listados dentro de la etiqueta <ScriptFileRefs> de sus correspondientes ficheros "AddonDesc.(UIAddon).xdb". Y se cargan automáticamente al iniciar el juego, o desde otro script, en función del valor de la etiqueta <AutoStart>. Aunque lo más importante sin lugar a dudas es tener claro que el funcionamiento de los addons se basa principalmente en la gestión de eventos. Es decir, los scripts dicen a qué sucesos que ocurren en el juego quieren reaccionar, e indican a cual función se les debe llamar cuando estos se produzcan. Allods adopta, en este sentido, el famoso modelo Hollywood: "No nos llame, ya le llamaremos". La lista de eventos disponibles es enorme, prácticamente para cualquier suceso que pueda ocurrir en el juego. Por ejemplo, para un personaje podemos programar un addon que reaccione cuando cambie de posición, cuando cambie su nivel de experiencia, cuando cambie la cantidad de dinero que tiene, cuando cambie su lista de amigos, cuando cambie de objetivo, cuando cambien sus talentos, ... y así un largo etcétera. Y lo mismo para las "parties", "raids", hermandades, objetos, inventarios, misiones, mapas, correo, ... Para registrar un manejador de eventos hay que realizar una llamada a "common.RegisterEventHandler(función, evento)", de forma que cuando ocurra el evento dado, Allods llamará automáticamente a la función indicada. En los addons de ejemplo que vienen con el juego hay uno muy sencillo llamado "SampleEventRegistration" que registra un evento de un temporizador que gestiona internamente el juego y que salta automáticamente cada segundo. El script "ScriptSampleEventRegistration.lua" de dicho addon contiene un código similar al siguiente: Global("counter", 0)El script declara un contador ("counter") en una variable global, para que su valor persista entre llamada y llamada, inicializándolo a cero. Registra una función ("OnEventSecondTimer") para que Allods la llame cada vez que salte el evento ("EVENT_SECOND_TIMER"). Y en cada activación motivada por la ocurrencia del evento incrementa el valor del contador y escribe su valor en el fichero de log por defecto, que recordemos se encuentra en el directorio "Personal\Logs" dentro de la carpeta donde se encuentra instalado el juego. Todas las funciones manejadoras de eventos reciben un único parámetro cuya interpretación depende enteramente del tipo de evento. Algo que resulta bastante natural en Lua, ya que es un lenguaje tipado dinámicamente. Así, para el evento del ejemplo, el parámetro no contiene ningún atributo. Pero para otros eventos, como el que salta cuando con nuestro personaje aceptamos una misión, por ejemplo, lo que se recibe es el identificador de la misión concreta que se ha aceptado, al que se accede con "params.questId". En la documentación se listan los eventos disponibles así como los parámetros concretos que recibe cada uno. De forma general, en los eventos asociados a misiones se reciben identificadores de misiones, en los referidos a personajes se reciben identificadores de avatares, y así sucesivamente. Estos identificadores son los que permiten realizar tareas concretas sobre los objetos del juego mediante la llamada a las funciones ofrecidas por el API de Allods. De igual forma que con los eventos, existen funciones para realizar prácticamente cualquier operación, excepto por supuesto para controlar los personajes. El API está pensado para reemplazar o añadir opciones a la interface de usuario del juego, o reaccionar a determinados estados de la lógica del juego, principalmente esto último para automatizar tareas como por ejemplo vender todos los objetos grises automáticamente cuando se abre un diálogo con un vendedor. La orientación a objetos de Lua permite escribir código ordinario en el que sobre un objeto se invoca un método con una serie de argumentos. Por ejemplo para que nuestro personaje acepte la realización de una misión dada basta con escribir la siguiente línea: avatar.AcceptQuest(questId)La variable "avatar" que aparece en el código anterior es global y se encuentra definida por defecto dentro de Allods y es accesible desde cualquier punto de cualquier script. Con ella podemos obtener información sobre el estado de nuestro personaje y realizar acciones con él. De igual forma se encuentran definidas otra serie de variables como "group", "raid", "mailBox", "guild", ... Hay que tener en cuenta que las variables globales siempre se encuentran instanciadas pero habrá muchas operaciones que no puedan hacerse con ellas si el personaje no se encuentra en el estado adecuado. Por ejemplo, no podrá abrir el correo si no se encuentra ante un buzón. Para ello hay funciones específicas que nos indican si los objetos encuentran en un estado adecuado para usarlas: LogInfo("mailBox: ", mailBox.IsReady() )No obstante, a estas alturas espero que haya quedado claro que la forma en la que se implementará normalmente los addons es respondiendo a los eventos correspondientes que nos avisarán cuando se está delante de un buzón, se ha recibido una invitación a un grupo, ... en vez de estar constantemente preguntando a las variables si se está en el estado adecuado.
Juan Mellado, 21 Agosto, 2010 - 08:45
Los addons de Allods son pequeños programas que se componen de las distintas partes de las que habitualmente consta una aplicación: interface de usuario, código de proceso, ficheros de recursos y librerías adicionales. El conjunto de estos ficheros es lo que se conoce como addon. Para crear un addon en Allods hay que crear un directorio dentro de la carpeta "data/Mods/Addons" donde se encuentra instalado el juego y poner en él todos los ficheros que forman el addon. Por ejemplo, si queremos crear un addon llamado "Prueba", debemos crear un directorio "data/Mods/Addons/Prueba" y poner en él todos sus ficheros. Aunque también es posible crearlos con varios niveles de directorios como "data/Mods/Addons/Pruebas/Prueba01". ¿Pero qué ficheros forman un addon en Allods? Pues lo mejor es verlo con un ejemplo real de un addon que viene con el juego que se llama "SampleInit". Se encuentra en el directorio "Mods/SampleAddons/SampleInit", y consta de tres ficheros: AddonDesc.(UIAddon).xdbEl primer fichero es obligatorio para todos los addons y tiene que tener siempre ese nombre fijo de "AddonDesc.(UIAddon).xdb". Es un XML en formato UTF-8 con una serie de etiquetas obligatorias que describe al addon. Veámoslas. La etiqueta <Name> contiene el nombre del addon. <Name>SampleInit</>La etiqueta <AutoStart> indica si el addon tiene que ejecutarse automáticamente al arrancar el juego. Es un simple valor booleano. <AutoStart>True</>La etiqueta <ScriptFileRefs> contiene la lista de ficheros con los scripts, escritos en Lua, que utiliza el addon. Cada entrada de la lista contiene el nombre de un fichero, que puede ser absoluto con respecto al directorio "data" del juego, o relativo a la ruta donde se encuentra el addon: <ScriptFileRefs>La etiqueta <Forms> contiene la lista de formularios que utiliza el addon. Cada elemento de la lista se compone de un identificador único y una referencia a un fichero .xdb donde se encuentra descrito el formulario correspondiente. Se utiliza la notación XPointer, que es una notación estándar que permite desde un fichero XML hacer referencia a una sección de otro fichero XML. <Forms>En el ejemplo de esta última etiqueta se define un formulario identificado como "Main" que se encuentra definido dentro de la sección "WidgetForm" de un fichero llamado "MainForm.(WidgetForm).xdb". La etiqueta <MainFormId> contiene el nombre del formulario principal del addon, que debe ser un identificador definido dentro de la lista contenida en la etiqueta <Forms>: <MainFormId>Main</MainFormId>De igual forma, es posible añadir otras etiquetas predefinidas, o incluso propias, como el nombre del autor, la versión de addon o la fecha de última actualización, aunque en la documentación no se indica más detalle acerca de ellas. El fichero "AddonDesc.(UIAddon).xdb" de este addon "SampleInit", al completo, contiene lo siguiente: <?xml version="1.0" encoding="UTF-8" ?>A estas alturas ya debería adivinarse el patrón que sigue el nombre de los ficheros .xdb, con un título (AddonDesc, MainForm, ...) seguido de un tipo (UIAddon, WidgetForm, ...) Estos tipos están predefinidos y sirven para indicar la clase de información que contiene el fichero, que además de información en formato de texto también admite ficheros de recursos binarios como pueden ser texturas. A continuación el fichero "MainForm.(WidgetForm).xdb" correspondiente a este mismo addon y que resulta bastante fácil de entender leyendo entre líneas: <?xml version="1.0" encoding="UTF-8" ?>Y por último, el contenido del fichero "ScriptSampleInit.lua" de este mismo addon que se limita a dejar constancia de su arranque en el fichero de log predefinido por el juego que se llama "mods.txt" y que se encuentra en el directorio "Personal/Logs": -----------------Para probar este simple addon de ejemplo basta con copiar la carpeta "SampleInit" de "data/Mods/SampleAddons" a "data/Mods/Addons". Al arrancar el juego aparecerá un nuevo botón, en la ventana de login, que nos permite activar o desactivar los addons, que por defecto se encuentran desactivados. Al entrar en el juego propiamente dicho, después de la ventana de selección de personaje, veremos como se graba el mensaje en el fichero de log, señal de que el addon se encuentra correctamente instalado y funcionando.
Juan Mellado, 14 Agosto, 2010 - 07:55
Como suelo hacer de vez en cuando, sobre todo después de unas largas vacaciones, he decidido hacer una serie de posts dedicados a un tema concreto, y esta vez le ha tocado a los "addons". Más concretamente a los de Allods Online. Un MMORPG gratuito que conocí hace un par de meses en un post que leí en Planet Stratos. El juego tiene la clásica ambientación fantástico-medieval con la mecánica y los elementos habituales de este tipo de juegos. Un par de facciones enfrentadas, unas cuantas razas por facción, y varias clases con árboles de talentos para tanqueo, sanación y daño. Misiones de "grinding" y "farming", algunas cuantas instancias para ir de "party" o "raid", profesiones, reputaciones y casa de subastas. Los desarrolladores son rusos, y eso se nota en algunos aspectos del juego, hay muchos NPCs con nombres como "Boris" o "Andrei", e incluso una región que se llama "Siveria". Aunque lo realmente curioso es que tienen la política de implantar las nuevas versiones primero en Rusia y luego en el resto de Europa y América. Es decir, que jugamos con un par de parches por debajo de la versión oficial rusa. Es más, por lo que he podido entender, la posibilidad de usar addons es algo que se ha añadido en el parche actual, o quizás en el anterior. Perfecto para mis propósitos. El juego, como ya he comentado, es gratuito, y esto quiere decir que se puede crear una cuenta, un personaje y jugar todo lo que se quiera, sin restricciones. Nuevamente perfecto para mis propósitos. Eso sí, existe la posibilidad de adquirir objetos que hacen la vida más fácil, como una bolsa con más casillas por ejemplo, pagando una pequeña cantidad de dinero. Pero es algo completamente opcional. Aunque hay otra serie de objetos que también se venden y sirven para potenciar el daño y la sanación, hasta un 100%, que mucha gente considera algo necesario tener, ya que si no el juego se hace muy difícil y el "leveling" (hasta el nivel 42) muy lento. Desgraciadamente el juego no está traducido al español, y creo que no existen planes para hacerlo en un futuro inmediato. De hecho, la documentación de los addons ni siquiera está traducida al inglés. Y es que la única información técnica oficial disponible es la que se incluye junto con la descarga del mismo juego, ¡y está en ruso!. Dentro del directorio de instalación del juego, en la carpeta "data\Mods\Docs". Son unas páginas HTML con una breve guía de construcción e instalación, así como una descripción de todas y cada una de las funciones disponibles del API. Ya que aunque todavía no lo he comentado, los addons se escriben utilizando Lua, uno de los lenguajes de scripts más utilizados para este tipo de tareas. Bueno, y llegado este punto, es hora de abrir un traductor de ruso y ponerse a leer un rato.
Juan Mellado, 7 Agosto, 2010 - 12:34
- ¿Color?
Juan Mellado, 26 Junio, 2010 - 09:50
Aunque empiezan diciendo que se consideran un sistema de tipo LAMP (Linux Apache MySQL PHP), enseguida aclaran que más bien es un "LAMP con heteroides". Utilizan versiones de Linux, MySQL y PHP que ellos mismos han optimizado. Además de mucho otro software, naturalmente, propio y ajeno, la mayoría de código abierto. - HipHop para PHP es uno de los desarrollos propios de Facebook más conocidos, y se trata básicamente de un compilador cruzado que toma código escrito en PHP y genera código equivalente en C++ que puede ser compilado con g++ para una ejecución de forma nativa más óptima. Con este enfoque aseguran haber conseguido hasta una reducción de un 50% del consumo de CPU en sus servidores. - Thrift es un desarrollo propio de Facebook que liberó y ahora forma parte de la fundación Apache. Sirve para poder realizar llamadas entre distintos lenguajes de programación, que en el caso de Facebook son unos cuantos: PHP, C++, Java, Erlang, ... La idea es que en un fichero de texto plano se definen las estructuras de datos y las funciones públicas, y la librería genera el código fuente correspondiente para el lenguaje de programación que se le indique. La librería garantiza que los datos serán serializados en el cliente y reconstruidos en el servidor donde quieran que se ejecuten estos de una forma totalmente transparente y eficiente. O sea, un RPC (posibilidad de realizar llamadas remotas) con su propio IDL (lenguaje de definición de interfaces). No obstante es un proyecto que ha decaido un poco, sobre todo por el auge de Avro que el mes pasado se convirtió en un proyecto "raíz" de Apache. De características similares, pero con un enfoque más atractivo, ya que no obliga a utilizar código fuente generado de forma automática por una herramienta. - Cassandra es otro de los productos estrella de Facebook. Es un sistema de almacenamiento distribuido altamente escalable y con una gran tolerancia a fallos. Es uno de los baluartes actuales de las base de datos "NoSQL" para el almacenamiento de pares (clave, valor). Hace un tiempo escribí un post explicando el modelo de datos en el que se basa su funcionamiento. Es un software muy interesante y que ha entrado a formar parte también de la fundación Apache. - Hadoop es un conjunto de proyectos de código abierto originales de la fundación Apache con los que se persigue que los desarrolladores tengamos las herramientas necesarias para poder generar programas distribuidos, escalables y con alta disponibilidad. Se compone de un núcleo de librerías comunes, varios frameworks, y una serie de software más específico implementado sobre los anteriores. Uno de los más populares es MapReduce que implementa las funciones Map y Reduce utilizadas para el procesamiento de grandes cantidades de información en entornos principalmente de cloud computing. La idea básica es que se parte de unos vectores con los datos a procesar a los que aplica la función Map para generar nuevos vectores en un dominio distinto, y luego se aplica la función Reduce para agrupar los vectores generados al dominio de salida deseado. Recomiendo leer el artículo de la Wikipedia para entenderlo mejor. Es muy interesante. - Hive es un subproyecto dentro de Hadoop, aunque es un desarrollo original de Facebook que luego liberó. Es un datawarehouse cuyo objetivo es permitir acceder a través de consultas SQL a los enormes vectores de información utilizados normalmente con Hadoop con el propósito de realizar análisis estadísticos o de tipo data-mining. - BigPipe es una de las "armas secretas" de Facebook. Es un servidor de páginas webs dinámicas que introduce el concepto de pagelets con el que descompone una página web en varias partes, de forma que cada una de ellas pueda generarse en paralelo. La idea es que cuando se solicita una página web esta se devuelva lo antes posible, pero con una estructura mínima que se compone de bloques vacíos (perfil, búsqueda, chat, ...). Estos bloques son las pagelets que se van generando en paralelo en el servidor, y que cuando están listas se envian al cliente y se renderizan con JavaScript. De esta forma se consigue que la generación de una única página web se haga en paralelo, en vez de forma secuencial como es lo más habitual, y que el fallo en un subsistema (perfil, búsqueda, chat, ...) no impida servir una página, aunque esté incompleta. - Memcached es un proyecto externo de código abierto muy popular al que Facebook ha contribuido optimizando algunas partes. Es un sistema distribuido de cache de objetos con un alto rendimiento. La idea es evitar tener que hacer consultas pesadas almacenando resultados previos en memoria, de forma que pueden ser servidos directamente en vez de ejecutando cada vez las consultas. O sea, el funcionamiento normal de una cache pero aplicado a gran escala, sobre queries que atacan una base de datos, clientes que solicitan páginas webs, o cualquier otro tipo de pares (clave, valor). Pero no es mágico, no es un software que se pone entre cliente y servidor y lo hace todo. Hay que programar. En los clientes hay que llamar a la cache para ver si tiene el dato, y si no lo tiene hacer la consulta de la forma habitual, y entonces llamar a la cache para que almacene el dato durante el tiempo que se quiera que sea válido. - Varnish es un acelerador de HTTP de código abierto. Se coloca entre los clientes y uno o más servidores web actuando como balanceador de carga. Pero es un software que ofrece mucha más funcionalidad que la de mero balanceador. Ofrece un servicio de cache para responder a las peticiones de forma inmediata sin tener que realizar realmente las llamadas a los servidores web, y permite ejecutar procesos a medida para prácticamente cualquier tipo de información o evento que se produce en una comunicación HTTP. Facebook lo utiliza sobre todo para servir las fotos e imágenes de los perfiles, ¡unos cuantos billones de ficheros cada día! - Scribe es el sistema de log desarrollado por Facebook y liberado como código abierto. La idea es que los cliente envian a servidores dedicados, a través del anteriormente mencionado Thrift, las trazas en forma de pares (categoría, mensaje). Y los servidores organizan todos los mensajes recibidos en función de sus categorías escribiéndolos finalmente en ficheros alojados en algún tipo de filesystem distribuido, ¡unas cuantas decenas de billones de mensajes cada día! |