28/08/2008 2 commentaires

Je suis un ancien joueur de Final Fantasy XI. Même si ce phénomène est particulièrement vrai dans ce jeu aux accents hardcore non dissimulés, il existe dans la plupart des MMORPGs. Les joueurs n’en parlent pas, ou plutôt, ne font pas exprès d’en parler. Les anciens frôlent parfois du doigt la vérité, mais elle est difficile à accepter.

Je parle de l’expérience traumatique sur les MMORPGs.

Categories: Conception Tags: , ,

27/05/2008 un commentaire

Ce week-end, j’ai fait mes premiers pas en utilisant Python. J’avais évidemment entendu parler de nombreuses fois de ce langages au cours de diverses discussions et dans le domaine professionnel (notamment parce que je bosse avec Trac), mais je n’avais jamais mis les mains dans le cambouis pour voir quel tronche ça avait.

En lisant The Pragmatic Programmer, je suis tombé sur une recommendation du style « étudiez au moins un langage par an », et ça m’a motivé. Du coup, voilà. Et ben putain, j’aurais du faire ça plus tôt. C’est carrément ultime. Syntaxe simple, légère, peu capricieuse mais forçant la lisibilité, documentation bien foutue, tutos poussés vraiment intéressants, vitesse d’execution excellente, grande quantité de bibliothèques, …

Je me réjouis vraiment d’utiliser ça dans un contexte un peu plus serieux que dans ma petite sandbox. Allez, je suis sûr qu’il va bien falloir deux ou trois moulinettes à coder dans la semaine qui arrive… Histoire de me mettre dans le bain et de passer en revue le langage rapidement, j’ai réimplémenté un algo que l’on utilise sur Dofus pour la génération des noms de personnages, et qui est accessoirement ultra-connu: les chaînes de Markov.

Z’allez voir, c’est que du bonheur.

Categories: Code Tags: , ,

23/05/2008 Aucun commentaire

Adobe a publié la semaine passée une première beta du Player Flash 10 (nom de code : Astro), implémentant une mise à jour de l’API de dessin, Hydra et quelques modifications de langages, dont le type Vector.

Je ne reviendrais pas dessus, car c’est un sujet qui a été largement couvert par de nombreux blogs, voici simplement quelques liens :

J’esperais plus des modifications de langage apportées par Astro. Si l’implémentation du proposal:Vector est une excellente chose, l’absence de nombreux éléments des drafts ECMA4 fait mal.

Et là où je déplore le manque, c’est surtout sur l’impossibilité de déclarer des classes génériques personnalisées :

package {
    public class CustomGeneric.
    {
    }
}

Et bim: 1084: Syntax error: expecting leftbrace before dotlessthan.

En lisant la discussion sur les paramètres-types, je m’attendais à pouvoir faire ça de mon côté. Et visiblement non. Dommage… Une prochaine fois? Après tout, ce n’est qu’une première beta.

Allez, salut.

Categories: Code Tags: ,

Les SWC produits par Flex Builder contiennent un SWF étrange.

12/04/2008 un commentaire

Je bosse actuellement sur un système de tests unitaires en AS3, car FlexUnit ne me convenait pas par la lourdeur (certainement subjective) de son utilisation. Le principe de base consiste à compiler le projet de tests unitaires sous forme d’un SWC, qui est ensuite chargé et décompressé par le système, qui en extrait le SWF de librairies afin de le charger, pour pouvoir exécuter le code des classes de tests.

Tout marche vachement bien, et hier soir, je me dis que je vais le ramener à la maison pour trifouiller un peu ce week-end. Et là, crack, impossible de le faire marcher de chez moi. Wtf? En fait, lorsque le SWF est chargé par un Loader, ce dernier ne produit pas d’évènement INIT, ni d’évènement COMPLETE. Il produit par contre des évènements PROGRESS, dont un où bytesLoaded == bytesTotal. Mais les classes contenues par le SWF ne sont (visiblement) jamais ajoutées à l’ApplicationDomain précisé dans le LoaderContext.

Après une petite analyse, il apparait que les SWC produits par FlexBuilder ne sont pas strictement identiques à un SWC produit par compc. À coup de Swfmill, la différence apparaît clairement:

SWF contenu dans un SWC produit par compc, exemple de contenu pour le tag 0×52 (ABC pour AVM2), en Base64 :

AAAAAFVuaXRUZXN0aW5nQ29t(...)

SWF contenu dans un SWC produit par FlexBuilder, même segment du même tag, en Base64 :

AQAAAFVuaXRUZXN0aW5nQ29t(...)

Ne me demandez pas ce que fout ce Q là, mais en le remplaçant par un A, le SWF fonctionne à nouveau. Si une personne connaissant mieux le bytecode AVM2 que moi (ce qui n’est pas difficile), et ayant une idée de ce que signifie ces entêtes, toute info est la bienvenue. Allez, salut.

Categories: Code Tags: ,

25/02/2008 3 commentaires

Tout le monde aura déjà écrit un code de ce genre :

var ldr : Loader = new Loader();
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
ldr.load(new URLRequest("http://www.bidon.com/trucmuche.jpg"));

Ca marche bien. Mais il se trouve que dans mon projet, on a tendance à avoir besoin de beaucoup, beaucoup de loaders. Je me suis donc dit « Allons, Tyn, utilise donc un pool ! » Ce qui marche également bien. On a un gain de plus de 1000% en utilisant un pool de Loader plutôt que d’en créer de nouveaux à chaque fois.

Mais qui dit pool dit nettoyage d’objet, et rendu dudit objet au pool après son utilisation. Hors, dans ce cas précis, j’ai un gros soucis: je ne peux pas récupérer mon objet Loader dans mon callback onIOError! C’est quand même très, très con. Ca signifie que je perds un élément de mon pool à chaque URL foireuse, ce qui est un leak inacceptable.

Voici donc un contournement foireux pour récupérer son objet Loader depuis un callback où LoaderInfo.loader n’est pas encore renseigné:

package net.tynambule.exp {
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	public class IOErrorCallbackWithLoader extends Sprite
	{
		private var _loaders : Dictionary = new Dictionary(true);
		public function IOErrorCallbackWithLoader()
		{
			var ldr : Loader = new Loader();
			ldr.contentLoaderInfo.addEventListener(Event.INIT, onInit);
			ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
			// Feinte ici :
			_loaders[ldr.contentLoaderInfo] = ldr;
			ldr.load(new URLRequest("existe-po.png"));
		}
		private function onInit(e : Event) : void
		{
			trace("Trop bien, le fichier existait!");
			// Ne pas oublier d'effacer ma référence, histoire que mon Loader puisse
			// être garbage collecté.
			delete _loaders[e.target];
		}
		private function onIOError(ioe : IOErrorEvent) : void
		{
			trace("Le fichier existait pas, mais j'ai toujours mon loader!");
			trace("Le voici :" + _loaders[ioe.target]);
			// Ne pas oublier d'effacer ma référence, histoire que mon Loader puisse
			// être garbage collecté.
			delete _loaders[ioe.target];
		}
	} }

Et hop. C’est quand même bien crade. Si un gentil développeur de chez Adobe passe par ici (sait-on jamais), c’est quand même con que le Loader ne soit pas accessible depuis l’objet LoaderInfo en cas d’erreur de chargement alors qu’il est disponible avant le chargement. Allez, salut.

Categories: Code Tags: ,