Änderung: Verbesserung der Socket-Verbindung und Implementierung von Autos im Taxi-Spiel

Änderungen:
- Hinzufügen von Logik zur Verwaltung von Backend- und Daemon-Verbindungsversuchen mit Retry-Mechanismus.
- Implementierung einer Autos-Generierung mit zufälligen Spawn-Positionen und Bewegungslogik.
- Einführung einer Minimap zur Anzeige der aktuellen Spielumgebung.
- Optimierung der Kollisionserkennung zwischen Taxi und Autos.
- Verbesserung der Speicherbereinigung und Performance durch throttling von Timer-Updates.

Diese Anpassungen erweitern die Spielmechanik und Benutzererfahrung, indem sie die Interaktivität und die grafische Darstellung im Taxi-Spiel verbessern.
This commit is contained in:
Torsten Schulz (local)
2025-10-06 11:58:51 +02:00
parent 1bde46430b
commit 828e45df35
2 changed files with 829 additions and 156 deletions

View File

@@ -11,6 +11,13 @@ const store = createStore({
connectionStatus: 'disconnected', // 'connected', 'connecting', 'disconnected', 'error'
daemonConnectionStatus: 'disconnected', // 'connected', 'connecting', 'disconnected', 'error'
user: JSON.parse(localStorage.getItem('user')) || null,
// Reconnect state management
backendRetryCount: 0,
daemonRetryCount: 0,
backendRetryTimer: null,
daemonRetryTimer: null,
backendConnecting: false,
daemonConnecting: false,
language: (() => {
// Verwende die gleiche Logik wie in main.js
const browserLanguage = navigator.language || navigator.languages[0];
@@ -112,6 +119,12 @@ const store = createStore({
state.socket.disconnect();
}
state.socket = null;
// Cleanup retry timer
if (state.backendRetryTimer) {
clearTimeout(state.backendRetryTimer);
state.backendRetryTimer = null;
}
state.backendConnecting = false;
},
setDaemonSocket(state, daemonSocket) {
state.daemonSocket = daemonSocket;
@@ -122,6 +135,12 @@ const store = createStore({
}
state.daemonSocket = null;
state.daemonConnectionStatus = 'disconnected';
// Cleanup retry timer
if (state.daemonRetryTimer) {
clearTimeout(state.daemonRetryTimer);
state.daemonRetryTimer = null;
}
state.daemonConnecting = false;
},
},
actions: {
@@ -142,74 +161,97 @@ const store = createStore({
commit('dologout');
router.push('/');
},
initializeSocket({ commit, state }) {
if (state.isLoggedIn && state.user) {
let currentSocket = state.socket;
const connectSocket = () => {
if (currentSocket) {
currentSocket.disconnect();
}
commit('setConnectionStatus', 'connecting');
// Socket.io URL für lokale Entwicklung und Produktion
let socketIoUrl = import.meta.env.VITE_SOCKET_IO_URL || import.meta.env.VITE_API_BASE_URL;
// Für lokale Entwicklung: direkte Backend-Verbindung
if (!socketIoUrl && (import.meta.env.DEV || window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1')) {
socketIoUrl = 'http://localhost:3001';
}
const socket = io(socketIoUrl, {
secure: true,
transports: ['websocket', 'polling']
});
socket.on('connect', () => {
retryCount = 0; // Reset retry counter on successful connection
commit('setConnectionStatus', 'connected');
const idForSocket = state.user?.hashedId || state.user?.id;
if (idForSocket) socket.emit('setUserId', idForSocket);
});
socket.on('disconnect', (reason) => {
commit('setConnectionStatus', 'disconnected');
retryConnection(connectSocket);
});
socket.on('connect_error', (error) => {
commit('setConnectionStatus', 'error');
});
commit('setSocket', socket);
};
let retryCount = 0;
const maxRetries = 10;
const retryConnection = (reconnectFn) => {
console.log(`Backend-Reconnect-Versuch ${retryCount + 1}/${maxRetries}`);
if (retryCount >= maxRetries) {
// Nach maxRetries alle 5 Sekunden weiter versuchen
console.log('Backend: Max Retries erreicht, versuche weiter alle 5 Sekunden...');
setTimeout(() => {
retryCount = 0; // Reset für nächsten Zyklus
reconnectFn();
}, 5000);
return;
}
retryCount++;
const delay = 5000; // Alle 5 Sekunden versuchen
console.log(`Backend: Warte ${delay}ms bis zum nächsten Reconnect-Versuch...`);
setTimeout(() => {
reconnectFn();
}, delay);
};
connectSocket();
}
},
initializeDaemonSocket({ commit, state }) {
if (!state.isLoggedIn || !state.user) {
initializeSocket({ commit, state, dispatch }) {
if (!state.isLoggedIn || !state.user || state.backendConnecting) {
return;
}
state.backendConnecting = true;
const connectSocket = () => {
// Cleanup existing socket and timer
if (state.socket) {
state.socket.disconnect();
}
if (state.backendRetryTimer) {
clearTimeout(state.backendRetryTimer);
state.backendRetryTimer = null;
}
commit('setConnectionStatus', 'connecting');
// Socket.io URL für lokale Entwicklung und Produktion
let socketIoUrl = import.meta.env.VITE_SOCKET_IO_URL || import.meta.env.VITE_API_BASE_URL;
// Für lokale Entwicklung: direkte Backend-Verbindung
if (!socketIoUrl && (import.meta.env.DEV || window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1')) {
socketIoUrl = 'http://localhost:3001';
}
const socket = io(socketIoUrl, {
secure: true,
transports: ['websocket', 'polling']
});
socket.on('connect', () => {
state.backendRetryCount = 0; // Reset retry counter on successful connection
state.backendConnecting = false;
commit('setConnectionStatus', 'connected');
const idForSocket = state.user?.hashedId || state.user?.id;
if (idForSocket) socket.emit('setUserId', idForSocket);
});
socket.on('disconnect', (reason) => {
commit('setConnectionStatus', 'disconnected');
dispatch('retryBackendConnection');
});
socket.on('connect_error', (error) => {
commit('setConnectionStatus', 'error');
dispatch('retryBackendConnection');
});
commit('setSocket', socket);
};
connectSocket();
},
retryBackendConnection({ commit, state }) {
if (state.backendRetryTimer || state.backendConnecting) {
return; // Already retrying or connecting
}
const maxRetries = 10;
console.log(`Backend-Reconnect-Versuch ${state.backendRetryCount + 1}/${maxRetries}`);
if (state.backendRetryCount >= maxRetries) {
// Nach maxRetries alle 5 Sekunden weiter versuchen
console.log('Backend: Max Retries erreicht, versuche weiter alle 5 Sekunden...');
state.backendRetryTimer = setTimeout(() => {
state.backendRetryCount = 0; // Reset für nächsten Zyklus
state.backendRetryTimer = null;
commit('setConnectionStatus', 'connecting');
// Recursive call to retry
setTimeout(() => this.dispatch('retryBackendConnection'), 100);
}, 5000);
return;
}
state.backendRetryCount++;
const delay = 5000; // Alle 5 Sekunden versuchen
console.log(`Backend: Warte ${delay}ms bis zum nächsten Reconnect-Versuch...`);
state.backendRetryTimer = setTimeout(() => {
state.backendRetryTimer = null;
this.dispatch('initializeSocket');
}, delay);
},
initializeDaemonSocket({ commit, state, dispatch }) {
if (!state.isLoggedIn || !state.user || state.daemonConnecting) {
return;
}
state.daemonConnecting = true;
// Daemon URL für lokale Entwicklung und Produktion
let daemonUrl = import.meta.env.VITE_DAEMON_SOCKET;
@@ -224,8 +266,16 @@ const store = createStore({
daemonUrl = 'wss://www.your-part.de:4551';
}
const connectDaemonSocket = () => {
// Cleanup existing socket and timer
if (state.daemonSocket) {
state.daemonSocket.close();
}
if (state.daemonRetryTimer) {
clearTimeout(state.daemonRetryTimer);
state.daemonRetryTimer = null;
}
// Protokoll-Fallback: zuerst mit Subprotokoll, dann ohne
const protocols = ['yourpart-protocol', undefined];
let attemptIndex = 0;
@@ -242,7 +292,8 @@ const store = createStore({
daemonSocket.onopen = () => {
opened = true;
retryCount = 0; // Reset retry counter on successful connection
state.daemonRetryCount = 0; // Reset retry counter on successful connection
state.daemonConnecting = false;
commit('setDaemonConnectionStatus', 'connected');
const payload = JSON.stringify({
event: 'setUserId',
@@ -259,7 +310,7 @@ const store = createStore({
tryConnectWithProtocol();
return;
}
retryConnection(connectDaemonSocket);
dispatch('retryDaemonConnection');
};
daemonSocket.onerror = (error) => {
@@ -270,7 +321,7 @@ const store = createStore({
tryConnectWithProtocol();
return;
}
retryConnection(connectDaemonSocket);
dispatch('retryDaemonConnection');
};
daemonSocket.addEventListener('message', (event) => {
@@ -295,35 +346,45 @@ const store = createStore({
tryConnectWithProtocol();
return;
}
retryConnection(connectDaemonSocket);
dispatch('retryDaemonConnection');
}
};
tryConnectWithProtocol();
};
let retryCount = 0;
const maxRetries = 15; // Increased max retries
const retryConnection = (reconnectFn) => {
console.log(`Daemon-Reconnect-Versuch ${retryCount + 1}/${maxRetries}`);
if (retryCount >= maxRetries) {
// Nach maxRetries alle 5 Sekunden weiter versuchen
console.log('Daemon: Max Retries erreicht, versuche weiter alle 5 Sekunden...');
setTimeout(() => {
retryCount = 0; // Reset für nächsten Zyklus
reconnectFn();
}, 5000);
return;
}
retryCount++;
const delay = 5000; // Alle 5 Sekunden versuchen
console.log(`Daemon: Warte ${delay}ms bis zum nächsten Reconnect-Versuch...`);
setTimeout(() => {
reconnectFn();
}, delay);
};
connectDaemonSocket();
},
retryDaemonConnection({ commit, state }) {
if (state.daemonRetryTimer || state.daemonConnecting) {
return; // Already retrying or connecting
}
const maxRetries = 15;
console.log(`Daemon-Reconnect-Versuch ${state.daemonRetryCount + 1}/${maxRetries}`);
if (state.daemonRetryCount >= maxRetries) {
// Nach maxRetries alle 5 Sekunden weiter versuchen
console.log('Daemon: Max Retries erreicht, versuche weiter alle 5 Sekunden...');
state.daemonRetryTimer = setTimeout(() => {
state.daemonRetryCount = 0; // Reset für nächsten Zyklus
state.daemonRetryTimer = null;
commit('setDaemonConnectionStatus', 'connecting');
// Recursive call to retry
setTimeout(() => this.dispatch('retryDaemonConnection'), 100);
}, 5000);
return;
}
state.daemonRetryCount++;
const delay = 5000; // Alle 5 Sekunden versuchen
console.log(`Daemon: Warte ${delay}ms bis zum nächsten Reconnect-Versuch...`);
state.daemonRetryTimer = setTimeout(() => {
state.daemonRetryTimer = null;
this.dispatch('initializeDaemonSocket');
}, delay);
},
setLanguage({ commit }, language) {
commit('setLanguage', language);
},
@@ -352,7 +413,8 @@ const store = createStore({
},
});
if (store.state.isLoggedIn && store.state.user) {
// Initialisierung beim Laden der Anwendung - nur einmal ausführen
if (store.state.isLoggedIn && store.state.user && !store.state.backendConnecting && !store.state.daemonConnecting) {
store.dispatch('initializeSocket');
store.dispatch('initializeDaemonSocket');
}