I'm experimenting a bit with NetStream to pass data between players in a online Flash multiplayer game.
I use the events dispatches by the NetConnection class so I know what is the current state of my client.
For example, when I have a "NetConnection.Connect.Success" I know that I can start using the NetStream class and pass the NetConnection object to it.
Everything makes sense and works ok.
But, Im running into a problem when it comes to listening the NetStream.Connect.Success event. Seems like this event is fired multiple times for no reason, it's fired the first time when two users connect to each other, which is fine, I can see their farID and pass it to the other peer, and everything works just fine.
However, after that first connection between those peers, 3 or 4 more NetStream.Connect.Success are fired for no apparent reason. That not only annoys me, because I don't understand why is that happening, but also kind of breaks my "event based" architecture to determine what to do next in terms of what event was fired.
I can send and receive messages without problems, until I get a NetStream.Connect.Closed, which usually happens some seconds later. Sometimes I never get a closed event, and sometimes when I get one, I still can send and receive messages, it's like another connection was closed instead of the one I'm using right now.
Like you see, it's really messy, I don't know if I'm making some mistake or the entire event system is just bad designed.
Another thing I don't know if I'm doing right, is that I assign the client property of the sending stream and the receiving stream to "this", not sure if that's ok, but since it "works".. I guess is not the responsible of this weird behavior.
(The amfphp service, what it does, is to interchange the farID's)
This is my code, it's a very simple chat app:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="700" height="700"
>
<s:VGroup width="100%">
<s:TextArea id="historyTxt" width="100%" verticalAlign="bottom" enabled="false"/>
<s:TextInput id="inputTxt" enter="sendMessage(event)"/>
</s:VGroup>
<s:Button id="joinBtn" x="250" y="300" width="200" height="100" label="JOIN" fontSize="20" click="init()"/>
<mx:Text id="nearIDTxT" x="10" y="647" text="nearID" alpha="0.7" fontStyle="italic"/>
<mx:Text id="farIDTxT" x="10" y="669" text="farID" alpha="0.5" fontStyle="italic"/>
<fx:Script>
<![CDATA[
import flash.display.SimpleButton;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.NetStatusEvent;
import flash.events.StatusEvent;
import flash.geom.Point;
import flash.net.GroupSpecifier;
import flash.net.NetConnection;
import flash.net.NetGroup;
import flash.net.NetStream;
import flash.net.registerClassAlias;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import flash.utils.Timer;
import flash.utils.getTimer;
private const SERVER:String = "rtmfp://p2p.rtmfp.net/";
private const DEVKEY:String = "cde41fe05bb01817e82e5398-2ab5d983d09f";
private const NAME:String = "Paul";
private static const BOT:int = 1;
private static const TOP:int = 0;
private var _groupSpecifier:GroupSpecifier;
private var _cirrusNc:NetConnection;
private var _amfphpNc:NetConnection;
private var _groupSpec:String;
private var seq:int = 0;
private var _user:String;
private var _status:String;
private var _sendStream:NetStream;
private var _receivingStream:NetStream;
private var _connected:Boolean;
public var res:Responder;
public function init():void
{
joinBtn.visible = false;
_status = "waiting";
_cirrusNc = new NetConnection();
_cirrusNc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
_cirrusNc.connect( SERVER + DEVKEY );
}
public function onResult(response:Object):void {
//here we ask if there is another player waiting to connect to someone
if(response == "waiting") {
//just wait
}
//if not:
else {
connectToPeer(response[1]);
}
}
public function sendMessage(e:Event):void {
_sendStream.send("handler", e.currentTarget.text);
e.currentTarget.text = "";
}
public function onFault(response:Object):void {
for (var i:* in response) {
trace(response[i]);
}
}
private function onNetStatus(event:NetStatusEvent):void {
switch(event.info.code){
case "NetConnection.Connect.Success":
trace(event.info.code);
nearIDTxT.text = _cirrusNc.nearID;
onCirrusConnect();
break;
case "NetStream.Play.Start":
trace(event.info.code);
break;
case "NetStream.Connect.Success":
trace(event.info.code);
if(!_connected){
_connected = true;
farIDTxT.text = event.info.stream.farID;
onPeerConnect(event.info.stream.farID);
}
default:
trace(event.info.code);
}
}
private function onCirrusConnect():void {
//connecting to amfphp
_amfphpNc = new NetConnection();
_amfphpNc.connect("http://localhost/Amfphp/");
res = new Responder(onResult, onFault);
_amfphpNc.call("Rendezvous.match", res, NAME, _cirrusNc.nearID);
//defining the send stream
_sendStream = new NetStream(_cirrusNc, NetStream.DIRECT_CONNECTIONS);
_sendStream.client = this;
_sendStream.publish("data");
}
private function connectToPeer(farID:String):void {
farIDTxT.text = farID;
//defining the receiving stream
_receivingStream = new NetStream(_cirrusNc, farID);
_receivingStream.client = this;
_receivingStream.play("data");
}
private function onPeerConnect(farID:String):void {
farIDTxT.text = farID;
//defining the receiving stream
_receivingStream = new NetStream(_cirrusNc, farID);
_receivingStream.client = this;
_receivingStream.play("data");
}
public function handler(message:String):void {
trace(message);
historyTxt.text = message;
}
]]>
</fx:Script>
</s:Application>