To allow a consistent way of handling traffic between client and server, we introduced the actions concept. This based on the Command design pattern and makes it quick for us to implement features that requires functionality on both client & server sides while keeping the code elegantly isolated in single-responsibility classes.

All our actions implement the IGameAction interface and will typically inherit, indirectly, from GameAction which is a PropertyHolder and contains some boilerplate code to take care of common tasks. We further derive ClientAction and ServerAction to specialize the actions based on where they will execute. Regardless of the type of action, they will always have an Invocation ID which is a GUID that will be retained throughout the cycle of execution on both client & server. It’s purpose is to allow us to correlate what’s going on different sides of the internet.

Client Actions

Client Actions are always executed via a centralized ActionProcessor that ensures the correct execution cycle takes place.

When a client action is invoked it’s CanInvoke() method is executed first and only if it returns true is the action allowed to execute. If it is allowed to execute then the Start() method is called on the client. This is where initial client-side work can take place. If this method returns true, then the action is serialized and sent to the server. This can return false when an action is intended to only run on the client, typically as a response to an incoming server event.

After the action is sent to the server and a response comes back the Conclude() method will be invoked. This is where we put the code we want to run after we get the response. We have access to the response details here and in some cases the action will only be invoked to query information from the server, so this is the place to consume that information.

Server Actions

The server actions have more complexity under the hood, but its interface is as simple. An Initialize() method is called before anything touches the event. Then as for client actions the CanInvoke() method is checked to decide whether to invoke the action or send an error response and finally the InvokeInternal() method is called where the action specific code executes and a response is returned.

A server action has access to the client device that made started the action (if any) as well as the associated player ID. It also handles authentication and provides a unified way to report errors back to the client.

When the server receives the action request from the client, the ActionHandler will create an instance of the server action by using the ServerActionFactory which uses the incoming info to create the action based on its type. This means that any new action has to be registered in the factory if it will be kicked off from the client.

Action Wrappers

Since the client and server communicate by sending and receiving messages, we need to ensure that both sides are on the same page. In particular that the properties they refer are exactly the same on either side. For that purpose we use action wrappers. These follow the decorator pattern and inherit from the GameActionDecorator base class. Their main purpose is to define the constant names of the properties and provide accessors and setters for them. The same wrapper files are referenced by both the client and server code, so any change in one will automatically be picked up on the other thus saving us the error prone hassle of tracking these names independently.



Author Lotus
Views 731
War to the Core

Recent Comments

Latest Updates

  • Solo missions

    Solo missions

    Hey guys, here are the specifics of the first two solo missions, those are sketches of the first two missions. First mission: A harvester is placed near the ship, generating supply caches. The player collects energy caches and escapes a ring of mines. No supply links allowed. The sensor component is introduced by one of […]Read More »
  • We made it to the Top 100!

    We made it to the Top 100!

    We are stoked that we managed to land on IndieDB’s Indie of the Year’s Top 100 list! We are also the only MOBA that made it to the list! The support we got from the community was overwhelming, and we would like to thank each and every person that helped us get this far. Whether […]Read More »
  • Full Campaign Series, Version 3

    Full Campaign Series, Version 3

    Characters: Daniel Blaze. Protagonist, player-character. Headstrong and rebellious. Ambiguous loyalty to the Shepherd Coalition. Joseph Blaze. Father of Daniel Blaze. Commander of the Leviathan mothership until executed for treason by the Shepherd Coalition. Sylvia. AI assistant. Provides intel, advice, mission objectives. Captain Zhukov. Cyborg commander assigned to hunt down player during the first several missions. […]Read More »
  • Story: Episode 1, Version 2

    Story: Episode 1, Version 2

    The Blaze family had long been controversial. They supported the Shepherds, but continually frustrated the Orthodox elements of their faction. Joseph Blaze was especially known for his tolerance of the weakling families that used genetic engineering to alleviate the sicknesses that exposure to the Earth’s surface had inflicted on them. Such tensions between orthodoxy and […]Read More »
  • Story: Episode 1

    Story: Episode 1

    Location: The Pole Base. When Daniel Blaze passed his final test and became the primary candidate to pilot the Leviathan, the Shepherds’ newest ship, he caused a quite a stir. Not because he’s the youngest member of the Pole fleet to be nominated for admiralship, the faction had already made peace with this as a […]Read More »
Skip to toolbar