room custom properties

OneManArmy
OneManArmy ✭✭✭
Hi, i have question about room custom properties.
Only master client should change room custom properties?
Or there is a way to correctly change room custom property, when 2 or more clients will change custom property simultaneously?

Example:
When 2 (or even 10) clients will change "val" simultaneously, then result will be 1.

int value = (int)PhotonNetwork.room.customProperties["val"];
value ++;
						
Hashtable setValue = new Hashtable();
setValue.Add("val", value); 
PhotonNetwork.room.SetCustomProperties(setValue, null, false);

Comments

  • JohnTube
    JohnTube mod
    edited February 2017
    Hi @OneManArmy,

    You should use CAS: "Check-And-Swap" or "Compare-And-Set" feature.
    Read more about it at this link (see "Check And Swap for Properties (CAS)" section)
  • OneManArmy
    OneManArmy ✭✭✭
    edited February 2017
    Can you provide an example?

    This is wrong, right?
    int value = (int)PhotonNetwork.room.customProperties["val"];
    int newValue  = value  + 1;
    
    Hashtable setValue = new Hashtable();
    setValue.Add("val", newValue);
    
    Hashtable expectedValue = new Hashtable();
    expectedValue.Add("val", value);
    
    PhotonNetwork.room.SetCustomProperties(setValue, expectedValue, false);
  • The code snippet you provided should be correct.
    You should handle how you set the property for first time you differently though.
  • I am getting this error:
    Operation failed: OperationResponse 252: ReturnCode: -2 (CAS update failed: property='val' has value='2'). Parameters: {} Server: GameServer
    UnityEngine.Debug:LogError(Object)
    NetworkingPeer:OnOperationResponse(OperationResponse) (at Assets/Plugins/PhotonNetwork/NetworkingPeer.cs:1532)
    ExitGames.Client.Photon.PeerBase:DeserializeMessageAndCallback(Byte[])
    ExitGames.Client.Photon.EnetPeer:DispatchIncomingCommands()
    ExitGames.Client.Photon.PhotonPeer:DispatchIncomingCommands()
    PhotonHandler:Update() (at Assets/Plugins/PhotonNetwork/PhotonHandler.cs:157)
    You should handle how you set the property for first time you differently though.
    differently? can you please provide an example?
  • Either initialize the room property during room creation or initialize it once without CAS (expected property parameter).
    The error you are getting is probably due to concurrency which happens if multiple calls to change a single property happen at the "same time" from different clients. So the server value might have been changed before the client getting notified about it so it sends an old value as expected one. I think you should just retry with new value.
  • OneManArmy
    OneManArmy ✭✭✭
    edited February 2017
    The same error, when "val" is initialized during room creation.
    I tried to initialize "val" in room (once without CAS). And i don't think that you can somehow initialize in room with CAS (you will get error "CAS update failed: there is no property='val' on server"), so problem should be somewhere else.

    Without CAS:
    Let's say we have key "val" 0 and three clients try to increse "val" by 1 (at the same time) = in result "val" will be 1, even if it must be 3.

    So, what exactly happens when we use CAS?
    Every client sets key "val" to 1 and as expected value 0.
    How result can be 3?
  • So, what exactly happens when we use CAS?
    Every client sets key "val" to 1 and as expected value 0.
    How result can be 3?

    You should not worry about value. IMO, you should repeat incrementation while operation response is CAS error until operation response is success or if you do not find this convenient coordinate this with MasterClient using events (or RPC, etc.) and let him handle the property update:
    
    void IncrementVal(){
    int value = (int)PhotonNetwork.room.customProperties["val"];
    int newValue  = value  + 1;
    
    Hashtable setValue = new Hashtable();
    setValue.Add("val", newValue);
    
    Hashtable expectedValue = new Hashtable();
    expectedValue.Add("val", value);
    
    PhotonNetwork.room.SetCustomProperties(setValue, expectedValue, false);
    }
  • Kinda late answer, but this page is what you got then google for "photon network custom room properties", so I'd like to share my experience.
    So, to keep some "shared" value (say, var x) in Photon network, you need special hashtable:
    private ExitGames.Client.Photon.Hashtable roomProp = new ExitGames.Client.Photon.Hashtable();
    (be sure to set it only locally to avoid conflicts, so put next two lines beneath "terminator": if(!photonView.IsMine){return;})
    Next, assign a hashtable key to this value:
    roomProp["keyName"] = x;
    Send it to Photon network:
    PhotonNetwork.CurrentRoom.SetCustomProperties(netProp);
    To read it from there:
    (var)PhotonNetwork.CurrentRoom.CustomProperties["keyName"]