baseline: OpenMU upstream b5a0961 (fresh source)

This commit is contained in:
Acentech Dev
2026-07-14 19:00:35 +03:00
parent 450402e47d
commit 36fc125d5c
11968 changed files with 748705 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
// <copyright file="NpcDialogClosedPlugIn075.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.GameServer.RemoteView.NPC;
using System.Runtime.InteropServices;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Views.NPC;
using MUnique.OpenMU.Network.Packets.ServerToClient;
using MUnique.OpenMU.Network.PlugIns;
using MUnique.OpenMU.PlugIns;
/// <summary>
/// The default implementation of the <see cref="IShowItemCraftingResultPlugIn"/> which is forwarding everything to the game client with specific data packets.
/// </summary>
[PlugIn]
[Display(Name = nameof(PlugInResources.NpcDialogClosedPlugIn075_Name), Description = nameof(PlugInResources.NpcDialogClosedPlugIn075_Description), ResourceType = typeof(PlugInResources))]
[Guid("BAC39AFE-F277-48FD-BB21-A3F905EE0E73")]
[MaximumClient(0, 255, ClientLanguage.Invariant)]
public class NpcDialogClosedPlugIn075 : INpcDialogClosedPlugIn
{
private readonly RemotePlayer _player;
/// <summary>
/// Initializes a new instance of the <see cref="NpcDialogClosedPlugIn075"/> class.
/// </summary>
/// <param name="player">The player.</param>
public NpcDialogClosedPlugIn075(RemotePlayer player)
{
this._player = player;
}
/// <inheritdoc />
public async ValueTask DialogClosedAsync(MonsterDefinition npc)
{
if (npc.NpcWindow == NpcWindow.ChaosMachine)
{
await this._player.Connection.SendCraftingDialogClosed075Async().ConfigureAwait(false);
}
}
}

View File

@@ -0,0 +1,80 @@
// <copyright file="OpenNpcWindowPlugIn.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.GameServer.RemoteView.NPC;
using System.Runtime.InteropServices;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Views.NPC;
using MUnique.OpenMU.Network;
using MUnique.OpenMU.Network.Packets.ServerToClient;
using MUnique.OpenMU.PlugIns;
/// <summary>
/// The default implementation of the <see cref="IOpenNpcWindowPlugIn"/> which is forwarding everything to the game client with specific data packets.
/// </summary>
[PlugIn]
[Display(Name = nameof(PlugInResources.OpenNpcWindowPlugIn_Name), Description = nameof(PlugInResources.OpenNpcWindowPlugIn_Description), ResourceType = typeof(PlugInResources))]
[Guid("3d77d6ef-479c-45f6-8ec9-a7bb046d306a")]
public class OpenNpcWindowPlugIn : IOpenNpcWindowPlugIn
{
private readonly RemotePlayer _player;
/// <summary>
/// Initializes a new instance of the <see cref="OpenNpcWindowPlugIn"/> class.
/// </summary>
/// <param name="player">The player.</param>
public OpenNpcWindowPlugIn(RemotePlayer player) => this._player = player;
/// <inheritdoc/>
public async ValueTask OpenNpcWindowAsync(NpcWindow window)
{
if (window == NpcWindow.NpcDialog)
{
if (this._player.OpenedNpc is not null)
{
await this._player.Connection.SendOpenNpcDialogAsync(this._player.OpenedNpc.Definition.Number.ToUnsigned(), 0).ConfigureAwait(false);
}
}
else
{
await this._player.Connection.SendNpcWindowResponseAsync(Convert(window)).ConfigureAwait(false);
}
}
private static NpcWindowResponse.NpcWindow Convert(NpcWindow window)
{
return window switch
{
NpcWindow.Merchant => NpcWindowResponse.NpcWindow.Merchant,
NpcWindow.Merchant1 => NpcWindowResponse.NpcWindow.Merchant1,
NpcWindow.VaultStorage => NpcWindowResponse.NpcWindow.VaultStorage,
NpcWindow.ChaosMachine => NpcWindowResponse.NpcWindow.ChaosMachine,
NpcWindow.DevilSquare => NpcWindowResponse.NpcWindow.DevilSquare,
NpcWindow.BloodCastle => NpcWindowResponse.NpcWindow.BloodCastle,
NpcWindow.PetTrainer => NpcWindowResponse.NpcWindow.PetTrainer,
NpcWindow.Lahap => NpcWindowResponse.NpcWindow.Lahap,
NpcWindow.CastleSeniorNPC => NpcWindowResponse.NpcWindow.CastleSeniorNPC,
NpcWindow.ElphisRefinery => NpcWindowResponse.NpcWindow.ElphisRefinery,
NpcWindow.RefineStoneMaking => NpcWindowResponse.NpcWindow.RefineStoneMaking,
NpcWindow.RemoveJohOption => NpcWindowResponse.NpcWindow.RemoveJohOption,
NpcWindow.IllusionTemple => NpcWindowResponse.NpcWindow.IllusionTemple,
NpcWindow.ChaosCardCombination => NpcWindowResponse.NpcWindow.ChaosCardCombination,
NpcWindow.CherryBlossomBranchesAssembly => NpcWindowResponse.NpcWindow.CherryBlossomBranchesAssembly,
NpcWindow.SeedMaster => NpcWindowResponse.NpcWindow.SeedMaster,
NpcWindow.SeedResearcher => NpcWindowResponse.NpcWindow.SeedResearcher,
NpcWindow.StatReInitializer => NpcWindowResponse.NpcWindow.StatReInitializer,
NpcWindow.DelgadoLuckyCoinRegistration => NpcWindowResponse.NpcWindow.DelgadoLuckyCoinRegistration,
NpcWindow.DoorkeeperTitusDuelWatch => NpcWindowResponse.NpcWindow.DoorkeeperTitusDuelWatch,
NpcWindow.LugardDoppelgangerEntry => NpcWindowResponse.NpcWindow.LugardDoppelgangerEntry,
NpcWindow.JerintGaionEvententry => NpcWindowResponse.NpcWindow.JerintGaionEvententry,
NpcWindow.JuliaWarpMarketServer => NpcWindowResponse.NpcWindow.JuliaWarpMarketServer,
NpcWindow.CombineLuckyItem => NpcWindowResponse.NpcWindow.CombineLuckyItem,
NpcWindow.GuildMaster => throw new ArgumentException("guild master dialog is opened by another action."),
NpcWindow.NpcDialog => throw new ArgumentException("The quest dialog is opened by another action"),
NpcWindow.LegacyQuest => throw new ArgumentException("The legacy quest dialog is opened by another action"),
_ => throw new ArgumentException($"Unhandled case {window}."),
};
}
}

View File

@@ -0,0 +1,62 @@
// <copyright file="ShowItemCraftingResultPlugIn.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.GameServer.RemoteView.NPC;
using System.Runtime.InteropServices;
using MUnique.OpenMU.DataModel.Entities;
using MUnique.OpenMU.GameLogic.Views.NPC;
using MUnique.OpenMU.Network.Packets.ServerToClient;
using MUnique.OpenMU.PlugIns;
/// <summary>
/// The default implementation of the <see cref="IShowItemCraftingResultPlugIn"/> which is forwarding everything to the game client with specific data packets.
/// </summary>
[PlugIn]
[Display(Name = nameof(PlugInResources.ShowItemCraftingResultPlugIn_Name), Description = nameof(PlugInResources.ShowItemCraftingResultPlugIn_Description), ResourceType = typeof(PlugInResources))]
[Guid("D4339CC0-3E44-4F51-9186-9C3CB02F99F6")]
public class ShowItemCraftingResultPlugIn : IShowItemCraftingResultPlugIn
{
private readonly RemotePlayer _player;
/// <summary>
/// Initializes a new instance of the <see cref="ShowItemCraftingResultPlugIn"/> class.
/// </summary>
/// <param name="player">The player.</param>
public ShowItemCraftingResultPlugIn(RemotePlayer player)
{
this._player = player;
}
/// <inheritdoc />
public async ValueTask ShowResultAsync(CraftingResult result, Item? createdItem)
{
var itemData = new byte[this._player.ItemSerializer.NeededSpace];
if (createdItem is { })
{
this._player.ItemSerializer.SerializeItem(itemData, createdItem);
}
await this._player.Connection.SendItemCraftingResultAsync(Convert(result), itemData).ConfigureAwait(false);
}
private static ItemCraftingResult.CraftingResult Convert(CraftingResult result)
{
return result switch
{
CraftingResult.Success => ItemCraftingResult.CraftingResult.Success,
CraftingResult.Failed => ItemCraftingResult.CraftingResult.Failed,
CraftingResult.NotEnoughMoney => ItemCraftingResult.CraftingResult.NotEnoughMoney,
CraftingResult.CharacterClassTooLow => ItemCraftingResult.CraftingResult.CharacterClassTooLow,
CraftingResult.CharacterLevelTooLow => ItemCraftingResult.CraftingResult.CharacterLevelTooLow,
CraftingResult.IncorrectBloodCastleItems => ItemCraftingResult.CraftingResult.IncorrectBloodCastleItems,
CraftingResult.NotEnoughMoneyForBloodCastle => ItemCraftingResult.CraftingResult.NotEnoughMoneyForBloodCastle,
CraftingResult.IncorrectMixItems => ItemCraftingResult.CraftingResult.IncorrectMixItems,
CraftingResult.InvalidItemLevel => ItemCraftingResult.CraftingResult.InvalidItemLevel,
CraftingResult.LackingMixItems => ItemCraftingResult.CraftingResult.LackingMixItems,
CraftingResult.TooManyItems => ItemCraftingResult.CraftingResult.TooManyItems,
_ => throw new ArgumentException($"Unknown crafting result {result}.", nameof(result)),
};
}
}

View File

@@ -0,0 +1,88 @@
// <copyright file="ShowMerchantStoreItemListPlugIn.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.GameServer.RemoteView.NPC;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging;
using MUnique.OpenMU.DataModel.Entities;
using MUnique.OpenMU.GameLogic.Views.NPC;
using MUnique.OpenMU.Network;
using MUnique.OpenMU.Network.Packets.ServerToClient;
using MUnique.OpenMU.PlugIns;
/// <summary>
/// The default implementation of the <see cref="IShowMerchantStoreItemListPlugIn"/> which is forwarding everything to the game client with specific data packets.
/// </summary>
[PlugIn]
[Display(Name = nameof(PlugInResources.ShowMerchantStoreItemListPlugIn_Name), Description = nameof(PlugInResources.ShowMerchantStoreItemListPlugIn_Description), ResourceType = typeof(PlugInResources))]
[Guid("53e00ae0-4d5b-4f63-88e0-7d526f8438af")]
public class ShowMerchantStoreItemListPlugIn : IShowMerchantStoreItemListPlugIn
{
private readonly RemotePlayer _player;
/// <summary>
/// Initializes a new instance of the <see cref="ShowMerchantStoreItemListPlugIn"/> class.
/// </summary>
/// <param name="player">The player.</param>
public ShowMerchantStoreItemListPlugIn(RemotePlayer player) => this._player = player;
/// <inheritdoc/>
public async ValueTask ShowMerchantStoreItemListAsync(ICollection<Item> storeItems, StoreKind storeKind)
{
var connection = this._player.Connection;
if (connection is null)
{
return;
}
int Write()
{
var itemSerializer = this._player.ItemSerializer;
int sizePerItem = StoredItemRef.GetRequiredSize(itemSerializer.NeededSpace);
var size = StoreItemListRef.GetRequiredSize(storeItems.Count, sizePerItem);
var span = connection.Output.GetSpan(size)[..size];
var packet = new StoreItemListRef(span)
{
ItemCount = (byte)storeItems.Count,
Type = Convert(storeKind),
};
int headerSize = StoreItemListRef.GetRequiredSize(0, 0);
int actualSize = headerSize;
int i = 0;
foreach (var item in storeItems)
{
if (item.Definition is null)
{
this._player.Logger.LogWarning("Item {0} has no definition.", item);
packet.ItemCount--;
continue;
}
var storedItem = new StoredItemRef(span[actualSize..]);
storedItem.ItemSlot = item.ItemSlot;
var itemSize = itemSerializer.SerializeItem(storedItem.ItemData, item);
actualSize += StoredItemRef.GetRequiredSize(itemSize);
i++;
}
span.Slice(0, actualSize).SetPacketSize();
return actualSize;
}
await connection.SendAsync(Write).ConfigureAwait(false);
}
private static StoreItemList.ItemWindow Convert(StoreKind storeKind)
{
return storeKind switch
{
StoreKind.Normal => StoreItemList.ItemWindow.Normal,
StoreKind.ChaosMachine => StoreItemList.ItemWindow.ChaosMachine,
StoreKind.ResurrectionFailed => StoreItemList.ItemWindow.ResurrectionFailed,
_ => throw new ArgumentException($"Unknown value {storeKind}", nameof(storeKind)),
};
}
}

View File

@@ -0,0 +1,34 @@
// <copyright file="ShowMessageOfObjectPlugIn.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.GameServer.RemoteView.NPC;
using System.Runtime.InteropServices;
using MUnique.OpenMU.GameLogic;
using MUnique.OpenMU.GameLogic.Views.NPC;
using MUnique.OpenMU.Network.Packets.ServerToClient;
using MUnique.OpenMU.PlugIns;
/// <summary>
/// The default implementation of the <see cref="IShowMessageOfObjectPlugIn"/> which is forwarding everything to the game client with specific data packets.
/// </summary>
[PlugIn]
[Display(Name = nameof(PlugInResources.ShowMessageOfObjectPlugIn_Name), Description = nameof(PlugInResources.ShowMessageOfObjectPlugIn_Description), ResourceType = typeof(PlugInResources))]
[Guid("41d28cd1-1fb7-4af7-b635-8af9923351bd")]
public class ShowMessageOfObjectPlugIn : IShowMessageOfObjectPlugIn
{
private readonly RemotePlayer _player;
/// <summary>
/// Initializes a new instance of the <see cref="ShowMessageOfObjectPlugIn"/> class.
/// </summary>
/// <param name="player">The player.</param>
public ShowMessageOfObjectPlugIn(RemotePlayer player) => this._player = player;
/// <inheritdoc />
public async ValueTask ShowMessageOfObjectAsync(string message, IIdentifiable sender)
{
await this._player.Connection.SendObjectMessageAsync(sender.Id, message).ConfigureAwait(false);
}
}