A modern TypeScript-based behavior pack for Minecraft Bedrock Edition v1.21+ that demonstrates best practices in software architecture, featuring enhanced wolf mechanics, raid party management, and a dynamic recruitment system.
- TypeScript Support: Fully typed codebase with strict mode enabled
- i18n (Internationalization): Multi-language message system
- SOLID Principles: Architecture following Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion principles
- DRY (Don't Repeat Yourself): Centralized message management and initialization patterns
- Hybrid Testing: Unit tests (Vitest) for pure logic + GameTest for Minecraft-specific features
- Microsoft Best Practices: Follows official Minecraft scripting samples and recommendations
- Modern Build System: Separate dev/prod configurations - production builds require no Beta APIs
- just-scripts: Professional build tooling with watch mode, bundling, and packaging
- Wolf Leveling System: Tamed wolves gain experience and level up (1→2→3) by killing hostile mobs
- Progressive stat increases: HP, attack damage, and visual size scaling
- Level 1: 20 HP, 4 damage, 1.0x scale
- Level 2: 30 HP, 6 damage, 1.15x scale (at 5 kills)
- Level 3: 40 HP, 8 damage, 1.3x scale (at 15 kills)
- Persistent progression via dynamic properties
- Enhanced Guard Behavior: Tamed wolves follow more closely (8 blocks vs vanilla 10) and proactively attack nearby hostile mobs
- Player Book: Interactive UI for managing your raid party, viewing leaderboards, recruiting units, and managing your army
- Raid Camps: Dynamic raid camp system with rewards and challenges
- Recruitment System: Hire and manage units for your raid party using emeralds
- Unit Pocketing: Store and release units strategically during raids
Minecraft.Raiders/
├── behavior_packs/MinecraftRaiders/ # Behavior pack definition
│ ├── manifest.prod.json # Production manifest (no Beta APIs)
│ ├── manifest.dev.json # Development manifest (with GameTest)
│ ├── manifest.json # Generated (gitignored)
│ ├── entities/ # Entity definitions
│ │ └── wolf.json # Wolf leveling component groups
│ └── scripts/ # Compiled JavaScript output
├── resource_packs/MinecraftRaiders/ # Resource pack definition
│ ├── manifest.json # Pack metadata
│ └── texts/
│ └── en_US.lang # Localization strings
├── scripts/ # TypeScript source code
│ ├── core/
│ │ ├── initialization/ # Pack initialization system
│ │ │ ├── IInitializer.ts
│ │ │ ├── WelcomeInitializer.ts
│ │ │ ├── PlayerBookInitializer.ts
│ │ │ ├── WolfLevelingInitializer.ts
│ │ │ ├── ResourceInitializer.ts
│ │ │ ├── RecruitmentInitializer.ts
│ │ │ ├── RaidCampInitializer.ts
│ │ │ └── CompassInitializer.ts
│ │ ├── messaging/ # i18n message system
│ │ │ ├── IMessageProvider.ts
│ │ │ ├── MessageProvider.ts
│ │ │ └── MessageProvider.test.ts # Unit tests (Vitest)
│ │ └── features/ # Feature implementations
│ │ ├── PlayerBookService.ts
│ │ ├── WolfLevelingService.ts
│ │ ├── ResourceService.ts
│ │ ├── RecruitmentService.ts
│ │ └── raidcamp/ # Raid camp subsystem
│ ├── gametests/ # In-game GameTest tests
│ │ ├── WelcomeGameTest.ts
│ │ ├── MessageProviderGameTest.ts
│ │ ├── WolfLevelingGameTest.ts
│ │ ├── RaidPartyGameTest.ts
│ │ └── RecruitmentGameTest.ts
│ ├── main.ts # Production entry point
│ └── main-dev.ts # Development entry point (with GameTest)
├── test/ # Test infrastructure
│ └── setup/ # Test configuration
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── just.config.ts # Build configuration
├── vitest.config.ts # Vitest configuration
├── eslint.config.mjs # Linting configuration
├── TESTING.md # Testing guide
└── README.md # This file
-
Single Responsibility: Each class has one reason to change
MessageProvider: Only manages messagesWelcomeInitializer: Only handles welcome logicWolfLevelingService: Only manages wolf progressionPlayerBookService: Only handles book UI presentation
-
Open/Closed: Open for extension, closed for modification
- New initializers can be added without modifying existing code
- Message system can be extended with new providers
- New unit types added without changing recruitment logic
-
Liskov Substitution: Derived classes are substitutable
- Any
IInitializercan be used interchangeably
- Any
-
Interface Segregation: Clients depend on focused interfaces
IMessageProvider: Message operations onlyIInitializer: Initialization operations onlyIPlayerBookService: UI operations onlyIWolfLevelingService: Wolf progression only
-
Dependency Inversion: Depend on abstractions, not concretions
WelcomeInitializerdepends onIMessageProviderinterfacePlayerBookServicedepends on multiple service interfaces- Main orchestrates dependencies via composition
- Centralized Messages: All messages defined in
MessageProvideranden_US.lang - Reusable Patterns: Initializer pattern allows extensibility
- No Duplication: Single source of truth for each feature
- Service Layer: Shared services (resources, recruitment) used across features
This project uses separate build configurations for development and production:
Development Mode (npm run local-deploy):
- Entry point:
main-dev.ts(includes GameTest imports) - Manifest:
manifest.dev.json(includes GameTest dependency) - Requires Beta APIs (for testing only)
Production Mode (npm run mcaddon):
- Entry point:
main.ts(excludes GameTest imports) - Manifest:
manifest.prod.json(no GameTest dependency) - No Beta APIs required ✅
The manifest.json file is auto-generated during builds and gitignored.
This project follows Microsoft's recommended testing approach for Minecraft Bedrock scripts, combining unit tests for pure logic with in-game GameTest validation.
- Unit Tests (Vitest) - Pure TypeScript logic and utilities
- GameTest Framework - In-game integration tests for Minecraft-specific features (development only)
- Manual Testing - User experience validation with
npm run local-deploy
See TESTING.md for comprehensive testing guide including:
- Build system overview
- Development workflow
- Unit test examples
- GameTest examples (wolf leveling, recruitment, raid camps)
- Manual testing procedures
- Release process
- Troubleshooting
- Node.js 16+
- npm or yarn
- Minecraft Bedrock Edition 1.21+
cd Minecraft.Raiders
npm install# Development workflow
npm run build # Build production version (no GameTest)
npm run build:dev # Build development version (with GameTest)
npm run local-deploy # Watch mode - auto-rebuild dev version and deploy on changes
npm run test # Run unit tests (Vitest) once
npm run test:watch # Run tests in watch mode
npm run test:ui # Open interactive test UI dashboard
npm run lint # Lint TypeScript code
npm run lint --fix # Auto-fix linting issues
npm run clean # Clean build artifacts
# Distribution
npm run mcaddon # Create .mcaddon package (production, no Beta APIs required)For Development:
npm install
npm run local-deploy
# In Minecraft: Enable GameTest Framework experiment, load world with "Minecraft Raiders (Dev)" packFor Distribution:
npm install
npm run mcaddon
# Share dist/packages/MinecraftRaiders.mcaddon - no Beta APIs required!See TESTING.md for complete testing guide.
# Unit Tests
npm run test # Run all unit tests once
npm run test:watch # Run tests in watch mode
npm run test:ui # Open interactive test UI dashboard
# GameTest (in-game, development only)
npm run local-deploy # Deploy dev version
# In Minecraft: /gametest runset batch
# Manual testing (rapid iteration)
npm run local-deploy # Deploy with auto-rebuild on changes// Good: Dependencies injected through constructor
const wolfLevelingService = new WolfLevelingService(messageProvider);
const playerBookService = new PlayerBookService(
messageProvider,
resourceService,
recruitmentService,
unitPocketService,
wealthCalculationService
);
// Allows easy testing and swapping implementations// All dependencies created and wired in one place (main.ts)
const messageProvider = new MessageProvider();
const resourceService = new ResourceService();
const recruitmentService = new RecruitmentService(resourceService, messageProvider);
const wolfLevelingService = new WolfLevelingService(messageProvider);
const initializers: IInitializer[] = [
new WelcomeInitializer(messageProvider),
new ResourceInitializer(resourceService, messageProvider),
new PlayerBookInitializer(playerBookService),
new WolfLevelingInitializer(wolfLevelingService),
new RecruitmentInitializer(recruitmentService),
new RaidCampInitializer(raidCampService),
new CompassInitializer(compassNavigationService, messageProvider, raidCampUIService),
];// Focused interfaces for specific concerns
interface IMessageProvider { ... }
interface IInitializer { ... }
interface IPlayerBookService { ... }
interface IWolfLevelingService { ... }
interface IResourceService { ... }// scripts/core/initialization/MyFeatureInitializer.ts
import { IInitializer } from "./IInitializer";
export class MyFeatureInitializer implements IInitializer {
constructor(private readonly myService: IMyService) {}
initialize(): void {
// Your initialization logic
world.afterEvents.playerSpawn.subscribe((event) => {
this.myService.doSomething(event.player);
});
}
}// scripts/main.ts
const myService = new MyService(messageProvider);
const initializers: IInitializer[] = [
new WelcomeInitializer(messageProvider),
new MyFeatureInitializer(myService), // Add here
];For pure logic (utility functions, message formatting, calculations):
// scripts/core/utilities/myUtils.test.ts
import { describe, it, expect } from "vitest";
import { myFunction } from "./myUtils";
describe("myFunction", () => {
it("should format correctly", () => {
expect(myFunction(input)).toBe(expected);
});
});For Minecraft features (entity interactions, world changes, UI):
// scripts/gametests/MyFeatureGameTest.ts
import * as gametest from "@minecraft/server-gametest";
export function myFeatureTest(test: gametest.Test) {
// Your in-game test logic
test.assert(condition, "Error message");
test.succeed();
}
gametest.register("MinecraftRaiders", "myFeature", myFeatureTest)
.structureName("MinecraftRaiders:simple")
.tag("suite:default")
.tag("batch");Then import in main-dev.ts (development entry point):
// scripts/main-dev.ts
import "./main"; // Import production code
import "./gametests/MyFeatureGameTest"; // Add GameTest import hereImportant: GameTests are only included in development builds. Production builds (npm run mcaddon) exclude GameTest files to avoid requiring Beta APIs.
Add messages to MessageProvider:
// scripts/core/messaging/MessageProvider.ts
private readonly messages: Record<string, string> = {
"my.custom.message": "My custom message",
// ...
};Also add to resource pack:
# resource_packs/MinecraftRaiders/texts/en_US.lang
my.custom.message=My custom message
Retrieve messages:
const message = messageProvider.getMessage("my.custom.message");
const withFallback = messageProvider.getMessage("missing.key", "Fallback text");- Target: ES6
- Module: ES2020
- Strict Mode: Enabled
- Source Maps: Enabled for debugging
- No Unused Variables: Enforced
@minecraft/server^2.0.0 - Minecraft Bedrock API@minecraft/server-ui^2.0.0 - UI framework for forms and dialogs@minecraft/vanilla-data^1.21.90 - Vanilla data types
Note: @minecraft/server-gametest is NOT a runtime dependency. It's only used during development and excluded from production builds.
typescript^5.5.4 - TypeScript compiler@minecraft/core-build-tasks^5.5.0 - Build system (just-scripts)@minecraft/server-gametest1.0.0-beta - GameTest framework (dev only)eslint-plugin-minecraft-linting^2.0.10 - Linting rulesvitest^2.1.0 - Unit test runner@vitest/ui^2.1.0 - Interactive test UI
Tamed wolves gain experience and level up by killing hostile mobs:
| Level | HP | Attack | Scale | Kills Required |
|---|---|---|---|---|
| 1 | 20 | 4 | 1.0x | 0 (base) |
| 2 | 30 | 6 | 1.15x | 5 |
| 3 | 40 | 8 | 1.3x | 15 |
- Visual Growth: Wolves visibly grow larger at each level
- Persistent Progress: Kill counts and levels persist across world reloads
- Owner Notifications: Players receive chat messages when their wolves level up
- Hostile Mobs Only: Only kills of hostile mobs (zombies, skeletons, etc.) count toward progression
- Baby Wolves: Bred wolves start at Level 1 and can progress normally
See TESTING.md - Manual Wolf Leveling Testing for complete test procedures.
Quick test:
# Tame a wolf
/summon wolf
# Spawn 5 hostile mobs for Level 2
/summon zombie
/summon skeleton
/summon creeper
/summon spider
/summon zombie
# Spawn 10 more for Level 3
# Wolf will level up automatically when kill thresholds are reachedWhen contributing, maintain the established patterns:
- Follow SOLID principles
- Write appropriate tests (see TESTING.md):
- Unit tests (Vitest) for pure logic
- GameTest for Minecraft-specific features (import in
main-dev.ts)
- Use dependency injection
- Keep interfaces focused
- Avoid code duplication
- Run
npm run lintbefore committing - Ensure
npm testpasses - Test GameTests in-game with
/gametest runset batch
npm run lint --fix # Fix linting issues
npm test # Run unit tests
npm run build # Verify production build works
npm run local-deploy # Test in Minecraft with dev build
# In Minecraft: /gametest runset batch
npm run mcaddon # Build production packageThis project is provided as-is for educational purposes.
- TESTING.md - Comprehensive testing guide (build system, unit tests, GameTest, manual testing, release process)