flash on 2011-2-18
/**
* Copyright wh0 ( http://wonderfl.net/user/wh0 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/h0Ma
*/
// TODO: %%% complete other TODOs
package {
import net.hires.debug.Stats;
import flash.display.Sprite;
public class FlashTest extends Sprite {
public function FlashTest() {
addChild(new Stats()).x = stage.stageWidth - 70;
addChild(new Driver());
}
}
}
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.utils.*;
import com.adobe.images.*;
import com.bit101.components.*;
import nochump.util.zip.*;
internal class Console extends Sprite {
public static var instance:Console;
private var flow:Number = 0;
public function Console() {
instance = this;
addEventListener(Event.ADDED_TO_STAGE, init);
}
protected function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
root.loaderInfo.uncaughtErrorEvents.addEventListener(
UncaughtErrorEvent.UNCAUGHT_ERROR,
function(e:UncaughtErrorEvent):void { error(e.error); }
);
}
private function advance(dy:Number):void {
flow += dy;
if (y > stage.stageHeight - flow) y = stage.stageHeight - flow;
}
public function trace(message:*):Label {
var l:Label = new Label(this, 0, flow, String(message));
advance(Math.max(18, l.textField.height + 1));
return l;
}
public function error(message:*):void {
trace(message).textField.textColor = 0xc00040;
}
protected function progress(name:String, eventDispatcher:EventDispatcher, scale:int, callback:Function=null):ProgressBar {
var l:Label = new Label(this, 0, flow, name);
var pb:ProgressBar = new ProgressBar(this, 93, flow + 5);
pb.width = 6;
pb.height = 9;
pb.visible = false;
advance(18);
eventDispatcher.addEventListener(ProgressEvent.PROGRESS, function(e:ProgressEvent):void {
pb.maximum = e.bytesTotal;
pb.visible = true;
if (e.bytesTotal > scale * 4) pb.width = int((e.bytesTotal / scale) + 2);
eventDispatcher.removeEventListener(ProgressEvent.PROGRESS, arguments.callee);
});
eventDispatcher.addEventListener(ProgressEvent.PROGRESS, function(e:ProgressEvent):void {
pb.value = e.bytesLoaded;
});
eventDispatcher.addEventListener(Event.COMPLETE, function(e:Event):void {
pb.value = pb.maximum;
pb.visible = true;
if (callback != null) callback(e);
});
return pb;
}
}
internal class ResourceLoader extends Console {
private static const BINS:Array = [
'recipe', 'ingredient', 'restaurant', 'lang_en', 'recipe_rewards',
'avatar', 'front', 'perk', 'mystery_box'
];
private static const SWFS:Array = [
'game_asset', 'ingredient_asset', 'indoor_asset', 'indoor_asset2',
'indoor_asset3', 'indoor_asset4', 'indoor_asset5', 'indoor_asset6',
'indoor_asset7', 'IGA_asset', 'collectibles', 'avatar_asset',
'perk_asset', 'recipe_asset'
];
private static const BASE:String = 'http://static-cdn.playfish.com/game/cooking/swf/';
private static const HERE:LoaderContext = new LoaderContext(
true,
ApplicationDomain.currentDomain,
SecurityDomain.currentDomain
);
public static var instance:ResourceLoader;
private var path:String;
private var remain:int = BINS.length + SWFS.length;
protected var xmls:Object = {};
public function ResourceLoader() {
super();
instance = this;
}
override protected function init(e:Event):void {
super.init(e);
trace('version:');
var it:InputText = new InputText(this, 40, 0);
it.height = 18;
var done:Boolean = false;
var pb:PushButton = new PushButton(this, 143, 0, 'OK', function(e:MouseEvent):void {
if (done) return;
it.enabled = false;
pb.enabled = false;
path = BASE + it.text + '/';
loadResources();
done = true;
});
pb.width = 30;
pb.height = 18;
}
private function loadResources():void {
var v:String;
for each (v in BINS) {
loadBIN(v);
}
if (Driver.SKIP_IMAGES) {
remain -= SWFS.length;
} else {
for each (v in SWFS) {
loadSWF(v);
}
}
}
private function loadBIN(name:String):void {
var ur:URLRequest = new URLRequest(path + name + '.bin');
var ul:URLLoader = new URLLoader(ur);
ul.dataFormat = URLLoaderDataFormat.BINARY;
progress(name, ul, 512, function(e:Event):void {
ul.data.uncompress();
xmls[name] = new XML(ul.data);
if (--remain <= 0) complete();
});
}
public function makeLoader(name:String):Loader {
var ur:URLRequest = new URLRequest(path + name + '.swf');
var l:Loader = new Loader();
l.load(ur, HERE);
return l;
}
private function loadSWF(name:String):void {
var l:Loader = makeLoader(name);
progress(name, l.contentLoaderInfo, 16384, function(e:Event):void {
if (--remain <= 0) complete();
});
}
protected function complete():void {
trace('all resources loaded');
}
}
internal class Driver extends ResourceLoader {
public static const SKIP_IMAGES:Boolean = false;
public static const SKIP_PAGES:Boolean = false;
private static const YIELD_INTERVAL:int = 20;
private var xmlTasks:Array = [];
private var pageTasks:Array = [];
private var driving:Boolean = true;
private var countdown:Label;
private var summary:Label;
private function makePage(database:String, category:String, group:String, taskClass:Class):void {
var pageTask:PageTask = new PageTask(database, group);
PageTask.addNavigation(category, pageTask);
var items:XMLList = xmls[database].group.(@name == group).item;
for each (var item:XML in items) {
var xmlTask:XMLTask = new taskClass(item, pageTask);
xmlTask.enqueueDependents();
xmlTasks.push(xmlTask);
}
pageTasks.push(pageTask);
}
private function prepareAll():void {
if (SKIP_IMAGES) trace('skipping images');
if (SKIP_PAGES) trace('skipping pages');
for each (var text:XML in xmls['lang_en'].content.(@lang == 'en').text) {
new LinkTextTask(text).enqueue();
}
for each (var reward:XML in xmls['recipe_rewards'].reward) {
new LinkRecipeRewardTask(reward).enqueue();
}
for each (var item:XML in xmls['perk']..item) {
new XMLNilTask(item).enqueueDependents();
}
new RenderRatingTask().enqueue();
makePage('recipe', 'Recipe', 'Starter', XMLRecipeTask);
makePage('recipe', 'Recipe', 'Main', XMLRecipeTask);
makePage('recipe', 'Recipe', 'Dessert', XMLRecipeTask);
makePage('recipe', 'Recipe', 'Drink', XMLRecipeTask);
makePage('ingredient', 'Ingredient', 'Ingredient', XMLIngredientTask);
makePage('restaurant', 'Restaurant', 'Wall Decoration', XMLRestaurantTask);
makePage('restaurant', 'Restaurant', 'Door', XMLRestaurantTask);
makePage('restaurant', 'Restaurant', 'Decoration', XMLRestaurantTask);
makePage('restaurant', 'Restaurant', 'Table', XMLRestaurantTask);
makePage('restaurant', 'Restaurant', 'Chair', XMLRestaurantTask);
makePage('restaurant', 'Restaurant', 'Functional', XMLRestaurantTask);
makePage('restaurant', 'Restaurant', 'Floor Tile', XMLRestaurantTask);
makePage('restaurant', 'Restaurant', 'Wallpaper', XMLRestaurantTask);
makePage('restaurant', 'Restaurant', 'Kitchen Appliance', XMLRestaurantTask);
makePage('restaurant', 'Restaurant', 'Garden', XMLRestaurantTask);
makePage('avatar', 'Avatar', 'Pants', XMLAvatarTask);
makePage('avatar', 'Avatar', 'Skirt', XMLAvatarTask);
makePage('avatar', 'Avatar', 'Shirt', XMLAvatarTask);
makePage('avatar', 'Avatar', 'Hat', XMLAvatarTask);
makePage('avatar', 'Avatar', 'Hair', XMLAvatarTask);
makePage('avatar', 'Avatar', 'Eyes', XMLTextureTask);
makePage('avatar', 'Avatar', 'Mouth', XMLTextureTask);
makePage('avatar', 'Avatar', 'Eyebrows', XMLTextureTask);
makePage('avatar', 'Avatar', 'Miscellaneous', XMLTextureTask);
makePage('avatar', 'Avatar', 'Facial Hair', XMLTextureTask);
makePage('front', 'Front', 'Window', XMLFrontTask);
makePage('front', 'Front', 'Door', XMLFrontTask);
makePage('front', 'Front', 'Roof', XMLFrontLargeTask);
makePage('front', 'Front', 'Wall Decoration', XMLFrontTask);
makePage('front', 'Front', 'Street Decoration', XMLFrontTask);
makePage('front', 'Front', 'Functional', XMLFrontTask);
makePage('front', 'Front', 'Tile', XMLFrontTask);
makePage('front', 'Front', 'Body', XMLFrontLargeTask);
makePage('front', 'Front', 'Banner', XMLFrontTask);
makePage('mystery_box', 'MysteryBox', 'MysteryBox', XMLMysteryBoxTask);
for each (var xmlTask:XMLTask in xmlTasks) {
xmlTask.enqueue();
}
for each (var pageTask:PageTask in pageTasks) {
pageTask.enqueue();
}
}
private function save():void {
var ba:ByteArray = Task.zip();
stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
new FileReference().save(ba, 'db.zip');
});
}
private function frame(e:Event):void {
if (Task.remaining) {
if (driving) {
var w:int = getTimer();
do {
var t:Task = Task.dequeue();
if (!t) {
driving = false;
break;
}
var s:String = t.summary;
summary.text = s;
try {
t.execute();
} catch (e:*) {
error(e + ' while ' + s);
}
} while (getTimer() - w < YIELD_INTERVAL);
}
if (!driving) {
summary.text = 'joining detached tasks';
}
}
if (Task.remaining) {
countdown.text = Task.remaining + ' tasks remaining';
} else {
removeEventListener(Event.ENTER_FRAME, frame);
countdown.text = 'done';
summary.text = 'click to save';
save();
}
}
override protected function complete():void {
super.complete();
prepareAll();
countdown = trace(Task.remaining + ' tasks remaining');
summary = trace('');
addEventListener(Event.ENTER_FRAME, frame);
}
}
internal class Task {
private static const archive:ZipOutput = new ZipOutput();
private static const queue:Array = [];
private static var index:int = 0;
private static var detached:int = 0;
public static function finish():ByteArray {
archive.finish();
return archive.byteArray;
}
public static function dequeue():Task {
if (queue[index]) {
return queue[index++];
} else {
return null;
}
}
public static function get remaining():int {
return queue.length - index + detached;
}
public static function zip():ByteArray {
archive.finish();
return archive.byteArray;
}
protected function trace(message:*):Label {
return Console.instance.trace(message);
}
protected function error(message:*):void {
Console.instance.error(message);
}
protected function write(name:String, data:ByteArray):void {
archive.putNextEntry(new ZipEntry(name));
archive.write(data);
archive.closeEntry();
}
public function get summary():String { return getQualifiedClassName(this); }
public function execute():void {}
public function enqueue():void {
queue.push(this);
}
protected function fork():void {
detached++;
}
protected function join():void {
detached--;
}
}
internal class RenderTask extends Task {
private static const nameSet:Object = {}
protected var name:String;
public function RenderTask(name:String) {
this.name = name;
}
protected function render(directory:String, mc:MovieClip, scale:Number):void {
var n:String = directory + '/' + name + '.png';
var r:Rectangle = mc.getBounds(null);
var left:Number = Math.floor(r.left * scale);
var top:Number = Math.floor(r.top * scale);
var bd:BitmapData = new BitmapData(
Math.ceil(r.right * scale) - left,
Math.ceil(r.bottom * scale) - top,
true, 0x00000000
);
bd.draw(mc, new Matrix(scale, 0, 0, scale, -left, -top));
write(n, PNGEncoder.encode(bd));
bd.dispose();
}
protected function hide(mc:MovieClip, variable:String, stop:Boolean=false):void {
if (mc[variable]) {
mc[variable].visible = false;
if (stop) mc[variable].stop();
}
}
protected function prepare(mc:MovieClip):void {
hide(mc, 'mc_rect');
hide(mc, 'mc_bound');
hide(mc, 'mc_mask');
}
protected function get imageScale():Number { return 1.0; }
protected function get iconScale():Number { return 0.5; }
override public function get summary():String { return 'rendering ' + name; }
private function clip():MovieClip {
var mc:MovieClip = new (ApplicationDomain.currentDomain.getDefinition(name) as Class)();
prepare(mc);
return mc;
}
override public function execute():void {
var mc:MovieClip = clip();
if (!isNaN(imageScale)) render('images', mc, imageScale);
if (!isNaN(iconScale)) render('icons', mc, iconScale);
}
override public function enqueue():void {
if (Driver.SKIP_IMAGES || name == 'null') return;
if (!(name in nameSet)) super.enqueue();
nameSet[name] = true;
}
public function debug():MovieClip {
var s:Stage = Console.instance.stage;
var mc:MovieClip = clip();
trace(describeType(mc)..variable.toXMLString());
mc.x = s.stageWidth >> 1;
mc.y = (s.stageHeight >> 1) + 100; // %%%
s.addChild(mc);
var l:Label = trace('mouseover to inspect');
mc.addEventListener(MouseEvent.MOUSE_MOVE, function(e:MouseEvent):void {
var a:Array = mc.getObjectsUnderPoint(new Point(e.stageX, e.stageY));
if (!a.length) return;
var d:DisplayObject = a.pop();
l.text = mc.name + ' / ' + d + ' ' + d.name + ' (' + d.parent.getChildIndex(d) + ' ' + d.parent.name + ')';
});
mc.addEventListener(MouseEvent.MOUSE_OUT, function(e:MouseEvent):void {
l.text = 'mouseover to inspect';
});
var r:Rectangle = mc.getBounds(s);
var sh:Shape = new Shape();
sh.graphics.lineStyle(0, 0x00ff00);
sh.graphics.drawRect(r.x, r.y, r.width, r.height);
s.addChild(sh);
return mc;
}
}
internal class RenderExternalTask extends RenderTask {
public function RenderExternalTask(name:String) { super(name); }
override public function get summary():String { return 'loading ' + name; }
override public function execute():void {
if (ApplicationDomain.currentDomain.hasDefinition(name)) {
super.execute();
return;
}
var l:Loader = ResourceLoader.instance.makeLoader('swf/' + name);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, complete);
l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);
fork();
}
private function complete(e:Event):void {
super.execute();
join();
}
private function ioError(e:IOErrorEvent):void {
error('IOError while ' + summary);
join();
}
}
internal class RenderRecipeTask extends RenderTask {
public function RenderRecipeTask(name:String) { super(name); }
override protected function prepare(mc:MovieClip):void {
if (mc.mc_plate) mc.mc_plate.gotoAndStop(2);
super.prepare(mc);
}
override protected function get imageScale():Number { return 2.75; }
override protected function get iconScale():Number { return 0.75; }
}
internal class RenderIngredientTask extends RenderTask {
public function RenderIngredientTask(name:String) { super(name); }
override protected function get imageScale():Number { return 1.5; }
}
internal class RenderRatingTask extends RenderTask {
public function RenderRatingTask() { super('StarRating'); }
override protected function get iconScale():Number { return NaN; }
override protected function render(directory:String, mc:MovieClip, scale:Number):void {
var origName:String = name;
for (var i:int = 1; i <= 5; i++) {
name = origName + i;
mc.gotoAndStop(i);
super.render(directory, mc, scale);
}
name = origName;
}
}
internal class RenderPlantTask extends RenderTask {
public function RenderPlantTask(name:String) { super(name); }
override protected function prepare(mc:MovieClip):void {
mc.gotoAndStop(mc.totalFrames);
super.prepare(mc);
}
override protected function get iconScale():Number { return NaN; }
}
internal class RenderRestaurantTask extends RenderTask {
public function RenderRestaurantTask(name:String) { super(name); }
private function loop(mc:MovieClip, variable:String, recurse:Boolean=false):void {
for (var i:int = 0; mc[variable + i]; i++) {
if (recurse) {
prepare(mc[variable + i]);
} else {
mc[variable + i].visible = false;
}
}
}
override protected function prepare(mc:MovieClip):void {
mc.stop();
hide(mc, 'property_chair', true);
hide(mc, 'property_table', true);
hide(mc, 'corner1');
hide(mc, 'corner2');
hide(mc, 'corner3');
hide(mc, 'corner4');
loop(mc, 'mc_customer');
hide(mc, 'mc_focus');
loop(mc, 'mc_walkable');
loop(mc, 'sub', true);
loop(mc, 'mc_attach', true);
hide(mc, 'mc_stove');
hide(mc, 'mc_drinkItem');
super.prepare(mc);
}
}
internal class RenderAvatarTask extends RenderTask {
public function RenderAvatarTask(name:String) { super(name); }
override protected function get imageScale():Number { return 1.5; }
}
internal class RenderFrontTask extends RenderExternalTask {
public function RenderFrontTask(name:String) { super(name); }
override protected function get imageScale():Number { return 1.5; }
override protected function get iconScale():Number { return 0.4; }
}
internal class RenderFrontLargeTask extends RenderFrontTask {
public function RenderFrontLargeTask(name:String) { super(name); }
override protected function get imageScale():Number { return 1.0; }
override protected function get iconScale():Number { return 0.2; }
}
internal class RenderNilTask extends RenderTask {
public function RenderNilTask(name:String) { super(name); }
override protected function get imageScale():Number { return NaN; }
override protected function get iconScale():Number { return 0.25; }
}
internal class RenderMysteryBoxTask extends RenderTask {
public function RenderMysteryBoxTask(name:String) { super(name); }
override protected function get iconScale():Number { return 1.0 / 6.0; }
override protected function prepare(mc:MovieClip):void {
hide(mc, 'mc_crate');
hide(mc, 'tf_count');
mc.getChildAt(0).visible = false;
super.prepare(mc);
}
}
internal class XMLTask extends Task {
public static const NOTHING:XML = XML('');
public static var idMap:Object = {};
public static var classMap:Object = {};
protected var item:XML;
private var pageTask:PageTask;
public var itemDescription:XML = <span class='text -link-itemDescription' />;
public var itemFunction:XML = <span class='text -link-itemFunction' />;
public var fromMysteryBoxes:XML = listUl('-link-fromMysteryBoxes');
public function XMLTask(item:XML, pageTask:PageTask) {
this.item = item;
this.pageTask = pageTask;
idMap[item.@id] = this;
classMap[item.attribute(classAttribute)] = this;
}
protected function name():XML {
return (<h2>{item.@name}</h2>);
}
protected function get classAttribute():String { return 'className'; }
protected function image(attributeName:String, force:Boolean=false):XML {
if (force || ('@' + attributeName) in item) {
var s:String = item.attribute(attributeName);
return (
<span class={'image ' + attributeName}>
<img src={'images/' + s + '.png'} alt={item.@name} title={item.@name} />
</span>
);
}
return NOTHING;
}
protected function link(icon:Boolean=true):XML {
if (icon) {
return (
<a href={pageTask.path + '#item' + item.@id}>
<img src={'icons/' + item.attribute(classAttribute) + '.png'} alt={item.@name} title={item.@name} />
</a>
);
} else {
return (<a href={pageTask.path + '#item' + item.@id}>{item.@name}</a>);
}
}
protected function nonEmpty(xml:XML):XML {
if (xml.children().length()) return xml;
return NOTHING;
}
protected function listUl(attributeName:String):XML {
return (<ul class={'list ' + attributeName} />);
}
public function listLi(icon:Boolean=true):XML {
return (<li>{link(icon)}</li>);
}
protected function literal(attributeName:String):XML {
if (('@' + attributeName) in item) {
var s:String = item.attribute(attributeName);
return (<span class={'literal ' + attributeName}>{s}</span>);
}
return NOTHING;
}
protected function date(attributeName:String):XML {
if (('@' + attributeName) in item) {
var s:String = item.attribute(attributeName);
s = s.substr(6, 4) + '/' + s.substr(3, 2) + '/' + s.substr(0, 2);
return (<span class={'date ' + attributeName}>{s}</span>);
}
return NOTHING;
}
protected function flag(attributeName:String):XML {
if (('@' + attributeName) in item) {
var s:String = item.attribute(attributeName).toLowerCase();
if (s != 'true' && s != '1' && s != 'yes' && s != 'on') return NOTHING;
return (<span class={'flag ' + attributeName} />);
}
return NOTHING;
}
protected function enum(attributeName:String):XML {
if (('@' + attributeName) in item) {
var s:String = item.attribute(attributeName);
return (<span class={'enum ' + attributeName + ' -enum-' + s} />);
}
return NOTHING;
}
protected function availability():XMLList {
return (
date('availableDate') +
date('expireDate') +
flag('invisible')
);
}
protected function description():XMLList {
return (
nonEmpty(itemDescription) +
nonEmpty(itemFunction)
);
}
protected function content():XML {
var div:XML =
<div id={'item' + item.@id} class="item">
{image(classAttribute, true)}
{name()}
</div>;
div.normalize();
return div;
}
override public function get summary():String { return 'creating entry ' + item.@name; }
override public function execute():void {
pageTask.appendChild(content());
}
public function enqueueDependents():void {
new RenderTask(item.attribute(classAttribute)).enqueue();
}
override public function enqueue():void {
if (!Driver.SKIP_PAGES) super.enqueue();
}
}
internal class XMLRecipeTask extends XMLTask {
public var ingredients:XML = listUl('ingredients');
public var unlockRecipes:XML = listUl('unlockRecipes');
public var rewards:XML = listUl('-link-rewards');
public function XMLRecipeTask(item:XML, pageTask:PageTask) { super(item, pageTask); }
override protected function content():XML {
var div:XML = super.content();
div.appendChild(
ingredients +
description() +
(
<div class="misc">
{flag('isLimited')}
{availability()}
{flag('foodKingFeed')}
</div>
) +
nonEmpty(unlockRecipes) +
nonEmpty(rewards) +
nonEmpty(fromMysteryBoxes)
);
div.normalize();
return div;
}
override public function enqueueDependents():void {
new LinkRecipeTask(item, this).enqueue();
new RenderRecipeTask(item.@className).enqueue();
}
}
internal class XMLIngredientTask extends XMLTask {
public static var nameMap:Object = {};
public var recipes:XML = listUl('-link-recipes');
public function XMLIngredientTask(item:XML, pageTask:PageTask) {
super(item, pageTask);
nameMap[item.@name] = this;
}
override protected function content():XML {
var div:XML = super.content();
div.appendChild(
enum('rarity') +
literal('cash') +
description() +
recipes +
(
<div class="misc">
{flag('isNew')}
{availability()}
{flag('foodKingFeed')}
{flag('fanPageFeed')}
{flag('noDaily')}
{flag('noFirstTimeVisit')}
{flag('noQuiz')}
{flag('noCoinShop')}
{literal('initial')}
{literal('freeGiftUnlockLevel')}
</div>
) +
image('plantClassName') +
nonEmpty(fromMysteryBoxes)
);
div.normalize();
return div;
}
override public function enqueueDependents():void {
new RenderIngredientTask(item.@className).enqueue();
if ('@plantClassName' in item) new RenderPlantTask(item.@plantClassName).enqueue();
}
}
internal class XMLRestaurantTask extends XMLTask {
public var fromRecipes:XML = listUl('-link-fromRecipes');
public function XMLRestaurantTask(item:XML, pageTask:PageTask) { super(item, pageTask); }
override protected function content():XML {
var div:XML = super.content();
div.appendChild(
literal('cost') +
literal('cash') +
description() +
(
<div class="misc">
{literal('unlockLevel')}
{availability()}
{flag('foodKingFeed')}
</div>
) +
nonEmpty(fromRecipes) +
nonEmpty(fromMysteryBoxes)
);
div.normalize();
return div;
}
override public function enqueueDependents():void {
new RenderRestaurantTask(item.@className).enqueue();
}
}
internal class XMLAvatarTask extends XMLTask {
public function XMLAvatarTask(item:XML, pageTask:PageTask) { super(item, pageTask); }
override protected function get classAttribute():String { return 'iconName'; }
override protected function content():XML {
var div:XML = super.content();
div.appendChild(
literal('cost') +
literal('cash') +
description() +
(
<div class="misc">
{availability()}
</div>
) +
nonEmpty(fromMysteryBoxes)
);
div.normalize();
return div;
}
override public function enqueueDependents():void {
if ('@iconName' in item) new RenderAvatarTask(item.@iconName).enqueue();
}
}
internal class XMLTextureTask extends XMLAvatarTask {
public function XMLTextureTask(item:XML, pageTask:PageTask) { super(item, pageTask); }
override protected function get classAttribute():String { return 'texture'; }
override public function enqueueDependents():void {
if ('@texture' in item) new RenderTask(item.@texture).enqueue();
}
}
internal class XMLFrontTask extends XMLTask {
public function XMLFrontTask(item:XML, pageTask:PageTask) { super(item, pageTask); }
override protected function content():XML {
var div:XML = super.content();
div.appendChild(
literal('cost') +
literal('cash') +
description() +
(
<div class="misc">
{literal('unlockLevel')}
{availability()}
{flag('foodKingFeed')}
</div>
) +
nonEmpty(fromMysteryBoxes)
);
div.normalize();
return div;
}
override public function enqueueDependents():void {
new RenderFrontTask(item.@className).enqueue();
}
}
internal class XMLFrontLargeTask extends XMLFrontTask {
public function XMLFrontLargeTask(item:XML, pageTask:PageTask) { super(item, pageTask); }
override public function enqueueDependents():void {
new RenderFrontLargeTask(item.@className).enqueue();
}
}
internal class XMLNilTask extends XMLTask {
public function XMLNilTask(item:XML) { super(item, null); }
override protected function link(icon:Boolean=true):XML {
if (icon) {
return (
<img src={'icons/' + item.attribute(classAttribute) + '.png'} alt={item.@name} title={item.@name} />
);
} else {
return XML(item.@name);
}
}
override public function enqueue():void {}
override public function enqueueDependents():void {
if ('@className' in item) new RenderNilTask(item.@className).enqueue();
}
}
internal class XMLMysteryBoxTask extends XMLTask {
public var contentItems:XML = listUl('contentItems');
public function XMLMysteryBoxTask(item:XML, pageTask:PageTask) { super(item, pageTask); }
private function pricing():XML {
var div:XML = <div class="pricing" />;
for each (var priceItem:XML in item.pricing.child('price-item')) {
// no mystery boxes are available for coins...
div.appendChild(
<span class="price-item">
<span class="quantity">{priceItem.@quantity}</span>
<span class="cash">{priceItem.@cash}</span>
</span>
);
}
return div;
}
override protected function content():XML {
var div:XML = super.content();
div.appendChild(
pricing() +
description() +
(
<div class="misc">
{availability()}
</div>
) +
nonEmpty(contentItems) +
nonEmpty(fromMysteryBoxes)
// TODO: unlocks
);
div.normalize();
return div;
}
override public function enqueueDependents():void {
new LinkMysteryBoxTask(item, this).enqueue();
new RenderMysteryBoxTask(item.@className).enqueue();
}
}
internal class PageTask extends Task {
private static var navigation:XML = <ul id="navigation" />;
private static var category:String = null;
public static function addNavigation(category:String, pageTask:PageTask):void {
var li:XML =
<li>
<a href={pageTask.path}>{pageTask.group}</a>
</li>;
if (category == PageTask.category) {
var lis:XMLList = navigation.li;
lis[lis.length() - 1].ul.appendChild(li);
} else {
PageTask.category = category;
navigation.appendChild(
<li class="database">
<span>{category}</span>
<ul>{li}</ul>
</li>
);
}
}
private var database:String;
private var group:String;
private var wrapper:XML = <div id="wrapper" />;
public function PageTask(database:String, group:String):void {
this.database = database;
this.group = group;
}
public function get groupId():String {
return group.replace(/ /g, '_');
}
public function get name():String {
return database + '-' + groupId;
}
public function get path():String {
return name + '.xhtml';
}
public function appendChild(child:Object):void {
wrapper.appendChild(child);
}
override public function get summary():String { return 'compiling page ' + path; }
override public function execute():void {
var html:XML =
<html>
<head>
<title>{group}</title>
<link rel="stylesheet" type="text/css" href="static/db.css" />
</head>
<body id={name}>
<h1>{group}</h1>
{navigation}
{wrapper}
</body>
</html>;
html.@xmlns = 'http://www.w3.org/1999/xhtml';
var ba:ByteArray = new ByteArray();
ba.writeUTFBytes(html.toXMLString());
write(path, ba);
}
override public function enqueue():void {
if (!Driver.SKIP_PAGES) super.enqueue();
}
}
internal class LinkTask extends Task {
protected var xml:XML;
public function LinkTask(xml:XML) {
this.xml = xml;
}
override public function enqueue():void {
if (!Driver.SKIP_PAGES) super.enqueue();
}
protected function split(attributeName:String):Array {
if (!('@' + attributeName in xml)) return [];
return xml.attribute(attributeName).split(/\s*,\s*/);
}
}
internal class LinkRecipeTask extends LinkTask {
private var recipeTask:XMLRecipeTask;
public function LinkRecipeTask(item:XML, recipeTask:XMLRecipeTask) {
super(item);
this.recipeTask = recipeTask;
}
override public function get summary():String { return 'linking recipe ' + xml.@name; }
override public function execute():void {
var ingredientTask:XMLIngredientTask;
var ingredientName:String;
var ingredientSet:Object = {};
for each (ingredientName in split('ingredients')) {
ingredientTask = XMLIngredientTask.nameMap[ingredientName];
recipeTask.ingredients.appendChild(ingredientTask.listLi());
ingredientSet[ingredientName] = true;
}
for (ingredientName in ingredientSet) {
ingredientTask = XMLIngredientTask.nameMap[ingredientName];
ingredientTask.recipes.appendChild(recipeTask.listLi());
}
for each (var recipeId:String in split('unlockRecipes')) {
var recipeTask2:XMLRecipeTask = XMLTask.idMap[recipeId];
recipeTask.unlockRecipes.appendChild(recipeTask2.listLi());
}
}
}
internal class LinkTextTask extends LinkTask {
private static const prefixMap:Object = {
'ItemDescription': 'itemDescription',
'ItemFunction': 'itemFunction'
};
private var className:String;
private var field:String;
public function LinkTextTask(text:XML):void { super(text); }
override public function get summary():String { return 'linking text ' + xml.@id; }
override public function execute():void {
var task:XMLTask = XMLTask.classMap[className];
if (!task) return;
var s:String = xml.toString();
s = s.replace(/\\n/g, '\n');
s = s.replace(/\\%/g, '%');
s = s.replace(/<[^>]*>/g, '');
// no description text contains meta replacements...
task[field].appendChild(s);
}
override public function enqueue():void {
var id:String = xml.@id;
for (var prefix:String in prefixMap) {
if (id.substr(0, prefix.length) == prefix) {
className = id.substr(prefix.length);
field = prefixMap[prefix];
super.enqueue();
break;
}
}
}
}
internal class LinkRecipeRewardTask extends LinkTask {
public function LinkRecipeRewardTask(reward:XML) { super(reward); }
override public function get summary():String { return 'linking reward ' + xml.@name; }
override public function execute():void {
var restaurantTask:XMLRestaurantTask = XMLTask.idMap[xml.@id];
for each (var recipe:XML in xml.recipe) {
var recipeTask:XMLRecipeTask = XMLTask.idMap[recipe.@id];
restaurantTask.fromRecipes.appendChild(recipeTask.listLi());
recipeTask.rewards.appendChild(restaurantTask.listLi());
}
}
}
internal class LinkMysteryBoxTask extends LinkTask {
private var mysteryBoxTask:XMLMysteryBoxTask;
public function LinkMysteryBoxTask(item:XML, mysteryBoxTask:XMLMysteryBoxTask) {
super(item);
this.mysteryBoxTask = mysteryBoxTask;
}
override public function get summary():String { return 'linking mystery box ' + xml.@name; }
override public function execute():void {
var task:XMLTask;
var itemId:String;
var contentItemSet:Object = {};
for each (var itemGroup:XML in xml.itemGroup) {
var ul:XML = <ul class="itemGroup" />;
var weight:int = parseInt(itemGroup.@weight, 10);
for each (var contentItem:XML in itemGroup.child('content-item')) {
itemId = contentItem.@id;
task = XMLTask.idMap[itemId];
var li:XML = task.listLi(false);
li.prependChild(
<span class="weight">{weight * parseInt(contentItem.@weight, 10)}</span>
);
ul.appendChild(li);
contentItemSet[itemId] = true;
}
mysteryBoxTask.contentItems.appendChild(
<li>{ul}</li>
);
}
for (itemId in contentItemSet) {
task = XMLTask.idMap[itemId];
task.fromMysteryBoxes.appendChild(mysteryBoxTask.listLi());
}
}
}