Sic/frame1.as
<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>