RaiseEvent suddenly broken after switching to Hashtables and RemoveFromRoomCache (Worked once)

So as the title says, I switched to hashtables in my customData for RaiseEvent, because there are some events I want to cache, and specific events I want to remove from cache (and not all - therefore the hashtable to filter just events with specific data).

I have experienced the following TWICE so far (I reverted all my code to a working commit using object[]) and started over between):

Using RaiseEvent with object[[] works fine. (Sending 1 Vector3 position and a couple ints for enums).
Debug.Log within OnEvent() just to be sure the events are being received, they are; correct byte codes, right data.
Debug.Log the bool generated by RaiseEvent() too just to be sure.
AddToRoomCacheGlobal works fine.
Refactor the data to use a Hashtable.
Works fine! Positions come through (this is infrequent, once per 1-2 seconds roughly). Enums are being set correctly.
Debug.Log within OnEvent() just to be sure the events are being received, they are; correct byte codes, right data.
Debug.Log the bool generated by RaiseEvent() too just to be sure.

Next, I decided to try firing my first RemoveFromRoomCache event with the Hashtable filter.
The position was not being received on the other client suddenly. Nor were the enums updating.
"Hmm" I thought. Maybe I'm firing the RemoveFromRoomCache too close to the RaiseEvent() with the new data (even though I'm using Reliable) and it's getting removed before it comes through.

So I take out JUST the RemoveFromRoomCache event. Changed NOTHING ELSE. Everything is back to _exactly_ the way it was when Hashtables were working.

Now broken. Nothing is coming through.
Debug.Log within OnEvent() just to be sure the events are being received, they are NOT. Only Photon (200 +) codes are coming through.
Debug.Log the bool generated by RaiseEvent() - the bool is still true - so don't know what's happening.

Can I get some feedback on this problem?

I've reverted to object[] data and it works again, and then gone through this process twice with same results.

Comments

  • Digging a little more.

    I decided to see if I could use RemoveFromRoomCache with object[] data. Even though I will need specific filtering later on, it still made sense to me to try to see if Hashtables + Remove was the culprit or just Remove.

    So indeed firing the RemoveFromRoomCache just before the RaiseEvent() even with object[] data doesn't work. Unfortunately there is no callback for a RaiseEvent() with RemoveFromRoomCache, even if you have ReceiverGroup.All.

    This seems like a MAJOR oversight considering you need to make sure the room is updated and ready for the new data before doing a RaiseEvent() with that data!!

    I then noticed something that makes it clear to me that RemoveFromRoomCache is the culprit:
    NO RaiseEvents work. Not just the single one that I experimented with RemoveFromRoomCache. ALL of them. I have dozens I use to send specific signals to other players, and with a SINGLE RemoveFromRoomCache having fired in a single RaiseEvent() elsewhere in my game, now ALL RaiseEvents() do not come through.

    ??????
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited August 2019
    Hi @steamcore,

    I'm trying to understand the issue you are describing.
    The text is too long and the issue itself can be summarized.

    So you are saying iwhen you call RaiseEvent with RemoveFromRoomCache and ReceiverGroup.All:

    A. all previously cached events are wiped out
    B. all future calls to RaiseEvent will not work

    is it A or B?

    Could you share code snippet of the RaiseEvent call itself?
    The RemoveFromRoomCache filter is composed of 3 things: event code, sender and data.
    What event code(s) are you using? avoid 0 as it's a wild card.
    What is the value of the sender (TargetActors) in the filter?
    About the data filter, I'm not sure what data structures are supported other than the Hashtable, I have to ask and test this further.
  • Hi @JohnTube thanks for responding.

    I'm saying B, but with something extra:

    After calling RaiseEvent with RemoveFromRoomCache, NO RaiseEvent calls work anymore, even ones that are unrelated to the event Code that I used for the RaiseEvent with RemoveFromRoomCache.

    Example (notice different event codes).
    RaiseEvent( 1, data, RaiseEventOptions.Default, SendOptions.Reliable); #works
    RaiseEvent( 2, data, RaiseEventOptions.Default, SendOptions.Reliable); #works
    RaiseEvent( 1, data, RaiseEventOptions.RemoveFromRoomCache, SendOptions.Reliable); #doesn't work
    RaiseEvent( 1, data, RaiseEventOptions.Default, SendOptions.Reliable); #no longer works
    RaiseEvent( 2, data, RaiseEventOptions.Default, SendOptions.Reliable); #no longer works
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited August 2019
    I just tried to reproduce and could not.
    Unfortunately there is no callback for a RaiseEvent() with RemoveFromRoomCache,
    There is no "high level" out of the box callback for this yes but you can listen to the operation response of OperationCode.RaiseEvent using
        private void OnEnable()
        {
            PhotonNetwork.NetworkingClient.OpResponseReceived += OpResponseReceived;
        }
    
        private void OpResponseReceived(OperationResponse operationResponse)
        {
            if (operationResponse.OperationCode == OperationCode.RaiseEvent && operationResponse.ReturnCode == ErrorCode.Ok)
            {
                // ACK here for RaiseEvent operation with CachingOption RemoveFromRoomCache = 6 or RemoveFromRoomCacheForActorsLeft = 7
            }
        }
    
        private void OnDisable()
        {
            PhotonNetwork.NetworkingClient.OpResponseReceived -= OpResponseReceived;
        }
    RaiseEvent( 1, data, RaiseEventOptions.RemoveFromRoomCache, SendOptions.Reliable); #doesn't work
    What does "doesn't work" mean here?
    In the example, there aren't any previously cached events.
    Also, there is no client that joins later or one that rejoins.
    How do you test this?

    test details:

    using ExitGames.Client.Photon;
    using Photon.Pun;
    using Photon.Realtime;
    using UnityEngine;
    
    public class RaiseEventsTest : MonoBehaviourPunCallbacks
    {
    
        // Use this for initialization
        private void Start()
        {
            PhotonNetwork.ConnectUsingSettings();
        }
    
        public override void OnEnable()
        {
            base.OnEnable();
            PhotonNetwork.NetworkingClient.EventReceived += OnEventReceived;
        }
    
        public override void OnDisable()
        {
            base.OnDisable();
            PhotonNetwork.NetworkingClient.EventReceived -= OnEventReceived;
        }
    
        public override void OnConnectedToMaster()
        {
            PhotonNetwork.JoinOrCreateRoom("test", new RoomOptions(), TypedLobby.Default);
        }
    
        public override void OnJoinedRoom()
        {
            PhotonNetwork.RaiseEvent(1, new Hashtable { { "k11", "v11" }, { "k12", "v12" } }, new RaiseEventOptions { Receivers = ReceiverGroup.All },
                SendOptions.SendReliable);
            PhotonNetwork.RaiseEvent(2, new Hashtable { { "k21", "v21" }, { "k22", "v22" } }, new RaiseEventOptions { Receivers = ReceiverGroup.All },
                SendOptions.SendReliable);
            PhotonNetwork.RaiseEvent(1, new Hashtable { { "k11", "v11" }, { "k12", "v12" } }, new RaiseEventOptions { CachingOption = EventCaching.RemoveFromRoomCache },
                SendOptions.SendReliable);
            PhotonNetwork.RaiseEvent(1, new Hashtable { { "k11", "v11" }, { "k12", "v12" } }, new RaiseEventOptions { Receivers = ReceiverGroup.All },
                SendOptions.SendReliable);
            PhotonNetwork.RaiseEvent(2, new Hashtable { { "k21", "v21" }, { "k22", "v22" } }, new RaiseEventOptions { Receivers = ReceiverGroup.All },
                SendOptions.SendReliable);
        }
    
        
    
        private void OnEventReceived(EventData eventData)
        {
            switch (eventData.Code)
            {
                case 1:
                case 2:
                    Debug.Log(eventData.ToStringFull());
                    break;
            }
        }
    }


    In the console logs I got:

    Event 1: {(Byte)245=(Hashtable){(String)k12=(String)v12, (String)k11=(String)v11}, (Byte)254=(Int32)1}
    Event 2: {(Byte)245=(Hashtable){(String)k21=(String)v21, (String)k22=(String)v22}, (Byte)254=(Int32)1}
    Event 1: {(Byte)245=(Hashtable){(String)k12=(String)v12, (String)k11=(String)v11}, (Byte)254=(Int32)1}
    Event 2: {(Byte)245=(Hashtable){(String)k21=(String)v21, (String)k22=(String)v22}, (Byte)254=(Int32)1}
  • steamcore
    steamcore ✭✭
    edited August 2019
    Apologies, I was not very descriptive with my example. The order is a little bit different than my example, which I simplified too much because I didn't want to be overly verbose again.

    The way it actually is set up is the RaiseEvent(RemoveFromRoomCache) for code 1 is in the same method as the RaiseEvent for code 1. Without that response code, I figured firing it in the same method would be fine as long as sent reliable. Maybe that is not ok? Either way, doesn't explain EVERY raiseEvent , all codes, not being received by any client after that.

    So it goes:
    
    void DoRaise ()
    {
        RaiseEvent( 1, data, RaiseEventOptions.RemoveFromRoomCache, SendOptions.Reliable);
        RaiseEvent( 1, data, RaiseEventOptions.Default, SendOptions.Reliable);  //not received on any clients
    }
    
    void DoOtherRaise()
    {
        RaiseEvent( 2, data, RaiseEventOptions.Default, SendOptions.Reliable); //not received on any clients
    }
    
    AFter DoRaise(), if I call DoOtherRaise() it is not received on any clients. (Even self if I do ReceiveOptions.All)

    I'm testing by running two, three, four clients on different machines.
  • Looking back over your snippet, you fire many raiseevents in the same method, however I see two things different: you do not have any AddToRoomCache in your events, and by extension do not fire any RemoveFromRoomCache before the event code for the raise event is fired at least once before. I'm going to start today by experimenting with not firing the remove before the first one is sent, then also splitting up the raiseEvent and the remove using the OpResponseReceived callback you showed above, and see if the behavior is any different.
  • Small update: Did confirm it doesn't work after firing the first RemoveFromRoomCache.

    Here's my code:
            public void DispatchEvent(PhotonEventID id, bool sendToAll, bool cacheEvent = false, params object[] data)
            {
    	        if (PhotonNetwork.InRoom == false)
    	        {
    		        Debug.LogError("Unable Dispatch PhotonEvent as not currently in a room");
    
    		        return;
    	        }
    
    	        var raiseEventOptions = RaiseEventOptions.Default;
    
                // Remove the previous cache and cache the new event
    	        if (cacheEvent && raiseFired>5)
    	        {
    		        raiseEventOptions.CachingOption = EventCaching.AddToRoomCache;
    
                    var clearCacheOptions = RaiseEventOptions.Default;
                    clearCacheOptions.CachingOption = EventCaching.RemoveFromRoomCache;
                    clearCacheOptions.Receivers = ReceiverGroup.All;
                    PhotonNetwork.RaiseEvent(id.Code, null, clearCacheOptions, SendOptions.SendReliable);
    	        }
    
    	        raiseEventOptions.Receivers = (sendToAll) ? ReceiverGroup.All : ReceiverGroup.Others;
    
    	        PhotonNetwork.RaiseEvent(id.Code, data, raiseEventOptions, SendOptions.SendReliable);
                raiseFired++;
            }


    As you can see, I wait until I've fired RaiseEvents five times until I try to remove any from cache. The 6th one is never received on ANY client! (even local if I change it to ReceiverGroup.All) !

    Moving on to test if spacing out the RemoveFromRoomCache from the RaiseEvent using the OpReceived callback helps at all.
  • In case there is doubt that I am seeing what I'm reporting:

    https://drive.google.com/open?id=1NAvzytLbyos0a3S8KZcJJqR8sIGEeiHv
  • @JohnTube any thoughts?
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited August 2019
    Hey @steamcore,

    Try changing
    var clearCacheOptions = RaiseEventOptions.Default;
    
    with
    var clearCacheOptions = new RaiseEventOptions();
    
    RaiseEventOptions.Default is an object, instance of class RaiseEventOptions. If you modify its fields or properties in one place (reference) it's modified elsewhere in all references (raiseEventOptions and clearCacheOptions in your case). Use it only when not modified.

    EDIT: nice good looking game btw. looks like No Man's Sky. Good job on the visuals.
  • AH! Brilliant catch my friend! Will fix in the morning and get back to you!
  • That was it! Thanks for the help! In a related note, this is a webgl game and I will be sending an email regarding Photon Voice support soon....
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited August 2019
    Hi @steamcore,

    (while this is off-topic, I thought about making a shortcut here)

    Photon Voice does not support WebGL.
    You can search the forum to find out why. Example discussion.
  • @JohnTube I have seen your responses elsewhere on the forum,
    If you think your project and your use case are interesting and you want this to happen you can send us an email to developer@photonengine.com to discuss more details and see if we can find a custom deal.


    I think our project is VERY interesting and a great use case for supporting webgl.