Categories
Game Development

Layered transport service provider

One problem I had a couple of years ago was how to write an accurate internet simulator feature for RakNet. What I have in there now is what you find in your average games – a user can intentionally add latency to outgoing messages and can randomly drop packets to simulate packetloss. But this is not accurate and not very full-featured.

Here’s a better design:

Maximum outgoing bandwidth – Represents your network card’s ability to send data through the wire.
Maximum incoming bandwidth – As above, but for incoming data
One-way trip time – The minimum time a datagram would take to get to a remote system; the base speed of the network
Per-message additional trip time – On the internet, many people are sending messages, so there will be some delay between each of your messages as other messages goes out. So this number represents the rest of the internet using the router’s bandwidth too. The effect to the sender is that as you flood the connection, your ping goes up. This is what actually happens and is how flow control is accomplished in modern reliable packet implementations (the old way used sliding windows which controlled throughput based on how fast the other system acked your messages).
Maximum router queue – This represents how much average memory each router has. Go beyond this and you start getting packetloss.
Randomly dropped packets – Due to noise on the wire
Out of order packets – As above

The problem with hardcoding this in the user level network layer is that you have to implement a control interface (changable at runtime), you have to do it on both systems, and it can be complex to implement in every circumstance. So I’m writing a layered transport service provider. This is sort of like RakNet’s plugin system, but for Winsock, and it gives you the ability to override various network events with a procedure table. This is stored as a system DLL, and installed and uninstalled by an EXE. I will have this EXE double as a control panel and will use interprocess communication to have the EXE control the invoked DLL.

By the way, to say this is complicated is understating the issue. It’s about 1000 lines of code for the installer, 10,000 lines of code to properly create a plugin that does nothing but pass the data through. You have to understand overlapped events, IO completion ports, support for versions of winsock, an entirely different set of code to install the driver on Vista (plus permission sets), you have to use .def files for export, and more. The article that I’m going by is 8,500 words long (about 20 pages) and takes hours of study to understand well enough to do anything.

After going through all this I think Shunra is justified in charging $500 for their simulator. The solution is hard to write. However, Shunra doesn’t support loopback last I contacted them. My implementation does, so I think I can sell mine to gave developers and others that want a loopback solution. Plus I can put a nice GUI on it, so you can control what is going on at runtime.

Categories
Game Development

Data structures for fun and optimization

I was updating the manual for RakNet and was reminded of how many data structures I’ve written for it.

From the manual:

DS_BinarySearchTree.h – Binary search tree, and an AVL balanced binary search tree.
DS_BPlusTree.h – BPlus tree for fast lookup, delete, and insert.
DS_BytePool.h – Returns data blocks at certain size thresholds to reduce memory fragmentation.
DS_ByteQueue.h – A queue specialized for reading and writing bytes.
DS_Heap.h – Heap data structure, includes both minheap and maxheap.
DS_HuffmanEncodingTree.h – Huffman encoding tree, used to find the minimal bitwise representation given a frequency table.
DS_HuffmanEncodingTreeFactory.h – Creates instances of the Huffman encoding tree.
DS_HuffmanEncodingTreeNode.h – Node in the Huffman encoding tree.
DS_LinkedList.h – Standard linked list.
DS_List.h – Dynamic array (sometimes improperly called a vector). Also doubles as a stack.
DS_Map.h – (Associative array) Ordered list with an per-element sort key.
DS_MemoryPool.h – Allocate and free reused instances of a fixed size structure, used to reduce memory fragmentation.
DS_OrderedChannelHeap.h – Maxheap which returns a node based on the relative weight of the node’s associated channel. Used for task scheduling with priorities.
DS_OrderedList.h – List ordered by an arbitrary key via quicksort.
DS_Queue.h – Standard queue implemented with an array
DS_QueueLinkedList.h – Standard queue implemented with a linked list
DS_RangeList.h – Stores a list of numerical values, and when the values are sequential, represents them as a range rather than individual elements. Useful when storing many values that are usually sequential.
DS_Table.h – Table with columns and rows, and operations on that table.
DS_Tree.h – Noncyclic graph
DS_WeightedGraph.h – Graph with weighted edges, used for routing via Dijkstra’s algorithm

Data structures is one of the few classes in college that has a significant real-world bearing. It’s one of the cornerstones of good design and optimization.

A few times I’ve been asked why I don’t just use STL.

1. STL can cause linker errors
2. STL uses exceptions.
3. STL doesn’t have every feature I need.
4. I don’t know how well STL is optimized, but I know exactly how well my code is optimized.
5. In college I was confused for months before I figured out when people said ‘vector’ they meant ‘dynamic array.’ It became a pet-peeve of mine.
6. In college I started writing my own data structures before I knew STL existed. None of my classes ever covered it And once I started I had momentum to keep going.
5. It’s something I find interesting and enjoy writing.

Aside from STL, of the game companies I’ve worked at, I’ve never seen any of them with as sophisticated a set of data structures as what I have in RakNet. When you need to process and track 30,000 messages a second you need heavy duty data structures like my memory-pool optimized B+ tree. Being able to support 30,000 messages vs. your standard game’s 20-30 messages a second is part of the polish you get with a dedicated mature library.

Categories
Uncategorized

In favor of nationalized health care

I’ve been trying to buy health insurance to cover myself as a private contractor. At every step where I deal with the insurance company I am reminded of the movie Sicko. I’m a healthy guy who has never had serious medical problems. I tried signing up for Health net 3 months ago. Part of the 50 page application form was to list every doctor visit in the last 6 years or so. So I put down two visits to the doctor two years ago, both for minor problems that cleared themselves up after a few days. 3 months and half a dozen phone calls later I get back a form letter asking for every imaginable detail of those doctor visits – who I saw, addresses, phone numbers, dates, treatment details, etc. It’s like if you get health insurance, you better not ever use it, because if you do you will never get insurance again. I was fed up so wrote back to them and told them to cancel my application. “I’ve already given you these details. You have authorization to look up my records. I don’t have the time or inclination to do your job for you. If this is how you treat a potential customer trying to give you money, how will you treat me when I actually need care?.”

Initially I was ambivalent about nationalized free health insurance. The free market’s incentives are to maximize profits. When it works, the way to do this is to provide the best service for the lowest possible price to attract and satisfy as many customers as possible. The government’s incentives are to satisfy their own customers, which are generally special interests or the bureaucracy itself. It’s different in every situation, but one doesn’t have to look far to find waste, fraud, or poor service where the government is concerned. Look at the lines at the post office or the DMV. There’s also the argument that when something is free you get unlimited demand. It is true this would result in longer lines and worse service compared to an ideal free market scenario.

However, after thinking this through I think nationalized health service is the correct choice. The free market doesn’t work where you have force or fraud – in theory it is the government’s job to prevent just that (although often the government is the cause of said force or fraud). Cox cable has a monopoly where I live. So when I had my cable modem installed I was forced to use their service. As a result, I had to pay $200 to lease a modem you could buy for $50, and a $300 installation fee for a guy to drop it off at my house, and the service didn’t work for a month and a half.

Does force or fraud exist in the health insurance business? I think force is an inherent part of the equation – a sick or dying person has no choice but to accept the services that are available to them. With Cox I could at least go without or move if I wanted to, but the guy in the movie who had to choose which fingers he wanted reattached had no such option. Unlike a typical business, the insurance company makes money by NOT providing service – turning down sick customers, or denying those who are already sick. So it’s undeniable that there is an incentive to commit fraud. Usually lawsuits work out fraud, but a person who has just undergone a major health problem (and paid for it themselves) usually doesn’t have the time or money to fight the insurance companies. A dead person certainly doesn’t. The only people with the resources to take on the insurance companies, the super-rich, pay for their own services anyway.

The only question that remains is will the waste, lines, and bureaucracy of the government be better than what we have now?

Categories
Game Development

Marketing middleware

Back when I started RakNet 5 years ago I was talking to a marketing guy. He something like “You’ll get a sale here and there, but to really be successful you have to approach the companies directly.” My reply was “That’s fine, but I want to add these features first before I start having big companies look at it.”

I didn’t even get a sale here and there, so maybe I was right, but I did go a bit overboard. Not until last week really did I sit down, ask myself “What feature should I add next to be more competitive?” and just couldn’t think of anything.

It’s time to switch to marketing, and hopefully this time it won’t take 5 years to reach my destination.

The first thing I can think to do is partnerships. 9 months ago the tech director at SOE told me if they didn’t already know me, they would have just used Quazal, because Quazal is a featured partner of Gamebryo. But the funny thing Gamebryo doesn’t have networking. The partnership is essentially an advertisement to look at Quazal if you need a networking solution. I’m not complaining, but pointing out the importance of partnerships and alliances. People will go with what they think works, and a featured partner is more likely to work than some library on the net you’ve never worked with before.

As much as I’d like to, I don’t have the connections or clout (yet) to get RakNet into Gamebryo. But where I do have a better chance is in the open source and small game community. If the competitor’s forums are any indication, RakNet is pretty much dominant in this market, even if it’s a market that doesn’t pay very well. But more users is always better, one can always monetize later.

Step 1: Ally more closely with Ogre 3D.

Ogre 3D is a great library not just for its features but because it has a massive userbase. Any forum post gets a response nearly immediately, and that is good not just for its own sake but the support level generated by that draws even more users. I’ve had a good relationship with that community from Galactic Melee so it’s a first draw to get more eyes looking at RakNet.

In that regard, yesterday I wrote a sample that uses Ogre 3D along with RakNet to demonstrate how to do graphical network interpolation code. The users seem to appreciate it. Some people in my own forum have been asking how to do what I did there so it solves two problems.

Step 2: Irrlicht

Irrlicht seems to be the next big graphics engine. I used it back when I was writing a web based shooter. I like it better than Ogre because the style reminds me more of RakNet. I contacted the author of Irrlicht, and he agreed to add RakNet to the toolset page if I were to do add native support, which I will do in a similar fashion. I’ll do this in the upcoming week

Step 3: Partner with smaller commercial game engines

Most game engines that I searched for already had networking. While I think a dedicated library like RakNet will be more advanced than what a game engine will offer as networking on the side, it’s probably a lost cause in most cases. However, I did find a few game engines that didn’t already have networking. Maybe none of my emails will get a response, but if they do this can be a good additional revenue stream as well as benefit for said game engine. This will require a lot more work since I’d actually be learning and supporting new engines, but is also a good opportunity.

Step 4: Pursue connections

(Coincidentally) I had lunch with a very well-connected friend today and he offered to help me get my foot in the door in several big opportunities. I won’t say what, since it may not pan out anyway, but it’s really great having friends to help you out or even just discuss ideas over.

The major money comes from friends and connections. Tip to the new guys: Never burn your bridges and make an effort to make friends with people. You never know who will help you out in the future, and of course you get to return the favor.

Anyway, I’m optimistic about the next 6 months. If RakNet can get a few big partners I think things can finally take off.

Categories
Game Development

Replica Manager 2 Done + Video

I spent an entire day on Sunday thinking about the architecture on how to write a generic system to create, destroy, serialize, and control scope over networked objects in C++. It’s a very hard problem to solve because you know nothing about the game objects themselves, or what complexities the end-users might introduce with their specific architecture.

In the end I decided on 3 classes. One class, ReplicaManager2, is the base plugin for the system. All it does is essentially serialization, deserialization, transmission, and bookkeeping. Stuff you wouldn’t normally care about. I have the user pass a class factory that generates connection instances, one per connection. This controls high-level and non-object specific functionality such as how to create object instances. Lastly, there is the base class Replica2, which game objects should derive from.

The main reason I did it this way, rather than putting everything in the ReplicaManager2 plugin (as I did in its predecessor) was so that the functionality can be easily overridden. This should solve a problem I had with the old system, where I ended up passing a ton of data to the callbacks in order to force it to get it to do what I wanted. By assuming users will override functions, this also gives me the ability to make assumptions and thus much more elaborate functions.

Improvements it has over the old system are:

1. Relay across systems actually works correctly. So you could have a server cluster, with n clients on each server, and everything would just get sent out properly. It automatically deals with cyclical connection graphs up to a depth of 1 away from the source node.

2. Defaults to polling for changes. Each tick, if an object is now constructable, or in scope, and it was not in the last tick (or vice-versa) the object is created or destroyed appropriately. The object is also serialized every n milliseconds, and if it serializes differently under the same context, the newly serialized value is transmitted. This is easier to use than event-based updates (which are also supported) so the user has to write less code.

3. Downloads construct all objects first, then deserializes them, and in the order they were originally created. This is likely what a user would do were they to hand-write the download system, and maximizes the chance that pointers and other dependencies will be valid on deserialization. This also allows you to have objects that cross-reference each other when deserializing, each both have already been created anyway.

4. It’s easier to modify events and more information is given about what triggered those events. For example, it’s now trivial to send using different reliability types based on the context of what is being sent, something that was hard to do before.

5. Changes are easier to initiate on the client, especially construction, which before would have taken custom game code.

Here’s a video that goes over the system. I start out too fast because I was tired of starting over when I made mistakes, but later on it gets better.
http://www.rakkarsoft.com/raknet/manual/ReplicaManager2.html

Categories
Game Development

Replica Manager 2

I’m working on the second iteration of the Replica Manager class. For those that don’t know it, this class is supposed to handle the details of sending and synchronizing objects across the network as new systems connect.

My first approach was data based. All the code was in the Replica Manager itself, and it would query an interface to get the data it needed to perform operations, such as serializing objects. In most cases, this worked OK. However, the problem with games is there is always complexity to work around, especially with existing systems, and if cases came up that I didn’t anticipate it was hard to go around the system. One example in particular was the initial object download. The first system would gather up all objects, serialize, and send them to you. However, this didn’t work if objects already existed globally (such as created when the map loaded). It also didn’t work if you cared about what order objects were downloaded in, which you would if they had dependencies on each other (such as cross referencing pointers).

My new approach is more code based, with data queries exposed only for very common or unlikely to change operations. So now the Replica Manager class itself mostly just encodes and decodes queries, and holds the data structures, with the actual functionality in the Replica class, the class you derive your own game objects from. This gave me a degree of flexibility I didn’t have before, because now I can implement complex operations since I know the user can override the code if necessary. One example is having a client locally create an object which is verified by the server, and deleted or synchronized on the client accordingly. Another example is automatically scoping objects with a simple callback, where before you had to do this by writing your own system.

The test case I’m solving is:


// Preexists on all systems, has objectID, still want to register it so I can call serialize automatically
class World {
int totalKills;
}

class Player : public Participant {
Soldier *soldier;
char name[256];
int teamNumber;
char killMessage[256];
int gameInstanceId; // Players may be spread out between multiple game instances
};

class Soldier {
Player *owningPlayer, *lastDamagingPlayer;
Gun gun;
float health; // Sent reliable ordered
float positionX, positionY; // Sent unreliable sequenced
bool isCloaked; // If cloaked, do not send position to non-teammates
};

class Gun {
Soldier *owningSoldier;
Player *owningPlayer;
int ammo;
};

class Bullet {
Gun *firingGun;
Player *owningPlayer;
RakNetTime timeFired;
};

So you have:

1. Classes that have pointers to classes that have pointers to themselves in return
2. The world object is assumed to preexist, so should not be dynamically downloaded, yet still needs to be updated
3. Cloaking, where an object either won’t be serialized at all, or only partly serialized (if a teammate)
4. Pointers which may be NULL
5. Object composition with serialized objects (so their parents should be dynamically downloaded, but not the objects themselves).
6. Serializing the object using a different send type, depending on what part is serialized.

These could all be solved with the old system too, but it was much harder and you had to really understand the code to know what to disable. If I do my job this test case should be solvable trivially.

Categories
Uncategorized

How to tip like a Gentleman?

I was reading How to tip like a gentleman. It seems like most people support what he wrote, but personally I think tipping is way out of hand.

One incident I remember was at Supercuts about two years ago. It’s $20 for a 20 minute haircut, they spent the whole time I was sitting there trying to sell me cosmetics, and did a bad job too. So for the tip I put a slash, and got a nasty look. Why should the lady expect a tip for doing her job at all, much less doing a bad job, and spending the whole time trying to advertise to me?

Another incident in was Las Vegas about 3 months ago in a taxi on the way back to the airport. The guy was nice enough but the fee is near $100 an hour. So I gave him like $40 for a $38 fair, told him to keep the change, and got a nasty look for it. I don’t know what’s supposed to be appropriate for a taxi, but good grief at that rate (if they keep half the money) they are pulling in probably 75K a year to drive a car, with no education and minimal training. I know it’s a risky job but it’s not like they are making minimum wage. That’s how it is in Europe, leave them the change if you want to, but it’s not expected. Now it’s like the opposite, you are expected to give a tip, so not only is a small tip not appreciated, they are mad for getting it.

About 3 months ago I went to semi-fast food restaurant. I paid by credit card, and there was a tip line to be filled in before you even got your food. And they didn’t even serve the food there, you had to get up and get it yourself. And even if they did, I don’t see the sense in tipping before I even get the service, so put a slash there. I got a bad look for that too.

A few dollars for good service is one thing. But I don’t think it should be expected, and certainly not for cases where someone is doing a job that is not interpersonal (driving a taxi, taking your order at a fast food outlet).

Categories
Uncategorized

Empire Earth III review

Empire Earth III, developed by Mad Doc Software, is an RTS where your civilization upgrades through the ages from about 1,000 BC to far in the future. This sounds like a fun design, like an RTS version of Civilization that goes beyond the modern era. The game is split into a world component (like XCOM) and an RTS component. In the world component, you assign each territory to produce military, commerce, research, or imperial points. You also move military units, and buy militia to defend provinces. There are several other AI controlled sides doing the same thing.

When conflict arises against either the native tribes defending each province, or an AI player, the game switches to the RTS map. Your starting units’ technology and numbers are based on your play in the world component. Base build-up is fairly standard, with the exception that you don’t really take specialized paths or make major decisions in base building. Most of the meat here lies in troop upgrades and deployment, with special abilities such as ranged units entrenching or using calvary vs. infantry.

The game was semi-fun for a day or so to see the different types of units you could get through research. However, I think the AI is too weak, and ultimately caused me to lose interest in the game. The main positive thing I can say about it is that your units will help each other out, so if someone is attacking you offscreen your units will move in to help out. On the negative side, units lack sufficient autonomous behavior, pathfinding is sometimes a problem, and most significantly about half the maps do not provide significant gameplay. Of those maps, half the time all opponents are neutral or cannot reach your base. So you build your base for 20 minutes until you have a good income stream, then just bribe all opponents to join your side, without a single bullet fired or sword swung. The other half of the time combat is not a significant challenge, and play progresses the same way. For example, if you build 3 towers (for nearly the same price as 3 regular units, buildable at any time) on most maps this renders you impervious. You could attack your opponents if you want, but it’s usually faster, cheaper, and easier just to save enough resources to bribe them. Towards the end I found myself dreading the RTS part of the game, trying to blow through the tedious parts as fast as possible so I could get back to the world component. On the last map I played before uninstalling, I built my base for 20 minutes, wondering where the attacking army was, and found them floating near the left edge of the world, never having disembarked their troop transports.

A few maps had pre-scripted challenges, and those were the most fun in the game. But they are far enough apart that it eventually became not not worthwhile to play through the unchallenging parts to get to them. It’s too bad too, I can see a lot of work went into the game, to have it all for naught.

I’d wait for this one to hit the bargain bin.

Categories
Uncategorized

React Operating System

Yesterday, I was reading about the React Operating System. I was chuckling about this for the rest of the day. I really admire what they are doing and I agree with their premise and solution. It is true that Windows has the problems of being bloated and closed source. It is true that Linux has the problems of requiring non-trivial operations through the command line, and having compatibility problems. So their basic solution is correct – an open source rewrite of Windows that is binary compatible with existing programs.

Going by their roadmap they are on version .34 and have been doing it since 1996. That’s a long time, but when you consider it’s a few guys accomplishing in their spare time what a billion dollar company has done… Great job!

Categories
Game Development

Sourceforge is a great service

Quick note: I’m really glad a service like Sourceforge exists. After all the trouble recently with source control providers it is really awesome that I can update RakNet without having to think about if the server is up or down, or security for my code, or paying for it. Plus you get a mailing list. It’s hard to set up but I’m glad I did.