I intend to handle Autonomous movement with an RPC. However "simulated proxy actors" can run using extrapolation between ticks, and so I need to handle that, hence needing previous state access.
Here are my initial ideas about how the system should network data:
Nearly (?) everything that should be able to interface over the network should derive from the Replicable base class
This will establish a network ID on the authority for that actor (server-side for nearly all cases) which is replicated to the non-authorities
A Generic actor network handling layer should exist. This will handle network scraping / RPC invocation. Essentially it will scrape attributes and rpc calls (which are invoked, not collected) and bundle the network ID of the actor calling / sending the data. This is then reconstructed on the other side of the network.
If this is the case, there are some issues I can foresee:
- How should I support RPC / replication from actors that are static. Take for example the clock. Both server and client need a clock instance, but the server is the authority on game time. How would you designate a network id here? (Ironic that I answered my previous question relating to pre-existing actors). The idea at the moment is that the ROLE_AUTHORITY assigns the network ID. In non-static cases actors will not exist with that ID and so they will be recreated by the replication system. Yet, in the case of statics, they will exist but they will not be aware of their ID outside of the authority. One method I could consider is simply not implementing it client side. If everything that should be replicated is created on the server and not on the client I would enforce an authority-instantiates principle, and clients would delete all actors, including bStatic. However, in doing this I would leave an incomplete system client side. How would I access game-specific actors (like game rules)? Just check if they exist somewhere? I suppose another solution is to preset the network ID on the actor, so it can be matched. Any ideas on how you / Unreal does it would be most welcome.
I have been asking the same question about global access for some time now. I think I need to break some fundamental ideas I have had from my time spent programming. In Python I have always been averse to using global scope namespaces. globals() repulses me in a lot of ways (it seems like most of the time if you're using it you shouldn't be). I think It is that I prefer direct passing of data (invoking functions etc), The same applies to using a module namespace. Is this wrong? I like to think of the scripts has being totally modular. Before the entry point is called, no instances of any data exist. But, the entry point has its own local namespace (it's in a function) so It usually means I have to pass a direct references to the rest of the functions that require these instances. The reason that I ask this is because when an Actor is created, it has to be told about the network interface instance, which will usually have been created in a local namespace and a reference stored inside an instantiated class.
Questions about Unreal RPC implementation:
Firstly, let me assume that I am correct in stating the following about RPC calls:
- Simulated functions can be executed by an actor with any ROLE
Non-simulated functions require ROLE_AutonomousProxy or higher to be executed
Functions can only be replicated between two actors (with a ROLE / REMOTEROLE == ROLE_AUTHORITY). And thus servers cannot broadcast.
Therefore, I ask, According to point 3, replicated functions can only be replicated from actors of the same net ID and with one of ROLE, REMOTEROLE == ROLE_AUTHORITY. So, how is this controlled to prevent cheating? I could just check the source of the call on the server, and match the call address to the address that the server believes controls that client.This would prevent the client from invoking calls on other actors it doesn't control, but it would still be able to call the function on the server actor of its local agent from any other actor in its world. This would mean someone could write a special bot that would invoke a server_move() call when the bot saw the local player, allowing the local player to avoid getting shot as easily. How would one create a secure cheat-proof (at the basic level at least) RPC system? Is this something that is enforced client side?
My last, and arguably biggest question is about design. I'm not sure how to structure the system; where to set the entry point; should it be the same for client and server. What rule should I follow to know when to separate or join logic? This is the most difficult question I face, and It is rather disconcerting if not upsetting that I cannot seem to think around it.
Fundamentally, I struggle to understand why you would go to the extra effort of writing an abstraction system that enables the use of the same Actor class in each game mode, and then explicitly define server and client code.
- Should I think of Server and Client as fundamentally different, with no common ground
- Should I think of Actors and replication as a singleton; providing an easy scripting system for people extending games
The specific issue is with the netmode enum. It seems stupid to have it on the client when you would just create a client flavour with the netmode set already. This seems to suggest that there is more of a factory going on than explicit differences between client server. This applies to the network layer (which has basic protocols and responses, which are only called by certain peers (for example request_connect is only received by a server). Or, should everything make use of the netmode and there is just a single game class (With the conditional... I think I will do this unless you offer advice against it). Any detailed help here would be much appreciated. Much appreciated.