Tienda In-Game Avanzada para Servidor de MU Online
Aprende a configurar una tienda in-game avanzada en tu servidor de MU Online con categorías, precios dinámicos y gestión de inventario segura.
En un servidor de MU Online, la experiencia del jugador no termina cuando sale del combate. La forma en que accede a items especiales, consumibles o beneficios de cuenta define en gran medida su percepcion del servidor. Una tienda in-game bien configurada elimina la friccion de salir al navegador, r
Introduccion: Por que una Tienda In-Game Marca la Diferencia
En un servidor de MU Online, la experiencia del jugador no termina cuando sale del combate. La forma en que accede a items especiales, consumibles o beneficios de cuenta define en gran medida su percepcion del servidor. Una tienda in-game bien configurada elimina la friccion de salir al navegador, reduce el abandono y da al administrador control fino sobre la economia interna del servidor.
Este tutorial cubre la configuracion avanzada de una tienda in-game sobre bases de datos SQL Server y archivos de configuracion XML tipicos de nucleos compatibles con Season 6 y posteriores. Se asume que ya tienes un servidor funcional con acceso a la base de datos MuOnline y al directorio de configuracion del GameServer.
Estructura de Archivos de la Tienda In-Game
Antes de editar cualquier configuracion, es fundamental entender donde vive cada pieza del sistema. La tienda in-game se compone de tres capas:
- Capa de datos - tablas SQL que almacenan items, categorias, transacciones y saldos de jugadores.
- Capa de configuracion - archivos XML que el GameServer lee al iniciar o recargarse.
- Capa de logica - parametros en
GameServerInfo.xmlque controlan el comportamiento del sistema (moneda aceptada, limites de compra, cooldowns).
La jerarquia tipica de archivos en el directorio del GameServer es la siguiente:
GameServer/
├── Config/
│ ├── GameServerInfo.xml → configuracion global del servidor
│ ├── Shop/
│ │ ├── ShopCategories.xml → definicion de categorias visibles
│ │ ├── ShopItems.xml → catalogo de items y precios
│ │ └── ShopLimits.xml → limites de compra por cuenta/dia
│ └── Rewards/
│ └── ShopRewardPackages.xml → paquetes y bundles con descuento
└── Logs/
└── ShopTransactions/ → logs diarios de transacciones
Cada archivo XML es leido en secuencia. Si un archivo tiene errores de sintaxis, el GameServer omite toda la seccion Shop y registra el error en ServerError.log. Por eso, siempre valida tus XML antes de reiniciar el servidor.
Configuracion de Categorias y Catalogo de Items
Definir Categorias en ShopCategories.xml
Las categorias organizan visualmente la tienda para el jugador. Una categoria mal nombrada o vacia genera confusion y abandono. Define categorias concretas y coherentes con tu loot table.
<!-- ShopCategories.xml -->
<ShopCategories>
<!-- Categoria 1: Armas y Armaduras -->
<Category id="1" name="Equipamiento" icon="icon_sword" order="1" enabled="1"/>
<!-- Categoria 2: Consumibles -->
<Category id="2" name="Consumibles" icon="icon_potion" order="2" enabled="1"/>
<!-- Categoria 3: Servicios de cuenta -->
<Category id="3" name="Servicios" icon="icon_star" order="3" enabled="1"/>
<!-- Categoria 4: Eventos (activa solo durante eventos) -->
<Category id="4" name="Evento Especial" icon="icon_event" order="4" enabled="0"/>
</ShopCategories>
El atributo enabled="0" oculta la categoria sin borrarla. Util para eventos temporales: activa y desactiva sin tocar el catalogo de items.
Definir Items en ShopItems.xml
Cada entrada de item vincula un producto con su categoria, precio y restricciones. Presta especial atencion a los campos ItemCode e ItemOption, que deben corresponder exactamente a los valores de la tabla Item en la base de datos MuOnline.
<!-- ShopItems.xml — fragmento con buenas practicas -->
<ShopItems>
<!-- Item basico sin opciones especiales -->
<Item
id="1001"
categoryId="1"
name="Sword of Destruction +9"
ItemCode="0x12"
ItemLevel="9"
ItemOption="0"
price="500"
currency="WCoin"
stock="-1"
limitPerAccount="1"
limitPerDay="0"
enabled="1"
/>
<!-- Item con descuento por tiempo limitado -->
<Item
id="1002"
categoryId="2"
name="Pack Jewel of Bless x30"
ItemCode="0x0E"
ItemLevel="0"
ItemOption="0"
ItemAmount="30"
price="200"
salePricePct="25"
SaleStart="2026-07-01T00:00:00"
SaleEnd="2026-07-07T23:59:59"
currency="WCoin"
stock="1000"
limitPerAccount="3"
limitPerDay="1"
enabled="1"
/>
<!-- Servicio: Reset de stats -->
<Item
id="2001"
categoryId="3"
name="Reset de Personaje"
ItemCode="SERVICE_RESET"
price="1000"
currency="WCoin"
stock="-1"
limitPerAccount="-1"
limitPerDay="1"
RequireLevel="400"
enabled="1"
/>
</ShopItems>
Campos clave a entender:
stock="-1"→ stock ilimitado.limitPerAccount="-1"→ sin limite por cuenta.limitPerDay="1"→ maximo una compra por dia calendario (reset a medianoche UTC del servidor).salePricePct="25"→ descuento del 25% aplicado automaticamente dentro de la ventana SaleStart/SaleEnd.RequireLevel="400"→ el personaje debe tener al menos nivel 400 para ver y comprar el item.
> [!CONSEJO] > Utiliza el campo RequireLevel combinado con limitPerAccount para disenar una progresion economica justa. Por ejemplo, los paquetes de Jewels baratos solo disponibles para cuentas con menos de 5 resets incentivan la permanencia de jugadores nuevos sin desequilibrar la economia de los veteranos.
Configuracion de la Base de Datos SQL
La tienda necesita dos tablas principales en la base de datos MuOnline. Si tu nucleo no las crea automaticamente, debes crearlas antes de activar el sistema.
-- Tabla de saldos de WCoin por cuenta
CREATE TABLE T_WCoinC (
AccountID VARCHAR(10) NOT NULL PRIMARY KEY,
WCoinC INT NOT NULL DEFAULT 0,
CONSTRAINT CK_WCoinC_NonNegative CHECK (WCoinC >= 0)
);
-- Tabla de log de transacciones de tienda
-- AccountID → identifica la cuenta → vinculado a T_WCoinC
-- SessionToken → previene duplicacion por reconexion rapida
CREATE TABLE T_ShopLog (
LogID INT IDENTITY(1,1) PRIMARY KEY,
AccountID VARCHAR(10) NOT NULL,
CharacterName VARCHAR(10) NOT NULL,
ItemID INT NOT NULL,
ItemName VARCHAR(100) NOT NULL,
Price INT NOT NULL,
Currency VARCHAR(20) NOT NULL,
Quantity INT NOT NULL DEFAULT 1,
TransactionDate DATETIME NOT NULL DEFAULT GETDATE(),
SessionToken VARCHAR(64) NOT NULL,
Result TINYINT NOT NULL -- 1=exitoso, 0=fallido
);
-- Indice para consultas de auditoria por fecha
CREATE INDEX IX_ShopLog_Date ON T_ShopLog (TransactionDate, AccountID);
El campo SessionToken es crucial para prevenir duplicaciones. Antes de procesar una compra, el servidor verifica que el token no exista ya en T_ShopLog. Si existe, rechaza la operacion aunque el cliente vuelva a enviarla.
Limites y Seguridad del Sistema
Configurar ShopLimits.xml
Los limites globales actuan como una segunda capa de proteccion sobre los limites por item definidos en ShopItems.xml.
<!-- ShopLimits.xml -->
<ShopLimits>
<!-- Gasto maximo diario por cuenta (en WCoin) -->
<GlobalDailyLimit currency="WCoin" maxAmount="5000"/>
<!-- Maximo de transacciones por sesion de juego -->
<SessionTransactionLimit max="20"/>
<!-- Cooldown entre compras del mismo item (segundos) -->
<ItemCooldown seconds="10"/>
<!-- IPs bloqueadas (abuso detectado) — se actualiza en caliente -->
<BlockedIPs>
<!-- <IP address="192.168.1.100"/> -->
</BlockedIPs>
</ShopLimits>
> [!ATENCION] > El GlobalDailyLimit no es un limite de gasto real de dinero: es un limite de consumo de WCoin acumulado por cuenta en 24 horas. Ajustalo segun la capacidad de obtencion de WCoin en tu servidor. Un limite demasiado bajo frustra a jugadores activos; uno demasiado alto puede ser explotado para farming masivo de items mediante multiples cuentas.
Habilitar la Tienda en GameServerInfo.xml
Finalmente, activa el subsistema de tienda en la configuracion principal del servidor:
<!-- Fragmento relevante de GameServerInfo.xml -->
<InGameShop>
<Enable>1</Enable>
<ShopNPCMap>0</ShopNPCMap> <!-- 0 = Lorencia, mapa de acceso al NPC -->
<ShopNPCX>135</ShopNPCX>
<ShopNPCY>118</ShopNPCY>
<ReloadOnChange>1</ReloadOnChange> <!-- recarga XML sin reiniciar el servidor -->
<LogTransactions>1</LogTransactions>
<CurrencyTable>T_WCoinC</CurrencyTable>
<LogTable>T_ShopLog</LogTable>
</InGameShop>
Con ReloadOnChange="1" activado, el GameServer monitorea los archivos XML de la carpeta Shop. Cada vez que guardas un cambio, el servidor los recarga automaticamente en un plazo de 30 segundos sin necesidad de reinicio. Esto es invaluable durante eventos donde necesitas ajustar precios o stock en tiempo real.
Mantenimiento y Monitoreo Continuo
Una tienda bien configurada no es estatica. Define una rutina de mantenimiento semanal:
- Revisar
T_ShopLogbuscando patrones de compra anomalos (muchas compras del mismo item por la misma IP en minutos). - Rotar los logs de transacciones archivando registros con mas de 90 dias en una tabla
T_ShopLog_Archive. - Actualizar el stock de items con
stock > 0para evitar que categorias populares queden vacias sin aviso. - Validar el XML despues de cada edicion con un validador de esquema antes de guardar en produccion.
Con estos fundamentos implementados, tu tienda in-game opera de forma robusta, auditada y preparada para escalar con el crecimiento de la poblacion de tu servidor.
Preguntas frecuentes
¿Qué es una tienda in-game en MU Online?
Es un sistema integrado en el servidor que permite a los jugadores comprar ítems, servicios o beneficios usando moneda del juego o puntos especiales, sin salir del cliente.
¿Cuál es la diferencia entre WebShop y tienda in-game?
El WebShop opera desde un navegador externo, mientras que la tienda in-game se accede directamente desde el cliente de MU, ofreciendo una experiencia más fluida e integrada.
¿Puedo configurar descuentos automáticos por tiempo en la tienda?
Sí, usando los parámetros de SaleStart y SaleEnd en el archivo ShopItems.xml puedes definir ventanas horarias o por fechas para aplicar descuentos automáticos.
¿Cómo evito que jugadores dupliquen ítems usando la tienda?
Implementa validación de transacción con token único por sesión y registra cada operación en la tabla T_ShopLog antes de entregar el ítem al personaje.