Skip to content

Dependency rule violations: common/ and client/ include game-specific headers #119

Description

@corepunch

Summary

The engine-level directories common/ and client/ contain #include directives that reach into game-specific code (game/, games/), violating the project dependency rules documented in AGENTS.md:

Engine modules (renderer/, client/, common/, server/ core paths) must remain game-agnostic.

Additionally, common/ files use the GAME_WORLD preprocessor flag to conditionally compile game-specific code paths, which puts game logic inside what should be engine infrastructure.


Violations

1. common/common.h — unconditional game-specific include

Line 7:

#include "games/warcraft-3/common/mapinfo.h"

The shared engine header common.h unconditionally includes a Warcraft-III-specific header. Every compilation unit that includes common.h (engine, client, server, renderer, tools) pulls in this dependency. This also likely pulls in game structs and types that the engine shouldnt know about.


2. common/routing.c — game-local include + server include

Lines 1–13:

#ifdef GAME_WORLD
#if defined(WOW) || defined(SC2)
#include "server/server.h"
#else
#include "game/g_local.h"   /* line 5 — game-specific */
#endif
#define ge (&globals)
#ifndef EDICT_NUM
#define EDICT_NUM(n) (globals.edicts + (n))
#endif
#else
#include "server/server.h"  /* line 12 — server engine from common */
#endif

Problems:

  • Line 5: #include "game/g_local.h" includes a game module header from common/.
  • Line 3, 12: #include "server/server.h" includes the server engine from common/. Common should be below both client and server.
  • Line 1: #ifdef GAME_WORLD used outside games/ to control compilation.

3. common/world.c — GAME_WORLD-guarded game code

Lines 31, 308:

#ifdef GAME_WORLD

These guard WC3 map-reading functions (CM_ReadInfo, CM_ReadPlacementHeader, CM_ReadDoodads, etc.) that belong in the game module, not in common/.


4. common/main.c — server include

Line 2:

#include "server/server.h"

The main() entry point lives in common but includes the server engine header.


5. client/cl_view.c, cl_parse.c, cl_input_w3.c — game-specific includes

cl_view.c line 6, cl_parse.c line 15, cl_input_w3.c line 3:

#ifdef SC2
#include "games/starcraft-2/common/sc2_map.h"
#endif

The client engine includes StarCraft II map types under #ifdef SC2.


6. common/common.h — GAME_WORLD struct/utility definitions

Lines 295–304:

#if defined(GAME_WORLD) && !defined(COMMON_GAME_WORLD_IMPORTS)
#define COMMON_GAME_WORLD_IMPORTS
extern struct game_import gi;
static inline HANDLE G_WorldReadFile(...) { ... }
static inline HANDLE G_WorldMemAlloc(...) { ... }
static inline void G_WorldMemFree(...) { ... }

common.h additionally defines game-world utility functions gated by GAME_WORLD.


What Needs To Happen

  1. common/routing.c — The pathfinding code itself is engine-neutral, but the #ifdef GAME_WORLD header/macro block at the top is the core problem. The ge pointer and EDICT_NUM macro should be provided by the caller (passed as parameters or via a context struct), not imported from common. The edict_t dependency (via stamp_entity_obstacle, CM_BuildHeatmap, etc.) means routing.c fundamentally depends on game entity types. Possible approaches:

    • Move routing.c to the game module (with a shared interface for tools).
    • Or refactor it to accept opaque callbacks/cursors so common doesnt need edict_t.
  2. common/world.c — Extract WC3 map-reading code (CM_ReadInfo, CM_ReadDoodads, CM_ReadPlacementHeader, etc.) into the game module (e.g. games/warcraft-3/common/). Leave only shared utilities like MapInfo_Release, PF_TextRemoveComments, CM_ReadModification, and FS_ReadArchiveFileIntoString in common.

  3. common/common.h — The #include "games/warcraft-3/common/mapinfo.h" can be forward-declared or moved to game code. The GAME_WORLD utility functions block can be provided via an import table instead of being inlined in the shared header.

  4. client/ SC2 includes — Extract client-side game hooks to per-game cl_input_*.c or cl_view_*.c files, or provide an abstracted map-information API in the renderer.

  5. common/main.c — The server include should probably be removed; main() can declare Sys_Init() itself or the server entry point should be elsewhere.


Files Affected

File Line(s) Issue
common/common.h 7 Unconditional #include "games/warcraft-3/common/mapinfo.h"
common/common.h 295–304 GAME_WORLD-guarded utilities in shared header
common/routing.c 1–13 Game-local + server includes, GAME_WORLD guard
common/world.c 31, 308 GAME_WORLD guarded game code in common
common/main.c 2 #include "server/server.h"
client/cl_view.c 6 #include "games/starcraft-2/common/sc2_map.h"
client/cl_parse.c 15 #include "games/starcraft-2/common/sc2_map.h"
client/cl_input_w3.c 3 #include "games/starcraft-2/common/sc2_map.h"

The renderer/ and server/ directories are clean — no violations found.

Metadata

Metadata

Assignees

No one assigned

    Labels

    cleanupCode cleanup, tech debt, architecture violations

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions