Chapter 4. DIY vs Re-Use: In Search of Balance
Business Perspective: DIY Your Added Value
Engine-Centric Approach: an Absolute Dependency a.k.a. Vendor Lock-In
Implications of Vendor Lock-In
Engine-Centric Approach: Pretty Much Inevitable for Indie MMORPG/MMOFPS
Engine-Centric Approach: You Still Need to Understand How It Works
Engine-Centric Approach: on “Temporary” dependencies
“Re-Use Everything in Sight” Approach: An Integration Nightmare
“DIY Everything”: The Risk of Never-Ending Story
"Responsible Re-Use" Approach: In Search of Balance
“Responsible Re-Use” Examples
“Responsible Re-Use”: on "Temporary" dependencies
Summary
Chapter 5. Reactor-fest Architecture. I got Event Loop. I got Event Loop. I got All Event Loop
On Terminology: Reactor, Event-Driven Program, Game Loop, ad-hoc Final State Machine, and so
What NOT to use - “OO” RPC Frameworks
Game Loop: Game Programming Classic
Event Loop as a Generalization of Game Loop
To React or Not to React?
Reactors or Not – Stay Away from Thread Sync in your Game Logic
Other Event-Driven Systems: GUI, Erlang, Node.js, and Java Reactor
On Separating Infrastructure Code from Logic Code
Advantages of Reactors
Reactors in Game Engines
Two All-Important Improvements to Classical Event-Driven Programming: Mostly-Non-Blocking Pro
Non-Blocking Processing
To Block, or Not to Block, That is THE Question. Mostly-non-blocking Reactors
Case 1. Processing while Call is in Progress, is Required at Logic Level
Case 2. No Processing at Logic level while Call is In Progress
Blocking or Non-Blocking? - Mostly-non-Blocking
Implementing Non-Blocking Processing for Games
Timers
Non-Blocking State Publishing
Point-to-Point Communications and other Non-Blocking Stuff
Handling non-blocking returns in Reactors
Take 1. Naïve Approach: Plain Messages (will work, but is Plain Ugly)
Take 2. Void-only RPCs (a tiny bit better, still Really Ugly)
Take 3. OO-Style: Less Error-Prone, but Still Way Too Much Boilerplate (
Exceptions
Cascading Exception Handlers
Take 4. Lambda Continuations and Callback Pyramid
On Continuations
Cascaded Exception Handling for Lambda Style
Take 5. Basic Futures
Differences from std::future<>, boost::future<>, folly::Future<>, etc.
Take 5 Summary
Take 6. Code Builder
Take 6a. Enter C++ Preprocessor
Offloading
Offloading Caveat: Keeping portions Large
DON’T offload unless Proven Necessary
Another Offloading Caveat: Flow Control
Take 7. Fibers/Coroutines
On boost:: coroutines and boost::context
On goroutines: BEWARE THREAD SYNC!
Take 8. async/await (.NET and JS proposal)
Surprise: All the different takes are functionally equivalent, and very close performan
Similarities to Node.js
Handling Non-Blocking Returns in Different Programming Languages
Serializing Reactor State
On serializable lambda closures in C++
Why so much discussion of this one thing?
TL;DR for Non-Blocking Communications in Reactors
Determinism
Distributed Systems: Debugging Nightmare
Non-Deterministic Tests are Pointless
The Holy Grail of Post Mortem
Portability: Platform-Independent Logic as “Nothing But Moving Bits Around”
Stronger than Platform-Independent: Determinism
Deterministic Logic: Benefits
On Replay-based Regression Testing and Patches
On Fuzz Testing
Deterministic Logic: On User Replay
Implementing Deterministic Logic
Deterministic Logic: Modes
Implementing Inputs-Log
Going Circular
Recordable/Replayable InfrastructureEventHandler
Implementing Deterministic Logic: Dealing with non-Determinism due to System Calls
Dealing with System Calls: Original Non-Deterministic Code
Dealing with System Calls: “wrapping”
Dealing with System Calls: “Pure Logic”
Dealing with System Calls: Input Parameters as Reactor Data Members
Dealing with System Calls: TLS-based Compromise
Dealing with System Calls: Pool of On-Demand Data
Dealing with System Calls: On-Demand Data via Exceptions
Dealing with System Calls: Which System Functions We're Speaking About and What to do A
Implementing Deterministic Logic: Other Sources of Non-Determinism
No Access to non-const Globals and TLS
On Pointers
On Threads
Implementing Deterministic Logic: non-Issues
PRNG
Logging/Tracing
Caching
On Isolation Perimeters
Implementing Deterministic Logic: Cross-Platform Determinism
Achieving Cross-Platform Determinism
Implementing Deterministic Logic: Summary
Types of Determinism vs Deterministic Goodies
Relation of Deterministic Reactor to Deterministic Finite Automata
Deterministic Finite State Machines: Nothing too New But...
TL;DR for Determinism Section
Divide et Impera, or How to Split the Hare the Hair the Reactor
Composition: Reactor-within-Reactor
State Pattern
Getting Rid of Big Ugly Switch
Common Data Members
Potentially Expensive Allocations
Hierarchical States
Stack-of-States
Reactors, Exceptions, and VALIDATE-CALCULATE-MODIFY Pattern
Validate-Calculate-Modify Pattern
Exceptions before Modification Stage are Safe, including CPU exceptions
RAII equivalents in Different Programming Languages
Posting Messages (calling RPCs, etc.) within Validate/Calculate
Exception Safety for Modify stage
Validate-Calculate-Modify-Simulate
Validate-Calculate-Modify Summary
Scaling Reactors
Splitting and Offloading
Reactor-with-Mirrored-State – Limited Relief
Reactor-with-Extractors
Reactor-fest Architecture
Reactor Factories
Reactors and Programming Languages
Relation of Reactor-Fest to Other Systems
Relation to Actor Concurrency
Relation to Erlang Concurrency, Akka Actors, and Node.js
Reactors and Microservices as Close Cousins
Physical Server – VM - Docker – Reactor as a Spectrum of Tradeoffs between Isolation an
Summary of Chapter 5
Appendix 5.A. C++-Specific Examples and Comments for Chapter 5
Avoiding Expensive Allocations
C++: Enforcing const-ness for Validate-Calculate-Modify
Chapter 6. Client-Side Architecture.
Graphics 101
On Developers, Game Designers, and Artists
On Using Game Engines as Pure Graphics Engines, and Vendor Lock-In
Types of Graphics
Games with Rudimentary Graphics
Games with 2D Graphics
On pre-rendered 3D
Games with 3D Graphics
Very Generic Architecture
Logic-to-Graphics API
Dual Graphics, including 2D+3D Graphics
Modules and Their Relationships
Game Logic Module
Game Logic Module & Graphics
Game Logic Module: Client-Side Prediction and Simulation
Game Logic Module: Game Loop
Game Logic Module: Keeping it Cross-Platform
Animation&Rendering Module
Communications Module
Sound Module
Relation to MVC
Differences from Classical 3D Single-Player Game
Interaction Examples in 3D World: Single-Player vs MOG
MMOFPS interaction example (shooting).
MMORPG interaction example (ragdoll).
UI interaction example.
Reactor-fest Client-Side Architecture
Reactor-fest Client Architecture
Reactor Specifics
Animation&Rendering Reactor and Game Loop
Communications Reactor and Blocking/Non-Blocking Sockets
Other Reactors
On Reactors and Latencies
Variations
On Code Bases for Different Platforms
Scaling Reactor-fest Architecture on the Client
Parallelizing Client-Side Reactors
Summary of Reactor-fest Architecture on the Client-Side
Programming Language for Game Client
One Language for Programmers, Another for Game Designers (MMORPG/MMOFPS etc.)
A word on CUDA and OpenCL
Different Languages Provide Different Protection from Bot Writers
Resilience to Reverse Engineering of Different Programming Languages
Compiled Languages
Languages which compile to Byte-Code
Interpreted Languages
On Compilers-with-Unusual-Targets
Summary
Language Availability for Game Client-Side Platforms
On Garbage Collection
On “Stop-the-World” problem
To GC or Not to GC?
On Consistency between Client-Side and Server-Side languages
Sprinkle with All The Usual Considerations
C++ as a Default Game Programming Language
On C++ and Cross-Platform Libraries
Big Fat Browser Problem
Line-to-Line Translations: “1.5 code bases”
Line-to-Line Translations: Are They Practical?
Client-on-Server Trick
Bottom Line for Chapter 6
Chapter 7. Client-Driven Development: Unity, UE, Lumberyard, and 3rd-party Network Libraries
On Client-Driven vs Server-Driven Development Workflows
On Server-Driven Development Workflow
Client-Driven Development Flow
Implementing Client-Driven Workflows
Single-player prototype and “continuous conversion”
Engine-Provided Server vs Standalone Server
Important Clarification: Development Workflow vs Data Flow
Three Most Popular 3rd-party Game Engines
Unity 5
Event-Driven Programming/Reactors
Built-In Communications: HLAPI (for Engine-Provided Server)
State Synchronization
RPCs (a.k.a. “Remote Actions”)
HLAPI Summary
Built-In Communications: LLAPI (both for Engine-Provided Server and Standalone Server)
3rd-party Communications for Unity: Photon Server
Photon Server SDK
Photon Cloud/PUN
3rd-party Communications for Unity: SmartFoxServer
3rd-party Communications for Unity: uLink
3rd-party Communications for Unity: DarkRift
3rd-party Communications for Unity: Lower-Level Libraries
Unity 5 Summary
Engine-Provided Server. HLAPI now, probably LLAPI later
Standalone Server with Export from Unity
Engine-Provided vs Standalone: Which One is Better?
Unreal Engine 4
Event-driven Programming/Reactors
UE for MOG
UE Communications: very close to Unity 5 HLAPI
UE Communications: Lower-Level C/C++ Libraries
Reliable UDP Libraries
Event Handling Libraries
Socket Wrapper Libraries
UE4 Summary: Engine-Provided and Standalone Servers
Amazon Lumberyard
A choice between Amazon-Only Hosting – and (hopefully) Co-Location
Amazon Lumberyard Communications: GridMate
Amazon Lumberyard: Summary and Engine-Provided/Standalone Servers
The engine that didn’t make it - Source
Comparison Table
Summary for Chapter 7