Remove a noisy debugging statement
Preparation for overhauling client/server sync.

Game now has a tick counter that starts at zero, and is incremented with every GameSpace update.  Tick count is sent to clients along with full registries, so clients can tell exactly how old the information is.  (Previously, the only possible action was to throw away all conflicting game state, and treat the new information as the current state of the world.)

Game now expects clients to send at_tick along with their requested moves.  Players aren't sending it yet, producing a bunch of warnings.  The idea is for players to specify that the action take place at a future time.  The Game stores all player moves until the right moment to process them.

Game now keeps a reference to the ServerPort, and consults it to find the ServerConnection corresponding to a Player's registry ID.  Player no longer keeps a reference to the Connection itself, because that was an unusual job for an Entity, and would have made planned changes harder.  Now we can freely copy the Player object without worrying about it holding onto objects besides its own state.

All input handling now resides in GameWindow.  Again, putting some of it into Player was a strange delegation of responsibility.

It's now possible to copy one GameSpace into another.  Not using that, just yet.

Player moves are now rebroadcast to other players.  Not making use of that, yet, either.
Use ClientEngine to track multiple points in time

Hoping to solve the sync problem this way.  All events now include a timestamp, so clients can all apply those events in the same way.
More work on ClientEngine integration.  Not working yet.

For one thing, I'm seeing registry updates (every 15 ticks) arriving well before the client has been able to process the same number of frames.  That means the client is falling behind; it probably takes too long to copy the GameSpace.

I'm also seeing errors about objects not being where they were expected to be, suggesting that the separation between one space and the next is not 100% clean.  Some object's location has fallen out of sync with its position in the grid.
Mostly working again.  Soooooo many updates.

Full registry updates temporarily disabled.  I'll come back to that.  I wanted to see the deltas pulling their weight without the registry refreshes compensating for their inadequacies.

New delta, 'update_entities'.  Currently sent only when a block's HP is raised.  The 'build' move must be sent to the server, because only the server is allowed to generate registry IDs at the moment, and the 'build' move does that first.  Subsequent 'build's just increase the existing block's HP, but it's hard to pre-calculate that on the client side when we can't presuppose the existence of the block we'd be modifying.  So the server has to tell the client that the new block's HP has increased.

GameSpace no longer included as the first argument when creating an entity.  That was getting too confusing.  Now, the field is set when 'space << entity' happens.  This leads to a couple other wrinkles:

1) On the client side, it's hard to assign an entity's owner, based on the registry ID, before we know which space's registry to look up that ID.  New OwnedEntity base class handles this, with a hook Entity.on_added_to_space (called by space=) that OwnedEntity overrides.  Block and Pellet now extend OwnedEntity.

2) Entity.warp() is called during update_from_json() before the object is injected into a space.  It now carefully uses space.process_moving_entity() only *after* it has been injected.

Code in ClientEngine for processing player moves was redundant; apply_deltas() handles that now.

Late updates received by the server are now delayed until the *next* tick.

Bugs fixed in grid creation and at().  It was "working", but only by accident.  It now makes more sense to examine a grid in a debugger.

Conflict checking is now done in 'space << entity'.

New players are added into the actual, correct center of the space now.
Re-enable registry syncs

Better handling of the case where the client falls way behind the server: Just start over with the server's conception of the world.  There is nothing to be gained by presenting a smoother, but inaccurate, picture of how things are, if we're slipping further and further behind.

Slightly better formula for constraining the server to 60 updates per second.  This version of Gosu apparently produces 60 frames per second, not 62-ish, so we can drop the client-side timing adjustments.

Client and server both now have options to enable profiling output and debug network traffic.
WIP - simpler handling of registry syncs
Moving toward testability

I think the only way I'll nail down the client/server interactions, to the point where they really stay solidly in sync, is to write some real tests.  So I've laid the groundwork for that.  I have a spec that wires up a client-space and server-space in the same VM, using fake objects for the ENet connection, so I can get complete visibility and control over the interactions.  It's also now possible to check whether one space == another space, and get a reasonable answer.

Discovered that it's a bad idea to have Cell extend Set.  Set stores everything as hash keys, but Entities are mutable.  Hash keys should never mutate while in use.

Also decided it's not advisable to have entities directly storing references to each other, as it complicates the logic on the client side.  Better to store only the other object's registry ID, and look up the actual object from the current GameSpace when needed.
Create a spec for GameSpace
More tightening

Also, Game.new now accepts an options hash, and allows modifying how often registry updates are broadcast
More consistency improvements

When the server sends a complete registry, we don't want to update it; we want to display it exactly as-is.  The *next* frame should be an updated copy of this one.

When the server sends add_npcs, it's saying these NPCs were added *during* this frame.  They aren't updated during the same tick.  So, on the client-side, wait until after the update to insert the new objects.

Make Player equality work.  Behavior of == and <=> must be consistent, so we should use all_state array for both.  Put player_name first so we sort based on that.

Make it possible to create Blocks of different levels.
A whole lot more revisions.

Hard work has paid off.  "Rise up" move now looks rock-solid.  RSpec test proves client and server stay exactly in sync, at least when they run at the same rate.

Added hash.rb with a short'n'sweet utility function, for recursively turning all the hash-keys into symbols.  No longer necessary to figure out when the code is expecting a string for a key.  We just fix 'em all when the hash is recovered from JSON.  Used for messages received over the network, and for state restored from storage.

It was getting tricky to keep the client in sync with the server, when they followed different logic.  The right solution seemed to be to allow the client to do anything the server did, including create new entities.  For that, the entity IDs needed to be predictable.  So we now use increasing integers for IDs, instead of UUIDs.  The space tracks which ID we should dispense next, and this information is conveyed to the client.

Likewise, when generating a move, the client creates its own delta and applies it, so it will match what the server (and other clients) will do.

Using a fiber for "rise up" wasn't working, because the server couldn't sync the client to any point in the middle of the move.  Replaced this with a ComplexMove, an object with state which is tied to the player executing it.  ComplexMoves are sent to the client during a registry broadcast.

Factored out Serializable, a module for handling the JSON <-> object conversion.  It's now used by ComplexMove as well as Entity.

Likewise, constants from Entity now live in EntityConstants, and are used by RiseUp.

Worlds now have a name and an ID.