EduCraft es una experiencia voxel educativa construida sobre noa-engine y Babylon.js. El proyecto combina exploración 3D, edición de bloques, guardado local, multijugador por WebSocket y minijuegos integrados orientados al aprendizaje musical.
docs/test/: frontend estático del juego, recursos, texturas, audio y minijuegos embebidos.server/: backend Node.js para presencia multijugador y sincronización por WebSocket.src/: base del motor y código heredado denoa-engine.build-and-deploy.sh: build manual del bundle del frontend.scripts/deploy-vps.sh: despliegue rápido al VPS.
- Mundo voxel interactivo con colocación y eliminación de bloques.
- Inventario y hotbar.
- Guardado local de ajustes y progreso con IndexedDB.
- Múltiples mundos.
- Multijugador en tiempo real con salas por mundo (presencia y bloques aislados por mundo).
- Interfaz in-game personalizada.
- Soporte de teclado, ratón y detección de entorno móvil.
- Bloques y dinámicas musicales.
- Panel web integrado con minijuegos HTML externos.
EduCraft puede abrir minijuegos de EduMusic desde carteles repartidos por las islas del mundo.
- La configuracion central de carteles secretos vive en docs/test/index.js.
- Cada entrada define
id,x,z,title,subtitleyurl. - Al acercarte a un cartel y pulsar
V, se abre el minijuego asociado en el panel web. - El sistema busca automaticamente el cartel secreto mas cercano, por lo que se pueden repartir muchos accesos sin cambiar la logica base.
Los juegos de la familia Atrapa notas usan el motor compartido docs/test/embedded-game/EduMusic/js/game.js, que ahora soporta recompensas por puntuacion.
Para que un juego desbloquee un bloque del inventario al alcanzar una puntuacion:
- Declara
rewardAtScoreen elwindow.GAME_CONFIGdel HTML del juego. - Declara
rewardPayloadcontitle,message,rewardy opcionalmenteclosePanel. - Asegurate de que
rewardcoincide exactamente con un bloque existente del catalogo en docs/test/registry.js.
Ejemplo simplificado:
<script>
window.GAME_CONFIG = {
id: 'solmi',
rankKey: 'solmi',
pitches: ['mi', 'sol'],
rewardAtScore: 50,
rewardPayload: {
title: 'Reto completado',
message: 'Has conseguido 50 puntos.',
reward: 'Cristal',
closePanel: true
}
};
</script>Si un juego no puntua o no debe desbloquear nada, no hace falta declarar esos campos: puede seguir siendo accesible desde su cartel solo como experiencia libre.
El backend WebSocket separa el estado por mundo usando salas en memoria.
- El parámetro
worlddel cliente se envía en elhelloy se normaliza en cliente y servidor. - Si no se especifica mundo, se usa
default. snapshot,deltayplayerLeftse emiten solo a clientes del mismo mundo.- Un jugador de
ABCno recibe presencia deDEF. - El terreno base procedural sigue siendo global e idéntico para todos los mundos.
- Las ediciones de bloques se superponen sobre ese terreno base y se aíslan por sala.
- El servidor mantiene en memoria las ediciones de bloques por mundo.
- Al entrar a un mundo, el cliente recibe el estado actual de ediciones de ese mundo.
- Al colocar/quitar bloques, el cliente aplica local inmediato y envía el cambio al servidor.
- El servidor valida y difunde el cambio solo dentro de la sala del mundo correspondiente.
En esta fase, la persistencia compartida entre jugadores es memoria del servidor (no disco). Si el servidor reinicia, las ediciones compartidas se pierden.
Cliente -> Servidor:
hello { v, name, world }move { v, x, y, z }blockUpdate { v, world?, x, y, z, blockId }ping { v, t }
Servidor -> Cliente:
welcome { v, id, tickRate, world }snapshot { v, players }delta { v, players }playerLeft { v, id }worldEdits { v, edits }blockUpdate { v, x, y, z, blockId, by }pong { v, t }error { v, message }
El roadmap tecnico del panel vive en docs/ADMIN_PANEL_ROADMAP.md.
El backend expone ahora dos rutas utiles para supervision:
/admin: pagina HTML con refresco automatico cada 5 segundos./admin/stats: JSON con jugadores activos, mundos activos, picos recientes y salud del proceso./admin/events: timeline reciente con filtros por tipo, mundo y jugador./admin/history: serie temporal de concurrencia y mundos activos./admin/worlds: resumen actual y pico reciente por mundo./admin/health: estado tecnico del proceso Node.
Las metricas disponibles hoy son:
activePlayers: conexiones WebSocket activas en este instante.activeWorlds: salas actualmente ocupadas.knownWorldsSinceBoot: mundos que han sido usados desde que se arranco el proceso del backend.
Importante: el backend sigue guardando el estado compartido en memoria. Eso significa que el conteo de mundos conocidos se reinicia cuando el servicio Node se reinicia.
WASD: moverRatón: mirarClic izquierdo: quitar bloqueClic derecho: colocar bloqueE: abrir o cerrar inventario1-9: seleccionar slot de hotbarEspacio: saltarShift: agacharseO: cambiar de mundo en la demo avanzadaZ: abrir inspector Babylon.js cuandodebugestá activo
Algunos controles pueden variar según la demo o la configuración activa.
nodeynpmrsyncpara despliegues al VPSsshpara acceso al servidorsystemden el VPS para el backendnginxo equivalente si se sirve el frontend con proxy inverso a/ws
Instala dependencias del frontend:
npm installInstala dependencias del backend:
cd server
npm installnpm testEsto arranca el entorno de prueba con webpack-dev-server usando docs/test/.
En local se mantienen activas las ayudas visuales de depuración.
npm run build:testEl bundle generado se escribe como docs/test/bundle.js.
Si necesitas recompilar también la demo hello-world, usa:
npm run buildcd server
npm run buildnpm run checkEste comando recompila el frontend, verifica que los bundles esperados existen y ejecuta los tests mínimos del protocolo del backend.
cd server
npm run devPor defecto el backend escucha en el puerto 8080.
La forma recomendada de desplegar EduCraft en producción es:
docs/test/servido como sitio estático.server/ejecutándose como servicio Node.js.nginxhaciendo proxy WebSocket desde/wsal backend.
El cliente usa por defecto:
ws://TU_HOST/wssi la página va por HTTPwss://TU_HOST/wssi la página va por HTTPS
Ese comportamiento está implementado en docs/test/index.js.
El script scripts/deploy-vps.sh automatiza el flujo de despliegue.
Hace lo siguiente:
- Compila el frontend.
- Crea las rutas remotas si faltan.
- Sincroniza
docs/test/al directorio web del VPS conrsync. - Sincroniza
server/al directorio backend del VPS conrsync. - Ejecuta en remoto
npm install,npm run buildy reinicia el serviciosystemd. - Ejecuta un healthcheck remoto para confirmar que el backend responde.
Copia la plantilla:
cp scripts/deploy.config.example scripts/deploy.configEdita scripts/deploy.config con tus valores reales:
VPS_HOST: IP o dominio del VPSVPS_USER: usuario SSHVPS_PORT: puerto SSHSSH_IDENTITY_FILE: ruta a una clave SSH concreta si no usas la predeterminadaREMOTE_BASE_DIR: ruta base del proyectoREMOTE_WEB_DIR: carpeta donde se publican los archivos estáticosREMOTE_SERVER_DIR: carpeta del backendREMOTE_SERVICE: nombre del serviciosystemd, por ejemploeducraft-wsSYSTEMCTL_BIN: ruta completa desystemctl, por ejemplo/usr/bin/systemctlHEALTHCHECK_URL: URL interna para validar el backend tras el reinicio
El archivo scripts/deploy.config está ignorado en Git.
En Debian suele ser buena idea dejar SYSTEMCTL_BIN="/usr/bin/systemctl" para que el despliegue use exactamente la misma ruta que se permite en sudoers.
./scripts/deploy-vps.shSi quieres usar un archivo de configuración distinto:
DEPLOY_CONFIG=./scripts/mi-config-vps.sh ./scripts/deploy-vps.sh- Hacer cambios en local.
- Probar frontend y backend localmente.
- Confirmar cambios en Git.
- Ejecutar
./scripts/deploy-vps.sh. - Verificar en el VPS que el servicio sigue sano.
Comprobación útil del backend en el servidor:
curl http://127.0.0.1:8080/health- El frontend necesita subir la carpeta completa
docs/test/, no solobundle.js. docs/test/incluyeindex.html, texturas, audio, fuentes, modelos y minijuegos embebidos.- Si cambias dependencias del backend, el despliegue ya ejecuta
npm installen remoto. - Si más adelante quieres acelerar despliegues, puedes ajustar el script para omitir
npm installcuando no cambienserver/package.jsonoserver/package-lock.json. - Las trazas visuales del cliente pueden activarse en local o con
?debug=1.
El plan de mejoras priorizado está documentado en docs/ROADMAP.md para continuar el trabajo más adelante.
EduCraft parte de una base de noa-engine, pero este repositorio ya está orientado a la aplicación final y a su despliegue. Para trabajo diario conviene tomar este README como referencia principal en lugar de la documentación original del motor.