Oli's old stuff

Tinkering with retro and electronics

Jul 25, 2016 - 6 minute read - oldcode

Manta-X Code (Part 2)

Removing PhysicsFS

I wanted to get the game running so I thought I’d go and remove the PhysicsFS dependency. I didn’t really need it at this point and can’t be bothered with another 3rd party library for the sake of it.

Turns out it was used in 3 classes:

    ModelManager (for loading Milkshape3d models)
    ShipClassManager (for loading XML data about the ships)
    TGAImage (for loading texture data)

Each of these essentially did the same series of operations:

  1. Check the file existed
  2. Allocate a buffer
  3. Read contents into the buffer
  4. Close file
  5. Do stuff with the buffer

As a side node, back then I was doing a lot of heap allocation and looking over the code, it was very easy for these buffers to be leaked when an error occurs. Now I’ll just use a std::unique_ptr until I can come up with a better allocation strategy.

I quickly hit the fact that my FileReader class I talked about before wasn’t implemented. I seemed to do a lot of this stuff back then, have code started and just not used or finished sigh. Anyway, it was farily trivial to implement a Win32 version of the FileReader and replace the PhysicsFS code. I’m not injecting the dependency still, so the classes are currently just creating their own FileReader and going from there.

The problem with removing PhysicsFS is that I added the dist\data directory to my search path using PhysicsFS. I wrapped up the file name in an immutable FilePath object which starts out as the root data directory. Now, instead of passing raw strings around to file load routines, I pass the path object. Seems to work ok.

With that all done, I can remove PhysicsFS (sorry Icculus!).

Current cloc 6092, that’s up by 200 lines or so. Not too bad considering I removed a huge dependency.

Also, the game compiles and starts now… but doesn’t run.

Entities

So digging into the file loading was pretty useful as it exposed me to how the manta.xml file is loaded. At first glance, this appeared to be a file thet describes the properties of the player.

The player’s ship is an instance of the GameShip class, which has the following inheritance hierarchy:

   FSM
    ^
    |
  Entity        <--- IMMO
    ^
    |
GameObject      <--- ICollidable
    ^
    |
ModelEntity
    ^
    |
GameShip

Every entity in the game has a finite state machine - wtf? As expected, they all base on that awful IMMO object.

So what is an Entity? It looks like it’s a graph of other entities (like Unity) - they have parents and children.

Entity Messaging

Entities also have a messaging system built into them. It’s not a game wide messaging system, looks like it’s specifically for entities.

    /////////////////////////////////////////////
	// Message handling interface
	//
	IEntityMessageFunctor *RegisterMessageHandler( long pMsgId, IEntityMessageFunctor *pHandler);
	//
	IEntityMessageFunctor *GetMessageHandler( long pMsgId );
	//
	int HandleEntityMessage( sEntityMessageInfo *msg );
	//
	void SendMessageToChildren( sEntityMessageInfo *msg );
	//////////////////////////////////////////////

The signature of of RegisterMessageHandler is weird, but looking at the implementation it essentially returns you the old handler for a message, replacing it with the one you just registered.

long pMsgId is badly named (looks like a pointer) and is essentially a constant defined in an enum:

enum EntityMessages
{
	ENT_MSG_CREATE,
	ENT_MSG_DESTROY,
	ENT_MSG_SHUTDOWN,
	ENT_MSG_UPDATE,

	ENT_MSG_ATTACHED,
	ENT_MSG_DETACHED,
};

I guess it’s a long instead of an enum EntityMessages to avoid including headers? I doubt it, as I had a huge header include issue anyway. Perhaps just another bad decision. There’s plenty here.

The IEntityMessageFunctor is essentially a message handler with the following definition:

class IEntityMessageFunctor
{
public:
	virtual int operator()(sEntityMessageInfo *msg) = 0;  // call using operator
	virtual int Call(sEntityMessageInfo *msg) = 0;        // call using function
};

This has a couple of obvious flaws in that handlers can mutate messages. I’m going to assume that they’re all heap allocated and the same instance is shared. Will have to confirm. Not sure why the message handler defines the call operator, probably thought it was cool back then. It’s obviously pointless.

I was wondering why I had a special baseclass for the messages, assuming that perhaps I just did some downcasting in the handler based on the message type… but no. Something weird.

The definition of the sEntityMessageInfo is:

struct sEntityMessageInfo
{
	sEntityMessageInfo();
	sEntityMessageInfo( long pMsg, Entity *pFrom, bool pRelay );

	long msg;
	Entity *from;
	bool relay;		// Relay to children?

	std::vector<sEntityMessageParam>	params;
};

WTF. Looks like the sender provides a flag to determine if the message is passed to the receiver’s children (how would it know?). Also, what the hell is sEntityMessageParam?!

I take a look and… yeah.

struct sEntityMessageParam
{
	enum msgType
	{
		MSG_TYPE_STRING,
		MSG_TYPE_LONG,
		MSG_TYPE_INT,
		MSG_TYPE_BOOL,
		MSG_TYPE_FLOAT,
		MSG_TYPE_USER
	};

	msgType Type;

	union
	{
		std::string		*m_string;
		size_t			m_long;
		int				m_int;
		bool			m_bool;
		float			m_float;
		void			*m_user;
	} Data;

};

It’s a variant type. Why? Why? WHY?!

I presume there was some legit reason, although right now I can’t comprehend what it might be. Perhaps scripting? shrug

I just noticed that every entity subscribes to a bunch of messages on construction, regardless if they consume them:

Entity::Entity()
{
	Erase(); _allocateID();
    RegisterMessageHandler( ENT_MSG_CREATE, new TEntityMessageFunctor<Entity>(this, &Entity::OnCreate) );
    RegisterMessageHandler( ENT_MSG_DESTROY, new TEntityMessageFunctor<Entity>(this, &Entity::OnDestroy) );
    RegisterMessageHandler( ENT_MSG_SHUTDOWN, new TEntityMessageFunctor<Entity>(this, &Entity::OnShutdown) );
    RegisterMessageHandler( ENT_MSG_UPDATE, new TEntityMessageFunctor<Entity>(this, &Entity::OnUpdate) );
    RegisterMessageHandler( ENT_MSG_ATTACHED, new TEntityMessageFunctor<Entity>(this, &Entity::OnAttached) );
    RegisterMessageHandler( ENT_MSG_DETACHED, new TEntityMessageFunctor<Entity>(this, &Entity::OnDetached) );
}

Also, it looks like the next entityId (returned by _allocateID()) is a static… and that there’s a freelist of ids:

Entity::~Entity()
{
	_freeID();
}

sigh

The weird thing is that Entity also seems to have the concept of rendering in it:

virtual int OnPreRender( sEntityMessageInfo *msg );
virtual int OnRender( sEntityMessageInfo *msg );
virtual int OnPostRender( sEntityMessageInfo *msg );

But the implemenations do nothing.

It’s a symptom of the inheritance structure that is in place. I’d assume I’d be adding all sorts of gubbins to this Entity if we continued.

Entity has both a position and rotation property, with a comment saying that they’re relative to the parent. When I look down the hierarchy, I also notice that GameObject has a postion and rotation which seems to be used. Essentially, I have no idea what the stuff on the base entity does - if anything.

Wrap up

Looking into this Entity code has been somewhat frustrating. There’s a lot of trash in here and a lot of stuff that doesn’t do anything. The first thing I’d look at doing is ripping out the message handling stuff and putting something a little cleaner in there - Ok a lot cleaner. After that, start breaking this idiotic hierarchy into components.

The first goal, however, is to get something rendering. The game runs but doesn’t show anything.