Skip to content

redsaporo/Roedalia

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

.NET 8 C# 12 SignalR MIT

El Cantar de la Chispa

~ Roedalia ~

Simulacion concurrente multihilo en C#/.NET 8 con dashboard web en tiempo real.
Una historia de amor entre ratones, contada con hilos, semaforos y TCP.


Sinopsis

En el reino de Roedalia, la princesa Elisabetha vive en su castillo rodeada de sus cuatro damas del lazo, mientras el caballero Lance patrulla la guarnicion con sus cuatro caballeros del Porton Norte. Ninguno sabe que el destino los unira.

Mientras tanto, los Alquimistas conspiran desde sus torres para impedirlo, preparando pociones que debilitan la Chispa — la fuerza magica que mide el vinculo entre ambos protagonistas.

La simulacion termina cuando ambos alcanzan Chispa 100 y se reunen. Los alquimistas intentan impedirlo. El destino decide.


Arquitectura

                    ┌──────────────────────────────────┐
                    │          Browser (Dashboard)      │
                    │  Canvas pixel-art + SignalR WS    │
                    └──────────┬───────────────────────┘
                               │ WebSocket :8080
                    ┌──────────▼───────────────────────┐
                    │        ASP.NET Core Server        │
                    │  ┌─────────────────────────────┐  │
                    │  │       GameServer (TCP)       │  │
                    │  │  MessageRouter + Handlers    │  │
                    │  └──────────┬──────────────────┘  │
                    │  ┌──────────▼──────────────────┐  │
                    │  │    5 State Singletons        │  │
                    │  │  Simulation │ Tavern │ Market │  │
                    │  │  NorthGate  │ Positions      │  │
                    │  └─────────────────────────────┘  │
                    │  ┌─────────────────────────────┐  │
                    │  │   EmbeddedClientManager      │  │
                    │  │  (arranca clientes in-proc)  │  │
                    │  └─────────────────────────────┘  │
                    └──────────┬───────────────────────┘
                               │ TCP :5000
          ┌────────────────────┼────────────────────┐
          ▼                    ▼                     ▼
  ┌───────────────┐  ┌─────────────────┐  ┌──────────────────┐
  │  Elisabetha   │  │     Lance       │  │   Alquimistas    │
  │  1 conexion   │  │  1 conexion     │  │  N conexiones    │
  │  5 hilos      │  │  5 hilos        │  │  1 hilo/alquim.  │
  │  (princesa +  │  │  (caballero +   │  │  (Mordecai,      │
  │   4 damas)    │  │   4 caballeros) │  │   Vespertino)    │
  └───────────────┘  └─────────────────┘  └──────────────────┘

El proyecto consta de 5 proyectos .NET con una separacion limpia de responsabilidades:

Proyecto Tipo Descripcion
Roedalia.Core Class Library Modelos, protocolo TCP, serializacion, configuracion
Roedalia.Server ASP.NET Core Servidor TCP + Dashboard web + Estado de juego
Roedalia.Client.Elisabetha Console App Elisabetha + 4 Damas del Lazo
Roedalia.Client.Lance Console App Lance + 4 Caballeros del Porton Norte
Roedalia.Client.Alquimistas Console App 2 Alquimistas (1 conexion TCP cada uno)

Conceptos de Concurrencia

Este proyecto es un laboratorio practico de programacion concurrente que demuestra:

Concepto Donde se usa
Hilos concurrentes Cada personaje corre en su propio Task con RunAsync()
CancellationToken Propagacion de cancelacion coordinada entre todos los hilos
SemaphoreSlim Exclusion mutua en ElisabethaState.AttendLock y LanceState.AttendLock
ConcurrentQueue Comunicacion productores-consumidores entre damas/caballeros y protagonistas
ConcurrentDictionary Registro de clientes TCP, posiciones de personajes, caballeros heridos
async/await Todo el modelo de concurrencia es asincronico, sin bloqueos
volatile Flags de estado compartido (SimulationEnded, CharacterReady)
Task.WhenAll / WhenAny Coordinacion de grupo: esperar a todos los hilos de un cliente
Productor-Consumidor Damas producen mensajes, Elisabetha los consume cuando atiende
Reader-Writer Lock Estado de Chispa protegido con semaforo para lecturas/escrituras atomicas
Graceful Shutdown CancellationToken + OperationCanceledException para parada limpia

La Chispa

La Chispa es el valor central de la simulacion (0-100) para cada protagonista. Representa el vinculo magico entre Elisabetha y Lance.

     ELISABETHA                          LANCE
 ┌─────────────────┐              ┌─────────────────┐
 │  Pergamino +20  │              │ Duelo limpio +7  │
 │  Reencuentro+10 │              │ Reencuentro +10  │
 │  ─────────────  │              │ ──────────────   │
 │  Rumor dama  -5 │              │ Duelo herida -5  │
 │  Baile oblig -5 │              │ Pocion alq. -20  │
 │  Pergam. mal -5 │              │ Amenaza alq.-30  │
 │  Pocion alq.-20 │              │                  │
 └────────┬────────┘              └────────┬─────────┘
          │                                │
          │     PRIMER ENCUENTRO           │
          │     (Taberna) ──────►  ambos = 75
          │                                │
          │     Pre-encuentro:             │
          │     Elisabetha cap 30          │
          │     Lance cap 50              │
          │                                │
          ▼                                ▼
     Chispa = 100                   Chispa = 100
          │                                │
          └───────────┐  ┌─────────────────┘
                      ▼  ▼
              SIMULACION FINALIZADA

Antes de conocerse: Elisabetha no puede superar Chispa 30 y Lance no puede superar Chispa 50. El primer encuentro en la Taberna eleva a ambos a 75.

Los Alquimistas son la fuerza antagonista: sus pociones restan -20 o -30 de Chispa, intentando que los protagonistas nunca lleguen a 100.


Personajes y sus Hilos

Elisabetha (1 hilo)

Princesa del Castillo de Roedalia. Cada turno elige aleatoriamente entre:

  • Atender a una dama — escucha rumores, confidencias o invitaciones al baile
  • Asistir al baile — solo si una dama la convencio (Chispa -5)
  • Leer pergaminos — 50% emocionante (+20) / 50% soporifero (-5)
  • Escaparse — al Mercado (compra productos) o a la Taberna (posible encuentro con Lance)

4 Damas del Lazo (4 hilos)

Isadora, Celestina, Brunilda y Rosmerta. Cada una:

  • Realiza labores — montar a caballo, esgrima, enterarse de rumores
  • Intenta contactar a Elisabetha — espera a ser la dama seleccionada (patron productor-consumidor con ConcurrentQueue)

Lance (1 hilo)

Caballero de la Guarnicion. Cada turno:

  • Habla con un companero — escucha confidencias u ofensas sobre Elisabetha
  • Desafia a duelo — solo si un caballero ofendio a Elisabetha. 80% victoria limpia (+7), 20% hiere al oponente (-5 + herida 30s)
  • Realiza guardia — en el Porton Norte (inspecciona carretas) o en la Taberna (posible encuentro con Elisabetha)

4 Caballeros del Porton Norte (4 hilos)

Roderick, Bramwell, Thorne y Gareth. Cada uno:

  • Vigila un lugar — Porton Norte, muralla este o torres de vigia
  • Intenta contactar a Lance — 75% confidencia, 25% ofensa sobre Elisabetha (provoca duelo)

2 Alquimistas (2 hilos, 2 conexiones TCP)

Mordecai y Vespertino. Antagonistas que operan desde las Torres:

  • Estudiar calderos (30s) — 30% pocion para Elisabetha, 30% para Lance, 40% fracaso
  • Visitar a Elisabetha — 30% logra aplicar pocion (Chispa -20)
  • Visitar a Lance — 80% intenta enganar con pocion (-20), 20% amenaza (-30)

Ubicaciones

Ubicacion Descripcion Quien la visita
Castillo Hogar de Elisabetha y las damas Elisabetha, Damas, Alquimistas
Guarnicion Cuartel de Lance y los caballeros Lance, Caballeros, Alquimistas
Taberna Punto de encuentro de Elisabetha y Lance Elisabetha, Lance
Mercado Comercio con 8 productos disponibles Elisabetha
Porton Norte Control de carretas (locales vs foraneas) Lance
Torres Laboratorio de los alquimistas Alquimistas

Dashboard Web

El dashboard en http://localhost:8080 muestra en tiempo real:

  • Mapa pixel-art con 6 ubicaciones renderizadas en Canvas
  • Sprites de personajes con animacion de movimiento, idle bounce y etiquetas de actividad
  • Barras de Chispa con 4 colores segun nivel (rojo/azul/naranja/verde)
  • Panel de estado con flags de encuentro y simulacion
  • Panel de ubicaciones con estado de Taberna, Porton Norte y Mercado
  • Log de eventos categorizado por colores (taberna, alquimista, duelo, mercado, epico...)
  • Sistema de particulas con 9 efectos (primer encuentro, reencuentro, duelo, pocion, simulacion finalizada...)
  • Panel de clientes embebidos para arrancar/detener los 3 grupos desde el browser
  • Boton de reinicio para resetear toda la simulacion sin reiniciar el servidor

Inicio Rapido

Requisitos

Ejecutar

# Clonar
git clone https://github.com/redsaporo/Roedalia.git
cd Roedalia

# Compilar
dotnet build Roedalia.sln

# Arrancar servidor (TCP :5000 + HTTP :8080)
dotnet run --project src/Roedalia.Server

Abrir http://localhost:8080 en el navegador.

Opcion A: Clientes embebidos (recomendado)

Pulsa "Iniciar Todos" en el panel CLIENTES del dashboard. Los personajes aparecen en el mapa y comienzan a moverse.

Opcion B: Clientes standalone

En terminales separadas:

# Terminal 2 - Elisabetha + 4 Damas
dotnet run --project src/Roedalia.Client.Elisabetha

# Terminal 3 - Lance + 4 Caballeros
dotnet run --project src/Roedalia.Client.Lance

# Terminal 4 - 2 Alquimistas
dotnet run --project src/Roedalia.Client.Alquimistas

Puertos personalizados

# Servidor con TCP en 6000 y HTTP en 9090
dotnet run --project src/Roedalia.Server -- 6000 9090

# Clientes conectando a puerto TCP personalizado
dotnet run --project src/Roedalia.Client.Elisabetha -- localhost 6000

Estructura del Proyecto

Roedalia/
├── Roedalia.sln
└── src/
    ├── Roedalia.Core/                  # Libreria compartida
    │   ├── GameConfig.cs               # Configuracion centralizada
    │   ├── Models/
    │   │   ├── Character.cs            # Enum CharacterType + nombres
    │   │   ├── Location.cs             # Enum LocationType
    │   │   ├── Product.cs              # Productos, carretas y reglas
    │   │   └── SparkLevel.cs           # Modelo de nivel de Chispa
    │   ├── Network/
    │   │   ├── TcpMessageClient.cs     # Cliente TCP con framing
    │   │   └── TcpMessageServer.cs     # Servidor TCP multi-cliente
    │   └── Protocol/
    │       ├── Message.cs              # Mensaje con Type + Payload JSON
    │       ├── MessageSerializer.cs    # Serializa/deserializa sobre NetworkStream
    │       ├── MessageType.cs          # Enum de tipos de mensaje
    │       ├── Requests/               # DTOs de peticiones
    │       └── Responses/              # DTOs de respuestas
    │
    ├── Roedalia.Server/                # Servidor principal
    │   ├── Program.cs                  # Entry point, DI, Kestrel
    │   ├── GameServer.cs               # TCP server + logica de simulacion
    │   ├── Dashboard/
    │   │   ├── DashboardHub.cs         # Hub SignalR (estado + control clientes)
    │   │   ├── WebDashboard.cs         # Broadcast periodico de estado
    │   │   └── EventEntry.cs           # Modelo de evento
    │   ├── Handlers/
    │   │   ├── MessageRouter.cs        # Enruta mensajes TCP a handlers
    │   │   ├── TavernHandler.cs        # Logica de la Taberna
    │   │   ├── MarketHandler.cs        # Logica del Mercado
    │   │   ├── NorthGateHandler.cs     # Logica del Porton Norte
    │   │   ├── SparkHandler.cs         # Modificacion de Chispa
    │   │   └── AlchemistHandler.cs     # Pociones y amenazas
    │   ├── Services/
    │   │   └── EmbeddedClientManager.cs # Lifecycle de clientes embebidos
    │   ├── State/
    │   │   ├── SimulationState.cs      # Chispa, encuentros, fin
    │   │   ├── TavernState.cs          # Presencia en taberna
    │   │   ├── MarketState.cs          # Ultimo cliente/producto
    │   │   ├── NorthGateState.cs       # Cola de carretas
    │   │   └── CharacterPositionState.cs # Posiciones en el mapa
    │   └── wwwroot/
    │       ├── index.html              # SPA del dashboard
    │       ├── css/style.css           # Estilos pixel-art
    │       └── js/
    │           ├── dashboard.js        # SignalR client + DOM updates
    │           ├── map.js              # Renderizado del mapa en Canvas
    │           └── sprites.js          # Sprites + sistema de particulas
    │
    ├── Roedalia.Client.Elisabetha/     # Cliente: grupo Elisabetha
    │   ├── Program.cs                  # Conexion + arranque de 5 hilos
    │   ├── Characters/
    │   │   ├── ElisabethaThread.cs     # Hilo principal de Elisabetha
    │   │   └── DamaDelLazo.cs          # Hilo de cada dama
    │   └── LocalState/
    │       └── ElisabethaState.cs      # Estado compartido del grupo
    │
    ├── Roedalia.Client.Lance/          # Cliente: grupo Lance
    │   ├── Program.cs                  # Conexion + arranque de 5 hilos
    │   ├── Characters/
    │   │   ├── LanceThread.cs          # Hilo principal de Lance
    │   │   └── CaballeroPortonNorte.cs # Hilo de cada caballero
    │   └── LocalState/
    │       └── LanceState.cs           # Estado compartido del grupo
    │
    └── Roedalia.Client.Alquimistas/    # Cliente: alquimistas
        ├── Program.cs                  # N conexiones TCP independientes
        └── Characters/
            └── AlquimistaThread.cs     # Hilo de cada alquimista

Protocolo TCP

La comunicacion usa un protocolo binario simple con framing por longitud:

┌──────────┬──────────┬─────────────────────┐
│ Length   │  Type    │  JSON Payload       │
│ (4 bytes)│ (4 bytes)│  (variable)         │
└──────────┴──────────┴─────────────────────┘

Tipos de mensaje: RegisterClient, EnterTavern, LeaveTavern, EnterMarket, MarketPurchase, InspectCart, SparkUpdate, SparkQuery, AlchemistVisitElisabetha, AlchemistVisitLance, SimulationEnd, Heartbeat, Ack, entre otros.

Cada mensaje lleva un payload JSON serializado con los datos de la peticion/respuesta correspondiente.


Tecnologias

Componente Tecnologia
Runtime .NET 8 / C# 12
Servidor web ASP.NET Core + Kestrel
Comunicacion TCP TcpListener / TcpClient con async streams
WebSocket SignalR
Frontend HTML5 Canvas + vanilla JavaScript
Fuente Press Start 2P (pixel-art)
Concurrencia Task, SemaphoreSlim, ConcurrentQueue, ConcurrentDictionary, CancellationToken

Licencia

MIT


"La Chispa ha triunfado en Roedalia."

About

El Cantar de la Chispa - Simulacion concurrente en C#/.NET 8 con dashboard web en tiempo real

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors