I have a single player VR game (search for “Marble Mechanics”) which I’m trying to make multiplayer.
The Server (listenServer) is responsible for creating the track segments in the world and replicating them to clients. Each track segment has a unique integer ID that is property Replicated with Initial Only condition.
A key aspect in this game is for the player to grab track segments. When grabbed, they can be deleted, duplicated or edited (longer, straighter, etc.). My understanding is that the client tells the Server to grab the corresponding track and so all of the work while grabbed would be done on the Server.
Since these are not inexpensive operations, I would prefer that the local clients do this work locally. Then once the local client drops a track segment, that client should push back to the Server what happened. The Server than accepts or rejects it and if accepted, updates the affected track segments in the world.
It seemed an easy way to do this is to extend the GrabComponent in VRPawn (from VRTemplate). I added three Event Dispatchers to GrabComponent. In VRPawn just before a track element is grabbed, we call a function CallBacks to set up bindings to the new Event Dispatchers.
Then in the track segment blueprint when its GrabComponent fires OnGrabbed or OnDropped, we fire of a corresponding message via the GrabComponent with information we need.
(we also have a OnDeletedIDs, but we won’t show it…)
Function CallBacks is in MyPawn (which is the parent of VRPawn) and simply sets up the bindings. When any newly binded Event is triggered, we unbind and try to call a RPC that should run on the Server.
And finally the Server functions are also in MyPawn.
(ignore all lines going off to the left, they are going to PrintStrings…). Already have a Server function in my player controller (CreateTracks) for creating track elements in the world, so that is reused in AddGroup.
Everything works fine if the client is on the ListenServer. None of the RPC on the Server (last image) get called if we’re on a different client. To be clear, the S_ArrayOfInts is just a structure that holds an array of unique integer IDs of the track segments. Usually that array is just one element, but the user can group track segments and so grabbing one, grabs all in the group. Also the ID2Tracks mapping maps the unique integer ID into a parameter structure which contains all the information required to reconstruct the track segment and place it correctly in the world.
How can I get the RPC Server functions to fire on the Server when triggered on a client that’s is not on ListenServer. I’m doing this all from the pawn (owned by PlayerController). I also tried to place the RPC Server functions into my PlayerController, but still it only works when the client is on the ListenServer.
Thanks for help. Or a better way of doing this?
UPDATE
Title is misleading. Turns out that most of the RPC running on the Server was executed from a client pawn. One was not. It was using a map as a parameter in the RPC function call. Runtime logs flagged an error. Splitting the map into two parallel arrays into a structure could be passed without trouble. There were no warnings/errors during Blueprint compiling or building the project.