Skip to content

Legacy Overview

What the original Applejack was, how it was built, and which copy to trust.


1. Identity

Name Applejack - Cider Core (gamemode/sh_init.lua:38)
Authors Lexi; original gamemode by kuromeku (sh_init.lua:40)
Base Derived from Sandbox — DeriveGamemode("Sandbox") (sh_init.lua:45)
Language Lua, Garry's Mod 12/13 era
Size 289 .lua files under gamemode/ and entities/
Internal prefix cider / cider_ — the gamemode's earlier name, still the entity and command prefix throughout

Applejack and Cider are the same thing. Cider was the original; Applejack is the fork that this repository preserves. The names are used interchangeably in the source, and every entity class, every console command and every network message still uses the cider prefix.


2. Engine era — everything here is dead API

The original targets an engine generation that no longer exists. Every one of these is removed from modern Garry's Mod, let alone S&box:

Legacy API Used for Status
usermessage / umsg.* All server → client messaging Removed (superseded by net, itself irrelevant to us)
datastream (require "datastream", sh_init.lua:46) Bulk table transfer Removed
glon Table serialisation into SQL columns and files Removed
tmysql MySQL access (init.lua:99) Third-party binary module, dead
file.FindInLua The entire file loader Removed
_R.Player, _R.Item metatables The object model Concept does not exist in C#
DTInt / NWVar Entity state replication Replaced by [Sync]

There is no use of the net library anywhere in the codebase — that is how old it is.

The practical consequence: 100% of the legacy transport, serialisation and persistence layers must be rewritten. There is nothing to salvage below the gameplay-rules line, and attempting to preserve any of it would be actively harmful. See 11_NETWORKING_LEGACY.md.


3. The two copies

legacy/ contains two snapshots of the same gamemode.

legacy/applejack-old-final/canonical

Use this as the reference for all behaviour documentation.

legacy/Applejack/ — a later content fork

110 files differ, but only ~27 differ once line endings and whitespace are normalised. Only two engine-level files genuinely diverge (libraries/sv_entity.lua, metatables/sv_player.lua), plus the vehicles plugin. Everything else is content.

Worth taking from it as concepts, not code:

Addition Why it matters
gamemode/plugins/crossserverchat/ Cross-server chat relay — evidence of a multi-server deployment
Tiered contraband: cider_money_printer_2/3/4, cider_drug_lab_2/3/4 An upgrade progression the canonical copy lacks; good input to the crafting/economy design
items/drinks/beer.lua Trivial

Conversely applejack-old-final has items/illegal_weapons/cider_tranq.lua, which the fork lacks.

Rule: when the two disagree on behaviour, document applejack-old-final and note the fork's variation in a footnote.

legacy/content/ — reference assets, not in git

~162 MB of Source 1 models, materials and sounds. Present on disk, deliberately excluded by .gitignore. It is copyrighted Garry's Mod content and cannot ship. It is useful only for reading art direction, prop naming and the container model list. No asset is migrated.


4. Load order

Understanding the boot sequence matters because in the original, load order is load-bearing — items query plugins at include time, and jobs query items. This coupling is one of the things the new architecture explicitly designs out (Architecture/02_MODULE_MODEL.md).

From gamemode/sh_init.lua:

timer.lua                        custom timer.Conditional
DeriveGamemode("Sandbox")
require("datastream")
sh_enumerations.lua
sh_config.lua                    ~25 KB of tuning values
sv_config.lua                    (server only — DB credentials)
libraries/*.lua                  explicit prefix-dispatched loop     ← pass 1
doload("libraries/")             generic loader                      ← pass 2  ⚠ DOUBLE INCLUDE
doload("metatables/")
doload("hooks/")
gamemode.Call("LibrariesLoaded")
sv_commands.lua, sv_umsgs.lua    (server)  /  cl_content.lua (client)
GM:LoadPlugins()                 ← plugins load BEFORE items
GM:LoadItems()                   ← items may call GM:GetPlugin(...)
sh_events.lua
sh_jobs.lua                      ← jobs reference item categories
derma/*.lua                      (client UI)

libraries/ is included twice — once by the explicit loop at sh_init.lua:105 and again by doload("libraries/") at sh_init.lua:157. Every library file executes twice on every boot. See 12_DEFECTS_AND_LESSONS.md.

File-prefix convention

The loader dispatches purely on the first three characters of the filename:

Prefix Server Client
sv_ include
cl_ AddCSLuaFile (sent to client) include
sh_ include + AddCSLuaFile include

This is a genuinely good idea badly implemented — realm is declared by filename rather than scattered if SERVER branches. The new architecture keeps the intent (explicit realm) with C# types and attributes instead of filename magic.


5. Top-level anatomy

gamemode/
├── sh_init.lua        (loader, above)
├── init.lua           47 KB  — server bootstrap, payday loop, damage rules
├── cl_init.lua        36 KB  — client bootstrap, HUD, ESP
├── sh_config.lua      25 KB  — all tuning values + container/contraband tables
├── sv_commands.lua    58 KB  — ~66 chat command implementations
├── sh_jobs.lua        job/team definitions (data)
├── sh_events.lua      event enumerations
├── libraries/         16 files, 4094 lines — the framework
├── metatables/        the data model (player, item, entity)
├── hooks/             sh_player, sv_player, sv_sandbox
├── items/             139 files across 15 categories — content
├── plugins/           16 plugins — optional gameplay
├── derma/             VGUI panels
└── scoreboard/
entities/
├── entities/          8 SENTs (cider_item, cider_padlock, printers, drug labs…)
├── weapons/           17 SWEPs on a shared rg_base
└── effects/           9 muzzle-flash / shell-eject effects

The three largest files — init.lua, cl_init.lua, sv_commands.lua — are classic God files. Between them they hold the game loop, damage model, spawn logic, HUD, and every command. Splitting these is the single biggest structural change in the rewrite.


6. What is worth taking

To be explicit, because the temptation runs the other way:

Take: the tuning values, the gameplay rules, the command vocabulary, the job hierarchy, the door/access model as a concept, the negative-size pocket mechanic, the log category taxonomy, the realm-declaration discipline.

Leave: every line of implementation. All of it.