Writing a Cross-Platform, Remote Logging Console in C++
Writing a Cross-Platform, Remote Logging Console inC++
I recently finished a small side project. As the title suggests, I made a debug log console that is cross-platform and remotely connects to games.
I had two main goals. First, I believe debugging tools for games should primarily be external. They shouldn’t be in-game overlays. A side project gives me an excuse to write this blog post to claim why. Second, there were a few open source libraries I wanted to learn more about. A side project is a great way to do so.
This post is kind of a project journal. It’s not a technical deep dive. I dipped my toes into a few waters for the first time. I learned a few things and maybe you can too.TLDR;
Mac should work but has an issue or two left to resolve. I don’t have access to a development Mac which makes it difficult. A generous reader might be able to submit a fix in a jiffy.
Source Code: GitHub
Before talking about my external console I want to talk about common internal tools.
Quake has the prototypical example of an in-game console. It is opened by tapping the tilde key. It’s super fast for both reading log messages and inputting console commands.
Another type of developer tool is the real-time performance overlay. They show frame rate, memory usage, CPU profiler, etc. These overlays can spiral out of control. Here’s a picture of Starcraft 2’s in-game developer tools.
Source: Designing for Performance, Scalability & Reliability: StarCraft II’sApproach
If you look closely you might notice a video game in the background. It’s completely obscured by gaudy debug visualizations. There are several more panels which developers can switch between. I’ll bet $5 you switch by entering obscure, undocumented keyboard shortcuts.
My belief is that these visualizers are superior when they exist in external tools. And that every game reaches a point where developers really, really wish they had remote access to this treasure trove of information.
External tools offer an obvious advantage for headless servers, multiplayer games, and non-PC platforms (Playstation, Xbox, mobile, etc). If you like to see both your game and your telemetry at the same time it’s even better for local PC development. Dual monitors have been a thing for quite awhile now.
There’s clearly value in hacking a debug panel over gameplay. It’s fast and easy. Especially with great libraries like ImGui. But remote tools provide so many advantages I’m inevitably frustrated when tools only exists in-game.Design Requirements
Now let’s move on to my side project. I had several initial requirements.One console should be able to connect to multiple games. Multiple consoles should be able to connect to the same game. Games should broadcast their presence for easy discoverability. Two-way communication; game-to-console and console-to-game. Console should run on Windows, Mac, and Linux. Consoles and games can run on different platforms and still connect. Write everything in C++
Most of these points focus on ease of use. Limiting connections or having to open a multiple windows is unnecessary pain.
The C++ requirement is strictly for educational purposes. I’m a game developer which, for better or worse, is a C++ world. I would not necessarily recommend C++ for tools.Technologies Used
These are some of the tools or technologies that were used in the final product. In some cases I tried several different options. Often times to great frustration. I’ll go into more detail for each of these below.
ASIO ― networking
Flatbuffers ― network protocol
ImGui ― user interface
GENie ― project generation
Travis / Appveyor ― continuous integration
VMPlayer ― Linux virtual machineNetworking
It turns out that cross-platform networking in C++ is pretty hard! Well, that’s not quite true. Let me rephrase. There aren’t many cross-platform libraries. The ones that do exist almost all suck.
I asked folks on Twitter what they used. The answer was almost universally “roll your own wrapper with the bare minimum number of features you need”. Blech!
Here’s a great StackOverflow post with a list of libraries. I tried several.ZeroMQ
Uses LGPL license. GPL and LGPL code is incompatible with my eyeballs.libuv
I should know better than to try something that is made for node.js . That’s on me really.
Poor documentation. Very poor examples. No explanation of object lifetime or memory ownership. Lots of allocations. Painful all around.nanomsg
Successor to ZeroMQ with an MIT license.
I like nanomsg quite a lot. It has a beautiful, elegant C interface. It’s very easy to use. I had a partial implementation working.
Unfortunately it isn’t the right fit for my needs. Nanomsg implements a handful of “scalability protocols”. I want UDP broadcast for discoverability which is, unfortunately, not among them.ASIO
ASIO is what my project uses. I partially chose ASIO because the C++17 Networking TS is based on it. It feels useful to get a preview of things to come.
To be honest, I kind of hate ASIO. It’s typical C++ bullshit . The code you are induced to write is ugly and hard to read. The underlying source code is inscrutable template crap. It breaks intellisense.
But it works. It’s stable. And it’s easy to integrate. Hrmph.POCO
I briefly investigated POCO. It shows promise. With a working ASIO implementation I can’t justify the time to implement POCO. Maybe someday down the road.POCO is a pretty big collection of libraries. I only need a couple. Ripping out the parts I want and gett
本文系统（linux）相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统
本文标题：Writing a Cross-Platform, Remote Logging Console in C++