Sic/frame1.as

From Organic Design wiki
Revision as of 23:45, 24 September 2013 by Nad (talk | contribs) (legacy)
Legacy.svg Legacy: This article describes a concept that has been superseded in the course of ongoing development on the Organic Design wiki. Please do not develop this any further or base work on this concept, this is only useful for a historic record of work done. You may find a link to the currently used concept or function in this article, if not you can contact the author to find out what has taken the place of this legacy item.

<as> // // Liscenced under LGPL: www.gnu.org/copyleft/lesser.html // // Nad - 2003 - SIC-Games // Frame1: GENERAL DECLARATIONS //

FSCommand("fullscreen",true);

// GLOBALS // SPACE // SPACE.CREATE // SPACE.FRAME // TEMPLATE // 3D OBJECT CLASSES // Spark // Ball // OBJECT CLASS // GUN FIRE CLASS // BULLET CLASS // GUN CLASS // STAR-BURST CLASS // TORUS CLASS // IMPLODE CLASS // STARFIELD CLASS // 3D MOTION CLASSES // FLOAT // INTERFACES // interfaces.addInterface // interfaces.deleteInterface // interfaces.sync // interfaces.ack // updateInterfaces // NETWORK // processOutgoingEvents // processIncomingEvents // createEvent // sendMessage // processMessage // SHELL

// _____________________________________________________________________________________________________________________ // // GLOBALS now = new Date(); time = now.getTime(); allSpaces = []; // Keep track of all spaces so all their frame() can be executed CWD = ;

// _____________________________________________________________________________________________________________________ // // SPACE // Initialise passed movieclip as a 3D space

function initialiseSpace(newSpace) { _root.allSpaces.push(newSpace); newSpace.create = _root.space.create; newSpace.frame = _root.space.frame; newSpace.active = true; // Enables/disables space dynamics newSpace.space = newSpace; // create() function used at all levels expects space to be this.space; newSpace.rotation = 0; // global rotation of space newSpace.shipRotation = 0; // global rotation of ship (which the screens are windows out of) newSpace.applySR = true; newSpace.zbuff = []; // Z ordered symbol-refs of all 3D objects newSpace.zbLength = 0; // Since zbuff is sorted, we can use an end-ptr instead of pushing/splicing newSpace.children = []; // Top layer children newSpace.template = _root.template; // Template object for creating new symbols into the space newSpace.zSCREEN = 1000; // Distance from origin (eye) to screen }

// _____________________________________________________________________________________________________________________ // // SPACE.CREATE // Method: The space and all its objects inherit this method for creating child objects // Creates a symbol for the 3D-object (spacer is used if classes[thisClass].symbol == null) // The passed data object extends the space.template used to initialise the new object // - called from events: guid,time,method,class... space = {}; space.create = function(parameters) { var space = this.space; var time = 1*parameters[1]; if (time == 0) time = _root.time; // Name object from create-event-guid (so it can be referred to across peers)

var instanceName = parameters[0]; if (instanceName == 0) instanceName = _root.guid(); var symbol, hasSymbol = false; var class = parameters[3]; var classRef = _root.classes[class]; if (class == 'obj') symbol = parameters[4]; else symbol = classRef.symbol; // Create new child symbol using the 3D-object template (space.template) space.createEmptyMovieClip(instanceName, 10000-space.zbLength); // NOTE! 10000-layer cos z-buffering not working var child = space[instanceName]; if (symbol != null) { child.createEmptyMovieClip('swf', 0); child.swf.loadMovie('./swf/'+symbol); hasSymbol = true; } var template = space.template; for (var i in template) child[i] = template[i]; this.children.push(child); // object available in hierachical update tree of frame() calls space.zbuff[space.zbLength++] = child; // place object into z-buffer for layer sorting // Populate new child symbol/object for (var i in classRef) child[i] = classRef[i]; child.space = space; child.class = class; child.parent = this; child.applySR = this.applySR; child.colour = new Color(child.swf); child.children = []; child.hasSymbol = hasSymbol; child.time = time; child._alpha = 0; child.die = false; // Set the objects' dynamics() and call its init() - parameters[3] is 3DO-class if (classRef.init != null) classRef.init.call(child, parameters); // names and stores parameters, creates children etc return child; };

// _____________________________________________________________________________________________________________________ // // SPACE.FRAME // Method: Called every frame (not generic) // - this is the top level frame function called by SWF on frame2 space.frame = function() { var space = this.space; // Execute the template.frame() of each top-level child for (var i = this.children.length-1; i >= 0; --i) { var obj = this.children[i]; obj.ax = obj.ay = obj.az = 0; obj.frame(); // delete from this child list if marked for death if (obj.die) this.children.splice(i,1); } // Reduce the 3D coordinates to 2D for *ALL* objects with symbols (ie all layers, empty) // - ax,ay,az are absolute positions calculated in child frame() exec layers for (var i = 0; i < space.zbLength; i++) { var obj = space.zbuff[i]; if (obj.die) obj.az = -100000000; // dead ones will get sorted to the end else { // Global rotation if (obj.applySR) { if (space.rotation != 0) obj.rotate('ax', 'az', space.rotation); // Ship rotation if (space.shipRotation != 0) { if (_root.network.thisIndex == 0) obj.rotate('ax', 'ay', space.shipRotation); else if (_root.network.thisIndex == 1) obj.rotate('ay', 'az', space.shipRotation); else if (_root.network.thisIndex == 2) obj.rotate('ay', 'ax', space.shipRotation); else if (_root.network.thisIndex == 3) obj.rotate('az', 'ay', space.shipRotation); } } // 3D -> 2D var m = space.zSCREEN/obj.az; obj._x = obj.ax*m; obj._y = obj.ay*m; // 3D -> Scale if (m < 0) m = 0; else if (m > 10) m = 10; obj._xscale = obj._yscale = obj.scale*m; // 3D -> Lighting //if (m <= 0.25) light = 1; else if (m < 1) light = (m-0.25)*10000/75; else light = 100; //light = light/2+50; //obj.colour.setTransform({ra:light, ga:light, ba:light}); obj._alpha = obj.alpha; } } // Sort buffer by Z and synchronise rendering levels for (var i = 0; i < space.zbLength-1; i++) { var obj = space.zbuff[i]; var maxz = obj.az, maxp = i; for (var j = i+1; j < space.zbLength; j++) if (space.zbuff[j].az > maxz) { maxz = space.zbuff[j].az; maxp = j; } if (maxp != i) { obj.swapDepths(space.zbuff[maxp]); space.zbuff[i] = space.zbuff[maxp]; space.zbuff[maxp] = obj; } }

// Delete nodes marked for death (they will have been sorted to the end of the buffer) while (space.zbuff[space.zbLength-1].die) space.zbuff[--space.zbLength].removeMovieClip();

//logClr(); //for (var i = 0; i < space.zbLength-1; i++) logAdd(space.zbuff[i].getDepth());

};

// _____________________________________________________________________________________________________________________ // // TEMPLATE // - Create a set of methods and properties inherited by all symbols created in the space // - various dynamics() and effects() can add and maintain other properties template = {}; template.space = null; // set by create() A ref to the space object template.create = space.create; // Inherits generic create() method template.parent = null; // Set by create(), a ref to the parent of this object template.children = null; // Children of this object (must be initialised by create) template.die = false; // Object deletion must be handled ny the space.frame() template.motion = []; // Motion functions to call in frame() template.colour = null; // Set by create() - objects colour transform template.scale = 100; // symbol scale template.alpha = 100; // symbol scale template.time = 0; // Objects' absolute birth time template.x = 0; // Objects relative position (ie relative to birth location and time) template.y = 0; // template.z = 0; //

// per-frame method for 3D-objects (not the space itself which has its own frame function) // - frame() calculates the absolute position from the relative positions in the parent-child chain of each object template.frame = function() { var p = [this.x, this.y, this.z]; var t = _root.time-this.time; // Initialise symbol when loaded var swf = this.swf; if ((swf._width > 0) && (++swf.ctr == 1)) { swf._x = -swf._width/2; swf._y = -swf._height/2; } // Update objects dynamic properties if (!this.die) { if (this.dynamics != null) this.dynamics(t); // Execute this objects' current motion effects x += f(t) for (var i = 0; i < this.motion.length; i++) _root.motion[this.motion[i]].call(this, t); // Update absolute location for space.frame() to render this.ax += this.x; this.ay += this.y; this.az += this.z; } // Execute the frame() of each child // - if this is dead, propagate death to descendents for (var i = this.children.length-1; i >= 0; --i) { var obj = this.children[i]; if (this.die) obj.die = true; else { obj.ax = this.ax; obj.ay = this.ay; obj.az = this.az; } obj.frame.call(obj); } // Restore x,y,z //this.x = p.shift();// *** bullet collision doesn't work properly when these are restored...? //this.y = p.shift(); //this.z = p.shift(); };

// Rotate an object template.rotate = function(x, y, a) { a += Math.atan2(this[y], this[x]); var r = Math.sqrt(this[x]*this[x]+this[y]*this[y]); this[x] = Math.cos(a)*r; this[y] = Math.sin(a)*r; };

// _____________________________________________________________________________________________________________________ // // 3D OBJECT CLASSES

// NOTE: (Not using languages' classes here as actionscript too lame-arse) // Each class has: // - init(data) used to create and layout child objects within itself (and can instantiate an asscoiated symbol too) // - dynamics() called from it's frame() which then also calls space.update // each dynamics can call a set of effects functions depending on its state and time // NOTE: dynamics must base all changes on time // NOTE: dynamics are responsible for their coordinates being relative to parent // - this is because some dynamics update their own coodinates and some their childrens // - classes may has only a symbol and no init() or dynamics()

// these phases and layers should be tree nodes classes = {}; // _____________________________________________________________________________________________________________________ // // Spark classes.spark = {}; classes.spark.init = function(parameters) { this.lat = parameters[4]; this.lon = parameters[5]; }; classes.spark.symbol = 'obj-spark.swf'; // Ball classes.ball = {}; classes.ball.init = function(parameters) { this.lat = parameters[4]; this.lon = parameters[5]; }; classes.ball.symbol = 'ball.swf'; // _____________________________________________________________________________________________________________________ // // OBJECT CLASS classes.obj = {}; classes.obj.init = function(parameters) { this.create([0,0,,'implode',0,0,0]); this.shootable = false; this.motion = ['float']; var ri = this.time; this.rc = 1500; this.rr = 200+_root.rnd(ri,2)*1000; this.rt = 0.0005+_root.rnd(ri,1)*0.0005; this.v = 0.0001+_root.rnd(ri+5,1)*0.0004; if (_root.rnd(ri+5,2) > 0.5) this.v = -this.v; this.yr = 50+_root.rnd(ri+10,1)*500; this.yt = 0.001+_root.rnd(ri+10,2)*0.001; }; classes.obj.dynamics = function(t) { var swf = this.swf; // fade object in this.alpha = t/20; if (this.alpha > 100) this.alpha = this.shootable = 100; // set object frame this.f = 1+Math.floor((t/50)%swf._totalframes); swf.gotoAndStop(this.f); // Motion var r = this.rc+_root.motion.squareSine(t*this.rt)*this.rr; this.y = Math.sin(t*this.yt)*this.yr; r += Math.cos(t*this.yt)*this.yr; this.x = r*Math.sin(t*this.v); this.z = r*Math.cos(t*this.v); }; // _____________________________________________________________________________________________________________________ // // GUN FIRE CLASS classes.fire = {}; classes.fire.symbol = 'obj-spark.swf'; classes.fire.init = function(parameters) { this.applySR = false; this.alpha = 0; this.state = false; }; classes.fire.dynamics = function(t) { this.swf.gotoAndStop(2); var gun = _root.gun; this.x = gun.object.ax+gun.ox[gun.frame]/10; this.y = gun.object.ay+gun.oy[gun.frame]/10; this.z = gun.object.az; if (this.state) { this.time = _root.time; this.state = false; _root.sounds.gun1.start(); this.space.create([0,0,,'bullet']); _root.gun.lastShot = _root.time; } this.alpha = 100-t/2; if (this.alpha < 0) this.alpha = 0; };

// _____________________________________________________________________________________________________________________ // // BULLET CLASS classes.bullet = {}; classes.bullet.symbol = 'obj-spark.swf'; classes.bullet.init = function(parameters) { this.applySR = false; this.x = _root.gun.fire.ax; this.y = _root.gun.fire.ay; this.z = _root.gun.fire.az; this.dx = (_root._xmouse-512) - _root.gun.fire.ax; this.dy = (_root._ymouse-384) - _root.gun.fire.ay; }; classes.bullet.dynamics = function(t) { this.swf.gotoAndStop(2); this.x = _root.gun.fire.ax + this.dx*t/200; this.y = _root.gun.fire.ay + this.dy*t/200; this.z = _root.gun.fire.az+t*5; if (this.z > 2000) this.die = true; // check all shootable objects for hit for (var i = 0; i < _root.game.children.length; i++) { var obj = _root.game.children[i]; if (obj.shootable) { var dx = this.x - obj.x; var dy = this.y - obj.y; var dz = this.z - obj.z; var d2 = dx*dx+dy*dy+dz*dz; if (d2<5000) { // Hit! - do death and explosion sounds locally _root.sounds['die'+int(Math.random()*10)].start(); createEvent('now,playSound,gun5,100', --_root.localguid); createEvent(+(_root.time+490)+',playSound,gun4,100', --_root.localguid); _root.game.create([0,0,,'starBurst',10,0.25,obj.x,obj.y,obj.z]); // propagate the kill createEvent('now,objects.kill,'+obj._name, null); // Make sure obj can't be hit twice and bullet can't hit twice obj.shootable = false; this.die = true; i = _root.game.children.length; } } } }; // _____________________________________________________________________________________________________________________ // // GUN CLASS classes.gun = {}; classes.gun.motion = ['float']; classes.gun.init = function(parameters) { this.applySR = false; }; classes.gun.symbol = 'obj-gun.swf'; classes.gun.dynamics = function(t) { this.x = 0; this.y = 30; this.z = 100; this.scale = 25; this.swf.gotoAndStop(_root.gun.frame); }; // _____________________________________________________________________________________________________________________ // // STAR-BURST CLASS classes.starBurst = {}; classes.starBurst.symbol = 'obj-spark.swf'; classes.subBurst = {}; // starBurst: stars,force,x,y,z classes.starBurst.init = function(parameters) { var guid = parameters[0]; this.stars = parameters[4]; this.force = parameters[5]; this.x = 1.0*parameters[6]; this.y = 1.0*parameters[7]; this.z = 1.0*parameters[8]; this._visible = false; var ri = this.time; for (var i = 0; i < this.stars; i++) { var lat = _root.rnd(ri,1)*2*Math.PI; var lon = _root.rnd(ri+10,1)*2*Math.PI; ri+=20; var obj = this.create([0,this.time,,'subBurst',4,1.5,500,lat,lon,ri]); } }; // subBurst: stars,force,start,fadeout,lat,lon classes.subBurst.init = function(parameters) { this.stars = parameters[4]; this.force = parameters[5]; this.start = parameters[6]; this.lat = parameters[7]; this.lon = parameters[8]; var ri = 1*parameters[9]; for (var i = 0; i < this.stars; i++) { var lat = _root.rnd(ri,3)*2*Math.PI; var lon = _root.rnd(ri+31,3)*2*Math.PI; ri+=51; var obj = this.create([0,0,,'spark',lat,lon]); obj.index = i; } }; classes.subBurst.symbol = 'obj-spark.swf'; classes.starBurst.dynamics = function(t) { var onlyOne = true; // This is a subBurst if (this.start != null) { this.swf.gotoAndStop(4); if (t > this.start) { this.radius = (t-this.start)*this.force; onlyOne = false; } } else { this.swf.gotoAndStop(1); this.radius = 100+t*this.force; } this.force = this.force*0.97; if (this.alpha < 0) this.alpha = 0; var a = 100-(t/30); if (a < 0) { if (this.parent == this.space) this.die = true; a = 0; } // Update child positions: x = 0 + f(t) stylz for (var i = 0; i < this.children.length; i++) { var star = this.children[i]; var s = this.radius*Math.cos(star.lon); star.x = s*Math.cos(star.lat+t/500); star.y = this.radius*Math.sin(star.lon)+t*t/8000; star.z = s*Math.sin(star.lat+t/500); if (onlyOne && (i>0)) star.alpha = 0; else star.alpha = a; } }; classes.subBurst.dynamics = classes.starBurst.dynamics; // _____________________________________________________________________________________________________________________ // // TORUS CLASS classes.torus = {}; // torus: points,radius,speed (has been converted specifically to target object) classes.torus.init = function(parameters) { this.applySR = false; this.points = 1*parameters[4]; this.radius = 1.0*parameters[5]; this.speed = 1.0*parameters[6]; for (var i = 0; i < this.points; i++) this.create([0,0,,'spark',50]); }; classes.torus.dynamics = function(t) { this.x = _root._xmouse-512; this.y = _root._ymouse-384; this.Z = 1000; var s; if (++this.ctr%50<12) s = 0; else s = t/250; var sec = Math.round(t/100); for (var i = 0; i < this.children.length; i++) { var point = this.children[i]; point.swf.gotoAndStop(1); var angle = 2*Math.PI*i/this.children.length+this.angle/this.children.length+s; var r = this.parent.radius+this.radius*Math.sin(angle); point.x = this.x+r*Math.cos(this.angle); point.y = this.y+this.radius*Math.cos(angle); point.z = this.z+r*Math.sin(this.angle); point.scale = 200; if (s == 0) point._visible = (sec%2==0); else point._visible = true; } };

// _____________________________________________________________________________________________________________________ // // IMPLODE CLASS classes.implode = {}; classes.implode.init = function(parameters) { this.stars = 25; this.radius = 200; this.x = 1.0*parameters[4]; this.y = 1.0*parameters[5]; this.z = 1.0*parameters[6]; var ri = this.time; for (var i = 0; i < this.stars; i++) { var lat = _root.rnd(ri,1)*2*Math.PI; var lon = _root.rnd(ri+10,1)*2*Math.PI; var obj = this.create([0,0,,'spark',lat,lon]); obj.v = _root.rnd(ri+20,1)*100+10; obj.scale = 50; ri+=30; } }; classes.implode.dynamics = function(t) { this.radius = 500-t/3; if (this.radius < 100) this.radius = 100; var a = t/10; if (a > 200) this.die = true; if (a > 100) a = 200-a; for (var i = 0; i < this.children.length; i++) { var star = this.children[i]; var r = this.radius*star.v/50; var s = r*Math.cos(star.lon); star.x = s*Math.cos(star.lat+t/star.v/2); star.y = r*Math.sin(star.lon); star.z = s*Math.sin(star.lat+t/star.v/2); star.alpha = a/2; } };

// _____________________________________________________________________________________________________________________ // // STARFIELD CLASS classes.starField = {}; classes.starField.init = function(parameters) { this.stars = 100; this.radius = 2000; var ri = this.time; for (var i = 0; i < this.stars; i++) { var lat = _root.rnd(ri,1)*2*Math.PI; var lon = _root.rnd(ri+10,1)*2*Math.PI; var obj = this.create([0,0,,'spark',lat,lon]); obj.v = _root.rnd(ri+20,1)*100+10; obj.scale = 50; ri+=30; } }; classes.starField.dynamics = function(t) { this.radius = 500-t/3; if (this.radius < 100) this.radius = 100; var a = t/10; if (a > 200) this.die = true; if (a > 100) a = 200-a; for (var i = 0; i < this.children.length; i++) { var star = this.children[i]; var r = this.radius*star.v/50; var s = r*Math.cos(star.lon); star.x = s*Math.cos(star.lat+t/star.v/2); star.y = r*Math.sin(star.lon); star.z = s*Math.sin(star.lat+t/star.v/2); star.alpha = a/2; } };

// _____________________________________________________________________________________________________________________ // // 3D MOTION CLASSES // - 3D Motion functions called by an objects' frame() if in its motion[] list

// FLOAT // Adds the metaparticles movement to passed object motion = {}; motion.float = function(t) { var a = t/400; var m = (this._width+this._height)*this.scale/10000; var api4 = a*Math.PI/4; var api8 = a*Math.PI/8; var cospi4 = Math.cos(api4); var cospi8 = Math.cos(api8); var sinpi4 = Math.sin(api4); var sinpi8 = Math.sin(api8); this.x += m*cospi4*sinpi8; this.y += m*cospi4*cospi8; this.z += m*sinpi4; }; motion.squareSine = function(t) { var i = Math.floor(t/Math.PI)%6; if ((i == 1) || (i == 2)) return -1; if (i > 3) return 1; return Math.cos(t); };

// _____________________________________________________________________________________________________________________ // // INTERFACES // the swf addresses the object structure directly (its hash)

// maintains a list of the active interfaces // - first when ordered by key (guid) is timeServer // - timeServer sends current time after it hasn't recvd a time for >5s interfaces = {}; interfaces.active = {};

// These functions are methods so they can be executed by event-messages // - addInterface should propagate an ack event so it gains everyones info // interfaces.addInterface interfaces.addInterface = function(parameters) { var guid = parameters.shift(); var method = parameters.shift(); var i = parameters[1]; logAdd('interfaces.addInterface('+i+')'); var ai = _root.interfaces.active; ai[i] = 1; updateInterfaces(); createEvent('now,interfaces.ack,'+_root.network.thisInterface, null); };

// interfaces.deleteInterface interfaces.deleteInterface = function(parameters) { logAdd('interfaces.deleteInterface()'); var guid = parameters.shift(); var time = parameters.shift(); var method = parameters.shift(); var i = parameters[0]; var ai = _root.interfaces.active; delete ai[i]; updateInterfaces(); };

// interfaces.sync interfaces.sync = function(parameters) { logAdd('sync'); _root.timeError = getTimer(); if (parameters[3] == _root.network.thisInterface) return; // don't ack our own sync if (_root.network.thisIndex != 0) return; // only the first interface responds to syncs createEvent('now,interfaces.ack,'+_root.network.thisInterface+','+_root.time, null); };

// Receiving an ack from another IF // - set time from ack; // interfaces.ack interfaces.ack = function(parameters) { var guid = parameters.shift(); var method = parameters.shift(); var i = parameters[1]; if (i == _root.network.thisInterface) return; // don't ack ourselves logAdd('interfaces.ack('+i+')'); var ai = _root.interfaces.active; ai[i] = 1; updateInterfaces(); };

// Currently just logs // updateInterface function updateInterfaces() { var ai = _root.interfaces.active; var orderedList = []; for (var guid in ai) orderedList.push(guid); orderedList.sort(); for (var i = 0; i < orderedList.length; i++) { var j = orderedList[i]; if (j == _root.network.thisInterface) _root.network.thisIndex = i; j = j.substr(-6); logAdd(' '+i+' : SWF-'+j.toUpperCase()); } var index = _root.network.thisIndex; logAdd(' My index is '+index); logAdd(' I am '+_root.network.thisInterface); var p = _root.demo.personas; var i = index%4; _root.demo.setPersona(p[i]); logAdd(" I have an index, so I've set my persona and angle..."); logAdd(" I am the "+p[i]+"."); _root.game.rotation = i*Math.PI/2; logAdd(" My space is rotated by "+(_root.game.rotation/Math.PI)+' Pi radians.'); }

// _____________________________________________________________________________________________________________________ // // NETWORK network = new XMLSocket(); network.port = 2012; network.thisGuid = guid(); network.thisPeer = null; // defined after first message from our peer network.peers = []; network.thisInterface = null; // known after peer known network.incomingEvents = {}; network.outgoingEvents = {}; network.finishedEvents = {};

// When connected to our peer, send out info network.onConnect = function(success) { _root.network.connected = success; sendMessage('port='+network.port+'&add=interface&guid='+network.thisGuid, ); };

// Decode incoming message network.onData = function(data) { var msg = data.split("|"); var subject = msg[0]; var content = msg[1]; // split subject query-string and extract our peer and our name logAdd(subject); var qs = subject.split("&"); for (var i = 0; i < qs.length; i++) { var j = qs[i].split("="); if (j[0] == 'to') _root.network.thisInterface = j[1]; if ((j[0] == 'from') && (_root.network.thisPeer == null)) { var peer = _root.network.thisPeer = j[1]; logAdd('My peer is '+peer); // make a guess at the persona (%n of last ip part) // var p = _root.demo.personas; // var k = peer.split('.'); // k = k[k.length-1].split(':'); // p = p[(k[0]%_root.demo.personas.length)-1]; // _root.demo.setPersona(p); // logAdd(" I'll take a guess at my persona from my own IP number..."); // logAdd(" I am the "+p+"."); } if (j[0] == 'peers') { _root.network.peers = j[1].split(','); _root.network.peers.push(_root.network.thisPeer); } } // Split content quey-string and execute each event (guid=time,cmd,parameters...) qs = content.split("&"); for (var i = 0; i < qs.length; i++) { var j = qs[i].split("="); if (_root.network.finishedEvents[guid] == null) createEvent(j[1], j[0]); // parameters, [guid] } };

// Send a message to the associated peer.pl function sendMessage(subject, content) { logAdd('Sending ('+subject+')'); _root.network.send(subject+"|"+content); // SWF automatically appends \x00 }

// _____________________________________________________________________________________________________________________ //

// Sends queue of local events needing propagation // processOutgoingEvents function processOutgoingEvents() { var oe = _root.network.outgoingEvents; var fe = _root.network.finishedEvents; // Build a query-string of the queued-events var msg = []; for (var guid in oe) msg.push(guid+"="+oe[guid]); var qs = msg.join("&"); // Send queued and unprocessed events if any if (qs.length > 0) sendMessage(, qs); // Clear outgoing events buffer now that they've been propagated _root.network.outgoingEvents = {}; }

// Executes events which were received before their birth-time // processIncomingEvents function processIncomingEvents() { var ie = _root.network.incomingEvents; var fe = _root.network.finishedEvents; _root.del = []; for (var guid in ie) createEvent(ie[guid], guid); // inefficient way - calls createEvent every time // Can't delete items in ie while looping through ie while (_root.del.length > 0) delete ie[_root.del.pop()]; }

// Create a new event locally // createEvent function createEvent(parameters, guid) { var ie = _root.network.incomingEvents; var oe = _root.network.outgoingEvents; var fe = _root.network.finishedEvents; var plist = parameters.split(","); var t = 1*plist[0]; // If no guid, event is new and needs to be propagated outward and also queued in incoming for local creation if (guid == null) { guid = _root.guid(); oe[guid] = parameters; } else if (fe[guid]) return; ie[guid] = parameters; // Execute events' method if birth-time past, else queue in incomings if (t <= _root.time) { var path = '_root.'+plist[1]; plist[0] = t; plist.unshift(guid); var eventMethod = eval(path); var parent = eval(parent(path)); logAdd(parameters); eventMethod.call(parent, plist); _root.del.push(guid); fe[guid] = true; } return guid; }

// _____________________________________________________________________________________________________________________ //

function guid() { return 'g'+(Math.random()+getTimer()); }

function parent(s) { return s.substr(0,s.lastIndexOf('.')); }

// Sends log output to its associated perl-peer for output // - use logPattern = ^\. to filter since they all start with ...guid function logAdd(entry) { //sendMessage('log='+entry, ); if (_root.shell._visible == false) return; _root.shell.lines.push(entry); while (_root.shell.lines.length>_root.shell.buffer) _root.shell.lines.shift(); _root.shell.text = _root.shell.lines.join("\n"); _root.shell.setTextFormat(_root.shell.format); }

function logClr() { _root.shell.lines = []; }

function tab(list, w) { for (var i = 0; i < list.length; i++) { var pad = ' '; var s = list[i]; var l = s.length; s = s.substr(0,w); if (s.length < w) s = s+p.substr(0,w-l); } }

// _____________________________________________________________________________________________________________________ // // SHELL function initialiseShell() { _root.createTextField('shell',5,0,0,1024,768); var shell = _root.shell; shell.multiline = true; shell.wordWrap = true; shell.border = false; shell.selectable = false; shell.wordwrap = false; shell.format = new TextFormat(); shell.format.color = 0xff00; shell.format.font = 'Courier New'; shell.format.size = 24; shell.lines = []; shell.buffer = 28; shell._visible = false; shell.state = 0; shell.onKeyDown = function() { var shell = _root.shell; _root.perl.perlScroll = false; _root.demo._visible = _root.demo.active = false; _root.game._visible = _root.game.active = true; _root.environment.lastActivity = _root.time; // Shell/game control key if (Key.isDown(Key.CONTROL) && Key.getCode() == Key.HOME) shell._visible = (shell.state = ++shell.state%3) != 0; // Return if shell invisible, else do command entry/execution if (!shell._visible) return; var s = shell.lines; var l = shell.lines.length-1; var start = _root.CWD.length+16; if (Key.getCode() == Key.DELETEKEY) s[l] = s[l].substr(0,start); else if (Key.getCode() == Key.BACKSPACE) { if (s[l].length > start) s[l] = s[l].substr(0, s[l].length-1); } else if (Key.getCode() == Key.ENTER) { var input = s[l].substr(start,1000); if (input != ) { // Extract command and data portions of input var obj; var cmd = input.split(' '); var parameters; if (cmd.length > 1) parameters = input.substr(input.indexOf(' ')+1,1000); cmd = cmd[0]; if ((cmd == '?') || (cmd == 'help')) { // help - lame, cmd code and syntax strings should be in shell object logAdd(' sickShell Commands:'); logAdd(' demo view peers'); logAdd(' ls cd set sync time'); logAdd(' interfaces perl connect'); logAdd(' Keys:'); logAdd(' CTRL + HOME  : enable/disable game and shell'); } else if (cmd == 'ls') { // ls if (parameters == null) obj = refFromPath(_root.CWD); else obj = refFromPath(parameters); var n=0; for (var i in obj) { var t = typeOf(obj[i]); if (obj == _root) { if (t == 'object' || t == 'movieclip') {s.push(' '+i+' ('+t+')'); n++;} } else {s.push(' '+i+' ('+t+')'); n++;} } logAdd(+n+' object(s).'); } else if (cmd == 'cd') { // cd if (parameters == '..') _root.CWD = fixPath(parent(_root.CWD)); else if (parameters != null) { obj = refFromPath(parameters); if (obj != null) _root.CWD = fixPath(parameters); } } else if (cmd == 'set') { // set var j = parameters.split('='); obj = refFromPath(j[0]); var t = typeOf(obj); if ((t != 'undefined') && (t != 'object') && (t != 'movieclip') && (t != 'function')) { obj=j[1]; logAdd(' '+j[0]+' set to '+j[1]); } else logAdd('Could not set '+j[0]+' to '+j[1]); } else if (cmd == 'connect') { // connect sendMessage('connect='+parameters, ); logAdd('Connection requested'); } else if (cmd == 'sync') { // sync _root.timeError = -getTimer(); logAdd('Time reset.'); } else if (cmd == 'time') { // time logAdd('Time : '+time); } else if (cmd == 'interfaces') { // interfaces updateInterfaces(); } else if (cmd == 'peers') { // peers for (var i = 0; i < _root.network.peers.length; i++) logAdd(' '+i+' : '+_root.network.peers[i]); logAdd(' My peer is '+_root.network.thisPeer); } else if (cmd == 'view') { // view _root.environment.angle = 0.0+parameters; logAdd(' View angle set to '+_root.environment.angle); } else if (cmd == 'demo') { // demo if (parameters == null) { _root.demo._visible = _root.demo.active = true; _root.game._visible = _root.game.active = false; } else { _root.demo.setPersona(parameters); logAdd(' Persona : '+_root.demo.persona); } } else if (cmd == 'rand') { // rand logAdd(prand(100)); } else logAdd('Unknown command: '+input); }; prompt(); } else s[l] += String.fromCharCode(Key.getAscii()); while (s.length > _root.shell.buffer) s.shift(); _root.shell.text = s.join("\n"); _root.shell.setTextFormat(_root.shell.format); }; Key.addListener(shell); prompt(); }

function prompt() { _root.shell.lines.push("sickShell:_root"+_root.CWD+'$'); }

// todo: change events to use this function refFromPath(path) { if (path == '.') return _root; var cwd = _root.CWD; if (path == ) path = cwd; else if (path.indexOf('.') != 0) path = cwd+'.'+path; var ref = eval('_root'+path); if (ref == null) logAdd("Couldn't resolve object!"); return ref; }

// todo: get rid of this shit function fixPath(path) { var cwd = _root.CWD; if (cwd == '.') cwd = ; if (path.indexOf('.') != 0) path = cwd+'.'+path; return path; } </as>