Skip to content

These docs were made completely by AI, so they might be right, or wrong, you'll need to test them yourself. This was made for a easier understanding of everything. So use at your own risk. If anything is wrong, please don't hurt to make a PR on the page you have a problem with. ON GITHUB

Custom GameRules

Legacy Console Edition has two separate “game rules” systems that can trip you up if you’re not aware of them. This page covers both and shows you how to add your own.

There are actually two different things called “game rules” in the codebase:

  1. Vanilla GameRules (GameRules in Minecraft.World) - The original Mojang system for things like doFireTick, keepInventory, etc. On console, 4J mostly gutted this and routed it through the host options system instead.

  2. Console GameRules (GameRuleManager + GameRuleDefinition in Minecraft.Client) - 4J’s custom system for tutorial objectives, mashup pack world generation, schematic placement, and DLC content. This is the one that handles things like “place a schematic at chunk X,Z” or “give the player an item when they use a tile.”

Most modders will care about the first one. The second one is more relevant if you’re building custom maps or tutorials.

4J replaced Mojang’s string-based GameRules with a bitmask stored in the app’s host options. The original GameRules class still exists but just redirects to the host options system:

// GameRules.cpp - the getBoolean() method just calls through to host options
bool GameRules::getBoolean(const int rule)
{
switch(rule)
{
case GameRules::RULE_DOFIRETICK:
return app.GetGameHostOption(eGameHostOption_FireSpreads);
case GameRules::RULE_MOBGRIEFING:
return app.GetGameHostOption(eGameHostOption_MobGriefing);
case GameRules::RULE_KEEPINVENTORY:
return app.GetGameHostOption(eGameHostOption_KeepInventory);
case GameRules::RULE_DOMOBSPAWNING:
return app.GetGameHostOption(eGameHostOption_DoMobSpawning);
case GameRules::RULE_DOMOBLOOT:
return app.GetGameHostOption(eGameHostOption_DoMobLoot);
case GameRules::RULE_DOTILEDROPS:
return app.GetGameHostOption(eGameHostOption_DoTileDrops);
case GameRules::RULE_NATURAL_REGENERATION:
return app.GetGameHostOption(eGameHostOption_NaturalRegeneration);
case GameRules::RULE_DAYLIGHT:
return app.GetGameHostOption(eGameHostOption_DoDaylightCycle);
default:
assert(0);
return false;
}
}

The built-in rule constants are defined in GameRules.h:

ConstantIDHost OptionWhat it does
RULE_DOFIRETICK0eGameHostOption_FireSpreadsFire spreads to nearby blocks
RULE_MOBGRIEFING1eGameHostOption_MobGriefingMobs can destroy blocks (creeper explosions, enderman stealing blocks, etc.)
RULE_KEEPINVENTORY2eGameHostOption_KeepInventoryItems stay in your inventory on death
RULE_DOMOBSPAWNING3eGameHostOption_DoMobSpawningMobs spawn naturally in the world
RULE_DOMOBLOOT4eGameHostOption_DoMobLootMobs drop items when killed
RULE_DOTILEDROPS5eGameHostOption_DoTileDropsBlocks drop items when broken
RULE_NATURAL_REGENERATION7eGameHostOption_NaturalRegenerationHealth regenerates from having full hunger
RULE_DAYLIGHT8eGameHostOption_DoDaylightCycleDay/night cycle progresses

Note that ID 6 (RULE_COMMANDBLOCKOUTPUT) is commented out in the source. It was removed from the console version since there are no command blocks.

LCE is missing a bunch of game rules that Java Edition has. There is no doWeatherCycle, no sendCommandFeedback, no showDeathMessages (though death messages are controlled by eGameSetting_DeathMessages as a client setting), no reducedDebugInfo, and no commandBlockOutput. Most of these make sense because the console version doesn’t have the text command system at all.

The host options enum in App_enums.h contains way more than just game rules. Here is every host option:

Enum ValueWhat it does
eGameHostOption_DifficultyWorld difficulty (Peaceful/Easy/Normal/Hard)
eGameHostOption_OnlineGameUnused placeholder
eGameHostOption_InviteOnlyUnused placeholder
eGameHostOption_FriendsOfFriendsAllow friends of friends to join
eGameHostOption_GamertagsShow gamertags above players
eGameHostOption_TutorialEnable tutorial mode (special case)
eGameHostOption_GameTypeSurvival, Creative, or Adventure
eGameHostOption_LevelTypeFlat or Default terrain
eGameHostOption_StructuresGenerate structures (villages, temples, etc.)
eGameHostOption_BonusChestSpawn a bonus chest near the player
eGameHostOption_HasBeenInCreativeTracks if the world was ever in Creative
eGameHostOption_PvPPlayers can damage each other
eGameHostOption_TrustPlayersTrusted players can build/break
eGameHostOption_TNTTNT explosions are enabled
eGameHostOption_FireSpreadsFire spreads to nearby blocks
eGameHostOption_CheatsEnabledHost privileges are on (special case)
eGameHostOption_HostCanFlyHost can fly in survival
eGameHostOption_HostCanChangeHungerHost is immune to hunger
eGameHostOption_HostCanBeInvisibleHost is invisible to other players
eGameHostOption_BedrockFogShow fog near bedrock level
eGameHostOption_NoHUDHide the HUD
eGameHostOption_AllSpecial value: returns all options packed into one int
eGameHostOption_DisableSavingPrevents the world from saving

The eGameHostOption_All value is a special case. When you call GetGameHostOption(eGameHostOption_All), it packs every boolean option into a bitmask and returns the whole thing as a single integer. This is used for network sync so the server can send all options to clients in one packet.

Options are saved in the save data, so new options can only be added at the end of the enum. Adding one in the middle would break every existing save file.

Host options are saved as part of the world’s NBT data. The entire set of boolean options gets packed into a bitmask by GetGameHostOption(eGameHostOption_All) and stored in the save file. When the world loads, the bitmask gets unpacked back into individual options.

For network play, the host sends all options to joining clients using the same bitmask approach. The PendingConnection and GameNetworkManager classes handle syncing these during the join process.

To add a new game rule, you need to touch three places:

Step 1: Add the host option enum value in App_enums.h:

enum eGameHostOption
{
// ... existing options ...
eGameHostOption_DisableSaving,
// Add your new option here (MUST be at the end)
eGameHostOption_DoWeatherCycle,
};

Step 2: Add the rule constant in GameRules.h:

class GameRules
{
public:
// ... existing rules ...
static const int RULE_DAYLIGHT;
static const int RULE_DOWEATHERCYCLE; // new
// ...
};

And define it in GameRules.cpp:

const int GameRules::RULE_DOWEATHERCYCLE = 9;

Step 3: Wire it up in GameRules::getBoolean():

case GameRules::RULE_DOWEATHERCYCLE:
return app.GetGameHostOption(eGameHostOption_DoWeatherCycle);

Step 4 (optional): Add a UI checkbox so players can toggle it from the host options menu. Look at UIScene_InGameHostOptionsMenu.cpp for how the existing toggles work. The pattern is:

// In the init function
m_checkboxDoWeatherCycle.init(
app.GetString(IDS_WEATHER_CYCLE),
eControl_DoWeatherCycle,
app.GetGameHostOption(eGameHostOption_DoWeatherCycle) != 0
);
// In the apply function
app.SetGameHostOption(
hostOptions,
eGameHostOption_DoWeatherCycle,
m_checkboxDoWeatherCycle.IsChecked()
);

When you need to check a game rule from gameplay code, you can either go through the GameRules class or call the host option directly:

// Through GameRules (preferred - goes through the level)
Level *level = /* your level pointer */;
if (level->getLevelData()->getGameRules()->getBoolean(GameRules::RULE_DOFIRETICK))
{
// fire can spread
}
// Or directly from the app (works anywhere)
if (app.GetGameHostOption(eGameHostOption_FireSpreads))
{
// fire can spread
}

The GameRules approach is better for gameplay code because it goes through the level, which means it works correctly in multiplayer. The direct app.GetGameHostOption() approach is fine for UI code or anything running on the host.

This is the more complex system. It’s used for mashup packs, tutorials, and DLC content. It handles things like:

  • Placing schematics during world generation
  • Generating custom structures at specific coordinates
  • Overriding biomes in certain areas
  • Tracking player progress (collect an item, use a tile, etc.)
  • Adding items to containers or spawners
  • Adding enchantments to placed items

The types are defined in ConsoleGameRulesConstants.h:

enum EGameRuleType
{
eGameRuleType_Root = 0,
eGameRuleType_LevelGenerationOptions,
eGameRuleType_ApplySchematic,
eGameRuleType_GenerateStructure,
eGameRuleType_GenerateBox,
eGameRuleType_PlaceBlock,
eGameRuleType_PlaceContainer,
eGameRuleType_PlaceSpawner,
eGameRuleType_BiomeOverride,
eGameRuleType_StartFeature,
eGameRuleType_AddItem,
eGameRuleType_AddEnchantment,
eGameRuleType_LevelRules,
eGameRuleType_NamedArea,
eGameRuleType_UseTileRule,
eGameRuleType_CollectItemRule,
eGameRuleType_CompleteAllRule,
eGameRuleType_UpdatePlayerRule,
eGameRuleType_Count
};

Here’s what each type does:

TypeClassPurpose
RootGameRuleDefinitionTop-level container, holds child rules
LevelGenerationOptionsLevelGenerationOptionsControls world gen settings for mashup packs
ApplySchematicApplySchematicRuleDefinitionPlaces a schematic (.schem) file at a specific chunk position
GenerateStructureConsoleGenerateStructureGenerates a structure (village, stronghold, etc.) at specific coords
GenerateBoxXboxStructureActionGenerateBoxFills a box region with a specific block
PlaceBlockXboxStructureActionPlaceBlockPlaces a single block at exact coordinates
PlaceContainerXboxStructureActionPlaceContainerPlaces a container (chest, dispenser) with items inside
PlaceSpawnerXboxStructureActionPlaceSpawnerPlaces a mob spawner with a specific entity type
BiomeOverrideBiomeOverrideForces a region to use a specific biome
StartFeatureStartFeatureKicks off a multi-step feature (like a tutorial segment)
AddItemAddItemRuleDefinitionAdds an item to a container placed by PlaceContainer
AddEnchantmentAddEnchantmentRuleDefinitionAdds an enchantment to an item placed by AddItem
LevelRulesLevelRulesetContainer for runtime gameplay rules
NamedAreaNamedAreaRuleDefinitionDefines a named region for triggers
UseTileRuleUseTileRuleDefinitionTriggers when a player uses a specific block
CollectItemRuleCollectItemRuleDefinitionTriggers when a player picks up a specific item
CompleteAllRuleCompleteAllRuleDefinitionTriggers when all child rules are completed
UpdatePlayerRuleUpdatePlayerRuleDefinitionModifies player state (give item, change gamemode, etc.)

The GameRuleManager loads these from DLC packs (.pck files). Each rule is a tree of definitions with attributes and children. The system reads a compressed binary file format that contains a string table, schematic files, and serialized rule objects.

The loading flow looks like this:

  1. GameRuleManager::loadGameRules(DLCPack *) reads rule headers from the pack
  2. readRuleFile() decompresses and parses the binary data
  3. Rules are organized into LevelGenerationOptions (world gen) and LevelRuleset (gameplay rules)
  4. During chunk generation, processSchematics() applies any schematic placements

Console game rules form a tree. The root node contains LevelGenerationOptions and LevelRuleset as children. Each of those contains their own children. For example, a mashup pack’s rule tree might look like:

Root
├── LevelGenerationOptions
│ ├── ApplySchematic (chunk 0,0 - castle.schem)
│ ├── ApplySchematic (chunk 5,3 - village.schem)
│ ├── BiomeOverride (region: desert)
│ └── GenerateStructure (nether fortress)
└── LevelRuleset
├── NamedArea (spawn_zone)
├── UseTileRule (use crafting table)
│ └── UpdatePlayerRule (give diamond)
└── CompleteAllRule
├── CollectItemRule (get wood)
└── CollectItemRule (get stone)

When a player completes a rule (like collecting an item), the server sends an UpdateGameRuleProgressPacket to notify the client. This packet carries the rule ID and the new state. The client uses this to update the tutorial UI or track completion progress.

For most modding purposes, you won’t need to touch this system directly. But if you’re building custom tutorial levels or mashup packs, this is where that logic lives.

FileWhat it does
GameRules.h/.cppVanilla rule constants and host option routing
App_enums.hHost option enum definitions
ConsoleGameRulesConstants.hConsole GameRule type and attribute enums
GameRuleManager.h/.cppLoads/saves console game rules from DLC packs
GameRuleDefinition.h/.cppBase class for all console rule definitions
GameRule.h/.cppRuntime state for a single console rule instance
LevelRuleset.h/.cppContainer for active gameplay rules
LevelGenerationOptions.h/.cppContainer for world generation rules
ApplySchematicRuleDefinition.h/.cppPlaces schematics during world gen
BiomeOverride.h/.cppForces biome in a region
CollectItemRuleDefinition.h/.cppTriggers on item pickup
UseTileRuleDefinition.h/.cppTriggers on block use
CompleteAllRuleDefinition.h/.cppTriggers when all children complete
UpdatePlayerRuleDefinition.h/.cppModifies player state
UpdateGameRuleProgressPacket.h/.cppNetwork packet for rule progress
UIScene_InGameHostOptionsMenu.cppUI for toggling host options