usuarios pre configurados
This commit is contained in:
@@ -8,24 +8,35 @@ const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Lobby',
|
||||
path: '/:uuid',
|
||||
name: 'LobbyWithUuid',
|
||||
component: Lobby
|
||||
},
|
||||
{
|
||||
path: '/game',
|
||||
name: 'Game',
|
||||
path: '/:uuid/game',
|
||||
name: 'GameWithUuid',
|
||||
component: Game
|
||||
},
|
||||
{
|
||||
path: '/demo',
|
||||
name: 'DemoGame',
|
||||
path: '/:uuid/demo',
|
||||
name: 'DemoGameWithUuid',
|
||||
component: DemoGame
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
name: 'Dashboard',
|
||||
component: Dashboard
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/missing-uuid'
|
||||
},
|
||||
{
|
||||
// simple fallback for users hitting root without UUID
|
||||
path: '/missing-uuid',
|
||||
component: {
|
||||
template: `<div style="padding:20px;font-family:sans-serif"><h2>Falta UUID</h2><p>Abre el juego escaneando tu código QR: snatchgame.nucleoriofrio.com/{uuid}</p></div>`
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Client, Room } from "colyseus.js";
|
||||
import { ref, Ref } from "vue";
|
||||
import { localDB } from "./db";
|
||||
|
||||
export interface PlayerData {
|
||||
sessionId: string;
|
||||
@@ -25,8 +24,8 @@ class ColyseusService {
|
||||
private client: Client;
|
||||
private currentRoom: Room | null = null;
|
||||
private apiBase: string;
|
||||
private readonly LS_KEY_RECONNECT = "snatch.game.rtoken";
|
||||
|
||||
// No local storage tokens: UUID in URL identifies the user
|
||||
|
||||
public lobbyRoom: Ref<Room | null> = ref(null);
|
||||
public gameRoom: Ref<Room | null> = ref(null);
|
||||
public playerName: Ref<string> = ref("");
|
||||
@@ -50,10 +49,8 @@ class ColyseusService {
|
||||
|
||||
async joinLobby(): Promise<Room> {
|
||||
try {
|
||||
// Initialize DB first to get UUID
|
||||
await localDB.init();
|
||||
const uuid = localDB.getUUID();
|
||||
|
||||
const uuid = this.getUuidFromPath();
|
||||
|
||||
const room = await this.client.joinOrCreate("lobby", { uuid });
|
||||
this.lobbyRoom.value = room;
|
||||
this.currentRoom = room;
|
||||
@@ -69,36 +66,18 @@ class ColyseusService {
|
||||
this.playerName.value = data.name;
|
||||
this.nameConfirmed.value = true;
|
||||
} else {
|
||||
// Initialize local DB and optionally auto-apply saved profile
|
||||
try {
|
||||
await localDB.init();
|
||||
const profile = localDB.getLocalPlayer();
|
||||
// Apply saved color silently
|
||||
if (profile?.color && profile.color !== this.playerColor.value) {
|
||||
this.setPlayerColor(profile.color);
|
||||
}
|
||||
if (profile?.name) {
|
||||
this.playerName.value = profile.name;
|
||||
try { localDB.setName(profile.name); } catch {}
|
||||
this.setPlayerName(profile.name);
|
||||
this.nameConfirmed.value = true;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Local DB init failed", e);
|
||||
}
|
||||
// No client-side persistence; user must confirm name once per session
|
||||
}
|
||||
});
|
||||
|
||||
room.onMessage("nameUpdated", (data) => {
|
||||
this.playerName.value = data.name;
|
||||
try { localDB.setName(data.name); } catch {}
|
||||
this.nameConfirmed.value = true;
|
||||
});
|
||||
|
||||
room.onMessage("colorUpdated", (data) => {
|
||||
if (data?.color) {
|
||||
this.playerColor.value = data.color;
|
||||
try { localDB.setColor(data.color); } catch {}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -110,28 +89,13 @@ class ColyseusService {
|
||||
}
|
||||
|
||||
async tryReconnectToOngoingGame(): Promise<Room | null> {
|
||||
try {
|
||||
const token = typeof window !== 'undefined' ? (window.localStorage.getItem(this.LS_KEY_RECONNECT) || "") : "";
|
||||
if (!token) return null;
|
||||
const room = await this.client.reconnect(token);
|
||||
this.gameRoom.value = room;
|
||||
this.currentRoom = room;
|
||||
// Ensure local session id reflects the active room session
|
||||
try { this.sessionId.value = (room as any).sessionId || this.sessionId.value; } catch {}
|
||||
try { if (typeof window !== 'undefined') window.localStorage.setItem(this.LS_KEY_RECONNECT, (room as any).reconnectionToken || token); } catch {}
|
||||
return room;
|
||||
} catch (e) {
|
||||
console.warn('Reconnection failed, clearing tokens');
|
||||
try {
|
||||
if (typeof window !== 'undefined') { window.localStorage.removeItem(this.LS_KEY_RECONNECT); }
|
||||
} catch {}
|
||||
return null;
|
||||
}
|
||||
// No stored reconnection tokens; rely on UUID flow and fresh joins
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
async setPlayerName(name: string): Promise<void> {
|
||||
if (this.lobbyRoom.value) {
|
||||
const uuid = localDB.getUUID();
|
||||
const uuid = this.getUuidFromPath();
|
||||
this.lobbyRoom.value.send("setName", { name, uuid });
|
||||
}
|
||||
}
|
||||
@@ -156,9 +120,11 @@ class ColyseusService {
|
||||
try {
|
||||
// Join the game room directly using the roomId
|
||||
console.log('Joining game room with name:', this.playerName.value);
|
||||
const uuid = this.getUuidFromPath();
|
||||
const gameRoom = await this.client.joinById(data.roomId, {
|
||||
playerName: this.playerName.value,
|
||||
playerColor: this.playerColor.value
|
||||
playerColor: this.playerColor.value,
|
||||
uuid
|
||||
});
|
||||
|
||||
// Ensure the room id is set
|
||||
@@ -172,7 +138,6 @@ class ColyseusService {
|
||||
this.currentRoom = gameRoom;
|
||||
// Update current session id for correct role mapping
|
||||
try { this.sessionId.value = (gameRoom as any).sessionId || this.sessionId.value; } catch {}
|
||||
try { if (typeof window !== 'undefined') window.localStorage.setItem(this.LS_KEY_RECONNECT, (gameRoom as any).reconnectionToken || ""); } catch {}
|
||||
console.log('gameRoom.value is now:', this.gameRoom.value);
|
||||
|
||||
// Don't register message handlers here - let the Game component handle them
|
||||
@@ -198,12 +163,13 @@ class ColyseusService {
|
||||
|
||||
async joinGameRoom(roomId: string): Promise<Room> {
|
||||
try {
|
||||
const uuid = this.getUuidFromPath();
|
||||
const gameRoom = await this.client.joinById(roomId, {
|
||||
playerName: this.playerName.value,
|
||||
playerColor: this.playerColor.value
|
||||
playerName: this.playerName.value,
|
||||
playerColor: this.playerColor.value,
|
||||
uuid
|
||||
});
|
||||
try { this.sessionId.value = (gameRoom as any).sessionId || this.sessionId.value; } catch {}
|
||||
try { if (typeof window !== 'undefined') window.localStorage.setItem(this.LS_KEY_RECONNECT, (gameRoom as any).reconnectionToken || ""); } catch {}
|
||||
this.gameRoom.value = gameRoom;
|
||||
this.currentRoom = gameRoom;
|
||||
|
||||
@@ -291,7 +257,6 @@ class ColyseusService {
|
||||
this.currentRoom = null;
|
||||
}
|
||||
}
|
||||
try { if (typeof window !== 'undefined') { window.localStorage.removeItem(this.LS_KEY_RECONNECT); } } catch {}
|
||||
}
|
||||
|
||||
leaveCurrentRoom(): void {
|
||||
@@ -350,6 +315,13 @@ class ColyseusService {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private getUuidFromPath(): string {
|
||||
if (typeof window === 'undefined') return '';
|
||||
const path = window.location.pathname.replace(/^\/+/, '');
|
||||
const seg = path.split('/')[0] || '';
|
||||
return seg;
|
||||
}
|
||||
}
|
||||
|
||||
export const colyseusService = new ColyseusService();
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { colyseusService } from '../services/colyseus';
|
||||
import { getStateCallbacks } from 'colyseus.js';
|
||||
|
||||
@@ -81,6 +81,8 @@ import PlayerStats from './games/PlayerStats.vue';
|
||||
import ChatWidget from './games/ChatWidget.vue';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const routeUuid = computed(() => (route.params as any)?.uuid as string || '');
|
||||
|
||||
const players = ref<any[]>([]);
|
||||
const gameStatus = ref('waiting');
|
||||
@@ -126,14 +128,7 @@ const currentComponent = computed(() => componentMap[currentVariant.value]);
|
||||
onMounted(() => {
|
||||
let room = colyseusService.gameRoom.value;
|
||||
if (!room) {
|
||||
// Try reconnection first
|
||||
colyseusService.tryReconnectToOngoingGame().then(r => {
|
||||
if (!r) {
|
||||
router.push('/');
|
||||
return;
|
||||
}
|
||||
setupRoom(r);
|
||||
});
|
||||
router.push(`/${routeUuid.value}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -181,7 +176,7 @@ onMounted(() => {
|
||||
$(player).listen("shameTokens", (v: number) => { const p = players.value.find(x => x.sessionId === key); if (p) p.shameTokens = v; });
|
||||
$(player).listen("color", (v: string) => { const p = players.value.find(x => x.sessionId === key); if (p) p.color = v; });
|
||||
});
|
||||
$(room.state).players.onRemove((player: any, key: string) => {
|
||||
$(room.state).players.onRemove((_: any, key: string) => {
|
||||
const i = players.value.findIndex(p => p.sessionId === key);
|
||||
if (i !== -1) players.value.splice(i, 1);
|
||||
});
|
||||
@@ -192,7 +187,7 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
room.onMessage("gameEnd", () => {
|
||||
try { if (typeof window !== 'undefined') { window.localStorage.removeItem('snatch.game.rtoken'); } } catch {}
|
||||
// no-op for local storage
|
||||
});
|
||||
|
||||
// Register additional message handlers to avoid warnings
|
||||
@@ -209,7 +204,7 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
// Handle room closure/disconnection
|
||||
room.onLeave((code) => {
|
||||
room.onLeave((code: number) => {
|
||||
console.log('[DemoGame] Room disconnected with code:', code);
|
||||
|
||||
// Handle shuffle disconnection specially
|
||||
@@ -223,36 +218,25 @@ onMounted(() => {
|
||||
} catch {}
|
||||
|
||||
// Redirect to lobby and let it handle the shuffle redirect
|
||||
router.push('/');
|
||||
router.push(`/${routeUuid.value}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal disconnection handling
|
||||
// Always clean up local storage when room closes
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.removeItem('snatch.game.roomId');
|
||||
window.localStorage.removeItem('snatch.game.sessionId');
|
||||
}
|
||||
} catch {}
|
||||
// no-op for local storage cleanup
|
||||
|
||||
// If not on lobby page, redirect there
|
||||
if (router.currentRoute.value.path !== '/') {
|
||||
if (router.currentRoute.value.path !== `/${routeUuid.value}`) {
|
||||
console.log('[DemoGame] Room closed, redirecting to lobby');
|
||||
router.push('/');
|
||||
router.push(`/${routeUuid.value}`);
|
||||
}
|
||||
});
|
||||
|
||||
room.onError((code, message) => {
|
||||
room.onError((code: number, message: any) => {
|
||||
console.error('[DemoGame] Room error:', code, message);
|
||||
// On error, also redirect to lobby
|
||||
try {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.removeItem('snatch.game.roomId');
|
||||
window.localStorage.removeItem('snatch.game.sessionId');
|
||||
}
|
||||
} catch {}
|
||||
router.push('/');
|
||||
// On error, redirect to lobby
|
||||
router.push(`/${routeUuid.value}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -276,8 +260,7 @@ function onAssignShame(val: boolean) { colyseusService.assignShame(val); }
|
||||
function leaveGame() {
|
||||
console.log('[DemoGame] User manually leaving game');
|
||||
colyseusService.leaveGame();
|
||||
try { if (typeof window !== 'undefined') { window.localStorage.removeItem('snatch.game.roomId'); window.localStorage.removeItem('snatch.game.sessionId'); } } catch {}
|
||||
router.push('/');
|
||||
router.push(`/${routeUuid.value}`);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -75,12 +75,13 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { colyseusService } from '../services/colyseus';
|
||||
import { localDB } from '../services/db';
|
||||
import { getStateCallbacks } from 'colyseus.js';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const routeUuid = computed(() => (route.params as any)?.uuid as string || '');
|
||||
const players = ref<any[]>([]);
|
||||
const gameStatus = ref('waiting');
|
||||
const timeRemaining = ref(600);
|
||||
@@ -99,16 +100,8 @@ onMounted(() => {
|
||||
console.log('Current game room:', room);
|
||||
|
||||
if (!room) {
|
||||
console.warn('No game room found, trying reconnection...');
|
||||
// Attempt reconnection if tokens are available
|
||||
colyseusService.tryReconnectToOngoingGame().then((r) => {
|
||||
if (!r) {
|
||||
console.error('Reconnection failed, redirecting to lobby...');
|
||||
router.push('/');
|
||||
return;
|
||||
}
|
||||
setupRoom(r);
|
||||
});
|
||||
console.warn('No game room found, redirecting to lobby...');
|
||||
router.push(`/${routeUuid.value}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -120,7 +113,7 @@ onMounted(() => {
|
||||
const $ = getStateCallbacks(room);
|
||||
|
||||
// Wait for the initial state sync (do not manually push players here to avoid duplicates)
|
||||
room.onStateChange.once((state) => {
|
||||
room.onStateChange.once((state: any) => {
|
||||
console.log('Initial state received:', state);
|
||||
gameStatus.value = state.gameStatus || 'waiting';
|
||||
timeRemaining.value = state.timeRemaining || 600;
|
||||
@@ -164,14 +157,14 @@ onMounted(() => {
|
||||
});
|
||||
});
|
||||
|
||||
$(room.state).players.onRemove((player: any, key: string) => {
|
||||
$(room.state).players.onRemove((_: any, key: string) => {
|
||||
const index = players.value.findIndex(p => p.sessionId === key);
|
||||
if (index !== -1) {
|
||||
players.value.splice(index, 1);
|
||||
}
|
||||
});
|
||||
|
||||
room.onMessage("playerInfo", (info) => {
|
||||
room.onMessage("playerInfo", (info: any) => {
|
||||
console.log('Received playerInfo:', info);
|
||||
colyseusService.sessionId.value = info.sessionId;
|
||||
colyseusService.playerName.value = info.name;
|
||||
@@ -182,10 +175,9 @@ onMounted(() => {
|
||||
gameStatus.value = 'playing';
|
||||
});
|
||||
|
||||
room.onMessage("gameEnd", (data) => {
|
||||
console.log("Game ended!", data);
|
||||
room.onMessage("gameEnd", () => {
|
||||
console.log("Game ended!");
|
||||
gameStatus.value = 'finished';
|
||||
try { if (typeof window !== 'undefined') { window.localStorage.removeItem('snatch.game.rtoken'); } } catch {}
|
||||
});
|
||||
|
||||
room.onMessage("gamePaused", () => {
|
||||
@@ -207,18 +199,17 @@ onUnmounted(() => {
|
||||
}
|
||||
});
|
||||
|
||||
function handleClick() {
|
||||
if (gameStatus.value !== 'playing') return;
|
||||
|
||||
colyseusService.sendClick();
|
||||
try { localDB.incClicks(1); } catch {}
|
||||
|
||||
isClicking.value = true;
|
||||
clearTimeout(clickTimeout);
|
||||
clickTimeout = setTimeout(() => {
|
||||
isClicking.value = false;
|
||||
}, 100);
|
||||
}
|
||||
function handleClick() {
|
||||
if (gameStatus.value !== 'playing') return;
|
||||
|
||||
colyseusService.sendClick();
|
||||
|
||||
isClicking.value = true;
|
||||
clearTimeout(clickTimeout);
|
||||
clickTimeout = setTimeout(() => {
|
||||
isClicking.value = false;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function formatTime(seconds: number): string {
|
||||
const mins = Math.floor(seconds / 60);
|
||||
@@ -228,7 +219,7 @@ function formatTime(seconds: number): string {
|
||||
|
||||
function leaveGame() {
|
||||
colyseusService.leaveGame();
|
||||
router.push('/');
|
||||
router.push(`/${routeUuid.value}`);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -83,12 +83,13 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, computed, watch } from 'vue';
|
||||
import PlayerStats from './games/PlayerStats.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { colyseusService } from '../services/colyseus';
|
||||
import { getStateCallbacks } from 'colyseus.js';
|
||||
import { localDB } from '../services/db';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const routeUuid = computed(() => (route.params as any)?.uuid as string || '');
|
||||
const inputName = ref('');
|
||||
const isJoining = ref(false);
|
||||
const colorInput = ref('#667eea');
|
||||
@@ -111,25 +112,9 @@ const previewPlayer = computed(() => ({
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// Try reconnect to an ongoing game first
|
||||
const reconnected = await colyseusService.tryReconnectToOngoingGame();
|
||||
if (reconnected) {
|
||||
router.push('/demo');
|
||||
return;
|
||||
}
|
||||
const room = await colyseusService.joinLobby();
|
||||
colorInput.value = colyseusService.playerColor.value || '#667eea';
|
||||
|
||||
// Initialize local DB and prefill inputs if available
|
||||
try {
|
||||
await localDB.init();
|
||||
const profile = localDB.getLocalPlayer();
|
||||
if (profile?.name) inputName.value = profile.name;
|
||||
if (profile?.color) colorInput.value = profile.color;
|
||||
} catch (e) {
|
||||
console.warn('Local DB not available', e);
|
||||
}
|
||||
|
||||
// Keep color input synced with server-updated color
|
||||
watch(() => colyseusService.playerColor.value, (c) => {
|
||||
if (c && c !== colorInput.value) colorInput.value = c;
|
||||
@@ -190,7 +175,6 @@ onUnmounted(() => {
|
||||
async function updateName() {
|
||||
// Send even if empty; server will assign a default unique name when empty
|
||||
const name = inputName.value.trim();
|
||||
try { localDB.setName(name); } catch {}
|
||||
await colyseusService.setPlayerName(name);
|
||||
}
|
||||
|
||||
@@ -205,7 +189,7 @@ async function handleQuickPlay() {
|
||||
console.log('Starting quickPlay...');
|
||||
try {
|
||||
const gameRoom = await colyseusService.quickPlay();
|
||||
console.log('Game room joined:', gameRoom?.id, 'Full room object:', gameRoom);
|
||||
console.log('Game room joined. Full room object:', gameRoom);
|
||||
|
||||
// Leave the lobby room before navigating
|
||||
if (colyseusService.lobbyRoom.value) {
|
||||
@@ -214,8 +198,8 @@ async function handleQuickPlay() {
|
||||
colyseusService.lobbyRoom.value = null;
|
||||
}
|
||||
|
||||
console.log('Navigating to /demo...');
|
||||
await router.push('/demo');
|
||||
console.log('Navigating to /:uuid/demo...');
|
||||
await router.push(`/${routeUuid.value}/demo`);
|
||||
console.log('Navigation complete');
|
||||
} catch (error) {
|
||||
console.error('Failed to join game:', error);
|
||||
@@ -234,7 +218,7 @@ async function joinRoom(roomId: string) {
|
||||
colyseusService.lobbyRoom.value.leave();
|
||||
colyseusService.lobbyRoom.value = null;
|
||||
}
|
||||
router.push('/demo');
|
||||
router.push(`/${routeUuid.value}/demo`);
|
||||
} catch (error) {
|
||||
console.error('Failed to join room:', error);
|
||||
isJoining.value = false;
|
||||
|
||||
@@ -6,15 +6,21 @@ export default defineConfig({
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: 3004,
|
||||
allowedHosts: ['z590.interno.com'],
|
||||
allowedHosts: ['z590.interno.com', 'snatchgame.interno.com'],
|
||||
cors: {
|
||||
origin: ['http://localhost:3004', 'http://z590.interno.com:3004']
|
||||
},
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:3000',
|
||||
target: process.env.VITE_DEV_API_PROXY_TARGET || 'http://localhost:3000',
|
||||
changeOrigin: true
|
||||
},
|
||||
'/ws': {
|
||||
target: process.env.VITE_DEV_WS_PROXY_TARGET || 'http://localhost:3000',
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
rewrite: (path) => path.replace(/^\/ws/, '')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user