Section 1
//BitString (com.adobe.images.BitString)
package com.adobe.images {
public class BitString {
public var val:int;// = 0
public var len:int;// = 0
public function BitString(){
len = 0;
val = 0;
super();
}
}
}//package com.adobe.images
Section 2
//JPGEncoder (com.adobe.images.JPGEncoder)
package com.adobe.images {
import flash.display.*;
import flash.utils.*;
import flash.geom.*;
public class JPGEncoder {
private var fdtbl_UV:Array;
private var std_ac_chrominance_values:Array;
private var std_dc_chrominance_nrcodes:Array;
private var std_dc_chrominance_values:Array;
private var ZigZag:Array;
private var YDC_HT:Array;
private var bytenew:int;// = 0
private var fdtbl_Y:Array;
private var YAC_HT:Array;
private var std_ac_chrominance_nrcodes:Array;
private var DU:Array;
private var std_ac_luminance_values:Array;
private var UVTable:Array;
private var UDU:Array;
private var YDU:Array;
private var byteout:ByteArray;
private var UVAC_HT:Array;
private var UVDC_HT:Array;
private var bytepos:int;// = 7
private var VDU:Array;
private var std_ac_luminance_nrcodes:Array;
private var std_dc_luminance_values:Array;
private var YTable:Array;
private var std_dc_luminance_nrcodes:Array;
private var bitcode:Array;
private var category:Array;
public function JPGEncoder(quality:Number=50){
var sf:int;
ZigZag = [0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63];
YTable = new Array(64);
UVTable = new Array(64);
fdtbl_Y = new Array(64);
fdtbl_UV = new Array(64);
std_dc_luminance_nrcodes = [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0];
std_dc_luminance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
std_ac_luminance_nrcodes = [0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125];
std_ac_luminance_values = [1, 2, 3, 0, 4, 17, 5, 18, 33, 49, 65, 6, 19, 81, 97, 7, 34, 113, 20, 50, 129, 145, 161, 8, 35, 66, 177, 193, 21, 82, 209, 240, 36, 51, 98, 114, 130, 9, 10, 22, 23, 24, 25, 26, 37, 38, 39, 40, 41, 42, 52, 53, 54, 55, 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117, 118, 119, 120, 121, 122, 131, 132, 133, 134, 135, 136, 137, 138, 146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163, 164, 165, 166, 167, 168, 169, 170, 178, 179, 180, 181, 182, 183, 184, 185, 186, 194, 195, 196, 197, 198, 199, 200, 201, 202, 210, 211, 212, 213, 214, 215, 216, 217, 218, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250];
std_dc_chrominance_nrcodes = [0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0];
std_dc_chrominance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
std_ac_chrominance_nrcodes = [0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119];
std_ac_chrominance_values = [0, 1, 2, 3, 17, 4, 5, 33, 49, 6, 18, 65, 81, 7, 97, 113, 19, 34, 50, 129, 8, 20, 66, 145, 161, 177, 193, 9, 35, 51, 82, 240, 21, 98, 114, 209, 10, 22, 36, 52, 225, 37, 241, 23, 24, 25, 26, 38, 39, 40, 41, 42, 53, 54, 55, 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117, 118, 119, 120, 121, 122, 130, 131, 132, 133, 134, 135, 136, 137, 138, 146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163, 164, 165, 166, 167, 168, 169, 170, 178, 179, 180, 181, 182, 183, 184, 185, 186, 194, 195, 196, 197, 198, 199, 200, 201, 202, 210, 211, 212, 213, 214, 215, 216, 217, 218, 226, 227, 228, 229, 230, 231, 232, 233, 234, 242, 243, 244, 245, 246, 247, 248, 249, 250];
bitcode = new Array(0xFFFF);
category = new Array(0xFFFF);
bytenew = 0;
bytepos = 7;
DU = new Array(64);
YDU = new Array(64);
UDU = new Array(64);
VDU = new Array(64);
super();
if (quality <= 0){
quality = 1;
};
if (quality > 100){
quality = 100;
};
sf = 0;
if (quality < 50){
sf = int((5000 / quality));
} else {
sf = int((200 - (quality * 2)));
};
initHuffmanTbl();
initCategoryNumber();
initQuantTables(sf);
}
private function RGB2YUV(img:BitmapData, xpos:int, ypos:int):void{
var pos:int;
var y:int;
var x:int;
var P:uint;
var R:Number;
var G:Number;
var B:Number;
pos = 0;
y = 0;
while (y < 8) {
x = 0;
while (x < 8) {
P = img.getPixel32((xpos + x), (ypos + y));
R = Number(((P >> 16) & 0xFF));
G = Number(((P >> 8) & 0xFF));
B = Number((P & 0xFF));
YDU[pos] = ((((0.299 * R) + (0.587 * G)) + (0.114 * B)) - 128);
UDU[pos] = (((-0.16874 * R) + (-0.33126 * G)) + (0.5 * B));
VDU[pos] = (((0.5 * R) + (-0.41869 * G)) + (-0.08131 * B));
pos++;
x++;
};
y++;
};
}
private function writeWord(value:int):void{
writeByte(((value >> 8) & 0xFF));
writeByte((value & 0xFF));
}
private function writeByte(value:int):void{
byteout.writeByte(value);
}
private function writeDHT():void{
var i:int;
writeWord(65476);
writeWord(418);
writeByte(0);
i = 0;
while (i < 16) {
writeByte(std_dc_luminance_nrcodes[(i + 1)]);
i++;
};
i = 0;
while (i <= 11) {
writeByte(std_dc_luminance_values[i]);
i++;
};
writeByte(16);
i = 0;
while (i < 16) {
writeByte(std_ac_luminance_nrcodes[(i + 1)]);
i++;
};
i = 0;
while (i <= 161) {
writeByte(std_ac_luminance_values[i]);
i++;
};
writeByte(1);
i = 0;
while (i < 16) {
writeByte(std_dc_chrominance_nrcodes[(i + 1)]);
i++;
};
i = 0;
while (i <= 11) {
writeByte(std_dc_chrominance_values[i]);
i++;
};
writeByte(17);
i = 0;
while (i < 16) {
writeByte(std_ac_chrominance_nrcodes[(i + 1)]);
i++;
};
i = 0;
while (i <= 161) {
writeByte(std_ac_chrominance_values[i]);
i++;
};
}
private function writeBits(bs:BitString):void{
var value:int;
var posval:int;
value = bs.val;
posval = (bs.len - 1);
while (posval >= 0) {
if ((value & uint((1 << posval)))){
bytenew = (bytenew | uint((1 << bytepos)));
};
posval--;
bytepos--;
if (bytepos < 0){
if (bytenew == 0xFF){
writeByte(0xFF);
writeByte(0);
} else {
writeByte(bytenew);
};
bytepos = 7;
bytenew = 0;
};
};
}
private function initHuffmanTbl():void{
YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes, std_dc_luminance_values);
UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes, std_dc_chrominance_values);
YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes, std_ac_luminance_values);
UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes, std_ac_chrominance_values);
}
public function encode(image:BitmapData):ByteArray{
var DCY:Number;
var DCU:Number;
var DCV:Number;
var ypos:int;
var xpos:int;
var fillbits:BitString;
byteout = new ByteArray();
bytenew = 0;
bytepos = 7;
writeWord(65496);
writeAPP0();
writeDQT();
writeSOF0(image.width, image.height);
writeDHT();
writeSOS();
DCY = 0;
DCU = 0;
DCV = 0;
bytenew = 0;
bytepos = 7;
ypos = 0;
while (ypos < image.height) {
xpos = 0;
while (xpos < image.width) {
RGB2YUV(image, xpos, ypos);
DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
xpos = (xpos + 8);
};
ypos = (ypos + 8);
};
if (bytepos >= 0){
fillbits = new BitString();
fillbits.len = (bytepos + 1);
fillbits.val = ((1 << (bytepos + 1)) - 1);
writeBits(fillbits);
};
writeWord(65497);
return (byteout);
}
private function initCategoryNumber():void{
var nrlower:int;
var nrupper:int;
var nr:int;
var cat:int;
nrlower = 1;
nrupper = 2;
cat = 1;
while (cat <= 15) {
nr = nrlower;
while (nr < nrupper) {
category[(32767 + nr)] = cat;
bitcode[(32767 + nr)] = new BitString();
bitcode[(32767 + nr)].len = cat;
bitcode[(32767 + nr)].val = nr;
nr++;
};
nr = -((nrupper - 1));
while (nr <= -(nrlower)) {
category[(32767 + nr)] = cat;
bitcode[(32767 + nr)] = new BitString();
bitcode[(32767 + nr)].len = cat;
bitcode[(32767 + nr)].val = ((nrupper - 1) + nr);
nr++;
};
nrlower = (nrlower << 1);
nrupper = (nrupper << 1);
cat++;
};
}
private function writeDQT():void{
var i:int;
writeWord(65499);
writeWord(132);
writeByte(0);
i = 0;
while (i < 64) {
writeByte(YTable[i]);
i++;
};
writeByte(1);
i = 0;
while (i < 64) {
writeByte(UVTable[i]);
i++;
};
}
private function writeAPP0():void{
writeWord(65504);
writeWord(16);
writeByte(74);
writeByte(70);
writeByte(73);
writeByte(70);
writeByte(0);
writeByte(1);
writeByte(1);
writeByte(0);
writeWord(1);
writeWord(1);
writeByte(0);
writeByte(0);
}
private function writeSOS():void{
writeWord(65498);
writeWord(12);
writeByte(3);
writeByte(1);
writeByte(0);
writeByte(2);
writeByte(17);
writeByte(3);
writeByte(17);
writeByte(0);
writeByte(63);
writeByte(0);
}
private function processDU(CDU:Array, fdtbl:Array, DC:Number, HTDC:Array, HTAC:Array):Number{
var EOB:BitString;
var M16zeroes:BitString;
var i:int;
var DU_DCT:Array;
var Diff:int;
var end0pos:int;
var startpos:int;
var nrzeroes:int;
var nrmarker:int;
EOB = HTAC[0];
M16zeroes = HTAC[240];
DU_DCT = fDCTQuant(CDU, fdtbl);
i = 0;
while (i < 64) {
DU[ZigZag[i]] = DU_DCT[i];
i++;
};
Diff = (DU[0] - DC);
DC = DU[0];
if (Diff == 0){
writeBits(HTDC[0]);
} else {
writeBits(HTDC[category[(32767 + Diff)]]);
writeBits(bitcode[(32767 + Diff)]);
};
end0pos = 63;
while ((((end0pos > 0)) && ((DU[end0pos] == 0)))) {
end0pos--;
};
if (end0pos == 0){
writeBits(EOB);
return (DC);
};
i = 1;
while (i <= end0pos) {
startpos = i;
while ((((DU[i] == 0)) && ((i <= end0pos)))) {
i++;
};
nrzeroes = (i - startpos);
if (nrzeroes >= 16){
nrmarker = 1;
while (nrmarker <= (nrzeroes / 16)) {
writeBits(M16zeroes);
nrmarker++;
};
nrzeroes = int((nrzeroes & 15));
};
writeBits(HTAC[((nrzeroes * 16) + category[(32767 + DU[i])])]);
writeBits(bitcode[(32767 + DU[i])]);
i++;
};
if (end0pos != 63){
writeBits(EOB);
};
return (DC);
}
private function initQuantTables(sf:int):void{
var i:int;
var t:Number;
var YQT:Array;
var UVQT:Array;
var aasf:Array;
var row:int;
var col:int;
YQT = [16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99];
i = 0;
while (i < 64) {
t = Math.floor((((YQT[i] * sf) + 50) / 100));
if (t < 1){
t = 1;
} else {
if (t > 0xFF){
t = 0xFF;
};
};
YTable[ZigZag[i]] = t;
i++;
};
UVQT = [17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99];
i = 0;
while (i < 64) {
t = Math.floor((((UVQT[i] * sf) + 50) / 100));
if (t < 1){
t = 1;
} else {
if (t > 0xFF){
t = 0xFF;
};
};
UVTable[ZigZag[i]] = t;
i++;
};
aasf = [1, 1.387039845, 1.306562965, 1.175875602, 1, 0.785694958, 0.5411961, 0.275899379];
i = 0;
row = 0;
while (row < 8) {
col = 0;
while (col < 8) {
fdtbl_Y[i] = (1 / (((YTable[ZigZag[i]] * aasf[row]) * aasf[col]) * 8));
fdtbl_UV[i] = (1 / (((UVTable[ZigZag[i]] * aasf[row]) * aasf[col]) * 8));
i++;
col++;
};
row++;
};
}
private function writeSOF0(width:int, height:int):void{
writeWord(65472);
writeWord(17);
writeByte(8);
writeWord(height);
writeWord(width);
writeByte(3);
writeByte(1);
writeByte(17);
writeByte(0);
writeByte(2);
writeByte(17);
writeByte(1);
writeByte(3);
writeByte(17);
writeByte(1);
}
private function computeHuffmanTbl(nrcodes:Array, std_table:Array):Array{
var codevalue:int;
var pos_in_table:int;
var HT:Array;
var k:int;
var j:int;
codevalue = 0;
pos_in_table = 0;
HT = new Array();
k = 1;
while (k <= 16) {
j = 1;
while (j <= nrcodes[k]) {
HT[std_table[pos_in_table]] = new BitString();
HT[std_table[pos_in_table]].val = codevalue;
HT[std_table[pos_in_table]].len = k;
pos_in_table++;
codevalue++;
j++;
};
codevalue = (codevalue * 2);
k++;
};
return (HT);
}
private function fDCTQuant(data:Array, fdtbl:Array):Array{
var tmp0:Number;
var tmp1:Number;
var tmp2:Number;
var tmp3:Number;
var tmp4:Number;
var tmp5:Number;
var tmp6:Number;
var tmp7:Number;
var tmp10:Number;
var tmp11:Number;
var tmp12:Number;
var tmp13:Number;
var z1:Number;
var z2:Number;
var z3:Number;
var z4:Number;
var z5:Number;
var z11:Number;
var z13:Number;
var i:int;
var dataOff:int;
dataOff = 0;
i = 0;
while (i < 8) {
tmp0 = (data[(dataOff + 0)] + data[(dataOff + 7)]);
tmp7 = (data[(dataOff + 0)] - data[(dataOff + 7)]);
tmp1 = (data[(dataOff + 1)] + data[(dataOff + 6)]);
tmp6 = (data[(dataOff + 1)] - data[(dataOff + 6)]);
tmp2 = (data[(dataOff + 2)] + data[(dataOff + 5)]);
tmp5 = (data[(dataOff + 2)] - data[(dataOff + 5)]);
tmp3 = (data[(dataOff + 3)] + data[(dataOff + 4)]);
tmp4 = (data[(dataOff + 3)] - data[(dataOff + 4)]);
tmp10 = (tmp0 + tmp3);
tmp13 = (tmp0 - tmp3);
tmp11 = (tmp1 + tmp2);
tmp12 = (tmp1 - tmp2);
data[(dataOff + 0)] = (tmp10 + tmp11);
data[(dataOff + 4)] = (tmp10 - tmp11);
z1 = ((tmp12 + tmp13) * 0.707106781);
data[(dataOff + 2)] = (tmp13 + z1);
data[(dataOff + 6)] = (tmp13 - z1);
tmp10 = (tmp4 + tmp5);
tmp11 = (tmp5 + tmp6);
tmp12 = (tmp6 + tmp7);
z5 = ((tmp10 - tmp12) * 0.382683433);
z2 = ((0.5411961 * tmp10) + z5);
z4 = ((1.306562965 * tmp12) + z5);
z3 = (tmp11 * 0.707106781);
z11 = (tmp7 + z3);
z13 = (tmp7 - z3);
data[(dataOff + 5)] = (z13 + z2);
data[(dataOff + 3)] = (z13 - z2);
data[(dataOff + 1)] = (z11 + z4);
data[(dataOff + 7)] = (z11 - z4);
dataOff = (dataOff + 8);
i++;
};
dataOff = 0;
i = 0;
while (i < 8) {
tmp0 = (data[(dataOff + 0)] + data[(dataOff + 56)]);
tmp7 = (data[(dataOff + 0)] - data[(dataOff + 56)]);
tmp1 = (data[(dataOff + 8)] + data[(dataOff + 48)]);
tmp6 = (data[(dataOff + 8)] - data[(dataOff + 48)]);
tmp2 = (data[(dataOff + 16)] + data[(dataOff + 40)]);
tmp5 = (data[(dataOff + 16)] - data[(dataOff + 40)]);
tmp3 = (data[(dataOff + 24)] + data[(dataOff + 32)]);
tmp4 = (data[(dataOff + 24)] - data[(dataOff + 32)]);
tmp10 = (tmp0 + tmp3);
tmp13 = (tmp0 - tmp3);
tmp11 = (tmp1 + tmp2);
tmp12 = (tmp1 - tmp2);
data[(dataOff + 0)] = (tmp10 + tmp11);
data[(dataOff + 32)] = (tmp10 - tmp11);
z1 = ((tmp12 + tmp13) * 0.707106781);
data[(dataOff + 16)] = (tmp13 + z1);
data[(dataOff + 48)] = (tmp13 - z1);
tmp10 = (tmp4 + tmp5);
tmp11 = (tmp5 + tmp6);
tmp12 = (tmp6 + tmp7);
z5 = ((tmp10 - tmp12) * 0.382683433);
z2 = ((0.5411961 * tmp10) + z5);
z4 = ((1.306562965 * tmp12) + z5);
z3 = (tmp11 * 0.707106781);
z11 = (tmp7 + z3);
z13 = (tmp7 - z3);
data[(dataOff + 40)] = (z13 + z2);
data[(dataOff + 24)] = (z13 - z2);
data[(dataOff + 8)] = (z11 + z4);
data[(dataOff + 56)] = (z11 - z4);
dataOff++;
i++;
};
i = 0;
while (i < 64) {
data[i] = Math.round((data[i] * fdtbl[i]));
i++;
};
return (data);
}
}
}//package com.adobe.images
Section 3
//ArrayUtil (com.threerings.util.ArrayUtil)
package com.threerings.util {
public class ArrayUtil {
public function ArrayUtil(){
super();
}
public static function shuffle(arr:Array, rando:Random=null):void{
var idx:int;
var tmp:Object;
var arr = arr;
var rando = rando;
var randFunc:Function = ((rando)!=null) ? rando.nextInt : function (n:int):int{
return (int((Math.random() * n)));
};
var ii:int = (arr.length - 1);
while (ii > 0) {
idx = randFunc((ii + 1));
tmp = arr[idx];
arr[idx] = arr[ii];
arr[ii] = tmp;
ii = (ii - 1);
};
}
public static function removeAllIf(arr:Array, pred:Function):Boolean{
return (removeIfImpl(arr, pred, false));
}
private static function createEqualsPred(element:Object):Function{
var element = element;
return (function (other:Object):Boolean{
return (Util.equals(other, element));
});
}
private static function removeImpl(arr:Array, element:Object, firstOnly:Boolean):Boolean{
return (removeIfImpl(arr, createEqualsPred(element), firstOnly));
}
public static function equals(ar1:Array, ar2:Array):Boolean{
if (ar1 === ar2){
return (true);
};
if ((((((ar1 == null)) || ((ar2 == null)))) || (!((ar1.length == ar2.length))))){
return (false);
};
var jj:int;
while (jj < ar1.length) {
if (!Util.equals(ar1[jj], ar2[jj])){
return (false);
};
jj++;
};
return (true);
}
private static function removeIfImpl(arr:Array, pred:Function, firstOnly:Boolean):Boolean{
var removed:Boolean;
var ii:int;
while (ii < arr.length) {
if (pred(arr[ii])){
var _temp1 = ii;
ii = (ii - 1);
arr.splice(_temp1, 1);
if (firstOnly){
return (true);
};
removed = true;
};
ii++;
};
return (removed);
}
public static function indexOf(arr:Array, element:Object):int{
var ii:int;
if (arr != null){
ii = 0;
while (ii < arr.length) {
if (Util.equals(arr[ii], element)){
return (ii);
};
ii++;
};
};
return (-1);
}
public static function removeFirst(arr:Array, element:Object):Boolean{
return (removeImpl(arr, element, true));
}
public static function indexIf(arr:Array, predicate:Function):int{
var ii:int;
if (arr != null){
ii = 0;
while (ii < arr.length) {
if (predicate(arr[ii])){
return (ii);
};
ii++;
};
};
return (-1);
}
public static function removeFirstIf(arr:Array, pred:Function):Boolean{
return (removeIfImpl(arr, pred, true));
}
public static function copyOf(arr:Array):Array{
return (arr.slice());
}
public static function copy(src:Array, srcoffset:uint, dst:Array, dstoffset:uint, count:uint):void{
var ii:uint;
while (ii < count) {
var _temp1 = dstoffset;
dstoffset = (dstoffset + 1);
var _local7 = _temp1;
var _temp2 = srcoffset;
srcoffset = (srcoffset + 1);
dst[_local7] = src[_temp2];
ii++;
};
}
public static function findIf(arr:Array, predicate:Function){
var index:int = ((arr)!=null) ? indexIf(arr, predicate) : -1;
return (((index >= 0)) ? arr[index] : undefined);
}
public static function removeLastIf(arr:Array, pred:Function):Boolean{
arr.reverse();
var removed:Boolean = removeFirstIf(arr, pred);
arr.reverse();
return (removed);
}
public static function stableSort(arr:Array, comp:Function=null):void{
var val:*;
var jj:int;
var compVal:*;
if (comp == null){
comp = Comparators.COMPARABLE;
};
var nn:int = arr.length;
var ii = 1;
while (ii < nn) {
val = arr[ii];
jj = (ii - 1);
while (jj >= 0) {
compVal = arr[jj];
if (comp(val, compVal) >= 0){
break;
};
arr[(jj + 1)] = compVal;
jj--;
};
arr[(jj + 1)] = val;
ii++;
};
}
public static function removeLast(arr:Array, element:Object):Boolean{
arr.reverse();
var removed:Boolean = removeFirst(arr, element);
arr.reverse();
return (removed);
}
public static function create(size:uint, val=null):Array{
var arr:Array = new Array(size);
var ii:uint;
while (ii < size) {
arr[ii] = val;
ii++;
};
return (arr);
}
public static function removeAll(arr:Array, element:Object):Boolean{
return (removeImpl(arr, element, false));
}
public static function sort(arr:Array):void{
arr.sort(Comparators.COMPARABLE);
}
public static function contains(arr:Array, element:Object):Boolean{
return (!((indexOf(arr, element) == -1)));
}
}
}//package com.threerings.util
Section 4
//Comparable (com.threerings.util.Comparable)
package com.threerings.util {
public interface Comparable {
function compareTo(:Object):int;
}
}//package com.threerings.util
Section 5
//Comparators (com.threerings.util.Comparators)
package com.threerings.util {
public class Comparators {
public function Comparators(){
super();
}
public static function COMPARABLE(c1:Comparable, c2:Comparable):int{
if (c1 == c2){
return (0);
};
if (c1 == null){
return (-1);
};
if (c2 == null){
return (1);
};
return (c1.compareTo(c2));
}
}
}//package com.threerings.util
Section 6
//Equalable (com.threerings.util.Equalable)
package com.threerings.util {
public interface Equalable {
function equals(:Object):Boolean;
}
}//package com.threerings.util
Section 7
//MultiLoader (com.threerings.util.MultiLoader)
package com.threerings.util {
import flash.events.*;
import flash.display.*;
import flash.utils.*;
import flash.system.*;
import flash.net.*;
public class MultiLoader {
protected var _forEach:Boolean;
protected var _targetsToKeys:Dictionary;
protected var _remaining:int;// = 0
protected var _complete:Function;
protected var _result:Object;
protected static const _activeMultiLoaders:Dictionary = new Dictionary();
public function MultiLoader(sources:Object, completeCallback:Function, generatorFn:Function=null, forEach:Boolean=false, isCompleteCheckFn:String=null, errorTypes:Array=null, completeType:String=null){
var key:*;
var val:Object;
var ed:IEventDispatcher;
var type:String;
var sources = sources;
var completeCallback = completeCallback;
var generatorFn = generatorFn;
var forEach = forEach;
var isCompleteCheckFn = isCompleteCheckFn;
var errorTypes = errorTypes;
var completeType = completeType;
_targetsToKeys = new Dictionary(true);
super();
if (errorTypes == null){
errorTypes = [ErrorEvent.ERROR, AsyncErrorEvent.ASYNC_ERROR, IOErrorEvent.IO_ERROR, SecurityErrorEvent.SECURITY_ERROR];
};
if (completeType == null){
completeType = Event.COMPLETE;
};
_complete = completeCallback;
_forEach = forEach;
var endCheckKey:* = null;
if ((sources is Array)){
_result = new Array();
} else {
if ((sources is Dictionary)){
_result = new Dictionary();
} else {
_result = new Object();
if (!Util.isPlainObject(sources)){
sources = {singleton_key:sources};
endCheckKey = "singleton_key";
};
};
};
for (key in sources) {
val = sources[key];
if (generatorFn != null){
val = ((val is Array)) ? generatorFn.apply(null, (val as Array)) : generatorFn(val);
//unresolved jump
var _slot1 = err;
val = _slot1;
};
_result[key] = val;
if ((((val is IEventDispatcher)) && ((((isCompleteCheckFn == null)) || (!(val[isCompleteCheckFn]())))))){
ed = IEventDispatcher(val);
_remaining++;
_targetsToKeys[ed] = key;
ed.addEventListener(completeType, handleComplete);
for each (type in errorTypes) {
ed.addEventListener(type, handleError);
};
} else {
if (_forEach){
checkReport(key);
};
};
};
if (!_forEach){
checkReport(endCheckKey);
};
if (_remaining > 0){
_activeMultiLoaders[this] = true;
};
}
protected function handleError(event:ErrorEvent):void{
_result[_targetsToKeys[event.target]] = new Error(event.text);
handleComplete(event);
}
protected function handleComplete(event:Event):void{
_remaining--;
checkReport(_targetsToKeys[event.target]);
}
protected function checkReport(key):void{
var thisResult:Object;
var key = key;
if (((!(_forEach)) && ((_remaining > 0)))){
return;
};
thisResult = (((_forEach) || ((key === "singleton_key")))) ? _result[key] : _result;
_complete(thisResult);
//unresolved jump
var _slot1 = err;
trace((("MultiLoader: Error calling completeCallback [result=" + thisResult) + "]."));
trace(("Cause: " + _slot1.getStackTrace()));
if (_forEach){
delete _result[key];
};
if (_remaining == 0){
delete _activeMultiLoaders[this];
};
}
public static function getContents(sources:Object, completeCallback:Function, forEach:Boolean=false, appDom:ApplicationDomain=null):void{
var sources = sources;
var completeCallback = completeCallback;
var forEach = forEach;
var appDom = appDom;
var complete:Function = function (retval:Object):void{
completeCallback(processProperty(retval, Loader, "content"));
};
getLoaders(sources, complete, forEach, appDom);
}
public static function getLoaders(sources:Object, completeCallback:Function, forEach:Boolean=false, appDom:ApplicationDomain=null):void{
var sources = sources;
var completeCallback = completeCallback;
var forEach = forEach;
var appDom = appDom;
var generator:Function = function (source):Object{
var source = source;
if ((source is String)){
source = new URLRequest(String(source));
} else {
if ((source is Class)){
source = new ((source as Class));
};
};
var l:Loader = new Loader();
var lc:LoaderContext = new LoaderContext(false, appDom);
Object(lc)["allowLoadBytesCodeExecution"] = true;
//unresolved jump
var _slot1 = err;
if ((source is URLRequest)){
l.load(URLRequest(source), lc);
} else {
if ((source is ByteArray)){
l.loadBytes(ByteArray(source), lc);
} else {
return (new Error(("Unknown source: " + source)));
};
};
return (l.contentLoaderInfo);
};
var complete:Function = function (retval:Object):void{
completeCallback(processProperty(retval, LoaderInfo, "loader"));
};
new MultiLoader(sources, complete, generator, forEach);
}
protected static function processProperty(retval:Object, testClass:Class, prop:String):Object{
var key:*;
var o:Object;
if ((retval is testClass)){
retval = retval[prop];
} else {
for (key in retval) {
o = retval[key];
if ((o is testClass)){
retval[key] = o[prop];
};
};
};
return (retval);
}
}
}//package com.threerings.util
Section 8
//Random (com.threerings.util.Random)
package com.threerings.util {
public class Random {
protected var q:int;
protected var r:int;
protected var p:int;
protected var x:Array;
protected static const MATRIX_A:uint = 2567483615;
protected static const UPPER_MASK:uint = 2147483648;
protected static const LOWER_MASK:uint = 2147483647;
protected static const M:int = 397;
protected static const N:int = 624;
protected static var seedUniquifier:uint = 2812526361;
public function Random(seed:uint=0){
super();
if (seed == 0){
seed = uint((seedUniquifier++ + uint((Math.random() * 4294967295))));
};
x = new Array();
setSeed(seed);
}
public function setSeed(seed:uint):void{
x[0] = seed;
var i = 1;
while (i < N) {
x[i] = (imul(1812433253, (x[(i - 1)] ^ (x[(i - 1)] >>> 30))) + i);
x[i] = (x[i] & 4294967295);
i++;
};
p = 0;
q = 1;
r = M;
}
public function nextInt(n:int=0):int{
var bits:int;
var val:int;
if (n < 0){
throw (new Error("n must be positive"));
};
if (n == 0){
return (int(next(32)));
};
do {
bits = int(next(31));
val = (bits % n);
} while (((bits - val) + (n - 1)) < 0);
return (val);
}
public function nextBoolean():Boolean{
return (!((next(1) == 0)));
}
protected function next(bits:int):uint{
var y:uint = ((x[p] & UPPER_MASK) | (x[q] & LOWER_MASK));
x[p] = ((x[r] ^ (y >>> 1)) ^ ((y & 1) * MATRIX_A));
y = x[p];
if (++p == N){
p = 0;
};
if (++q == N){
q = 0;
};
if (++r == N){
r = 0;
};
y = (y ^ (y >>> 11));
y = (y ^ ((y << 7) & 2636928640));
y = (y ^ ((y << 15) & 4022730752));
y = (y ^ (y >>> 18));
return ((y >>> (32 - bits)));
}
protected function imul(a:Number, b:Number):Number{
var al:Number = (a & 0xFFFF);
var ah:Number = (a >>> 16);
var bl:Number = (b & 0xFFFF);
var bh:Number = (b >>> 16);
var ml:Number = (al * bl);
var mh:Number = (((((ml >>> 16) + (al * bh)) & 0xFFFF) + (ah * bl)) & 0xFFFF);
return (((mh << 16) | (ml & 0xFFFF)));
}
public function nextNumber():Number{
return ((next(32) / 4294967296));
}
}
}//package com.threerings.util
Section 9
//Util (com.threerings.util.Util)
package com.threerings.util {
import flash.utils.*;
public class Util {
public function Util(){
super();
}
public static function init(target:Object, initProps:Object, defaults:Object=null, maskProps:Object=null):void{
var prop:String;
for (prop in initProps) {
if ((((maskProps == null)) || (!((prop in maskProps))))){
target[prop] = initProps[prop];
};
};
if (defaults != null){
for (prop in defaults) {
if ((((initProps == null)) || (!((prop in initProps))))){
target[prop] = defaults[prop];
};
};
};
}
public static function XMLtoString(xml:XML, settings:Object=null):String{
var xml = xml;
var settings = settings;
return ((safeXMLOp(function (){
return (xml.toString());
}, settings) as String));
}
public static function unfuckVarargs(args:Array):Array{
return (((((args.length == 1)) && ((args[0] is Array)))) ? (args[0] as Array) : args);
}
public static function XMLtoXMLString(xml:XML, settings:Object=null):String{
var xml = xml;
var settings = settings;
return ((safeXMLOp(function (){
return (xml.toXMLString());
}, settings) as String));
}
public static function newXML(value:Object, settings:Object=null):XML{
var value = value;
var settings = settings;
return ((safeXMLOp(function (){
return (new XML(value));
}, settings) as XML));
}
public static function safeXMLOp(fn:Function, settings:Object=null){
var fn = fn;
var settings = settings;
var oldSettings:Object = XML.settings();
try {
try {
XML.setSettings(settings);
var _local4:* = fn();
//unresolved jump
0;
return (_local4);
} finally {
};
} finally {
XML.setSettings(oldSettings);
};
}
public static function isSimple(obj:Object):Boolean{
var type = typeof(obj);
switch (type){
case "number":
case "string":
case "boolean":
return (true);
case "object":
return ((((obj is Date)) || ((obj is Array))));
default:
return (false);
};
}
public static function equals(obj1:Object, obj2:Object):Boolean{
var ba1:ByteArray;
var ba2:ByteArray;
var ii:int;
if (obj1 === obj2){
return (true);
};
if ((obj1 is Equalable)){
return ((obj1 as Equalable).equals(obj2));
};
if ((((obj1 is Array)) && ((obj2 is Array)))){
return (ArrayUtil.equals((obj1 as Array), (obj2 as Array)));
};
if ((((obj1 is ByteArray)) && ((obj2 is ByteArray)))){
ba1 = (obj1 as ByteArray);
ba2 = (obj2 as ByteArray);
if (ba1.length != ba2.length){
return (false);
};
ii = 0;
while (ii < ba1.length) {
if (ba1[ii] != ba2[ii]){
return (false);
};
ii++;
};
return (true);
};
return (false);
}
public static function isPlainObject(obj:Object):Boolean{
return ((getQualifiedClassName(obj) == "Object"));
}
}
}//package com.threerings.util
Section 10
//ValueEvent (com.threerings.util.ValueEvent)
package com.threerings.util {
import flash.events.*;
public class ValueEvent extends Event {
protected var _value:Object;
public function ValueEvent(type:String, value:Object, bubbles:Boolean=false, cancelable:Boolean=false){
super(type, bubbles, cancelable);
_value = value;
}
public function get value():Object{
return (_value);
}
override public function clone():Event{
return (new ValueEvent(type, _value, bubbles, cancelable));
}
}
}//package com.threerings.util
Section 11
//Chunker (com.whirled.contrib.Chunker)
package com.whirled.contrib {
import com.whirled.*;
import flash.events.*;
import flash.utils.*;
import com.threerings.util.*;
public class Chunker extends EventDispatcher {
protected var _nextSend:int;
protected var _timer:Timer;
protected var _outTokens:int;
protected var _ctrl:EntityControl;
protected var _msgName:String;
protected var _inData:ByteArray;
protected var _outData:ByteArray;
protected static const MIN_SEND_WAIT:int = 200;
public static const TRY_COMPRESS:int = 1;
public static const ALWAYS_COMPRESS:int = 0;
public static const NEVER_COMPRESS:int = 2;
protected static const END_TOKEN:int = (1 << 1);
protected static const NO_TOKENS:int = 0;
protected static const OBJECT_TOKEN:int = (1 << 2);
protected static const COMPRESSED_TOKEN:int = (1 << 3);
protected static const START_TOKEN:int = (1 << 0);
protected static const MAX_CHUNK_DATA:int = 1020;
public function Chunker(ctrl:EntityControl, msgName:String="chunk", receivedCallback:Function=null){
var ctrl = ctrl;
var msgName = msgName;
var receivedCallback = receivedCallback;
super();
_ctrl = ctrl;
_msgName = msgName;
_ctrl.addEventListener(ControlEvent.MESSAGE_RECEIVED, handleMessage);
_ctrl.addEventListener(Event.UNLOAD, handleUnload);
if (receivedCallback != null){
addEventListener(Event.COMPLETE, function (event:ValueEvent):void{
receivedCallback(event.value);
});
};
}
protected function sendChunk(... _args):void{
var toSend:int;
toSend = Math.min(MAX_CHUNK_DATA, _outData.bytesAvailable);
var newPosition:int = (_outData.position + toSend);
var tokens:int = _outTokens;
if (_outData.position == 0){
tokens = (tokens | START_TOKEN);
};
if (newPosition == _outData.length){
tokens = (tokens | END_TOKEN);
};
var outBytes:ByteArray = new ByteArray();
outBytes.writeByte(tokens);
outBytes.writeBytes(_outData, _outData.position, toSend);
_outData.position = newPosition;
_ctrl.sendMessage(_msgName, outBytes);
_nextSend = (getTimer() + MIN_SEND_WAIT);
if (newPosition == _outData.length){
_outData = null;
if (_timer != null){
_timer.reset();
};
};
}
protected function handleUnload(event:Event):void{
if (_timer != null){
_timer.stop();
};
}
public function send(data:Object, compressStrategy:int=1):void{
var cData:ByteArray;
var now:int;
_outData = new ByteArray();
_outTokens = NO_TOKENS;
if ((data is ByteArray)){
_outData.writeBytes((data as ByteArray));
} else {
_outData.writeObject(data);
_outTokens = (_outTokens | OBJECT_TOKEN);
};
if (compressStrategy == ALWAYS_COMPRESS){
_outData.compress();
_outTokens = (_outTokens | COMPRESSED_TOKEN);
} else {
if (compressStrategy == TRY_COMPRESS){
cData = new ByteArray();
cData.writeBytes(_outData);
now = getTimer();
cData.compress();
if (countChunks(cData.length) < countChunks(_outData.length)){
_outData = cData;
_outTokens = (_outTokens | COMPRESSED_TOKEN);
};
};
};
_outData.position = 0;
checkSendChunk();
}
protected function chunkReceived(inBytes:ByteArray):void{
var tokens:int = inBytes.readByte();
if ((tokens & START_TOKEN) != NO_TOKENS){
_inData = new ByteArray();
};
if (_inData == null){
return;
};
inBytes.readBytes(_inData, _inData.position);
_inData.position = (_inData.position + (inBytes.length - 1));
if ((tokens & END_TOKEN) == NO_TOKENS){
checkSendChunk();
return;
};
if ((tokens & COMPRESSED_TOKEN) != NO_TOKENS){
_inData.uncompress();
};
_inData.position = 0;
var isObject = !(((tokens & OBJECT_TOKEN) == NO_TOKENS));
var value:Object = (isObject) ? _inData.readObject() : _inData;
_inData = null;
dispatchEvent(new ValueEvent(Event.COMPLETE, value));
}
protected function checkSendChunk():void{
var now:int;
if (_outData == null){
return;
};
now = getTimer();
var wait:int = (_nextSend - now);
if (wait <= 0){
sendChunk();
} else {
if (_timer == null){
_timer = new Timer(1, 1);
_timer.addEventListener(TimerEvent.TIMER, sendChunk);
};
_timer.delay = wait;
_timer.start();
};
}
protected function handleMessage(event:ControlEvent):void{
if (event.name == _msgName){
chunkReceived((event.value as ByteArray));
};
}
protected static function countChunks(dataLength:int):int{
return ((int((dataLength / MAX_CHUNK_DATA)) + ((0)==(dataLength % MAX_CHUNK_DATA)) ? 0 : 1));
}
}
}//package com.whirled.contrib
Section 12
//AbstractControl (com.whirled.AbstractControl)
package com.whirled {
import flash.events.*;
import flash.display.*;
import flash.errors.*;
public class AbstractControl extends EventDispatcher {
protected var _funcs:Object;
protected var _subControls:Array;
public function AbstractControl(disp:DisplayObject, initialUserProps:Object=null){
super();
_subControls = createSubControls();
if ((this is AbstractSubControl)){
return;
};
if (disp.root == null){
throw (new Error("Display object used to instantiate a control must be on the stage"));
};
disp.root.loaderInfo.addEventListener(Event.UNLOAD, handleUnload, false, 0, true);
var userProps:Object = ((initialUserProps)!=null) ? initialUserProps : new Object();
setUserProps(userProps);
var event:ConnectEvent = new ConnectEvent();
event.props.userProps = userProps;
disp.root.loaderInfo.sharedEvents.dispatchEvent(event);
if (Boolean(event.props.alreadyConnected)){
throw (new Error("You've already set up a Control instance. There should only be one."));
};
var hostProps:Object = event.props.hostProps;
if (hostProps != null){
gotHostProps(hostProps);
};
}
override public function dispatchEvent(event:Event):Boolean{
throw (new IllegalOperationError());
}
protected function createSubControls():Array{
return (null);
}
protected function callHostCode(name:String, ... _args){
var func:Function;
var name = name;
var args = _args;
if (_funcs != null){
func = (_funcs[name] as Function);
if (func == null){
trace((("Host code \"" + name) + "\" not found!"));
} else {
return (func.apply(null, args));
};
//unresolved jump
var _slot1 = err;
trace(((((("Error! Your code is broken! Unable to call a host method, perhaps " + "you've been shut down? [msg=") + _slot1.message) + ", trace=") + _slot1.getStackTrace()) + "]."));
} else {
checkIsConnected();
};
return (undefined);
}
protected function setUserProps(o:Object):void{
var ctrl:AbstractSubControl;
for each (ctrl in _subControls) {
ctrl.setUserPropsFriend(o);
};
}
protected function handleUnload(event:Event):void{
dispatch(event);
}
function callHostCodeFriend(name:String, args:Array){
args.unshift(name);
return (callHostCode.apply(this, args));
}
override public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void{
super.removeEventListener(type, listener, useCapture);
}
override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void{
super.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
public function doBatch(fn:Function, ... _args):void{
var fn = fn;
var args = _args;
callHostCode("startTransaction");
try {
try {
fn.apply(null, args);
} finally {
};
} finally {
callHostCode("commitTransaction");
};
}
protected function checkIsConnected():void{
if (!isConnected()){
throw (new IllegalOperationError(("The control is not connected to the host framework, please check isConnected(). " + "If false, your SWF is being viewed standalone and should adjust.")));
};
}
protected function dispatch(event:Event):void{
var event = event;
super.dispatchEvent(event);
//unresolved jump
var _slot1 = err;
trace("Error dispatching event to user code.");
trace(_slot1.getStackTrace());
}
protected function gotHostProps(o:Object):void{
var ctrl:AbstractSubControl;
_funcs = o;
for each (ctrl in _subControls) {
ctrl.gotHostPropsFriend(o);
};
}
public function isConnected():Boolean{
return (!((_funcs == null)));
}
}
}//package com.whirled
import flash.events.*;
class ConnectEvent extends Event {
public var props:Object;
private function ConnectEvent(propsObj:Object=null){
super("controlConnect", true, false);
props = ((propsObj) || ({}));
}
override public function clone():Event{
return (new ConnectEvent(props));
}
}
Section 13
//AbstractSubControl (com.whirled.AbstractSubControl)
package com.whirled {
import flash.events.*;
public class AbstractSubControl extends AbstractControl {
protected var _parent:AbstractControl;
public function AbstractSubControl(parent:AbstractControl){
_parent = parent;
_parent.addEventListener(Event.UNLOAD, handleUnload, false, 0, true);
super(null);
}
function setUserPropsFriend(o:Object):void{
setUserProps(o);
}
override protected function callHostCode(name:String, ... _args){
return (_parent.callHostCodeFriend(name, _args));
}
override public function isConnected():Boolean{
return (_parent.isConnected());
}
function gotHostPropsFriend(o:Object):void{
gotHostProps(o);
}
override public function doBatch(fn:Function, ... _args):void{
_args.unshift(fn);
_parent.doBatch.apply(null, _args);
}
}
}//package com.whirled
Section 14
//ActorControl (com.whirled.ActorControl)
package com.whirled {
import flash.display.*;
public class ActorControl extends EntityControl {
protected var _orient:Number;// = 0
protected var _isMoving:Boolean;
public function ActorControl(disp:DisplayObject){
super(disp);
}
public function getState():String{
return ((isConnected()) ? (callHostCode("getState_v1") as String) : null);
}
override protected function setUserProps(o:Object):void{
super.setUserProps(o);
o["appearanceChanged_v2"] = appearanceChanged_v2;
o["stateSet_v1"] = stateSet_v1;
}
protected function stateSet_v1(newState:String):void{
dispatchCtrlEvent(ControlEvent.STATE_CHANGED, newState);
}
protected function appearanceChanged_v2(location:Array, orient:Number, moving:Boolean, sleeping:Boolean):void{
_location = location;
_orient = orient;
_isMoving = moving;
dispatchCtrlEvent(ControlEvent.APPEARANCE_CHANGED);
}
public function setOrientation(orient:Number):void{
callHostCode("setOrientation_v1", orient);
}
public function setState(state:String):void{
callHostCode("setState_v1", state);
}
public function setMoveSpeed(pixelsPerSecond:Number):void{
callHostCode("setMoveSpeed_v1", pixelsPerSecond);
}
public function isMoving():Boolean{
return (_isMoving);
}
public function setPixelLocation(x:Number, y:Number, z:Number, orient:Number):void{
var bounds:Array = getRoomBounds();
setLogicalLocation((x / bounds[0]), (y / bounds[1]), (z / bounds[2]), orient);
}
public function getOrientation():Number{
return (_orient);
}
override protected function gotInitProps(o:Object):void{
super.gotInitProps(o);
_orient = (o["orient"] as Number);
_isMoving = (o["isMoving"] as Boolean);
}
public function setLogicalLocation(x:Number, y:Number, z:Number, orient:Number):void{
callHostCode("setLocation_v1", x, y, z, orient);
}
}
}//package com.whirled
Section 15
//AvatarControl (com.whirled.AvatarControl)
package com.whirled {
import flash.display.*;
import com.threerings.util.*;
public class AvatarControl extends ActorControl {
protected var _states:Array;
protected var _isSleeping:Boolean;
protected var _actions:Array;
public function AvatarControl(disp:DisplayObject){
_actions = [];
_states = [];
super(disp);
}
public function setPreferredY(pixels:int):void{
callHostCode("setPreferredY_v1", pixels);
}
override protected function setUserProps(o:Object):void{
super.setUserProps(o);
o["avatarSpoke_v1"] = avatarSpoke_v1;
o["getActions_v1"] = getActions_v1;
o["getStates_v1"] = getStates_v1;
}
public function registerStates(... _args):void{
var states:Array = Util.unfuckVarargs(_args);
verifyActionsOrStates(states, false);
_states = states;
}
protected function avatarSpoke_v1():void{
dispatchCtrlEvent(ControlEvent.AVATAR_SPOKE);
}
protected function getStates_v1():Array{
return (_states);
}
override protected function appearanceChanged_v2(location:Array, orient:Number, moving:Boolean, sleeping:Boolean):void{
_isSleeping = sleeping;
super.appearanceChanged_v2(location, orient, moving, sleeping);
}
protected function verifyActionsOrStates(vals:Array, isAction:Boolean):void{
var jj:int;
var name:String = (isAction) ? "action" : "state";
var ii:int;
while (ii < vals.length) {
if (vals[ii] != null){
if (!(vals[ii] is String)){
throw (new ArgumentError((((("All " + name) + "s must be Strings (") + ii) + ").")));
};
if (String(vals[ii]).length > 64){
throw (new ArgumentError((("All " + name) + "s must be less than 64 characters.")));
};
};
jj = 0;
while (jj < ii) {
if (vals[jj] === vals[ii]){
throw (new ArgumentError(((("Duplicate " + name) + " specified: ") + vals[ii])));
};
jj++;
};
ii++;
};
}
protected function getActions_v1():Array{
return (_actions);
}
override protected function gotInitProps(o:Object):void{
super.gotInitProps(o);
_isSleeping = (o["isSleeping"] as Boolean);
}
public function isSleeping():Boolean{
return (_isSleeping);
}
public function registerActions(... _args):void{
var actions:Array = Util.unfuckVarargs(_args);
verifyActionsOrStates(actions, true);
_actions = actions;
}
override public function getState():String{
var state:String = super.getState();
if ((((state == null)) && ((_states.length > 0)))){
state = (_states[0] as String);
};
return (state);
}
}
}//package com.whirled
Section 16
//BaseDataPack (com.whirled.BaseDataPack)
package com.whirled {
import flash.events.*;
import flash.utils.*;
import flash.geom.*;
import com.threerings.util.*;
import nochump.util.zip.*;
import flash.errors.*;
public class BaseDataPack extends EventDispatcher {
protected var _metadata:XML;
protected var _zip:ZipFile;
protected static const CONTENT_DATANAME:String = "_CONTENT";
protected static const METADATA_FILENAME:String = "_data.xml";
public function BaseDataPack(bytes:ByteArray=null){
super();
if (bytes != null){
bytesAvailable(bytes);
};
}
protected function parseValueFromString(string:String, type:String):Object{
var bits:Array;
var string = string;
var type = type;
switch (type){
case "String":
case "Choice":
return (unescape(string));
case "Number":
return (parseFloat(string));
case "int":
return (parseInt(string));
case "Boolean":
return (("true" == string.toLowerCase()));
case "Color":
return (parseInt(string, 16));
case "Array":
return (string.split(",").map(function (item:String, ... _args):String{
return (unescape(item));
}));
case "Point":
bits = string.split(",");
return (new Point(parseFloat(bits[0]), parseFloat(bits[1])));
case "Rectangle":
bits = string.split(",");
return (new Rectangle(parseFloat(bits[0]), parseFloat(bits[1]), parseFloat(bits[2]), parseFloat(bits[3])));
default:
trace(("Unknown resource type: " + type));
return (string);
};
}
protected function validateName(name:String):void{
switch (name){
case null:
case CONTENT_DATANAME:
throw (new ArgumentError(("Invalid name: " + name)));
};
}
public function isComplete():Boolean{
return (!((_metadata == null)));
}
public function getString(name:String):String{
var data:* = getData(name);
return (((data)==null) ? null : String(data));
}
public function getRectangle(name:String):Rectangle{
return ((getData(name, "Rectangle") as Rectangle));
}
public function getBoolean(name:String):Boolean{
return (Boolean(getData(name, "Boolean")));
}
protected function getFileInternal(name:String, asString:Boolean){
var value:String = getFileName(name);
if (value == null){
return (undefined);
};
var bytes:ByteArray = getFileBytes(value);
if (((asString) && (!((bytes == null))))){
return (bytesToString(bytes));
};
return (bytes);
}
protected function getDatum(list:XMLList, name:String):XML{
var x:XML;
for each (x in list) {
if (x.attribute("name") == name){
return (x);
};
};
return (null);
}
protected function getFileBytes(fileName:String):ByteArray{
var entry:ZipEntry = _zip.getEntry(fileName);
if (entry == null){
return (null);
};
return (_zip.getInput(entry));
}
protected function validateAccess(name:String):String{
validateComplete();
validateName(name);
return (escape(name));
}
protected function getFileName(name:String):String{
name = validateAccess(name);
var datum:XML = getDatum(_metadata..file, name);
if (datum == null){
return (null);
};
return (parseValue(datum, "value", "String"));
}
protected function bytesAvailable(bytes:ByteArray):void{
var bytes = bytes;
bytes.position = 0;
_zip = new ZipFile(bytes);
//unresolved jump
var _slot1 = zipError;
dispatchError(("Unable to read datapack: " + _slot1.message));
return;
var dataFile:ZipEntry = _zip.getEntry(METADATA_FILENAME);
if (dataFile == null){
dispatchError((("No " + METADATA_FILENAME) + " contained in DataPack."));
return;
};
var asString:String = bytesToString(_zip.getInput(dataFile));
_metadata = Util.newXML(asString);
//unresolved jump
var _slot1 = error;
dispatchError(("Could not parse datapack: " + _slot1.message));
return;
}
protected function extractStringValue(datum:XML, valueField:String="value"){
var val:XMLList = datum.@[valueField];
if ((((val.length == 0)) || ((val[0] === undefined)))){
return (undefined);
};
var value:String = String(val[0]);
return (value);
}
public function getData(name:String, formatType:String=null){
name = validateAccess(name);
var datum:XML = getDatum(_metadata..data, name);
if (datum == null){
return (undefined);
};
var data:* = parseValue(datum);
if (((((!((formatType == null))) && (!((formatType == "String"))))) && ((data is String)))){
data = parseValueFromString(String(data), formatType);
};
return (data);
}
public function getPoint(name:String):Point{
return ((getData(name, "Point") as Point));
}
public function getArray(name:String):Array{
var retval:Array;
var data:* = getData(name, "Array");
if ((data is Array)){
return ((data as Array));
};
if (data == null){
return (null);
};
retval = new Array();
retval.push(data);
return (retval);
}
public function getColor(name:String):uint{
return (uint(getData(name, "Color")));
}
protected function dispatchError(message:String):void{
if (willTrigger(ErrorEvent.ERROR)){
dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, message));
} else {
trace(("Unhandled DataPack load error: " + message));
};
}
protected function validateComplete():void{
if (!isComplete()){
throw (new IllegalOperationError("DataPack is not loaded."));
};
}
public function getFile(name:String):ByteArray{
return ((getFileInternal(name, false) as ByteArray));
}
public function getFileAsXML(name:String):XML{
return (Util.newXML(getFileAsString(name)));
}
public function getFileAsString(name:String):String{
return ((getFileInternal(name, true) as String));
}
protected function bytesToString(ba:ByteArray):String{
ba.position = 0;
return (ba.readUTFBytes(ba.bytesAvailable));
}
public function getInt(name:String):int{
return (int(getData(name, "int")));
}
protected function parseValue(datum:XML, valueField:String="value", typeOverride:String=null){
var str:* = extractStringValue(datum, valueField);
if (str === undefined){
return (str);
};
var type:String = ((typeOverride)!=null) ? typeOverride : String(datum.@type);
return (parseValueFromString(str, type));
}
public function getNumber(name:String):Number{
return (Number(getData(name, "Number")));
}
}
}//package com.whirled
Section 17
//ControlEvent (com.whirled.ControlEvent)
package com.whirled {
import flash.events.*;
public class ControlEvent extends Event {
protected var _value:Object;
protected var _name:String;
public static const APPEARANCE_CHANGED:String = "appearanceChanged";
public static const STATE_CHANGED:String = "stateChanged";
public static const HOVER_OUT:String = "hoverOut";
public static const AVATAR_SPOKE:String = "avatarSpoke";
public static const CONTROL_ACQUIRED:String = "controlAcquired";
public static const MEMORY_CHANGED:String = "memoryChanged";
public static const HOVER_OVER:String = "hoverOver";
public static const SIGNAL_RECEIVED:String = "signalRecieved";
public static const ENTITY_LEFT:String = "entityLeft";
public static const CHAT_RECEIVED:String = "chatReceived";
public static const ACTION_TRIGGERED:String = "actionTriggered";
public static const ENTITY_MOVED:String = "entityMoved";
public static const MESSAGE_RECEIVED:String = "messageRecieved";
public static const ENTITY_ENTERED:String = "entityEntered";
public function ControlEvent(type:String, name:String=null, value:Object=null){
super(type);
_name = name;
_value = value;
}
public function get value():Object{
return (_value);
}
override public function get target():Object{
return (super.target);
}
public function get name():String{
return (_name);
}
override public function toString():String{
return ((((((("ControlEvent [type=" + type) + ", name=") + _name) + ", value=") + _value) + "]"));
}
override public function clone():Event{
return (new ControlEvent(type, _name, _value));
}
}
}//package com.whirled
Section 18
//DataPack (com.whirled.DataPack)
package com.whirled {
import flash.events.*;
import flash.utils.*;
import flash.system.*;
import com.threerings.util.*;
import flash.net.*;
public class DataPack extends BaseDataPack {
protected var _loader:URLLoader;
public function DataPack(source:Object, completeListener:Function=null, errorListener:Function=null){
var bytes:ByteArray;
super();
if ((source is String)){
source = new URLRequest(String(source));
} else {
if ((source is Class)){
source = new ((source as Class));
};
};
var req:URLRequest;
if ((source is URLRequest)){
req = URLRequest(source);
} else {
if ((source is ByteArray)){
bytes = ByteArray(source);
} else {
throw (new TypeError("Expected a String or ByteArray"));
};
};
if (completeListener != null){
addEventListener(Event.COMPLETE, completeListener);
};
if (errorListener != null){
addEventListener(ErrorEvent.ERROR, errorListener);
};
if (req != null){
_loader = new URLLoader();
_loader.dataFormat = URLLoaderDataFormat.BINARY;
_loader.addEventListener(Event.COMPLETE, handleLoadingComplete);
_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleLoadError);
_loader.addEventListener(IOErrorEvent.IO_ERROR, handleLoadError);
_loader.load(req);
} else {
bytesAvailable(bytes);
};
}
protected function handleLoadError(event:ErrorEvent):void{
close();
dispatchError(("Error loading datapack: " + event.text));
}
public function close():void{
if (_loader != null){
_loader.close();
//unresolved jump
var _slot1 = err;
_loader = null;
};
}
protected function doGetObjects(sources:Object, callback:Function, appDom:ApplicationDomain, returnRawLoaders:Boolean):void{
var toCall:Function;
var key:*;
var o:Object;
if ((sources is String)){
sources = getFile(String(sources));
} else {
for (key in sources) {
o = sources[key];
if ((o is String)){
sources[key] = getFile(String(o));
};
};
};
toCall = (returnRawLoaders) ? MultiLoader.getLoaders : MultiLoader.getContents;
toCall(sources, callback, false, appDom);
}
public function getLoaders(sources:Object, callback:Function, appDom:ApplicationDomain=null):void{
doGetObjects(sources, callback, appDom, true);
}
protected function handleLoadingComplete(event:Event):void{
var ba:ByteArray = ByteArray(_loader.data);
_loader = null;
bytesAvailable(ba);
}
override protected function bytesAvailable(bytes:ByteArray):void{
super.bytesAvailable(bytes);
if (isComplete()){
dispatchEvent(new Event(Event.COMPLETE));
};
}
public function getDisplayObjects(sources:Object, callback:Function, appDom:ApplicationDomain=null):void{
doGetObjects(sources, callback, appDom, false);
}
public static function load(sources:Object, completeListener:Function):void{
var sources = sources;
var completeListener = completeListener;
var generator:Function = function (source):DataPack{
return (new DataPack(source));
};
new MultiLoader(sources, completeListener, generator, false, "isComplete", [ErrorEvent.ERROR]);
}
}
}//package com.whirled
Section 19
//EntityControl (com.whirled.EntityControl)
package com.whirled {
import flash.events.*;
import flash.display.*;
import flash.utils.*;
import flash.media.*;
public class EntityControl extends AbstractControl {
protected var _hasControl:Boolean;// = false
protected var _ticker:Timer;
protected var _datapack:ByteArray;
protected var _location:Array;
protected var _propertyProvider:Function;
protected var _tickInterval:Number;// = 0
public static const PROP_ORIENTATION:String = "std:orientation";
public static const PROP_MEMBER_ID:String = "std:member_id";
public static const PROP_NAME:String = "std:name";
public static const PROP_DIMENSIONS:String = "std:dimensions";
public static const PROP_HOTSPOT:String = "std:hotspot";
public static const PROP_MOVE_SPEED:String = "std:move_speed";
public static const PROP_LOCATION_PIXEL:String = "std:location_pixel";
public static const TYPE_FURNI:String = "furni";
public static const TYPE_PET:String = "pet";
public static const PROP_LOCATION_LOGICAL:String = "std:location_logical";
public static const PROP_TYPE:String = "std:type";
public static const TYPE_AVATAR:String = "avatar";
public function EntityControl(disp:DisplayObject){
super(disp);
if (Object(this).constructor == EntityControl){
throw (new Error(("Do not directly use EntityControl. " + "Use the appropriate subclass: AvatarControl, FurniControl, etc.")));
};
}
public function setMemory(key:String, value:Object, callback:Function=null):void{
callHostCode("updateMemory_v1", key, value, callback);
}
public function setTickInterval(interval:Number):void{
_tickInterval = ((((interval > 100)) || ((interval <= 0)))) ? interval : 100;
if (_hasControl){
recheckTicker();
};
}
public function getInstanceId():int{
return (int(callHostCode("getInstanceId_v1")));
}
protected function entityMoved_v2(entityId:String, destination:Array):void{
if (_hasControl){
dispatchCtrlEvent(ControlEvent.ENTITY_MOVED, entityId, destination);
};
}
protected function entityEntered_v1(entityId:String):void{
if (_hasControl){
dispatchCtrlEvent(ControlEvent.ENTITY_ENTERED, entityId);
};
}
public function triggerAction(name:String, arg:Object=null):void{
callHostCode("sendMessage_v1", name, arg, true);
}
protected function messageReceived_v1(name:String, arg:Object, isAction:Boolean):void{
dispatchCtrlEvent((isAction) ? ControlEvent.ACTION_TRIGGERED : ControlEvent.MESSAGE_RECEIVED, name, arg);
}
protected function gotInitProps(o:Object):void{
_location = (o["location"] as Array);
_datapack = (o["datapack"] as ByteArray);
}
function dispatchCtrlEvent(ctrlEvent:String, key:String=null, value:Object=null):void{
if (hasEventListener(ctrlEvent)){
dispatch(new ControlEvent(ctrlEvent, key, value));
};
}
public function getCamera(index:String=null):Camera{
return ((isConnected()) ? (callHostCode("getCamera_v1", index) as Camera) : Camera.getCamera(index));
}
public function getDefaultDataPack():ByteArray{
return (_datapack);
}
protected function recheckTicker():void{
if (((_hasControl) && ((_tickInterval > 0)))){
if (_ticker == null){
_ticker = new Timer(_tickInterval);
_ticker.addEventListener(TimerEvent.TIMER, dispatch);
} else {
_ticker.delay = _tickInterval;
};
_ticker.start();
} else {
stopTicker();
};
}
public function getMyEntityId():String{
return (callHostCode("getMyEntityId_v1"));
}
protected function receivedChat_v2(entityId:String, message:String):void{
if (_hasControl){
dispatchCtrlEvent(ControlEvent.CHAT_RECEIVED, entityId, message);
};
}
override protected function setUserProps(o:Object):void{
super.setUserProps(o);
o["memoryChanged_v1"] = memoryChanged_v1;
o["gotControl_v1"] = gotControl_v1;
o["messageReceived_v1"] = messageReceived_v1;
o["signalReceived_v1"] = signalReceived_v1;
o["receivedChat_v2"] = receivedChat_v2;
o["entityEntered_v1"] = entityEntered_v1;
o["entityLeft_v1"] = entityLeft_v1;
o["entityMoved_v2"] = entityMoved_v2;
o["lookupEntityProperty_v1"] = lookupEntityProperty_v1;
}
public function getPixelLocation():Array{
if (_location == null){
return (null);
};
var bounds:Array = getRoomBounds();
var ii:int;
while (ii < _location.length) {
bounds[ii] = (bounds[ii] * _location[ii]);
ii++;
};
return (bounds);
}
public function getEntityIds(type:String=null):Array{
var entities:Array = callHostCode("getEntityIds_v1", type);
return (((entities)==null) ? [] : entities);
}
public function getMicrophone(index:int=0):Microphone{
return ((isConnected()) ? (callHostCode("getMicrophone_v1", index) as Microphone) : Microphone.getMicrophone(index));
}
public function registerPropertyProvider(func:Function):void{
_propertyProvider = func;
}
protected function stopTicker():void{
if (_ticker != null){
_ticker.stop();
_ticker = null;
};
}
public function setHotSpot(x:Number, y:Number, height:Number=NaN):void{
callHostCode("setHotSpot_v1", x, y, height);
}
public function getLogicalLocation():Array{
return (_location);
}
public function showPopup(title:String, panel:DisplayObject, width:Number, height:Number, backgroundColor:uint=0xFFFFFF, backgroundAlpha:Number=1):Boolean{
return ((callHostCode("showPopup_v1", title, panel, width, height, backgroundColor, backgroundAlpha) as Boolean));
}
public function getViewerName(id:int=0):String{
return ((callHostCode("getViewerName_v1", id) as String));
}
protected function memoryChanged_v1(key:String, value:Object):void{
dispatchCtrlEvent(ControlEvent.MEMORY_CHANGED, key, value);
}
protected function gotControl_v1():void{
if (_hasControl){
return;
};
_hasControl = true;
dispatchCtrlEvent(ControlEvent.CONTROL_ACQUIRED);
recheckTicker();
}
override protected function handleUnload(evt:Event):void{
super.handleUnload(evt);
_hasControl = false;
stopTicker();
}
public function canManageRoom(memberId:int=0):Boolean{
return ((callHostCode("canEditRoom_v1", memberId) as Boolean));
}
protected function signalReceived_v1(name:String, arg:Object):void{
if (_hasControl){
dispatchCtrlEvent(ControlEvent.SIGNAL_RECEIVED, name, arg);
};
}
public function getMemories():Object{
var mems:Object = callHostCode("getMemories_v1");
return (((mems)==null) ? {} : mems);
}
public function sendSignal(name:String, arg:Object=null):void{
callHostCode("sendSignal_v1", name, arg);
}
public function getEntityProperty(key:String, entityId:String=null):Object{
return (callHostCode("getEntityProperty_v1", entityId, key));
}
override protected function checkIsConnected():void{
}
public function sendMessage(name:String, arg:Object=null):void{
callHostCode("sendMessage_v1", name, arg, false);
}
public function hasControl():Boolean{
return (_hasControl);
}
public function getRoomBounds():Array{
return ((callHostCode("getRoomBounds_v1") as Array));
}
protected function lookupEntityProperty_v1(key:String):Object{
return (((_propertyProvider == null)) ? null : _propertyProvider(key));
}
public function clearPopup():void{
callHostCode("clearPopup_v1");
}
protected function entityLeft_v1(entityId:String):void{
if (_hasControl){
dispatchCtrlEvent(ControlEvent.ENTITY_LEFT, entityId);
};
}
public function getMemory(key:String, defval:Object=null):Object{
var value:Object = callHostCode("lookupMemory_v1", key);
return (((value)==null) ? defval : value);
}
override protected function gotHostProps(o:Object):void{
super.gotHostProps(o);
if (("initProps" in o)){
gotInitProps(o.initProps);
delete o.initProps;
};
}
}
}//package com.whirled
Section 20
//Inflater (nochump.util.zip.Inflater)
package nochump.util.zip {
import flash.utils.*;
public class Inflater {
private var lencode:Object;
private var bitcnt:int;
private var bitbuf:int;
private var incnt:uint;
private var inbuf:ByteArray;
private var distcode:Object;
private static const LENS:Array = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258];
private static const MAXDCODES:int = 30;
private static const MAXCODES:int = 316;
private static const MAXBITS:int = 15;
private static const MAXLCODES:int = 286;
private static const FIXLCODES:int = 288;
private static const LEXT:Array = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0];
private static const DISTS:Array = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 0x0101, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577];
private static const DEXT:Array = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13];
public function Inflater(){
super();
}
public function inflate(buf:ByteArray):uint{
var last:*;
var type:*;
incnt = (bitbuf = (bitcnt = 0));
var err:int;
do {
last = bits(1);
type = bits(2);
if (type == 0){
stored(buf);
} else {
if (type == 3){
throw (new Error("invalid block type (type == 3)", -1));
};
lencode = {count:[], symbol:[]};
distcode = {count:[], symbol:[]};
if (type == 1){
constructFixedTables();
} else {
if (type == 2){
err = constructDynamicTables();
};
};
if (err != 0){
return (err);
};
err = codes(buf);
};
} while (err == 0);
return (err);
}
private function constructFixedTables():void{
var lengths:Array = [];
var symbol:int;
while (symbol < 144) {
lengths[symbol] = 8;
symbol++;
};
while (symbol < 0x0100) {
lengths[symbol] = 9;
symbol++;
};
while (symbol < 280) {
lengths[symbol] = 7;
symbol++;
};
while (symbol < FIXLCODES) {
lengths[symbol] = 8;
symbol++;
};
construct(lencode, lengths, FIXLCODES);
symbol = 0;
while (symbol < MAXDCODES) {
lengths[symbol] = 5;
symbol++;
};
construct(distcode, lengths, MAXDCODES);
}
private function stored(buf:ByteArray):void{
bitbuf = 0;
bitcnt = 0;
if ((incnt + 4) > inbuf.length){
throw (new Error("available inflate data did not terminate", 2));
};
var len:uint = inbuf[incnt++];
var _temp1 = len;
len = (_temp1 | (inbuf[++] << 8));
if (((!((inbuf[incnt++] == (~(len) & 0xFF)))) || (!((inbuf[incnt++] == ((~(len) >> 8) & 0xFF)))))){
throw (new Error("stored block length did not match one's complement", -2));
};
if ((incnt + len) > inbuf.length){
throw (new Error("available inflate data did not terminate", 2));
};
while (len--) {
buf[buf.length] = inbuf[incnt++];
};
}
public function setInput(buf:ByteArray):void{
inbuf = buf;
inbuf.endian = Endian.LITTLE_ENDIAN;
}
private function constructDynamicTables():int{
var symbol:int;
var len:int;
var lengths:Array = [];
var order:Array = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
var nlen:int = (bits(5) + 0x0101);
var ndist:int = (bits(5) + 1);
var ncode:int = (bits(4) + 4);
if ((((nlen > MAXLCODES)) || ((ndist > MAXDCODES)))){
throw (new Error("dynamic block code description: too many length or distance codes", -3));
};
var index:int;
while (index < ncode) {
lengths[order[index]] = bits(3);
index++;
};
while (index < 19) {
lengths[order[index]] = 0;
index++;
};
var err:int = construct(lencode, lengths, 19);
if (err != 0){
throw (new Error("dynamic block code description: code lengths codes incomplete", -4));
};
index = 0;
while (index < (nlen + ndist)) {
symbol = decode(lencode);
if (symbol < 16){
var _temp1 = index;
index = (index + 1);
var _local10 = _temp1;
lengths[_local10] = symbol;
} else {
len = 0;
if (symbol == 16){
if (index == 0){
throw (new Error("dynamic block code description: repeat lengths with no first length", -5));
};
len = lengths[(index - 1)];
symbol = (3 + bits(2));
} else {
if (symbol == 17){
symbol = (3 + bits(3));
} else {
symbol = (11 + bits(7));
};
};
if ((index + symbol) > (nlen + ndist)){
throw (new Error("dynamic block code description: repeat more than specified lengths", -6));
};
while (symbol--) {
var _temp2 = index;
index = (index + 1);
_local10 = _temp2;
lengths[_local10] = len;
};
};
};
err = construct(lencode, lengths, nlen);
if ((((err < 0)) || ((((err > 0)) && (!(((nlen - lencode.count[0]) == 1))))))){
throw (new Error("dynamic block code description: invalid literal/length code lengths", -7));
};
err = construct(distcode, lengths.slice(nlen), ndist);
if ((((err < 0)) || ((((err > 0)) && (!(((ndist - distcode.count[0]) == 1))))))){
throw (new Error("dynamic block code description: invalid distance code lengths", -8));
};
return (err);
}
private function bits(need:int):int{
var val:int = bitbuf;
while (bitcnt < need) {
if (incnt == inbuf.length){
throw (new Error("available inflate data did not terminate", 2));
};
val = (val | (inbuf[incnt++] << bitcnt));
bitcnt = (bitcnt + 8);
};
bitbuf = (val >> need);
bitcnt = (bitcnt - need);
return ((val & ((1 << need) - 1)));
}
private function construct(h:Object, length:Array, n:int):int{
var offs:Array = [];
var len:int;
while (len <= MAXBITS) {
h.count[len] = 0;
len++;
};
var symbol:int;
while (symbol < n) {
var _local8 = h.count;
var _local9 = length[symbol];
var _local10 = (_local8[_local9] + 1);
_local8[_local9] = _local10;
symbol++;
};
if (h.count[0] == n){
return (0);
};
var left = 1;
len = 1;
while (len <= MAXBITS) {
left = (left << 1);
left = (left - h.count[len]);
if (left < 0){
return (left);
};
len++;
};
offs[1] = 0;
len = 1;
while (len < MAXBITS) {
offs[(len + 1)] = (offs[len] + h.count[len]);
len++;
};
symbol = 0;
while (symbol < n) {
if (length[symbol] != 0){
_local9 = offs;
_local10 = length[symbol];
var _local11 = (_local9[_local10] + 1);
_local9[_local10] = _local11;
_local8 = _local9[_local10];
h.symbol[_local8] = symbol;
};
symbol++;
};
return (left);
}
private function decode(h:Object):int{
var count:int;
var code:int;
var first:int;
var index:int;
var len = 1;
while (len <= MAXBITS) {
code = (code | bits(1));
count = h.count[len];
if (code < (first + count)){
return (h.symbol[(index + (code - first))]);
};
index = (index + count);
first = (first + count);
first = (first << 1);
code = (code << 1);
len++;
};
return (-9);
}
private function codes(buf:ByteArray):int{
var symbol:*;
var len:*;
var dist:*;
do {
symbol = decode(lencode);
if (symbol < 0){
return (symbol);
};
if (symbol < 0x0100){
buf[buf.length] = symbol;
} else {
if (symbol > 0x0100){
symbol = (symbol - 0x0101);
if (symbol >= 29){
throw (new Error("invalid literal/length or distance code in fixed or dynamic block", -9));
};
len = (LENS[symbol] + bits(LEXT[symbol]));
symbol = decode(distcode);
if (symbol < 0){
return (symbol);
};
dist = (DISTS[symbol] + bits(DEXT[symbol]));
if (dist > buf.length){
throw (new Error("distance is too far back in fixed or dynamic block", -10));
};
while (len--) {
buf[buf.length] = buf[(buf.length - dist)];
};
};
};
} while (symbol != 0x0100);
return (0);
}
}
}//package nochump.util.zip
Section 21
//ZipConstants (nochump.util.zip.ZipConstants)
package nochump.util.zip {
class ZipConstants {
static const ENDOFF:uint = 16;
static const CENSIG:uint = 33639248;
static const CENNAM:uint = 28;
static const EXTSIG:uint = 134695760;
static const LOCSIG:uint = 67324752;
static const ENDSIG:uint = 101010256;
static const CENVER:uint = 6;
static const DEFLATED:uint = 8;
static const LOCNAM:uint = 26;
static const ENDTOT:uint = 10;
static const LOCVER:uint = 4;
static const CENHDR:uint = 46;
static const CENOFF:uint = 42;
static const EXTHDR:uint = 16;
static const LOCHDR:uint = 30;
static const STORED:uint = 0;
static const ENDHDR:uint = 22;
function ZipConstants(){
super();
}
}
}//package nochump.util.zip
Section 22
//ZipEntry (nochump.util.zip.ZipEntry)
package nochump.util.zip {
import flash.utils.*;
public class ZipEntry {
private var _compressedSize:int;// = -1
private var _extra:ByteArray;
var offset:int;
private var _crc:uint;
var version:int;
var dostime:uint;
private var _size:int;// = -1
private var _method:int;// = -1
private var _comment:String;
var flag:int;
private var _name:String;
public function ZipEntry(name:String){
super();
_name = name;
}
public function set compressedSize(csize:int):void{
_compressedSize = csize;
}
public function get size():int{
return (_size);
}
public function set size(size:int):void{
_size = size;
}
public function get name():String{
return (_name);
}
public function get time():Number{
var d:Date = new Date((((dostime >> 25) & 127) + 1980), (((dostime >> 21) & 15) - 1), ((dostime >> 16) & 31), ((dostime >> 11) & 31), ((dostime >> 5) & 63), ((dostime & 31) << 1));
return (d.time);
}
public function get extra():ByteArray{
return (_extra);
}
public function set time(time:Number):void{
var d:Date = new Date(time);
dostime = ((((((((d.fullYear - 1980) & 127) << 25) | ((d.month + 1) << 21)) | (d.day << 16)) | (d.hours << 11)) | (d.minutes << 5)) | (d.seconds >> 1));
}
public function get crc():uint{
return (_crc);
}
public function get method():int{
return (_method);
}
public function isDirectory():Boolean{
return ((_name.charAt((_name.length - 1)) == "/"));
}
public function set method(method:int):void{
_method = method;
}
public function set crc(crc:uint):void{
_crc = crc;
}
public function get comment():String{
return (_comment);
}
public function set extra(extra:ByteArray):void{
_extra = extra;
}
public function get compressedSize():int{
return (_compressedSize);
}
public function toString():String{
return (_name);
}
public function set comment(comment:String):void{
_comment = comment;
}
}
}//package nochump.util.zip
Section 23
//ZipError (nochump.util.zip.ZipError)
package nochump.util.zip {
import flash.errors.*;
public class ZipError extends IOError {
public function ZipError(message:String="", id:int=0){
super(message, id);
}
}
}//package nochump.util.zip
Section 24
//ZipFile (nochump.util.zip.ZipFile)
package nochump.util.zip {
import flash.utils.*;
public class ZipFile {
private var entryTable:Dictionary;
private var entryList:Array;
private var buf:ByteArray;
private var locOffsetTable:Dictionary;
public function ZipFile(data:IDataInput){
super();
buf = new ByteArray();
buf.endian = Endian.LITTLE_ENDIAN;
data.readBytes(buf);
readEntries();
}
public function get size():uint{
return (entryList.length);
}
private function findEND():uint{
var i:uint = (buf.length - ZipConstants.ENDHDR);
var n:uint = Math.max(0, (i - 0xFFFF));
while (i >= n) {
if (buf[i] != 80){
} else {
buf.position = i;
if (buf.readUnsignedInt() == ZipConstants.ENDSIG){
return (i);
};
};
i--;
};
throw (new ZipError("invalid zip"));
}
private function readEND():void{
var b:ByteArray = new ByteArray();
b.endian = Endian.LITTLE_ENDIAN;
buf.position = findEND();
buf.readBytes(b, 0, ZipConstants.ENDHDR);
b.position = ZipConstants.ENDTOT;
entryList = new Array(b.readUnsignedShort());
b.position = ZipConstants.ENDOFF;
buf.position = b.readUnsignedInt();
}
private function readEntries():void{
var tmpbuf:ByteArray;
var len:uint;
var e:ZipEntry;
readEND();
entryTable = new Dictionary();
locOffsetTable = new Dictionary();
var i:uint;
while (i < entryList.length) {
tmpbuf = new ByteArray();
tmpbuf.endian = Endian.LITTLE_ENDIAN;
buf.readBytes(tmpbuf, 0, ZipConstants.CENHDR);
if (tmpbuf.readUnsignedInt() != ZipConstants.CENSIG){
throw (new ZipError("invalid CEN header (bad signature)"));
};
tmpbuf.position = ZipConstants.CENNAM;
len = tmpbuf.readUnsignedShort();
if (len == 0){
throw (new ZipError("missing entry name"));
};
e = new ZipEntry(buf.readUTFBytes(len));
len = tmpbuf.readUnsignedShort();
e.extra = new ByteArray();
if (len > 0){
buf.readBytes(e.extra, 0, len);
};
buf.position = (buf.position + tmpbuf.readUnsignedShort());
tmpbuf.position = ZipConstants.CENVER;
e.version = tmpbuf.readUnsignedShort();
e.flag = tmpbuf.readUnsignedShort();
if ((e.flag & 1) == 1){
throw (new ZipError("encrypted ZIP entry not supported"));
};
e.method = tmpbuf.readUnsignedShort();
e.dostime = tmpbuf.readUnsignedInt();
e.crc = tmpbuf.readUnsignedInt();
e.compressedSize = tmpbuf.readUnsignedInt();
e.size = tmpbuf.readUnsignedInt();
entryList[i] = e;
entryTable[e.name] = e;
tmpbuf.position = ZipConstants.CENOFF;
locOffsetTable[e.name] = tmpbuf.readUnsignedInt();
i++;
};
}
public function getInput(entry:ZipEntry):ByteArray{
var _local4:ByteArray;
var _local5:Inflater;
buf.position = ((locOffsetTable[entry.name] + ZipConstants.LOCHDR) - 2);
var len:uint = buf.readShort();
buf.position = (buf.position + (entry.name.length + len));
var b1:ByteArray = new ByteArray();
if (entry.compressedSize > 0){
buf.readBytes(b1, 0, entry.compressedSize);
};
switch (entry.method){
case ZipConstants.STORED:
return (b1);
case ZipConstants.DEFLATED:
_local4 = new ByteArray();
_local5 = new Inflater();
_local5.setInput(b1);
_local5.inflate(_local4);
return (_local4);
default:
throw (new ZipError("invalid compression method"));
};
}
public function get entries():Array{
return (entryList);
}
public function getEntry(name:String):ZipEntry{
return (entryTable[name]);
}
}
}//package nochump.util.zip
Section 25
//Camvatar (Camvatar)
package {
import com.whirled.*;
import flash.events.*;
import flash.display.*;
import flash.utils.*;
import flash.media.*;
import flash.geom.*;
import flash.system.*;
import com.adobe.images.*;
import com.whirled.contrib.*;
public class Camvatar extends Sprite {
protected var _quality:Number;
protected var _loader:Loader;
protected var _camera:Camera;
protected var _height:int;
protected var _width:int;
protected var _ctrl:AvatarControl;
protected var _nextLoader:Loader;
protected var _suspended:Boolean;
protected var _encoder:JPGEncoder;
protected var _config:Boolean;
protected var _chunker:Chunker;
protected var _snapshot:BitmapData;
protected var _oWidth:int;
protected var _oHeight:int;
protected var _inControl:Boolean;
protected var _video:Video;
public function Camvatar(){
super();
_loader = new Loader();
_nextLoader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleLoaderComplete);
_nextLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleLoaderComplete);
addChild(_loader);
_ctrl = new AvatarControl(this);
_ctrl.addEventListener(Event.UNLOAD, handleUnload);
_chunker = new Chunker(_ctrl, "", chunkReceived);
DataPack.load(_ctrl.getDefaultDataPack(), gotPack);
_suspended = (this.stage == null);
addEventListener(Event.ADDED_TO_STAGE, handleAddRemove);
addEventListener(Event.REMOVED_FROM_STAGE, handleAddRemove);
if (_ctrl.hasControl()){
initSending();
} else {
_ctrl.addEventListener(ControlEvent.CONTROL_ACQUIRED, initSending);
};
}
protected function gotPack(pack:DataPack):void{
_config = pack.getBoolean("showCameraConfig");
_width = pack.getNumber("width");
_height = pack.getNumber("height");
_oWidth = pack.getNumber("camWidth");
_oHeight = pack.getNumber("camHeight");
_quality = pack.getNumber("quality");
_ctrl.setHotSpot((_width / 2), _height, (_height + 10));
initSending();
}
protected function handleUnload(event:Event):void{
_inControl = false;
}
protected function gotStatus(... _args):void{
_camera.setMode(_width, _height, _camera.fps);
if (_video != null){
_video.clear();
if (_video.x != 0){
removeChild(_video);
};
};
_video = new Video();
_video.width = _width;
_video.height = _height;
_video.attachCamera(_camera);
_snapshot = new BitmapData(_video.width, _video.height, false);
checkSend();
}
protected function initSending(... _args):void{
if (((!(_ctrl.hasControl())) || ((_width == 0)))){
return;
};
if (_config){
Security.showSettings(SecurityPanel.CAMERA);
};
_inControl = true;
_camera = _ctrl.getCamera();
if (_camera == null){
trace("Got no camera");
return;
};
_camera.addEventListener(StatusEvent.STATUS, gotStatus);
_encoder = new JPGEncoder(_quality);
gotStatus();
}
protected function checkSend():void{
if (((!(_inControl)) || (_suspended))){
return;
};
if (_camera.muted){
trace("Camera muted");
return;
};
_snapshot.draw(_video, new Matrix((_width / _oWidth), 0, 0, (_height / _oHeight)));
_chunker.send(_encoder.encode(_snapshot));
}
protected function handleLoaderComplete(event:Event):void{
addChild(_nextLoader);
_loader.unload();
removeChild(_loader);
var tmp:Loader = _loader;
_loader = _nextLoader;
_nextLoader = tmp;
}
protected function chunkReceived(data:Object):void{
_nextLoader.loadBytes((data as ByteArray));
checkSend();
}
protected function handleAddRemove(event:Event):void{
_suspended = (event.type == Event.REMOVED_FROM_STAGE);
checkSend();
}
}
}//package