Expand my Community achievements bar.

SharedProperty.value = undefined

Avatar

Level 2

I am working on an online collaborative boardgame, using AFCS for the syncing of all different game states of the game.

The game consists of different types of components, one of which is a 'Shield' component which has a certain strength. The strengths of these 'Shields' have to be syncronised for all players. Whenever the gaming board (which is a space-ship) gets hit by a certain thread, a certain shield decreases in strength.

I thought doing this with AFCS would be rather easy, as I used it already for other properties of the gameboard that have to be in sync. The problem is that whenever I want to decrease the value of the shared property for the strength of the shield ('_sharedCurrentStrength'), _sharedCurrentStrength.value is indecated as being 'undefined'.

Here is some piece of my code:

private var _sharedCurrentStrength:SharedProperty;
private var _connectSession:IConnectSession;

//Called upon creationComplete of the Shield component
private function init():void{
     _sharedCurrentStrength = new SharedProperty();
     _sharedCurrentStrength.sharedID = "_strength";
     _sharedCurrentStrength.connectSession = _connectSession;
     _sharedCurrentStrength.addEventListener(SharedPropertyEvent.CHANGE, onSharedCurrentStrengthChange);
     _sharedCurrentStrength.subscribe();
}

public function onSharedCurrentStrengthChange(event:Event):void{
     currentStrength = _sharedCurrentStrength.value;
}
              
[Bindable(event="currentStrengthChange")]
public function get currentStrength():Number{
     return _currentStrength;
}

//the value of _sharedCurrentStrength is still undefined after running through this function...       
public function set currentStrength(value:Number):void{
     _currentStrength = value;
     if(_sharedCurrentStrength != null)
          _sharedCurrentStrength.value = value;
     dispatchEvent(new Event("currentStrengthChange"));
}

//This value is set from whithin the main class of the application
public function set connectSession(value:IConnectSession):void{
     _connectSession = value;
}

Am I something doing wrong? What is required for a SharedProperty to be able to change the value, as this way of working  works in the main class of the application? Can a value of a SharedProperty be given a default value (so it is not 'undefined')...

Al suggestions are welcome!

11 Replies

Avatar

Former Community Member

Hi,

I don't know whether I understood your question clearly. But SharedProperty is used just to hold and pass a particular value. If you want to decrease a value, you need to put the logic in the code to use the sharedproperty accordingly. I will paste a sample code that decreases the value, basically it's your code with some modifications to use sharedproperty in decreasing value .

<?xml version="1.0" encoding="utf-8"?>

<mx:Application

xmlns:mx="http://www.adobe.com/2006/mxml"

layout="absolute"

width="500"

height="480"

xmlns:rtc="AfcsNameSpace">

<mx:Script>

<![CDATA[

import com.adobe.rtc.events.SharedPropertyEvent;

import com.adobe.rtc.sharedModel.SharedProperty;

import com.adobe.rtc.session.IConnectSession;

public var _sharedCurrentStrength:SharedProperty;

private var _connectSession:IConnectSession;

private var _currentStrength:int = 5 ;

//Called upon creationComplete of the Shield component

private function init():void{

_sharedCurrentStrength = new SharedProperty();

sharedCurrentStrength.sharedID = "strength";

_sharedCurrentStrength.connectSession = cSession;

_sharedCurrentStrength.addEventListener(SharedPropertyEvent.CHANGE, onSharedCurrentStrengthChange);

_sharedCurrentStrength.subscribe();

}

public function onSharedCurrentStrengthChange(event:Event):void{

currentStrength = _sharedCurrentStrength.value; }

[Bindable(event="currentStrengthChange")]

public function get currentStrength():Number{

return _currentStrength;

}

public function set currentStrength(value:Number):void{

_currentStrength = value;

if(_sharedCurrentStrength != null)

_sharedCurrentStrength.value = value;

dispatchEvent(new Event("currentStrengthChange")); }

]]>

</mx:Script>

<!--

You would likely use external authentication here for a deployed application;

you would certainly not hard code Adobe IDs here.

-->

<rtc:AdobeHSAuthenticator

id="auth"

userName="username"

password="password" />

<rtc:ConnectSessionContainer id="cSession" authenticator="" width="100%"

height="100%" creationComplete="init()" roomURL="your url" backgroundColor="0x333333" >

<mx:VBox width="100%" height="100%" verticalGap="2" paddingBottom="5" paddingTop="5">

<mx:Button click="{currentStrength-=1}" label="SetVal"/>

</mx:VBox>

</rtc:ConnectSessionContainer>

</mx:Application>

Hope this helps you.

Thanks

Hironmay Basu

Avatar

Former Community Member

Hi there Here_84,

One thing worth noticing is that you seem to have some circular logic here :

1. set currentStrength calls _sharedCurrentStrength.value

2. this goes to the service, which eventually fires onSharedCurrentStrengthChange

3. which calls set currentStrength, start again at 1.

What you should try is only updating your local value after the shared value has round-tripped. I'd code it this way :

public function onSharedCurrentStrengthChange(event:Event):void{

//only update the local copy and fire my binding event

_currentStrength = _sharedCurrentStrength.value;

dispatchEvent(new Event("currentStrengthChange"));

}

public function set currentStrength(value:Number):void{

//note, just pass the call through to the sharedProperty, don't update local values or fire events

_sharedCurrentStrength.value = value;

}

As to why your sharedProp.value is always null... Is the connectSession being set? Do you ever receive a onSharedCurrentStrengthChange? Everything else seems ok.

nigel

Avatar

Employee

Hi Herre,

About the undefined part, I did run your code with slight modifications and it seems to work and the shared property seems to update itself. (I update the shared Properties value when its synced).

At this point I am guessing that you are setting the SharedProperty even before its synchronized.

public var _sharedCurrentStrength:SharedProperty;
private var _connectSession:IConnectSession;



//Called upon creationComplete of the Shield component
private function init():void{
     _sharedCurrentStrength = new SharedProperty();
     _sharedCurrentStrength.sharedID = "_strength";
     _sharedCurrentStrength.connectSession = sess;
     _sharedCurrentStrength.addEventListener(SharedPropertyEvent.CHANGE, onSharedCurrentStrengthChange);
     _sharedCurrentStrength.addEventListener(CollectionNodeEvent.SYNCHRONIZATION_CHANGE,setValue);
     _sharedCurrentStrength.subscribe();
}

protected function setValue(p_evt:CollectionNodeEvent):void
{
currentStrength = 50;
}

[Bindable(event="currentStrengthChange")]
public function get currentStrength():Number{
     return _currentStrength;
}

public function set currentStrength(value:Number):void{
     _currentStrength = value;
     if(_sharedCurrentStrength != null && _sharedCurrentStrength.isSynchronized)
          _sharedCurrentStrength.value = value;
     dispatchEvent(new Event("currentStrengthChange"));
}

public function onSharedCurrentStrengthChange(event:Event):void{
     currentStrength = _sharedCurrentStrength.value;
trace("***" + currentStrength);
}
         

Avatar

Level 2

Hironmay,

the logic for decrementing is implemented in the main class of the application. There do something similar to the thing you proposed, like shield.currentstrength -= 1

Thanks anyway for the quick response.

Avatar

Level 2

Nigel,

thanks for the response. What you are proposing seems logical, and I tried it before. Problem is that I indeed never come into the onSharedCurrentStrengthChange function. The connectSession has been set though...

On the creationComplete event of the main application I know tried to call the init-function, and pass the connectsession through to the shield component:

(some functions in the parent 'Ship' class)

//Called on creationComplete of the Ship
private function init():void{
     //Some other initialising stuff also comes here
     ...

     //I pass the connectSession through, 'shield' is initialised in the mxml
     shield.init(_connectSession);

     //I set the initial strength of the shield
     shield.currentStrength = SHIELD_INIT_STRENGTH;
}

//Called in the mxml declaration of Main.mxml (the one with the authenticator and ConnectSessionContainer)
[Bindable("connectSessionChange")]
public function set connectSession(value:IConnectSession):void{
     _connectSession = value;
}

(some of the functions in the 'Shield' class)

public function init(cs:IConnectSession):void{
     _sharedCurrentStrength = new SharedProperty();
     _sharedCurrentStrength.sharedID = "_strength";
     _sharedCurrentStrength.connectSession = cs;
     _sharedCurrentStrength.addEventListener(SharedPropertyEvent.CHANGE, onSharedCurrentStrengthChange);
     _sharedCurrentStrength.subscribe();
}

//I enter this function, 'value' has the correct value, altough '_sharedCurrentStrength.value' always contains 'undefined'
public function set currentStrength(value:Number):void{
     _sharedCurrentStrength.value = value;
}

//I never enter this function...
private function onSharedCurrentStrengthChange(event:Event):void{
     _currentStrength = _sharedCurrentStrength.value;
     dispatchEvent(new Event("currentStrengthChange"));
}

 

Could my problem have something to do with the passing of the connectSession (altough it is not null, and seem to have the correct values)? My main application (the one that sets up the connectSessionContainer etc...) passes the connectSession through to the Ship class (which uses the conenctSession correctely and shares all values as I wanted), which passes the connectSession through to the Shield class. Sharing and syncing in this class does not seem to work... Is there any parameter that I shoul check in the connectSession that could make things more clear?

Thanks in advance.

Message was edited by: Herre_84

Avatar

Former Community Member

I just gave an example of decrementing by doing it in the file itself.

Is your problem solved now ? If not, can you put for the test case where you decrement within the class itself and send us a sample complete code ?

Thanks

Hironmay Basu

Avatar

Level 2

Hironmay,

The way you proposed was more or less the way I was doing it, therefore my problem still isn't solved. As I described in my latest reply, I seem not to be able to come into the sync-handler. On monday I'll try to reproduce my problem and post the code.

Thanks anyway.

Avatar

Former Community Member

It's weird since I always do that way and never had any problem in receiving the value. Unless I see an complete example code of yours , I can't comment offhand as approach seems fine. I will wait for code.

Thanks

Hironmay Basu

Avatar

Level 2

Hironmay,

I've attached a test application which reproduces the error/problem I encounter in my actual code.

I've created a Main application (which sets up all the connections etc...), a 'Ship' component (in this case just a HBox) and a 'Shield' component (just a label indicating the damage). The way everything is initiated etc... is similar to the way I do it in my actual application. Pressing one of the buttons will decrease the according damage of each 'Shield'.

In the test application I've put 3 of those Shields, and I found out that only the first two 'Damages' have NaN's, while the Damage that is last initiated has the right value... My actual application acts similar, although I did not notice it last week. Maybe this can help finding the solution (knowing this, I can try some things myself too, as I probably do something wrong during initation)...

If you could find the time looking at my code, I would really appreciate it.

Thanks in advance, Hans

Avatar

Level 2

I think I found out what I was doing wrong: apparently the sharedID of a SharedProperty has to be unique. For every component I initialised, I used the same sharedID, and therefor only the last initiated component was having the correct value. Should I then just pass the sharedID value through as a string, or can I generate a random value in the init function of the component itself?

Thanks for the help anyway,

Hans

Avatar

Former Community Member

Hi,

Normally if you don't pass a value of sharedID for SharedProperty, it generates one. However, since you are creating many components, you should pass unique values yourself. You can pass the unique values as strings and you need to do this yourself either by assigning some unique values or generating some random values.

Thanks

Hironmay Basu