Files
novafarma/SYSTEMS_INTEGRATION_GUIDE.md

14 KiB

🔌 SYSTEMS INTEGRATION GUIDE

Created: January 4, 2026
Purpose: How to integrate new game systems into Phaser 3


📦 INITIALIZED SYSTEMS

Sleep System Integration

1. Import & Initialize:

// In GameScene.js or MainGameScene.js
import SleepSystem from '../systems/SleepSystem.js';

create() {
    // Initialize sleep system
    this.sleepSystem = new SleepSystem(this);
    
    // Register with game state
    this.game.registry.set('sleepSystem', this.sleepSystem);
}

2. Hook into Player Interaction:

// When player interacts with bed
onBedInteraction(bedSprite) {
    const bedInfo = this.sleepSystem.getCurrentBedInfo();
    
    // Show sleep UI
    this.showSleepMenu({
        bedName: bedInfo.name,
        energyRegen: bedInfo.energyRegen,
        canSleep: bedInfo.canSleep
    });
}

// When player clicks "Sleep" button
onSleepButtonClick() {
    const result = this.sleepSystem.sleep();
    
    if (result.success) {
        // Hide UI
        this.hideSleepMenu();
        
        // Play sleep animation/fade
        this.cameras.main.fadeOut(1000, 0, 0, 0);
        
        // Wait for sleep to complete
        this.sleepSystem.on('wakeUp', (data) => {
            this.cameras.main.fadeIn(1000);
            this.showMessage(`Good morning! +${data.energyRestored} Energy`);
        });
    } else {
        this.showMessage(result.message);
    }
}

3. Bed Purchase Integration:

onBedShopInteraction() {
    const beds = this.sleepSystem.bedTypes;
    
    // Show shop UI with available beds
    this.showBedShop(beds);
}

onPurchaseBed(bedType) {
    const result = this.sleepSystem.purchaseBed(bedType);
    
    if (result.success) {
        this.showMessage(result.message);
        
        // Trigger furniture placement (drag-and-drop)
        this.startFurniturePlacement(bedType);
    } else {
        this.showMessage(result.message);
    }
}

4. Update Loop:

update(time, delta) {
    // Sleep system doesn't need frequent updates
    // (handled by events and timers)
}

Crafting Tables Integration

1. Import & Initialize:

import CraftingTablesSystem from '../systems/CraftingTablesSystem.js';

create() {
    this.craftingSystem = new CraftingTablesSystem(this);
    this.game.registry.set('craftingSystem', this.craftingSystem);
}

2. Hook into Crafting Table Interaction:

onCraftingTableInteraction(tableSprite) {
    const uiData = this.craftingSystem.getCraftingUIData();
    
    // Show crafting menu
    this.showCraftingMenu({
        currentTable: uiData.currentTable,
        recipes: uiData.availableRecipes,
        isCrafting: uiData.isCrafting,
        currentCraft: uiData.currentCraft
    });
}

3. Recipe Selection:

onRecipeClick(recipeId) {
    const canCraft = this.craftingSystem.canCraft(recipeId);
    
    if (canCraft.canCraft) {
        // Show craft confirmation
        this.showCraftConfirmation(recipeId);
    } else {
        // Show why can't craft
        if (canCraft.missingIngredients) {
            this.showMissingIngredients(canCraft.missingIngredients);
        } else {
            this.showMessage(canCraft.reason);
        }
    }
}

onConfirmCraft(recipeId, quantity) {
    const result = this.craftingSystem.craft(recipeId, quantity);
    
    if (result.success) {
        this.showMessage(result.message);
        
        // Show crafting progress bar
        this.showCraftingProgress(result.craftJob);
    } else {
        this.showMessage(result.message);
    }
}

4. Crafting Progress UI:

update(time, delta) {
    // Update crafting system
    this.craftingSystem.update(delta / 1000); // Convert ms to seconds
    
    // Update crafting progress bar
    if (this.craftingSystem.currentCraft) {
        const progress = 1 - (this.craftingSystem.currentCraft.timeRemaining / 
                              this.craftingSystem.currentCraft.totalTime);
        this.updateCraftingProgressBar(progress);
    }
}

// Listen for crafting events
create() {
    this.craftingSystem.game.on('craftingStarted', (data) => {
        this.showMessage(`Crafting ${data.quantity}x ${data.recipe.name}...`);
    });
    
    this.craftingSystem.game.on('craftingCompleted', (data) => {
        this.playSound('craft_complete');
        this.showItemGain(data.recipe.output.item, data.quantity);
    });
}

5. Large Table Purchase:

onLargeTableShopInteraction() {
    const largeTable = this.craftingSystem.tables.LARGE;
    
    if (largeTable.unlocked) {
        this.showMessage('You already own the Large Planning Table!');
    } else {
        this.showPurchaseConfirmation({
            item: 'Large Planning Table',
            cost: largeTable.cost,
            requirements: largeTable.requirements
        });
    }
}

onConfirmLargeTablePurchase() {
    const result = this.craftingSystem.purchaseLargeTable();
    
    if (result.success) {
        this.showMessage(result.message);
        this.startFurniturePlacement('large_table');
    } else {
        this.showMessage(result.message);
    }
}

Bakery Shop Integration

1. Import & Initialize:

import BakeryShopSystem from '../systems/BakeryShopSystem.js';

create() {
    this.bakerySystem = new BakeryShopSystem(this);
    this.game.registry.set('bakerySystem', this.bakerySystem);
    
    // Check if bakery should be unlocked (from save file)
    if (this.player.ownedBuildings.includes('bakery')) {
        this.bakerySystem.isUnlocked = true;
        this.bakerySystem.isOpen = true;
    }
}

2. Bakery Entrance Interaction:

onBakeryEnterInteraction() {
    // Check if unlocked
    if (!this.bakerySystem.isUnlocked) {
        this.showBuildingUnlockUI('bakery');
        return;
    }
    
    // Check if open
    if (!this.bakerySystem.isOpen) {
        const hours = this.bakerySystem.getShopUIData().openingHours;
        this.showMessage(`Bakery is closed. Open: ${hours}`);
        return;
    }
    
    // Enter bakery
    this.scene.start('BakeryInteriorScene');
}

3. Bakery Interior Scene:

// BakeryInteriorScene.js
import Phaser from 'phaser';

export default class BakeryInteriorScene extends Phaser.Scene {
    constructor() {
        super({ key: 'BakeryInteriorScene' });
    }
    
    create() {
        // Load interior tilemap
        this.map = this.make.tilemap({ key: 'bakery_interior' });
        
        // Get bakery system
        this.bakerySystem = this.game.registry.get('bakerySystem');
        
        // Show shop UI
        this.showShopUI();
        
        // Baker NPC
        this.baker = this.add.sprite(200, 150, 'npc_baker');
        this.baker.setInteractive();
        this.baker.on('pointerdown', () => this.talkToBaker());
    }
    
    showShopUI() {
        const shopData = this.bakerySystem.getShopUIData();
        
        // Create shop menu
        this.shopMenu = this.add.container(400, 300);
        
        // Display inventory items
        Object.values(shopData.inventory).forEach((item, index) => {
            const itemButton = this.createShopItem(item, index);
            this.shopMenu.add(itemButton);
        });
    }
    
    createShopItem(item, index) {
        const y = index * 60;
        
        const button = this.add.container(0, y);
        
        // Item name
        const nameText = this.add.text(0, 0, item.name, {
            fontSize: '18px',
            color: '#ffffff'
        });
        
        // Price
        const priceText = this.add.text(200, 0, `${item.price}g`, {
            fontSize: '16px',
            color: '#ffdd00'
        });
        
        // Stock
        const stockText = this.add.text(300, 0, `Stock: ${item.stock}`, {
            fontSize: '14px',
            color: '#aaaaaa'
        });
        
        button.add([nameText, priceText, stockText]);
        button.setInteractive(new Phaser.Geom.Rectangle(0, 0, 400, 50), Phaser.Geom.Rectangle.Contains);
        button.on('pointerdown', () => this.onBuyItem(item.id));
        
        return button;
    }
    
    onBuyItem(itemId) {
        // Show quantity selector
        this.showQuantitySelector(itemId, (quantity) => {
            const result = this.bakerySystem.buyItem(itemId, quantity);
            
            if (result.success) {
                this.playSound('purchase');
                this.refreshShopUI();
                this.showMessage(`Purchased! ${result.totalPrice}g`);
            } else {
                this.showMessage(result.message);
            }
        });
    }
    
    talkToBaker() {
        const baker = this.bakerySystem.baker;
        const dialogueOptions = baker.dialogue;
        
        // Random greeting
        const greeting = Phaser.Utils.Array.GetRandom(dialogueOptions.greeting);
        
        this.showDialogue(baker.name, greeting, [
            {
                text: 'Buy items',
                action: () => this.showShopUI()
            },
            {
                text: 'Order birthday cake',
                action: () => this.showBirthdayCakeMenu()
            },
            {
                text: 'About baking competition',
                action: () => this.showCompetitionInfo()
            },
            {
                text: 'Leave',
                action: () => this.scene.start('TownSquareScene')
            }
        ]);
    }
}

4. Gift System Integration:

onGiftItemToNPC(itemId, npcId) {
    // Check if item is from bakery
    const bakeryItem = this.bakerySystem.inventory[itemId];
    
    if (bakeryItem) {
        const result = this.bakerySystem.giftItem(itemId, npcId);
        
        if (result.success) {
            this.showNPCReaction(npcId, result.reaction);
            this.playHeartAnimation(npcId, result.heartsAdded);
        }
    }
}

5. Time-based Updates:

// In main game loop
update(time, delta) {
    // Check if hour has changed
    if (this.timeSystem.hasHourChanged()) {
        this.bakerySystem.update();
        
        // Check if bakery just opened/closed
        const bakeryData = this.bakerySystem.getShopUIData();
        if (bakeryData.isOpen !== this.lastBakeryState) {
            this.onBakeryStatusChange(bakeryData.isOpen);
            this.lastBakeryState = bakeryData.isOpen;
        }
    }
}

🎮 COMPLETE GAME INTEGRATION

Main Game Scene Setup:

// MainGameScene.js
import SleepSystem from '../systems/SleepSystem.js';
import CraftingTablesSystem from '../systems/CraftingTablesSystem.js';
import BakeryShopSystem from '../systems/BakeryShopSystem.js';

export default class MainGameScene extends Phaser.Scene {
    create() {
        // Initialize all systems
        this.sleepSystem = new SleepSystem(this);
        this.craftingSystem = new CraftingTablesSystem(this);
        this.bakerySystem = new BakeryShopSystem(this);
        
        // Register globally
        this.game.registry.set('sleepSystem', this.sleepSystem);
        this.game.registry.set('craftingSystem', this.craftingSystem);
        this.game.registry.set('bakerySystem', this.bakerySystem);
        
        // Set up event listeners
        this.setupSystemEvents();
    }
    
    setupSystemEvents() {
        // Sleep events
        this.sleepSystem.game.on('wakeUp', (data) => {
            this.onPlayerWakeUp(data);
        });
        
        // Crafting events
        this.craftingSystem.game.on('craftingCompleted', (data) => {
            this.onCraftingComplete(data);
        });
        
        // Bakery events (if needed)
        // ...
    }
    
    update(time, delta) {
        const deltaSeconds = delta / 1000;
        
        // Update systems
        this.sleepSystem.update(deltaSeconds);
        this.craftingSystem.update(deltaSeconds);
        this.bakerySystem.update();
    }
}

Save/Load Integration:

// Save game state
saveGame() {
    const saveData = {
        player: this.player.getSaveData(),
        sleepSystem: {
            playerBed: this.sleepSystem.playerBed,
            unlockedBeds: Object.values(this.sleepSystem.bedTypes)
                .filter(bed => bed.unlocked)
                .map(bed => bed.id)
        },
        craftingSystem: {
            currentTable: this.craftingSystem.currentTable.id,
            unlockedRecipes: this.craftingSystem.unlockedRecipes,
            largeTableUnlocked: this.craftingSystem.tables.LARGE.unlocked
        },
        bakerySystem: {
            isUnlocked: this.bakerySystem.isUnlocked,
            birthdayOrders: this.bakerySystem.birthdayCakeOrders
        }
    };
    
    localStorage.setItem('game_save', JSON.stringify(saveData));
}

// Load game state
loadGame() {
    const saveData = JSON.parse(localStorage.getItem('game_save'));
    
    if (saveData) {
        // Restore sleep system
        saveData.sleepSystem.unlockedBeds.forEach(bedId => {
            const bedType = Object.keys(this.sleepSystem.bedTypes)
                .find(key => this.sleepSystem.bedTypes[key].id === bedId);
            if (bedType) {
                this.sleepSystem.bedTypes[bedType].unlocked = true;
            }
        });
        
        // Restore crafting system
        this.craftingSystem.tables.LARGE.unlocked = saveData.craftingSystem.largeTableUnlocked;
        this.craftingSystem.unlockedRecipes = saveData.craftingSystem.unlockedRecipes;
        
        // Restore bakery system
        this.bakerySystem.isUnlocked = saveData.bakerySystem.isUnlocked;
        this.bakerySystem.birthdayCakeOrders = saveData.bakerySystem.birthdayOrders;
    }
}

Created: January 4, 2026
Status: Ready for implementation