Design Decision I Most Regret

I previously mentioned that I’m a stickler for good platform code. Of all the design decisions I’ve ever made, there is one that I regret above all others. To this day, it haunts me mercilessly. It has appeared over and over again in countless lines of code for Half-Life 1, and silently passed to a few Half-Life 2 plugins. What is it?

The [g|s]_et_pdata functions in AMX Mod X allow you to reach into a CBaseEntity’s private data (i.e., its member variables) and pull out values given an offset from the this pointer. What’s the problem? Let’s take a look at how each of the retrieval mechanisms work:

  • 4-byte retrievals are given by a 4-byte aligned offset ((int *)base + offset)
  • Float retrievals are offset by a float aligned offset ((float *)base + offset)

At the time, I probably didn’t understand how addressing or memory really worked. I was also basing the API off years of code that already made these mistakes — learning from an incorrect source doesn’t help. So, what’s the actual problem?

In C/C++, given pointer X and offset Y, the final address is computed as X + Y * sizeof(X). That means when we do (int)base, the actual offset becomes offset * sizeof(int), or 4*offset. Not only have we lost byte addressability, but to get unaligned values we have to do various bitwise operations. This type of deep-rooted mistake is easily visible in the following code in the cstrike module:

Select All Code:
if ((int)*((int *)pPlayer->pvPrivateData + OFFSET_SHIELD) & HAS_SHIELD)
	return 1;

It turns out HAS_SHIELD is a bitmask to clear unwanted data, when in reality, the offset is wrong and (int *) should be (bool *).

Alas, backwards compatibility prevents us from ever making these API changes, and changing internal usage would then confuse users further.

In summary, the practice of casting to random types is ridiculous and SourceMod’s API summarily kills it off. The entire practice can now be expressed in a function like this:

Select All Code:
template <typename T>
void get_data(void *base, size_t offset, T * buffer)
{
   *buffer = *(T *)((char *)base + offset);
}

1 thought on “Design Decision I Most Regret

  1. すっぽんの恵み 口コミ

    大分県ネットランキング3位!高級すっぽん鍋の料亭「やまさ」の女将が「すっぽんの恵み」の創業者!

    すっぽん一筋100年、伝統の安心院(あじむ)すっぽん鍋を激安で全国の人に堪能してもらいたい!との思いから制作が始まったすっぽんのスペシャリストによるサプリです。

    子供を産んでから育児に追われる毎日の君へ。最近体力に自信がなくなってきた・・とお悩みではありませんか?

    そこで手軽にすっぽんの成分が摂れると人気なのがこの「すっぽんの恵み」です。

    初回のみ500円(7日分送料無料)と非常に格安ですので、すっぽんサプリを摂って効果を検証してみるのもいいでしょう。実際、お試し品だけでも効果が最高だったという口コミも多々ありました。

Comments are closed.