Expand my Community achievements bar.

UserManager.userCollection order

Avatar

Former Community Member

Hi,

I'm currently working on a multiplayer game based on AFCS. Players will have to play after each other. The current player client is responsible to find the next player and give him the turn.

To do so, I was thinking about using the userCollection and I was assuming that it was a shared Collection identical for all clients. So, to find the next player, the current player only had to search for himself in the Collection and give the turn to the next user in the list.

But, unfortunately, it seems that the userCollection isn't a shared object, at least the userCollection order is different for each user, meaning that I can't use it to find the next player.

Did I do something wrong? If not, is it possible to have the same order for all clients in the userCollection? Or do I have to code my own sharedUserCollection (which I would hate because it's asking for unconsistencies)?

Axel

1 Reply

Avatar

Former Community Member

Hi Axel,

  Well, you're not going to love this, but the UserManager does indeed sort each user's collection differently. The main difference is that a given user is always first on their own roster list (for their role), so their own item gets sorted to the front.

  I don't think you would find it too hard to maintain your own collection. I'll take a stab at it, we'll go purely alphabetically by displayName. Note that as people come and go, they potentially get inserted or deleted into/from the middle of the order. Not sure if that messes up your workflow or not.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application creationComplete="onCreationComplete()" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:authentication="com.adobe.rtc.authentication.*" xmlns:session="com.adobe.rtc.session.*">
    <authentication:AdobeHSAuthenticator id="authenticator" userName="blah"/>
    <session:ConnectSession id="cSession" authenticator="{authenticator}" synchronizationChange="addMyDesc()" roomURL="http://connectnow.acrobat.com/xxx/xxx"/>
    <mx:Script>
        <![CDATA[
            import com.adobe.rtc.sharedManagers.descriptors.UserDescriptor;
            import mx.collections.Sort;
            import mx.collections.ArrayCollection;
            import com.adobe.rtc.events.UserEvent;
            import mx.controls.Alert;
            import com.adobe.rtc.events.RoomManagerEvent;
           
            protected var _myUserCollection:ArrayCollection = new ArrayCollection();
            protected var _sorter:Sort = new Sort();

            protected function addMyDesc():void
            {

                // for reasons that are unclear to me, the arrival of my own userDesc doesn't trigger a UserCreate event. Feed my desc into the list manually once we're synched up.
                if (cSession.isSynchronized) {
                    addUserDesc(cSession.userManager.getUserDescriptor(cSession.userManager.myUserID));
                } else {
                    _myUserCollection = new ArrayCollection();
                }
            }
           
            protected function onUserCreate(p_evt:UserEvent):void
            {
                addUserDesc(p_evt.userDescriptor);
            }
           
            protected function addUserDesc(p_userDesc:UserDescriptor):void
            {
                // Find out where it should go. Note that sorter can't handle 0-length finds (!?!)
                var idx:int = (_myUserCollection.length) ? _sorter.findItem(_myUserCollection.source,
                                p_userDesc, Sort.ANY_INDEX_MODE, true, compareFunction) : 0;
                _myUserCollection.addItemAt(p_userDesc, idx);
            }
           
            protected function onUserRemove(p_evt:UserEvent):void
            {
                // Find out where the old descriptor was.
                var idx:int = _sorter.findItem(_myUserCollection.source, p_evt.userDescriptor, Sort.ANY_INDEX_MODE, false, compareFunction);
                _myUserCollection.removeItemAt(idx);
            }
           
            private function onCreationComplete():void
            {
                cSession.userManager.addEventListener(UserEvent.USER_CREATE, onUserCreate);
                cSession.userManager.addEventListener(UserEvent.USER_REMOVE, onUserRemove);
                cSession.login();
            }
           
            protected function compareFunction(p_descA:Object, p_descB:Object, p_fields:Array=null):int
            {
                if (p_descA.userID==p_descB.userID) {
                    // in cases we're searching for the user who was deleted, if their userIDs match, we've found him!
                    return 0;
                }
                // notice some weirdness here - it's possible for users to have the same name. Use the userID for disambiguation
                if(String(p_descA.displayName+p_descA.userID).toLowerCase() < String(p_descB.displayName+p_descB.userID).toLowerCase()) return -1;
                else if(String(p_descB.displayName+p_descB.userID).toLowerCase() < String(p_descA.displayName+p_descA.userID).toLowerCase()) return 1;
                else return 0; // should not get here, but just in case.
            }

        ]]>
    </mx:Script>
    <mx:List dataProvider="{_myUserCollection}" labelField="displayName" width="100" height="300"/>
</mx:Application>