fix(v2): comprehensive bug fix round — all reported issues
1. Server stats: now shows player count, latency (rounded), uptime hours
2. Rares/Kills counters: fixed API response fields (all_time/total)
3. Chat send: wired socket.send with v1 envelope { player_name, command }
4. Stats button: opens Grafana iframe grid (4 panels, time range selector)
5. Char button: opens character window with attributes/skills/vitals from
/character-stats/{name} API, structured display with sections
6. Inventory button: full inventory window with equipment table (material,
set, imbue, AL, dmg, work, tink) + pack contents pill grid + filter
7. Radar button: opens radar window, sends start/stop commands via socket
8. Sidebar links: added Inventory Search, Suitbuilder, Player Debug
9. Color palette: expanded from 30 to 60 distinct colors matching v1
10. Window types properly routed: stats- prefix → Grafana, char- → character
data, inv- → inventory, radar- → radar with socket commands
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
de7b547349
commit
b77450b6eb
19 changed files with 529 additions and 223 deletions
|
|
@ -13,6 +13,7 @@ export interface DashboardState {
|
|||
totalKills: number;
|
||||
recentRares: RareMessage[];
|
||||
chatMessages: Map<string, Array<{ text: string; color?: number; timestamp: string }>>;
|
||||
socketRef: React.RefObject<WebSocket | null>;
|
||||
}
|
||||
|
||||
export function useLiveData(): DashboardState {
|
||||
|
|
@ -63,7 +64,7 @@ export function useLiveData(): DashboardState {
|
|||
}
|
||||
}, [updateChar]);
|
||||
|
||||
useWebSocket(handleWS);
|
||||
const socketRef = useWebSocket(handleWS);
|
||||
|
||||
// HTTP polls as fallback/initial load
|
||||
useEffect(() => {
|
||||
|
|
@ -131,8 +132,8 @@ export function useLiveData(): DashboardState {
|
|||
const fetch = async () => {
|
||||
try {
|
||||
const [rares, kills] = await Promise.all([getTotalRares(), getTotalKills()]);
|
||||
setTotalRares(rares.total_rares ?? rares.count ?? 0);
|
||||
setTotalKills(kills.total_kills ?? kills.count ?? 0);
|
||||
setTotalRares((rares as any).all_time ?? 0);
|
||||
setTotalKills((kills as any).total ?? 0);
|
||||
} catch { /* ignore */ }
|
||||
};
|
||||
fetch();
|
||||
|
|
@ -140,5 +141,5 @@ export function useLiveData(): DashboardState {
|
|||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
return { characters, serverHealth, totalRares, totalKills, recentRares, chatMessages };
|
||||
return { characters, serverHealth, totalRares, totalKills, recentRares, chatMessages, socketRef };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,25 @@
|
|||
import { useRef, useCallback } from 'react';
|
||||
|
||||
// Matches v1 script.js PALETTE — 30 accessible colors
|
||||
// Matches v1 script.js PALETTE — 60 distinct high-contrast colors
|
||||
const PALETTE = [
|
||||
'#1f77b4','#ff7f0e','#2ca02c','#d62728','#9467bd','#8c564b','#e377c2','#7f7f7f',
|
||||
'#bcbd22','#17becf','#aec7e8','#ffbb78','#98df8a','#ff9896','#c5b0d5','#c49c94',
|
||||
'#f7b6d2','#c7c7c7','#dbdb8d','#9edae5','#393b79','#637939','#8c6d31','#843c39',
|
||||
'#7b4173','#5254a3','#6b6ecf','#9c9ede','#d6616b','#ce6dbd',
|
||||
// Original colorblind-friendly (10)
|
||||
'#1f77b4','#ff7f0e','#2ca02c','#d62728','#9467bd',
|
||||
'#8c564b','#e377c2','#7f7f7f','#bcbd22','#17becf',
|
||||
// Extended high-contrast (10)
|
||||
'#ff4444','#44ff44','#4444ff','#ffff44','#ff44ff',
|
||||
'#44ffff','#ff8844','#88ff44','#4488ff','#ff4488',
|
||||
// Darker variants (10)
|
||||
'#cc3333','#33cc33','#3333cc','#cccc33','#cc33cc',
|
||||
'#33cccc','#cc6633','#66cc33','#3366cc','#cc3366',
|
||||
// Brighter variants (10)
|
||||
'#ff6666','#66ff66','#6666ff','#ffff66','#ff66ff',
|
||||
'#66ffff','#ffaa66','#aaff66','#66aaff','#ff66aa',
|
||||
// Additional distinct (10)
|
||||
'#990099','#009900','#000099','#990000','#009999',
|
||||
'#999900','#aa5500','#55aa00','#0055aa','#aa0055',
|
||||
// Light pastels (10)
|
||||
'#ffaaaa','#aaffaa','#aaaaff','#ffffaa','#ffaaff',
|
||||
'#aaffff','#ffccaa','#ccffaa','#aaccff','#ffaacc',
|
||||
];
|
||||
|
||||
function hashColor(name: string): string {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import type { WSMessage } from '../types';
|
|||
|
||||
type MessageHandler = (msg: WSMessage) => void;
|
||||
|
||||
export function useWebSocket(onMessage: MessageHandler) {
|
||||
export function useWebSocket(onMessage: MessageHandler): React.RefObject<WebSocket | null> {
|
||||
const wsRef = useRef<WebSocket | null>(null);
|
||||
const reconnectTimer = useRef<number>(0);
|
||||
const onMessageRef = useRef(onMessage);
|
||||
|
|
@ -41,4 +41,6 @@ export function useWebSocket(onMessage: MessageHandler) {
|
|||
wsRef.current = null;
|
||||
};
|
||||
}, [connect]);
|
||||
|
||||
return wsRef;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue