Untitled

 avatar
unknown
typescript
10 days ago
5.6 kB
2
Indexable
import { Service, OnStart } from "@flamework/core";
import { Players, ReplicatedStorage, Workspace } from "@rbxts/services";
import { Events } from "server/network";
import { PlayerDataService } from "./PlayerDataService";

/**
 * Simplified CandyService - handles candy clicking mechanics and spawning
 */
@Service()
export class CandyService implements OnStart {
	private playerCandyModels = new Map<Player, Model>();

	constructor(private readonly playerDataService: PlayerDataService) {}

	onStart(): void {
		// Handle player connections
		Players.PlayerAdded.Connect((player) => {
			this.onPlayerAdded(player);
		});

		Players.PlayerRemoving.Connect((player) => {
			this.onPlayerRemoving(player);
		});

		// Handle existing players
		for (const player of Players.GetPlayers()) {
			this.onPlayerAdded(player);
		}

		Events.candyClicked.connect((player) => {
			this.processCandyClick(player, 1);
		});
	}

	/**
	 * Handle player joining - spawn their candy
	 */
	private onPlayerAdded(player: Player): void {
		// Wait a bit for player data to load
		task.wait(2);
		const playerData = this.playerDataService.getPlayerData(player);
		if (playerData) {
			this.spawnCandyForPlayer(player, playerData.candyState.currentLevel);
		}
	}

	/**
	 * Handle player leaving - cleanup their candy
	 */
	private onPlayerRemoving(player: Player): void {
		const candyModel = this.playerCandyModels.get(player);
		if (candyModel) {
			candyModel.Destroy();
			this.playerCandyModels.delete(player);
		}
	}

	/**
	 * Spawn candy model for player from Assets or create a basic one
	 */
	private spawnCandyForPlayer(player: Player, candyLevel: number): void {
		// Clean up existing candy first
		const existingCandy = this.playerCandyModels.get(player);
		if (existingCandy) {
			existingCandy.Destroy();
		}

		let candyModel: Model;

		// Try to find Assets folder in ReplicatedStorage
		const assetsFolder = ReplicatedStorage.FindFirstChild("Assets") as Folder;
		if (assetsFolder) {
			// Find candy model for current level
			const candyModelName = `Candy_Level_${candyLevel}`;
			const candyTemplate = assetsFolder.FindFirstChild(candyModelName) as Model;
			if (candyTemplate) {
				// Clone from assets
				candyModel = candyTemplate.Clone();
				print(`Spawned ${candyModelName} from Assets for ${player.Name}`);
			} else {
				// Create basic candy if asset not found
				candyModel = this.createBasicCandy(candyLevel);
				print(`Created basic candy (level ${candyLevel}) for ${player.Name} - Asset not found`);
			}
		} else {
			// Create basic candy if Assets folder doesn't exist
			candyModel = this.createBasicCandy(candyLevel);
			print(`Created basic candy (level ${candyLevel}) for ${player.Name} - No Assets folder`);
		}

		// Configure the model
		candyModel.Name = `${player.Name}_Candy`;
		candyModel.Parent = Workspace;

		// Position the candy
		if (candyModel.PrimaryPart) {
			candyModel.PrimaryPart.Position = new Vector3(0, 10, 0);
		} else {
			// If no PrimaryPart, position the first part
			const firstPart = candyModel.FindFirstChildOfClass("BasePart") as BasePart;
			if (firstPart) {
				firstPart.Position = new Vector3(0, 10, 0);
			}
		}

		// Set up click detection
		this.setupClickDetection(player, candyModel);

		// Store reference
		this.playerCandyModels.set(player, candyModel);
	}

	/**
	 * Create a basic candy model for testing
	 */
	private createBasicCandy(candyLevel: number): Model {
		// Create model
		const candyModel = new Instance("Model");
		candyModel.Name = `Candy_Level_${candyLevel}`;

		// Create main candy part
		const candyPart = new Instance("Part");
		candyPart.Name = "CandyPart";
		candyPart.Size = new Vector3(4, 4, 4);
		candyPart.Shape = Enum.PartType.Ball;
		candyPart.Material = Enum.Material.Neon;
		candyPart.BrickColor = BrickColor.Red();
		candyPart.CanCollide = false;
		candyPart.Anchored = true;
		candyPart.Parent = candyModel;

		// Set as PrimaryPart
		candyModel.PrimaryPart = candyPart;

		// Create ClickDetector
		const clickDetector = new Instance("ClickDetector");
		clickDetector.MaxActivationDistance = 50;
		clickDetector.Parent = candyPart;

		return candyModel;
	}

	/**
	 * Set up click detection for candy model
	 */
	private setupClickDetection(player: Player, candyModel: Model): void {
		// Find ClickDetector in the model
		const clickDetector = candyModel.FindFirstChildOfClass("ClickDetector");
		if (!clickDetector) {
			warn(`No ClickDetector found in ${candyModel.Name}`);
			return;
		}

		// Connect click event
		clickDetector.MouseClick.Connect((clickingPlayer) => {
			if (clickingPlayer === player) {
				this.processCandyClick(player, 1);
			}
		});
	}

	/**
	 * Process a candy click from a player
	 */
	private processCandyClick(player: Player, clickCount: number): void {
		this.playerDataService.updatePlayerData(player, (data) => {
			// Simple click processing - add points and increment clicks
			const pointsEarned = clickCount * data.prestige.permanentMultiplier;
			data.candyPoints += pointsEarned;
			data.totalCandyPoints += pointsEarned;
			data.totalClicks += clickCount;
			data.candyState.clicksOnCurrentCandy += clickCount;
			data.candyState.lastClickTime = tick();

			// Send update to client
			Events.candyStateUpdated(player, data.candyState);
			print(`${player.Name} clicked candy! Points earned: ${pointsEarned}`);
			return pointsEarned;
		});
	}
}
Editor is loading...
Leave a Comment