Files
HexUnlockedWeb/store/useWebsocketStore.ts
T
2026-06-20 06:48:01 -03:00

118 lines
3.2 KiB
TypeScript

import { create } from 'zustand';
import { useInventoryStore } from './useInventoryStore';
import { mapStoreToSpooferConfig, mapSpooferConfigToStore } from './wsProtocol';
interface WebsocketState {
socket: WebSocket | null;
isConnected: boolean;
connect: () => void;
}
let lastTogglesJson = '';
let lastInventoryJson = '';
export const useWebsocketStore = create<WebsocketState>((set, get) => ({
socket: null,
isConnected: false,
connect: () => {
if (get().socket) return;
const ws = new WebSocket('ws://localhost:4444');
ws.onopen = () => {
console.log('Connected to WS server');
set({ socket: ws, isConnected: true });
};
ws.onclose = () => {
console.log('Disconnected. Retrying in 2s');
set({ socket: null, isConnected: false });
setTimeout(() => get().connect(), 2000);
};
ws.onerror = (err) => {
console.log('WS Error:', err);
ws.close();
};
ws.onmessage = async (msg) => {
try {
const payload = JSON.parse(msg.data);
if (payload.action === 0) {
const mapped = await mapSpooferConfigToStore(payload.profile);
lastInventoryJson = JSON.stringify({
unlockedCharacters: mapped.unlockedCharacters,
unlockedCustomizations: mapped.unlockedCustomizations,
unlockedDLCs: mapped.unlockedDLCs,
unlockedPerks: mapped.unlockedPerks,
items: mapped.items,
offerings: mapped.offerings,
addons: mapped.addons
});
lastTogglesJson = JSON.stringify({
spoofItems: payload.toggles?.spoofItems ?? false,
spoofPerks: payload.toggles?.spoofPerks ?? false,
spoofCatalog: payload.toggles?.spoofCatalog ?? false,
spoofDLCs: payload.toggles?.spoofDLCs ?? false
});
useInventoryStore.getState().importProfile(mapped);
useInventoryStore.getState().importToggles(payload.toggles);
}
} catch (e) {
console.error('Failed to parse WS message', e);
}
};
}
}));
let syncTimeout: any = null;
useInventoryStore.subscribe((state) => {
if (syncTimeout) clearTimeout(syncTimeout);
syncTimeout = setTimeout(() => {
const { socket, isConnected } = useWebsocketStore.getState();
if (!isConnected || !socket || socket.readyState !== WebSocket.OPEN) return;
const toggles = {
spoofItems: state.spoofItems,
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 }));
}
const inventory = {
unlockedCharacters: state.unlockedCharacters,
unlockedCustomizations: state.unlockedCustomizations,
unlockedDLCs: state.unlockedDLCs,
unlockedPerks: state.unlockedPerks,
items: state.items,
offerings: state.offerings,
addons: state.addons
};
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);
});