Untitled

 avatar
unknown
typescript
10 days ago
3.7 kB
2
Indexable
/**
 * PlayerDataService - Simplified player data management using ProfileService
 */

import { Service, OnStart } from "@flamework/core";
import { Players } from "@rbxts/services";
import { PlayerData } from "shared/types";
import ProfileService from "@rbxts/profileservice";

const DEFAULT_PLAYER_DATA: PlayerData = {
	playerId: 0,
	username: "",
	candyPoints: 0,
	totalCandyPoints: 0,
	totalClicks: 0,
	candyState: {
		currentLevel: 1,
		clicksOnCurrentCandy: 0,
		lastClickTime: 0,
	},
	upgrades: [],
	// Pet system and boosters removed for simplification
	prestige: {
		prestigeLevel: 0,
		permanentMultiplier: 1,
	},

	settings: {
		musicEnabled: true,
		sfxEnabled: true,
		notificationsEnabled: true,
		autoSaveEnabled: true,
	},
	stats: {
		totalUpgradesPurchased: 0,
		playtimeSeconds: 0,
		lastLogin: 0,
		createdAt: 0,
	},
};

@Service()
export class PlayerDataService implements OnStart {
	private profileStore = ProfileService.GetProfileStore("PlayerData2", DEFAULT_PLAYER_DATA);
	private profiles = new Map<Player, PlayerData>();
	private loadedPlayers = new Set<Player>();

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

		// Handle player leaving
		Players.PlayerRemoving.Connect((player) => {
			this.unloadPlayerData(player);
		});

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

	/**
	 * Load player data from ProfileService
	 */
	private loadPlayerData(player: Player): void {
		const profileKey = `Player_${player.UserId}`;

		const profile = this.profileStore.LoadProfileAsync(profileKey);

		if (profile !== undefined) {
			profile.AddUserId(player.UserId);
			profile.Reconcile();

			// Handle profile release (player leaves while profile is loading)
			profile.ListenToRelease(() => {
				this.profiles.delete(player);
				this.loadedPlayers.delete(player);
				player.Kick("Profile released. Please rejoin.");
			});

			// Check if player is still in game
			if (player.Parent === Players) {
				this.profiles.set(player, profile.Data);

				// Initialize player data if needed
				const data = profile.Data as PlayerData;
				data.playerId = player.UserId;
				data.username = player.Name;

				// Calculate offline progress

				this.loadedPlayers.add(player);

				print(`[PlayerDataService] Loaded data for ${player.Name}`);
			} else {
				// Player left before profile loaded
				profile.Release();
			}
		} else {
			// Profile couldn't be loaded
			player.Kick("Unable to load your data. Please try again later.");
			warn(`[PlayerDataService] Failed to load profile for ${player.Name}`);
		}
	}

	/**
	 * Unload player data and release profile
	 */
	private unloadPlayerData(player: Player): void {
		const profile = this.profiles.get(player);
		if (profile !== undefined) {
			this.profiles.delete(player);
			this.loadedPlayers.delete(player);
			print(`[PlayerDataService] Released data for ${player.Name}`);
		}
	}

	/**
	 * Get player data
	 */
	getPlayerData(player: Player): PlayerData | undefined {
		return this.profiles.get(player);
	}

	/**
	 * Update player data with a callback function
	 */
	updatePlayerData<T>(player: Player, updateFn: (data: PlayerData) => T): T | undefined {
		const data = this.getPlayerData(player);
		if (!data) return undefined;
		return updateFn(data);
	}

	/**
	 * Get all loaded players
	 */
	getLoadedPlayers(): Player[] {
		return [...this.loadedPlayers];
	}
}
Editor is loading...
Leave a Comment