LAN Cliente - vykymoon/rpg-character-creator GitHub Wiki
El cliente tiene tres piezas: el cliente de red (GameClient), el cliente gráfico (GameApp) y el lector de personajes (CharacterLoader).
Extiende WebSocketClient. Recibe un Consumer<String> que se invoca con cada mensaje del servidor:
client.setOnState(this::handleMessage);Por defecto imprime en consola ([client] estado recibido: …), de modo que el mismo cliente sirve para la consola (ClientMain) y para la UI (GameApp). También registra en consola la conexión, el cierre y los errores.
Herramienta de pruebas sin interfaz.
mvn compile exec:java@client -Dexec.args="ws://localhost:8887 p1"- Argumentos:
[url] [playerId](por defectows://localhost:8887yplayer-<ms%1000>). - Envía
joincon soloplayerId. - Luego lee líneas:
x yenvía unmove;salircierra.
Lee characters.json sin depender de las clases del modelo, de forma tolerante, y devuelve objetos Info (name, race, characterClass, items, skills, stats).
| Dato | Claves aceptadas (en orden) |
|---|---|
| Nombre |
name, nombre
|
| Raza |
race, raza
|
| Clase |
characterClass, class, clazz, clase
|
| Ítems |
outfit, outfits, items, inventory, equipment (se acumulan) |
| Habilidades | skills |
| Stats |
stats, finalStats, baseStats (objeto) |
- El archivo puede ser un arreglo o un objeto que contenga un arreglo.
- Si un valor es un objeto, usa su
name,nombreotitlecomo etiqueta; si no, el JSON tal cual. -
Búsqueda del archivo:
src/main/resources/data/characters.json,data/characters.json,characters.json. Si no aparece,GameAppabre unFileChooser.
Importante: un personaje guardado por el wizard tiene los stats como campos planos (
strength,dexterity, …), no dentro de un objetostats. Por eso la sección Stats de la barra lateral deGameAppqueda vacía. Ver Limitaciones y Mejoras.
Clase principal alternativa: mvn compile javafx:run@game, o desde la galería con Multijugador LAN.
-
pickCharacter()— carga los personajes y muestra unChoiceDialog. Si no hay ninguno: "No hay personajes guardados. Crea uno en el wizard primero." y sale. -
Pide la URL del servidor (por defecto
ws://localhost:8887). - Genera
playerId = nombre + "#" + (currentTimeMillis % 1000). - Conecta con
connectBlocking(3, SECONDS). Si falla: "No se pudo conectar a " y sale. - Envía
joincon nombre, raza, clase e ítems. - Crea el lienzo (50×50 celdas de 14 px = 700×700 px) y la barra lateral (220 px).
- Registra el manejo de teclado y muestra la ventana
"RPG LAN - <nombre>"(no redimensionable). - Carga la imagen de fondo y dibuja.
Al cerrar la ventana: client.close() + Platform.exit().
| Tecla | Acción |
|---|---|
| ↑ / W | Arriba |
| ↓ / S | Abajo |
| ← / A | Izquierda |
| → / D | Derecha |
Se usa un addEventFilter (no un handler) y se hace consume() para que las flechas no muevan la selección de las listas de la barra lateral.
Se ejecuta en el hilo de red y delega la UI con Platform.runLater.
type |
Acción |
|---|---|
map |
Guarda mapRows (usado para la validación local del movimiento) y redibuja |
state |
Reconstruye el mapa de jugadores (PV: x, y, nombre, clase) y redibuja |
- Toma la posición propia del último
staterecibido (si aún no existe, no hace nada). - Calcula la celda destino.
- Si según
mapRowses caminable (.o=), envíamove. -
No actualiza la posición localmente: espera el
statedel servidor (modelo autoritativo). El chequeo local solo evita mandar mensajes inútiles.
- Fondo:
background_multiplayer.jpgestirada al lienzo; si no carga, color sólido#1e2327. - Cada jugador: círculo de 12 px con color derivado del hash de su clase (
Color.hsb(hash % 360, 0.6, 0.95)), de modo que misma clase = mismo color. - El jugador propio lleva un anillo dorado.
- El nombre se dibuja encima del círculo.
Nombre (negrita), "Raza / Clase", y secciones Stats, Items y Habilidades (listas de 120 px, no enfocables). Al pie: "Mover: flechas / WASD".
Intenta, en orden: /map/background_multiplayer.jpg, /battle/map/background_multiplayer.jpg, /background_multiplayer.jpg, y como último recurso una ruta absoluta de Windows en Descargas. Los archivos reales están en src/main/resources/sprites/map/ (.jpg y .png).
Las tres rutas del classpath no coinciden con la ubicación real (
/sprites/map/…). Ver Limitaciones y Mejoras.