fix: prevent sync spam

This commit is contained in:
2026-06-19 04:42:59 -03:00
parent c2b94bec4a
commit 4617d6c9fa
3 changed files with 43 additions and 49 deletions
+2 -2
View File
@@ -50,8 +50,8 @@ export default function Home() {
}, []); }, []);
/* /*
profile handling profile handling
*/ */
const handleDownload = () => { const handleDownload = () => {
const blob = new Blob([importText], { type: 'application/json' }); const blob = new Blob([importText], { type: 'application/json' });
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob);
+41 -42
View File
@@ -40,11 +40,9 @@ export const useWebsocketStore = create<WebsocketState>((set, get) => ({
try { try {
const payload = JSON.parse(msg.data); const payload = JSON.parse(msg.data);
// C++ sends action=0 (INIT_CONFIG) on WebSocket open
if (payload.action === 0) { if (payload.action === 0) {
const mapped = await mapSpooferConfigToStore(payload.profile); const mapped = await mapSpooferConfigToStore(payload.profile);
// Snapshot current state strings to prevent echo
lastInventoryJson = JSON.stringify({ lastInventoryJson = JSON.stringify({
unlockedCharacters: mapped.unlockedCharacters, unlockedCharacters: mapped.unlockedCharacters,
unlockedCustomizations: mapped.unlockedCustomizations, unlockedCustomizations: mapped.unlockedCustomizations,
@@ -71,48 +69,49 @@ export const useWebsocketStore = create<WebsocketState>((set, get) => ({
} }
})); }));
// Subscribe to store changes and sync to C++ client let syncTimeout: any = null;
useInventoryStore.subscribe((state) => { useInventoryStore.subscribe((state) => {
const { socket, isConnected } = useWebsocketStore.getState(); if (syncTimeout) clearTimeout(syncTimeout);
if (!isConnected || !socket || socket.readyState !== WebSocket.OPEN) return;
// --- Check toggles --- syncTimeout = setTimeout(() => {
const toggles = { const { socket, isConnected } = useWebsocketStore.getState();
spoofItems: state.spoofItems, if (!isConnected || !socket || socket.readyState !== WebSocket.OPEN) return;
spoofPerks: state.spoofPerks,
spoofCatalog: state.spoofCatalog,
spoofDLCs: state.spoofDLCs
};
const togglesJson = JSON.stringify(toggles);
if (togglesJson !== lastTogglesJson) {
lastTogglesJson = togglesJson;
socket.send(JSON.stringify({ action: 2, toggles }));
}
// --- Check inventory --- const toggles = {
const inventory = { spoofItems: state.spoofItems,
unlockedCharacters: state.unlockedCharacters, spoofPerks: state.spoofPerks,
unlockedCustomizations: state.unlockedCustomizations, spoofCatalog: state.spoofCatalog,
unlockedDLCs: state.unlockedDLCs, spoofDLCs: state.spoofDLCs
unlockedPerks: state.unlockedPerks, };
items: state.items, const togglesJson = JSON.stringify(toggles);
offerings: state.offerings, if (togglesJson !== lastTogglesJson) {
addons: state.addons lastTogglesJson = togglesJson;
}; socket.send(JSON.stringify({ action: 2, toggles }));
const inventoryJson = JSON.stringify(inventory); }
if (inventoryJson !== lastInventoryJson) {
lastInventoryJson = inventoryJson;
mapStoreToSpooferConfig(state).then((profile) => { const inventory = {
// Re-check connection in case it dropped during async mapping unlockedCharacters: state.unlockedCharacters,
const ws = useWebsocketStore.getState(); unlockedCustomizations: state.unlockedCustomizations,
if ( unlockedDLCs: state.unlockedDLCs,
ws.isConnected && unlockedPerks: state.unlockedPerks,
ws.socket && items: state.items,
ws.socket.readyState === WebSocket.OPEN offerings: state.offerings,
) { addons: state.addons
ws.socket.send(JSON.stringify({ action: 1, profile })); };
} const inventoryJson = JSON.stringify(inventory);
}); if (inventoryJson !== lastInventoryJson) {
} lastInventoryJson = inventoryJson;
mapStoreToSpooferConfig(state).then((profile) => {
const ws = useWebsocketStore.getState();
if (
ws.isConnected &&
ws.socket &&
ws.socket.readyState === WebSocket.OPEN
)
ws.socket.send(JSON.stringify({ action: 1, profile }));
});
}
}, 250);
}); });
-5
View File
@@ -59,7 +59,6 @@ export async function mapStoreToSpooferConfig(state: {
const perkMap = new Map<string, { role: number }>(); const perkMap = new Map<string, { role: number }>();
allPerks.forEach((p: { id: string; role: number }) => perkMap.set(p.id, p)); allPerks.forEach((p: { id: string; role: number }) => perkMap.set(p.id, p));
// --- DLCs ---
const dlcListSteam: string[] = []; const dlcListSteam: string[] = [];
const dlcListEGS: string[] = []; const dlcListEGS: string[] = [];
const dlcListGRDK: string[] = []; const dlcListGRDK: string[] = [];
@@ -87,13 +86,11 @@ export async function mapStoreToSpooferConfig(state: {
dlcListGRDK.push(dlc.dlcIds.grdk); dlcListGRDK.push(dlc.dlcIds.grdk);
} }
// --- Items ---
const camperItems: Record<string, number> = {}; const camperItems: Record<string, number> = {};
for (const [id, qty] of Object.entries(state.items)) { for (const [id, qty] of Object.entries(state.items)) {
if (qty > 0 && itemIdSet.has(id)) camperItems[id] = qty; if (qty > 0 && itemIdSet.has(id)) camperItems[id] = qty;
} }
// --- Offerings ---
const camperOfferings: Record<string, number> = {}; const camperOfferings: Record<string, number> = {};
const slasherOfferings: Record<string, number> = {}; const slasherOfferings: Record<string, number> = {};
const globalOfferings: Record<string, number> = {}; const globalOfferings: Record<string, number> = {};
@@ -107,7 +104,6 @@ export async function mapStoreToSpooferConfig(state: {
else globalOfferings[id] = qty; else globalOfferings[id] = qty;
} }
// --- Addons ---
const camperAddons: Record<string, number> = {}; const camperAddons: Record<string, number> = {};
const slasherAddons: Record<string, number> = {}; const slasherAddons: Record<string, number> = {};
@@ -119,7 +115,6 @@ export async function mapStoreToSpooferConfig(state: {
else camperAddons[id] = qty; else camperAddons[id] = qty;
} }
// --- Perks ---
const camperPerks: string[] = []; const camperPerks: string[] = [];
const slasherPerks: string[] = []; const slasherPerks: string[] = [];