mirror of
https://github.com/sven-n/MuMain
synced 2026-08-15 20:32:27 -04:00
The engine now boots into the login scene, renders via SDL/OpenGL, and connects to a server on Linux. Brings up the remaining runtime pieces and fixes the bugs that surfaced once the game actually ran. Networking (.NET client library on Linux): - Build MUnique.Client.Library as a native linux-x64 Native AOT shared object and dlopen the .so instead of the Windows .dll. - Fix the native-to-managed string marshalling: the client passes wchar_t*, which is 4-byte UTF-32 on Linux but the library decoded it as UTF-16, garbling the server address into a bogus IP so connect() hung forever on the main thread (the apparent "black screen"). Decode by the platform's real wchar_t width. Updates the XSLT template so regeneration stays correct. Runtime fixes uncovered by running: - Config was never read on Linux: the exe-dir split looked for a backslash only, so config.ini was never found and every setting fell back to its default. Accept either path separator. - UI piled into the top-left: CInput::Create bailed on the null SDL window handle before setting the screen size, so centered windows computed negative positions. Set the size regardless of the handle off Windows. - LP64 width bugs reading binary assets (size fields are 32-bit on disk, but long/size_t are 8 bytes on Linux x64): pet.bmd speed array, BMD encrypted size, camera walk-script waypoint count. - Double fclose() of the same handle (filter file, object files): tolerated on the old CRT, a double-free on glibc. - mu_swprintf bounds the buffer by its real array size to stop a fortify abort, and the GL frame can be dumped via MU_CAPTURE_FRAME for headless verification. Portable subsystems: - GDI text backend backed by stb_truetype (CreateFont/CreateDIBSection/ TextOut), so UI text renders without Win32 GDI. - Case-correcting path resolver so Windows-style asset paths resolve on a case-sensitive filesystem, wired through every file-open shim. - GameShop compiles on Linux: the UI and list managers build, only the WinINet/urlmon downloader is excluded, with the download entry points failing gracefully. - Portable shims extended: StrSafe, Sleep/GetLastError, file attribute and directory helpers, system-info for the crash log, and the Linux entry point now calls the shared WinMain bootstrap.
289 lines
10 KiB
HTML
289 lines
10 KiB
HTML
<?xml version="1.0" encoding="utf-8"?>
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
|
|
xmlns:pd="http://www.munique.net/OpenMU/PacketDefinitions"
|
|
>
|
|
<xsl:param name="subNamespace" />
|
|
<xsl:output method="text" indent="yes" />
|
|
<xsl:include href="Common.xslt" />
|
|
|
|
<xsl:template match="pd:PacketDefinitions">
|
|
<xsl:text>// <copyright file="ConnectionManager.cs" company="MUnique">
|
|
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
|
// </copyright>
|
|
|
|
//------------------------------------------------------------------------------
|
|
// <auto-generated>
|
|
// This source code was auto-generated by an XSL transformation.
|
|
// Do not change this file. Instead, change the XML data which contains
|
|
// the packet definitions and re-run the transformation (publish/rebuild the
|
|
// client library project).
|
|
// </auto-generated>
|
|
//------------------------------------------------------------------------------
|
|
|
|
// ReSharper disable RedundantVerbatimPrefix
|
|
// ReSharper disable AssignmentIsFullyDiscarded
|
|
// ReSharper disable UnusedMember.Global
|
|
// ReSharper disable UseObjectOrCollectionInitializer
|
|
|
|
#nullable enable
|
|
namespace MUnique.Client.Library;
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
using MUnique.OpenMU.Network;
|
|
using MUnique.OpenMU.Network.Packets;
|
|
using MUnique.OpenMU.Network.Packets.</xsl:text><xsl:value-of select="$subNamespace"/><xsl:text>;
|
|
|
|
/// <summary>
|
|
/// Extension methods to start writing messages of this namespace on a <see cref="IConnection"/>.
|
|
/// </summary>
|
|
public unsafe partial class ConnectionManager
|
|
{</xsl:text>
|
|
<xsl:apply-templates select="pd:Packets/pd:Packet" mode="ext2" />
|
|
<xsl:text>}</xsl:text>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="pd:Packet[not(pd:Fields/pd:Field/pd:Type = 'Structure[]')]" mode="ext2">
|
|
<xsl:value-of select="$newline" />
|
|
<xsl:text>
|
|
/// <summary>
|
|
/// Sends a <see cref="</xsl:text>
|
|
<xsl:apply-templates select="pd:Name" />
|
|
<xsl:text>" /> to this connection.
|
|
/// </summary>
|
|
/// <param name="handle">The handle of the connection.</param></xsl:text>
|
|
<xsl:apply-templates select="pd:Fields/pd:Field" mode="paramdoc">
|
|
<xsl:sort select="pd:DefaultValue"/>
|
|
</xsl:apply-templates>
|
|
<xsl:call-template name="WriteRemarks" />
|
|
<xsl:text> [UnmanagedCallersOnly(EntryPoint = "Send</xsl:text>
|
|
<xsl:apply-templates select="pd:Name" />
|
|
<xsl:text>")]
|
|
public static void </xsl:text>
|
|
<xsl:text>Send</xsl:text>
|
|
<xsl:apply-templates select="pd:Name" />
|
|
<xsl:text>(int handle</xsl:text>
|
|
<xsl:if test="count(pd:Fields/pd:Field) > 0">
|
|
<xsl:text>, </xsl:text>
|
|
</xsl:if>
|
|
<xsl:apply-templates select="pd:Fields/pd:Field" mode="params">
|
|
<xsl:sort select="pd:DefaultValue"/>
|
|
</xsl:apply-templates>
|
|
<xsl:text>)</xsl:text>
|
|
<xsl:value-of select="$newline"/>
|
|
<xsl:text> {
|
|
if (!Connections.TryGetValue(handle, out var connection))
|
|
{
|
|
return;
|
|
}
|
|
|
|
try</xsl:text>
|
|
<xsl:text>
|
|
{
|
|
connection.CreateAndSend(pipeWriter =>
|
|
{
|
|
var length = </xsl:text>
|
|
<xsl:choose>
|
|
<xsl:when test="pd:Length">
|
|
<xsl:apply-templates select="pd:Name" />
|
|
<xsl:text>Ref.Length</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test="not(pd:Length)">
|
|
<xsl:apply-templates select="pd:Name" />
|
|
<xsl:text>Ref.GetRequiredSize(</xsl:text>
|
|
<xsl:apply-templates select="pd:Fields/pd:Field[(pd:Type = 'Binary' or pd:Type = 'String') and not(pd:Length)]" mode="length"/>
|
|
<xsl:text>)</xsl:text>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
throw new NotImplementedException()
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
<xsl:text>;
|
|
var packet = new </xsl:text>
|
|
<xsl:apply-templates select="pd:Name" />
|
|
<xsl:text>Ref(pipeWriter.GetSpan(length)[..length]);</xsl:text>
|
|
<xsl:if test="pd:Fields/pd:Field">
|
|
<xsl:value-of select="$newline"/>
|
|
<xsl:apply-templates select="pd:Fields/pd:Field" mode="assignment" />
|
|
</xsl:if>
|
|
<xsl:text>
|
|
return length;
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.WriteLine(ex);
|
|
}
|
|
}</xsl:text>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="pd:Field[(pd:Type = 'Binary')]" mode="length">
|
|
<xsl:text>(int)</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>ByteLength</xsl:text>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="pd:Field[(pd:Type = 'String')]" mode="length">
|
|
<xsl:text>Encoding.UTF8.GetByteCount(NativeInterop.PtrToWideString(@</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>)!)</xsl:text>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="pd:Field" mode="paramdoc">
|
|
<xsl:value-of select="$newline"/>
|
|
<xsl:text> /// <param name="</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>"></xsl:text>
|
|
<xsl:choose>
|
|
<xsl:when test="pd:Description">
|
|
<xsl:value-of select="pd:Description"/>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:text>The</xsl:text>
|
|
<xsl:call-template name="splitName">
|
|
<xsl:with-param name="name" select="pd:Name" />
|
|
</xsl:call-template>
|
|
<xsl:text>.</xsl:text>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
|
|
<xsl:text></param></xsl:text>
|
|
|
|
<xsl:if test="(pd:Type = 'Binary')">
|
|
<xsl:value-of select="$newline"/>
|
|
<xsl:text> /// <param name="</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>ByteLength</xsl:text>
|
|
<xsl:text>">The length of <paramref name="</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>"/>.</xsl:text>
|
|
<xsl:text></param></xsl:text>
|
|
</xsl:if>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="pd:Type[. = 'Binary']" mode="type">Memory<byte></xsl:template>
|
|
|
|
<xsl:template match="pd:DefaultValue" mode="params">
|
|
<xsl:choose>
|
|
<xsl:when test=". = 'true'">1</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:value-of select="."/>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:template>
|
|
<xsl:template match="pd:Field" mode="params">
|
|
<xsl:if test="position() > 1">
|
|
<xsl:text>, </xsl:text>
|
|
</xsl:if>
|
|
<xsl:apply-templates select="pd:Type" mode="blittabletype"/>
|
|
<xsl:text> @</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:if test="pd:DefaultValue">
|
|
<xsl:text> = </xsl:text>
|
|
<xsl:apply-templates select="pd:DefaultValue" mode="params"/>
|
|
</xsl:if>
|
|
<xsl:if test="(pd:Type = 'Binary')">
|
|
<xsl:text>, uint </xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>ByteLength</xsl:text>
|
|
</xsl:if>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="pd:Field" mode="listparams">
|
|
<xsl:if test="position() > 1">
|
|
<xsl:text>, </xsl:text>
|
|
</xsl:if>
|
|
<xsl:text>@</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
</xsl:template>
|
|
|
|
<xsl:template match="pd:Field" mode="assignment">
|
|
<xsl:choose>
|
|
<xsl:when test="pd:Type='Binary'">
|
|
<xsl:text> new Span<byte>(@</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>, (int)</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>ByteLength).CopyTo(packet.</xsl:text>
|
|
<xsl:value-of select="pd:Name"/>
|
|
<xsl:text>);</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test="pd:Type='Boolean'">
|
|
<xsl:text> packet.</xsl:text>
|
|
<xsl:value-of select="pd:Name"/>
|
|
<xsl:text> = @</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text> == 1;</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test="pd:Type='String'">
|
|
<xsl:text> packet.</xsl:text>
|
|
<xsl:value-of select="pd:Name"/>
|
|
<xsl:text> = NativeInterop.PtrToWideString(@</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>);</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test="pd:Type='Binary'">
|
|
<xsl:text> packet.</xsl:text>
|
|
<xsl:value-of select="pd:Name"/>
|
|
<xsl:text> = new Span<byte>(@</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>, (int)</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>ByteLength);</xsl:text>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:text> packet.</xsl:text>
|
|
<xsl:value-of select="pd:Name"/>
|
|
<xsl:text> = @</xsl:text>
|
|
<xsl:call-template name="LowerCaseName" />
|
|
<xsl:text>;</xsl:text>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
<xsl:value-of select="$newline"/>
|
|
</xsl:template>
|
|
|
|
<xsl:template name="WriteRemarks">
|
|
<xsl:if test="pd:SentWhen or pd:CausedReaction">
|
|
<xsl:text>
|
|
/// <remarks>
|
|
/// Is sent </xsl:text>
|
|
<xsl:choose>
|
|
<xsl:when test="pd:Direction = 'ClientToServer'">
|
|
<xsl:text>by the client when: </xsl:text>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:text>by the server when: </xsl:text>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
<xsl:value-of select="pd:SentWhen"/>
|
|
<xsl:text>
|
|
/// Causes reaction </xsl:text>
|
|
<xsl:choose>
|
|
<xsl:when test="pd:Direction = 'ClientToServer'">
|
|
<xsl:text>on server side: </xsl:text>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:text>on client side: </xsl:text>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
<xsl:value-of select="pd:CausedReaction"/>
|
|
<xsl:text>
|
|
/// </remarks></xsl:text>
|
|
<xsl:value-of select="$newline" />
|
|
</xsl:if>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="text()" mode="params"></xsl:template>
|
|
<xsl:template match="text()" mode="listparams"></xsl:template>
|
|
<xsl:template match="text()" mode="paramdoc"></xsl:template>
|
|
<xsl:template match="text()" mode="assignment"></xsl:template>
|
|
<xsl:template match="text()" mode="ext2"></xsl:template>
|
|
<xsl:template match="text()" mode="length"></xsl:template>
|
|
<xsl:template match="text()" mode="writer"></xsl:template>
|
|
<xsl:template match="text()"></xsl:template>
|
|
|
|
</xsl:stylesheet>
|