baseline: OpenMU upstream b5a0961 (fresh source)
This commit is contained in:
14
src/Interfaces/AllianceGuildEntry.cs
Normal file
14
src/Interfaces/AllianceGuildEntry.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
// <copyright file="AllianceGuildEntry.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// An entry of the alliance guild list.
|
||||
/// </summary>
|
||||
/// <param name="Id">The unique identifier of the guild.</param>
|
||||
/// <param name="GuildName">The name of the guild.</param>
|
||||
/// <param name="MemberCount">The number of members in the guild.</param>
|
||||
/// <param name="Logo">The logo of the guild.</param>
|
||||
public record AllianceGuildEntry(uint Id, string GuildName, int MemberCount, Memory<byte> Logo);
|
||||
61
src/Interfaces/ChatServerAuthenticationInfo.cs
Normal file
61
src/Interfaces/ChatServerAuthenticationInfo.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
// <copyright file="ChatServerAuthenticationInfo.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Authentication info of a chat server client.
|
||||
/// This is created by the chatserver through <see cref="IChatServer.RegisterClientAsync"/>
|
||||
/// and the chat client needs to provide all of this information to authenticate itself.
|
||||
/// </summary>
|
||||
public class ChatServerAuthenticationInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatServerAuthenticationInfo" /> class.
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the client in the room.</param>
|
||||
/// <param name="roomId">The room identifier.</param>
|
||||
/// <param name="clientName">Name of the client.</param>
|
||||
/// <param name="hostAddress">The address of the chat server which hosts the chat room.</param>
|
||||
/// <param name="authenticationToken">The authentication token.</param>
|
||||
public ChatServerAuthenticationInfo(byte index, ushort roomId, string clientName, string hostAddress, string authenticationToken)
|
||||
{
|
||||
this.Index = index;
|
||||
this.RoomId = roomId;
|
||||
this.ClientName = clientName;
|
||||
this.AuthenticationToken = authenticationToken;
|
||||
this.HostAddress = hostAddress;
|
||||
this.AuthenticationRequiredUntil = DateTime.Now.AddSeconds(30);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the client in the room.
|
||||
/// </summary>
|
||||
public byte Index { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the room identifier of the room which is reserved for the client.
|
||||
/// </summary>
|
||||
public ushort RoomId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the client, usually character name.
|
||||
/// </summary>
|
||||
public string ClientName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authentication token. It's like a random passwort which the client has to provide to enter the chat room.
|
||||
/// </summary>
|
||||
public string AuthenticationToken { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the (IP-)address of the chat server which hosts the chat room.
|
||||
/// </summary>
|
||||
public string HostAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the datetime until a authentication of at least two clients is required. If this time passed by, the chat room will be closed automatically.
|
||||
/// </summary>
|
||||
public DateTime AuthenticationRequiredUntil { get; }
|
||||
}
|
||||
36
src/Interfaces/Friend.cs
Normal file
36
src/Interfaces/Friend.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
// <copyright file="Friend.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The friend class used by the <see cref="IFriendServer"/>.
|
||||
/// </summary>
|
||||
public class Friend
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier.
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the id of the character.
|
||||
/// </summary>
|
||||
public Guid CharacterId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the id of the friend character.
|
||||
/// </summary>
|
||||
public Guid FriendId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the friend request got accepted.
|
||||
/// </summary>
|
||||
public bool Accepted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this request is open.
|
||||
/// </summary>
|
||||
public bool RequestOpen { get; set; }
|
||||
}
|
||||
32
src/Interfaces/FriendViewItem.cs
Normal file
32
src/Interfaces/FriendViewItem.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
// <copyright file="FriendViewItem.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// A friend view item, which includes the character names.
|
||||
/// </summary>
|
||||
public class FriendViewItem : Friend
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FriendViewItem"/> class.
|
||||
/// </summary>
|
||||
/// <param name="characterName">Name of the character.</param>
|
||||
/// <param name="friendName">Name of the friend.</param>
|
||||
public FriendViewItem(string characterName, string friendName)
|
||||
{
|
||||
this.CharacterName = characterName;
|
||||
this.FriendName = friendName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the character.
|
||||
/// </summary>
|
||||
public string CharacterName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the friend.
|
||||
/// </summary>
|
||||
public string FriendName { get; set; }
|
||||
}
|
||||
55
src/Interfaces/Guild.cs
Normal file
55
src/Interfaces/Guild.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// <copyright file="Guild.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// A guild is a group of players who like to play together.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You may wonder where the Id is. The original server and this <see cref="IGuildServer"/> uses an integer id for guilds, too.
|
||||
/// I decided to manage these keys in memory and on demand, they are not persistent.
|
||||
/// I could've used an integer Id as primary key in the persistent Guild class, but don't do it by purpose:
|
||||
/// We would lose the ability to easily merge two databases (realms), if we do that. Even if we use a separate integer id column in the database,
|
||||
/// it needs to be re-assigned after a merge.
|
||||
/// </remarks>
|
||||
public class Guild
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the logo.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It's like a 16 color 8x8 pixel bitmap, therefore has a size of 32 bytes.
|
||||
/// </remarks>
|
||||
public byte[]? Logo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the score.
|
||||
/// </summary>
|
||||
public int Score { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the guild notice which can be set by the guild master.
|
||||
/// </summary>
|
||||
/// <remarks>Visible in green color after a character entered the game.</remarks>
|
||||
public string? Notice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the hostile guild. Members of a hostile guild can be killed without consequences.
|
||||
/// </summary>
|
||||
public virtual Guild? Hostility { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parent alliance guild.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The alliance guild.
|
||||
/// </value>
|
||||
public virtual Guild? AllianceGuild { get; set; }
|
||||
}
|
||||
38
src/Interfaces/GuildMemberStatus.cs
Normal file
38
src/Interfaces/GuildMemberStatus.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
// <copyright file="GuildMemberStatus.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The guild member status of a guild member.
|
||||
/// </summary>
|
||||
public class GuildMemberStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GuildMemberStatus"/> class.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <param name="position">The position.</param>
|
||||
public GuildMemberStatus(uint guildId, GuildPosition position)
|
||||
{
|
||||
this.GuildId = guildId;
|
||||
this.Position = position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the guild identifier.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The guild identifier.
|
||||
/// </value>
|
||||
public uint GuildId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The position.
|
||||
/// </value>
|
||||
public GuildPosition Position { get; }
|
||||
}
|
||||
37
src/Interfaces/GuildPosition.cs
Normal file
37
src/Interfaces/GuildPosition.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
// <copyright file="GuildPosition.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The position of a character in a guild.
|
||||
/// Some of them have special skills in the castle siege event.
|
||||
/// </summary>
|
||||
public enum GuildPosition : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Undefined position, not a guild member.
|
||||
/// </summary>
|
||||
Undefined,
|
||||
|
||||
/// <summary>
|
||||
/// A normal guild member.
|
||||
/// </summary>
|
||||
NormalMember,
|
||||
|
||||
/// <summary>
|
||||
/// The guild master.
|
||||
/// </summary>
|
||||
GuildMaster,
|
||||
|
||||
/// <summary>
|
||||
/// The battle master.
|
||||
/// </summary>
|
||||
BattleMaster,
|
||||
|
||||
/// <summary>
|
||||
/// The assistant guild master (needed for castle siege NPC management).
|
||||
/// </summary>
|
||||
AssistantMaster,
|
||||
}
|
||||
25
src/Interfaces/IChatServer.cs
Normal file
25
src/Interfaces/IChatServer.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// <copyright file="IChatServer.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The interface for a chat server.
|
||||
/// </summary>
|
||||
public interface IChatServer : IManageableServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers the client to the server.
|
||||
/// </summary>
|
||||
/// <param name="roomId">The room identifier.</param>
|
||||
/// <param name="clientName">Name of the client.</param>
|
||||
/// <returns>The authentication info.</returns>
|
||||
ValueTask<ChatServerAuthenticationInfo?> RegisterClientAsync(ushort roomId, string clientName);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the chat room.
|
||||
/// </summary>
|
||||
/// <returns>The new chat room id.</returns>
|
||||
ValueTask<ushort> CreateChatRoomAsync();
|
||||
}
|
||||
63
src/Interfaces/IConfigurationChangePublisher.cs
Normal file
63
src/Interfaces/IConfigurationChangePublisher.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
// <copyright file="IConfigurationChangePublisher.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for an object which publishes configuration changes to other services.
|
||||
/// </summary>
|
||||
public interface IConfigurationChangePublisher
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a publisher which doesn't publish at all.
|
||||
/// </summary>
|
||||
static IConfigurationChangePublisher None { get; } = new NoneConfigurationChangePublisher();
|
||||
|
||||
/// <summary>
|
||||
/// A configuration has changed.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="configuration">The changed configuration.</param>
|
||||
Task ConfigurationChangedAsync(Type type, Guid id, object configuration);
|
||||
|
||||
/// <summary>
|
||||
/// A configuration has been added.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="configuration">The added configuration.</param>
|
||||
Task ConfigurationAddedAsync(Type type, Guid id, object configuration);
|
||||
|
||||
/// <summary>
|
||||
/// A configuration has been removed.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="id">The identifier.</param>
|
||||
Task ConfigurationRemovedAsync(Type type, Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// A publisher which doesn't publish changes at all.
|
||||
/// </summary>
|
||||
private class NoneConfigurationChangePublisher : IConfigurationChangePublisher
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task ConfigurationChangedAsync(Type type, Guid id, object configuration)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ConfigurationAddedAsync(Type type, Guid id, object configuration)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ConfigurationRemovedAsync(Type type, Guid id)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/Interfaces/IConnectServer.cs
Normal file
12
src/Interfaces/IConnectServer.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
// <copyright file="IConnectServer.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The interface for a connect server.
|
||||
/// </summary>
|
||||
public interface IConnectServer : IManageableServer, IGameServerStateObserver
|
||||
{
|
||||
}
|
||||
23
src/Interfaces/IConnectServerInstanceManager.cs
Normal file
23
src/Interfaces/IConnectServerInstanceManager.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
// <copyright file="IConnectServerInstanceManager.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for an instance which manages connect servers.
|
||||
/// </summary>
|
||||
public interface IConnectServerInstanceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a connect server with the specified definition.
|
||||
/// </summary>
|
||||
/// <param name="connectServerDefinitionId">The connect server definition identifier.</param>
|
||||
ValueTask InitializeConnectServerAsync(Guid connectServerDefinitionId);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the connect server instance of the specified definition.
|
||||
/// </summary>
|
||||
/// <param name="connectServerDefinitionId">The connect server definition identifier.</param>
|
||||
ValueTask RemoveConnectServerAsync(Guid connectServerDefinitionId);
|
||||
}
|
||||
101
src/Interfaces/IConnectServerSettings.cs
Normal file
101
src/Interfaces/IConnectServerSettings.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
// <copyright file="IConnectServerSettings.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The connectServerSettings of the connect server.
|
||||
/// </summary>
|
||||
public interface IConnectServerSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the identifier of the configuration on which this settings are based on.
|
||||
/// </summary>
|
||||
Guid ConfigurationId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the server identifier.
|
||||
/// </summary>
|
||||
/// <remarks>Should be unique within all <see cref="IConnectServerSettings"/>.</remarks>
|
||||
byte ServerId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Will be displayed in the server list in the admin panel as <see cref="IManageableServer.Description"/>.
|
||||
/// </remarks>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the client should get disconnected when a unknown packet is getting received.
|
||||
/// </summary>
|
||||
bool DisconnectOnUnknownPacket { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum size of the packets which should be received from the client. If this size is exceeded, the client will be disconnected.
|
||||
/// </summary>
|
||||
/// <remarks>DOS protection.</remarks>
|
||||
byte MaximumReceiveSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the client listener port.
|
||||
/// </summary>
|
||||
int ClientListenerPort { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the client which is expected to connect.
|
||||
/// </summary>
|
||||
IGameClientVersion Client { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the timeout after which clients without activity get disconnected.
|
||||
/// </summary>
|
||||
TimeSpan Timeout { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current patch version.
|
||||
/// </summary>
|
||||
byte[] CurrentPatchVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the patch address.
|
||||
/// </summary>
|
||||
string PatchAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum connections per ip.
|
||||
/// </summary>
|
||||
int MaxConnectionsPerAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the <see cref="MaxConnectionsPerAddress"/> should be checked.
|
||||
/// </summary>
|
||||
bool CheckMaxConnectionsPerAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum connections the connect server should handle.
|
||||
/// </summary>
|
||||
int MaxConnections { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the listener backlog for the client listener.
|
||||
/// </summary>
|
||||
int ListenerBacklog { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum FTP requests per connection.
|
||||
/// </summary>
|
||||
int MaxFtpRequests { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum ip requests per connection.
|
||||
/// </summary>
|
||||
int MaxIpRequests { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum server list requests per connection.
|
||||
/// </summary>
|
||||
int MaxServerListRequests { get; }
|
||||
}
|
||||
53
src/Interfaces/IEventPublisher.cs
Normal file
53
src/Interfaces/IEventPublisher.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
// <copyright file="IEventPublisher.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for a publisher of events which happen on the game server
|
||||
/// and might have multiple interested subscribers/services.
|
||||
/// </summary>
|
||||
public interface IEventPublisher
|
||||
{
|
||||
/// <summary>
|
||||
/// Notifies that a player entered the game with a character.
|
||||
/// </summary>
|
||||
/// <param name="serverId">The identifier of the server on which the player entered.</param>
|
||||
/// <param name="characterId">The character identifier.</param>
|
||||
/// <param name="characterName">Name of the character.</param>
|
||||
ValueTask PlayerEnteredGameAsync(byte serverId, Guid characterId, string characterName);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies that a player entered the game with a character.
|
||||
/// </summary>
|
||||
/// <param name="serverId">The identifier of the server on which the player entered.</param>
|
||||
/// <param name="characterId">The character identifier.</param>
|
||||
/// <param name="characterName">Name of the character.</param>
|
||||
/// <param name="guildId">If the character is in a guild, a guild id can be passed.</param>
|
||||
ValueTask PlayerLeftGameAsync(byte serverId, Guid characterId, string characterName, uint guildId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the guild server that a guild message was sent and maybe needs to be forwarded to the game servers.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild id.</param>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
ValueTask GuildMessageAsync(uint guildId, string sender, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the guild server that an alliance message was sent and maybe needs to be forwarded to the game servers.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild id.</param>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
ValueTask AllianceMessageAsync(uint guildId, string sender, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies that a client tried to log into an already logged-in account.
|
||||
/// The connected player can be notified about that.
|
||||
/// </summary>
|
||||
/// <param name="serverId">The identifier of the server on which the client tried to enter.</param>
|
||||
/// <param name="loginName">The login name.</param>
|
||||
ValueTask PlayerAlreadyLoggedInAsync(byte serverId, string loginName);
|
||||
}
|
||||
109
src/Interfaces/IFriendServer.cs
Normal file
109
src/Interfaces/IFriendServer.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="IFriendServer.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Defines some server ids which are used for some specific states.
|
||||
/// </summary>
|
||||
public enum SpecialServerId : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the server id which represents being offline.
|
||||
/// </summary>
|
||||
Offline = 0xFF,
|
||||
|
||||
/// <summary>
|
||||
/// Gets the server id which represents being invisible (=offline to other players).
|
||||
/// </summary>
|
||||
Invisible = 0xFE,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The friend server interface.
|
||||
/// </summary>
|
||||
public interface IFriendServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Forwards the letter.
|
||||
/// </summary>
|
||||
/// <param name="letter">The letter.</param>
|
||||
ValueTask ForwardLetterAsync(LetterHeader letter);
|
||||
|
||||
/// <summary>
|
||||
/// Handles the friend request response.
|
||||
/// </summary>
|
||||
/// <param name="characterName">The character name of the responder.</param>
|
||||
/// <param name="friendName">The character name of the requester.</param>
|
||||
/// <param name="accepted">Indicating whether the request got accepted.</param>
|
||||
ValueTask FriendResponseAsync(string characterName, string friendName, bool accepted);
|
||||
|
||||
/// <summary>
|
||||
/// Is called when a player entered the game.
|
||||
/// It will cause a response with <see cref="IFriendSystemSubscriber.InitializeMessengerAsync"/>
|
||||
/// and a state update for friends.
|
||||
/// </summary>
|
||||
/// <param name="serverId">The server identifier.</param>
|
||||
/// <param name="characterId">The character identifier.</param>
|
||||
/// <param name="characterName">Name of the character.</param>
|
||||
ValueTask PlayerEnteredGameAsync(byte serverId, Guid characterId, string characterName);
|
||||
|
||||
/// <summary>
|
||||
/// Is called when a player leaves the game.
|
||||
/// It will cause a state update for friends.
|
||||
/// </summary>
|
||||
/// <param name="characterId">The character identifier.</param>
|
||||
/// <param name="characterName">Name of the character.</param>
|
||||
ValueTask PlayerLeftGameAsync(Guid characterId, string characterName);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the online visibility state of a character.
|
||||
/// </summary>
|
||||
/// <param name="serverId">The server identifier.</param>
|
||||
/// <param name="characterId">Id of the character.</param>
|
||||
/// <param name="characterName">Name of the character.</param>
|
||||
/// <param name="isVisible">If set to <c>true</c>, the character is visible as online. Otherwise, it appears as offline for other players, but is still online.</param>
|
||||
ValueTask SetPlayerVisibilityStateAsync(byte serverId, Guid characterId, string characterName, bool isVisible);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether two players are friends (accepted friend relationship).
|
||||
/// </summary>
|
||||
/// <param name="characterName">The character name of the first player.</param>
|
||||
/// <param name="friendName">The character name of the second player.</param>
|
||||
/// <returns>True if the two players are friends; otherwise false.</returns>
|
||||
ValueTask<bool> IsFriendAsync(string characterName, string friendName);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a friend request to the friend, and adds a new friend view item to the players friend list.
|
||||
/// </summary>
|
||||
/// <param name="playerName">The name of the requesting player.</param>
|
||||
/// <param name="friendName">The name of the requested friend.</param>
|
||||
/// <returns>If a new friend view item got added to the players friend list.</returns>
|
||||
ValueTask<bool> FriendRequestAsync(string playerName, string friendName);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the friend.
|
||||
/// </summary>
|
||||
/// <param name="name">The player who is deleting a friend from his friend list.</param>
|
||||
/// <param name="friendName">Name of the friend who should be deleted.</param>
|
||||
ValueTask DeleteFriendAsync(string name, string friendName);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new chat room.
|
||||
/// </summary>
|
||||
/// <param name="playerName">Name of the player who is creating the chat room.</param>
|
||||
/// <param name="friendName">Name of the friend who should be invited to the chat room.</param>
|
||||
ValueTask CreateChatRoomAsync(string playerName, string friendName);
|
||||
|
||||
/// <summary>
|
||||
/// Invites a friend to an existing chat room.
|
||||
/// </summary>
|
||||
/// <param name="selectedCharacterName">Name of the selected character.</param>
|
||||
/// <param name="friendName">Name of the friend.</param>
|
||||
/// <param name="roomNumber">The room number.</param>
|
||||
/// <returns>The success of the invitation.</returns>
|
||||
ValueTask<bool> InviteFriendToChatRoomAsync(string selectedCharacterName, string friendName, ushort roomNumber);
|
||||
}
|
||||
52
src/Interfaces/IFriendSystemSubscriber.cs
Normal file
52
src/Interfaces/IFriendSystemSubscriber.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
// <copyright file="IFriendSystemSubscriber.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
using System.Collections.Immutable;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for an object which subscribes for changes in the friends system.
|
||||
/// </summary>
|
||||
public interface IFriendSystemSubscriber
|
||||
{
|
||||
/// <summary>
|
||||
/// Notifies the game server that a letter got received for an online player.
|
||||
/// </summary>
|
||||
/// <param name="letter">The letter header.</param>
|
||||
ValueTask LetterReceivedAsync(LetterHeader letter);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the server that a player made a friend request to another player, which is online on this server.
|
||||
/// </summary>
|
||||
/// <param name="requester">The requester.</param>
|
||||
/// <param name="receiver">The receiver.</param>
|
||||
ValueTask FriendRequestAsync(string requester, string receiver);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the game server that a friend online state changed.
|
||||
/// </summary>
|
||||
/// <param name="player">The player who is playing on the server, and needs to get notified.</param>
|
||||
/// <param name="friend">The friend whose state changed.</param>
|
||||
/// <param name="serverId">The new server identifier of the <paramref name="friend"/>.</param>
|
||||
ValueTask FriendOnlineStateChangedAsync(string player, string friend, int serverId);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the game server that a chat room got created on the chat server for a player which is online on this game server.
|
||||
/// </summary>
|
||||
/// <param name="playerAuthenticationInfo">Authentication information of the player who should get notified about the created chat room.</param>
|
||||
/// <param name="friendName">Name of the friend player which is expected to be in the chat room.</param>
|
||||
ValueTask ChatRoomCreatedAsync(ChatServerAuthenticationInfo playerAuthenticationInfo, string friendName);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the messenger of a player.
|
||||
/// </summary>
|
||||
/// <param name="initializationData">The initialization data.</param>
|
||||
ValueTask InitializeMessengerAsync(MessengerInitializationData initializationData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The data of a messenger initialization for <see cref="IFriendSystemSubscriber.InitializeMessengerAsync"/>.
|
||||
/// </summary>
|
||||
public record MessengerInitializationData(string PlayerName, IImmutableList<string> Friends, IImmutableList<string> OpenFriendRequests);
|
||||
36
src/Interfaces/IGameClientVersion.cs
Normal file
36
src/Interfaces/IGameClientVersion.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
// <copyright file="IGameClientVersion.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the game client (binary) version which is supposed to connect.
|
||||
/// </summary>
|
||||
public interface IGameClientVersion
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the description.
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the season.
|
||||
/// </summary>
|
||||
byte Season { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the episode.
|
||||
/// </summary>
|
||||
byte Episode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the version which is defined in the client binaries.
|
||||
/// </summary>
|
||||
byte[] Version { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the serial which is defined in the client binaries.
|
||||
/// </summary>
|
||||
byte[] Serial { get; }
|
||||
}
|
||||
158
src/Interfaces/IGameServer.cs
Normal file
158
src/Interfaces/IGameServer.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
// <copyright file="IGameServer.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The state of the server.
|
||||
/// </summary>
|
||||
public enum ServerState
|
||||
{
|
||||
/// <summary>
|
||||
/// The server has finished stopping.
|
||||
/// </summary>
|
||||
Stopped,
|
||||
|
||||
/// <summary>
|
||||
/// The server is currently starting, but has not yet finished initialization.
|
||||
/// </summary>
|
||||
Starting,
|
||||
|
||||
/// <summary>
|
||||
/// The server started and is available.
|
||||
/// </summary>
|
||||
Started,
|
||||
|
||||
/// <summary>
|
||||
/// The server is not available anymore and is stopping it's services.
|
||||
/// </summary>
|
||||
Stopping,
|
||||
|
||||
/// <summary>
|
||||
/// The server state is unknown, because of a timeout.
|
||||
/// </summary>
|
||||
Timeout,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Types of messages.
|
||||
/// </summary>
|
||||
public enum MessageType
|
||||
{
|
||||
/// <summary>
|
||||
/// The message is shown as centered golden message in the client.
|
||||
/// </summary>
|
||||
GoldenCenter = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The message is shown as blue entry.
|
||||
/// </summary>
|
||||
BlueNormal = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The message is a guild notice (green center).
|
||||
/// </summary>
|
||||
GuildNotice = 2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for the inter-server communication.
|
||||
/// </summary>
|
||||
public interface IGameServer : IManageableServer, IFriendSystemSubscriber
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a chat message to all connected guild members.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <param name="sender">The sender character name.</param>
|
||||
/// <param name="message">The message which should be sent.</param>
|
||||
ValueTask GuildChatMessageAsync(uint guildId, string sender, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the game server that a guild got deleted.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
ValueTask GuildDeletedAsync(uint guildId);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the game server that a guild member got removed from a guild.
|
||||
/// </summary>
|
||||
/// <param name="playerName">Name of the player which got removed from a guild.</param>
|
||||
ValueTask GuildPlayerKickedAsync(string playerName);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a chat message to all connected alliance members.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <param name="sender">The sender character name.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
ValueTask AllianceChatMessageAsync(uint guildId, string sender, string message);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a global message to all connected players with the specified message type.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="messageType">Type of the message.</param>
|
||||
ValueTask SendGlobalMessageAsync(string message, MessageType messageType);
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects the player from the game.
|
||||
/// </summary>
|
||||
/// <param name="playerName">Name of the player.</param>
|
||||
/// <returns>True, if the player has been disconnected; False, otherwise.</returns>
|
||||
ValueTask<bool> DisconnectPlayerAsync(string playerName);
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects the account from the game.
|
||||
/// </summary>
|
||||
/// <param name="accountName">Name of the account.</param>
|
||||
/// <returns>True, if the account has been disconnected; False, otherwise.</returns>
|
||||
ValueTask<bool> DisconnectAccountAsync(string accountName);
|
||||
|
||||
/// <summary>
|
||||
/// Bans the player from the game.
|
||||
/// </summary>
|
||||
/// <param name="playerName">Name of the player.</param>
|
||||
/// <returns>True, if the player has been banned; False, otherwise.</returns>
|
||||
ValueTask<bool> BanPlayerAsync(string playerName);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the guild to the player.
|
||||
/// </summary>
|
||||
/// <param name="characterName">Name of the character.</param>
|
||||
/// <param name="guildStatus">The guild status of the character.</param>
|
||||
ValueTask AssignGuildToPlayerAsync(string characterName, GuildMemberStatus guildStatus);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies that a client tried to log into an already logged-in account.
|
||||
/// The connected player can be notified about that.
|
||||
/// </summary>
|
||||
/// <param name="serverId">The identifier of the server on which the client tried to enter.</param>
|
||||
/// <param name="loginName">The login name.</param>
|
||||
ValueTask PlayerAlreadyLoggedInAsync(byte serverId, string loginName);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the game server that an alliance between two guilds has been created.
|
||||
/// </summary>
|
||||
/// <param name="masterGuildId">The master guild identifier.</param>
|
||||
/// <param name="memberGuildId">The member guild identifier.</param>
|
||||
ValueTask AllianceCreatedAsync(uint masterGuildId, uint memberGuildId);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the game server that an alliance between two guilds has been disbanded.
|
||||
/// </summary>
|
||||
/// <param name="masterGuildId">The master guild identifier.</param>
|
||||
/// <param name="memberGuildId">The member guild identifier.</param>
|
||||
ValueTask AllianceDisbandedAsync(uint masterGuildId, uint memberGuildId);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the game server that the hostility between two guilds (or alliances) has changed.
|
||||
/// </summary>
|
||||
/// <param name="guildIdA">The identifier of the first guild.</param>
|
||||
/// <param name="allianceGuildIdsA">All guild IDs in the alliance of guild A (or just [guildIdA] if not in an alliance).</param>
|
||||
/// <param name="guildIdB">The identifier of the second guild.</param>
|
||||
/// <param name="allianceGuildIdsB">All guild IDs in the alliance of guild B (or just [guildIdB] if not in an alliance).</param>
|
||||
/// <param name="created"><c>true</c> if hostility was created; <c>false</c> if it was removed.</param>
|
||||
ValueTask GuildHostilityChangedAsync(uint guildIdA, IReadOnlyList<uint> allianceGuildIdsA, uint guildIdB, IReadOnlyList<uint> allianceGuildIdsB, bool created);
|
||||
}
|
||||
29
src/Interfaces/IGameServerInstanceManager.cs
Normal file
29
src/Interfaces/IGameServerInstanceManager.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
// <copyright file="IGameServerInstanceManager.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for an instance which manages game servers.
|
||||
/// </summary>
|
||||
public interface IGameServerInstanceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Restarts all servers of this container.
|
||||
/// </summary>
|
||||
/// <param name="onDatabaseInit">If set to <c>true</c>, this method is called during a database initialization.</param>
|
||||
ValueTask RestartAllAsync(bool onDatabaseInit);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a game server.
|
||||
/// </summary>
|
||||
/// <param name="serverId">The server identifier.</param>
|
||||
ValueTask InitializeGameServerAsync(byte serverId);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the game server instance.
|
||||
/// </summary>
|
||||
/// <param name="serverId">The server identifier.</param>
|
||||
ValueTask RemoveGameServerAsync(byte serverId);
|
||||
}
|
||||
33
src/Interfaces/IGameServerStateObserver.cs
Normal file
33
src/Interfaces/IGameServerStateObserver.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
// <copyright file="IGameServerStateObserver.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
using System.Net;
|
||||
|
||||
/// <summary>
|
||||
/// An interface for an object which observes the state of game servers.
|
||||
/// </summary>
|
||||
public interface IGameServerStateObserver
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers the game server, so that it can be accessed through the connect server.
|
||||
/// </summary>
|
||||
/// <param name="gameServer">The game server information.</param>
|
||||
/// <param name="publicEndPoint">The public end point.</param>
|
||||
void RegisterGameServer(ServerInfo gameServer, IPEndPoint publicEndPoint);
|
||||
|
||||
/// <summary>
|
||||
/// Un-registers the game server from the observer.
|
||||
/// </summary>
|
||||
/// <param name="gameServerId">The game server identifier.</param>
|
||||
void UnregisterGameServer(ushort gameServerId);
|
||||
|
||||
/// <summary>
|
||||
/// Is called when the number of <see cref="ServerInfo.CurrentConnections"/> changed for a server.
|
||||
/// </summary>
|
||||
/// <param name="serverId">The server id.</param>
|
||||
/// <param name="currentConnections">The number of current connections, <see cref="ServerInfo.CurrentConnections"/>.</param>
|
||||
void CurrentConnectionsChanged(ushort serverId, int currentConnections);
|
||||
}
|
||||
246
src/Interfaces/IGuildServer.cs
Normal file
246
src/Interfaces/IGuildServer.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
// <copyright file="IGuildServer.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
using System.Collections.Immutable;
|
||||
|
||||
/// <summary>
|
||||
/// Describes the relationship between two guilds.
|
||||
/// </summary>
|
||||
public enum GuildRelationship
|
||||
{
|
||||
/// <summary>
|
||||
/// No special relationship.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Both guilds are in the same alliance.
|
||||
/// </summary>
|
||||
Union = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The guilds are rivals / hostile to each other.
|
||||
/// </summary>
|
||||
Rival = 2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the result of an alliance creation attempt.
|
||||
/// </summary>
|
||||
public enum AllianceCreationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The alliance creation failed for an unspecified reason.
|
||||
/// </summary>
|
||||
Failed,
|
||||
|
||||
/// <summary>
|
||||
/// The alliance was created successfully.
|
||||
/// </summary>
|
||||
Success,
|
||||
|
||||
/// <summary>
|
||||
/// The master guild could not be found.
|
||||
/// </summary>
|
||||
MasterGuildNotFound,
|
||||
|
||||
/// <summary>
|
||||
/// The target guild could not be found.
|
||||
/// </summary>
|
||||
TargetGuildNotFound,
|
||||
|
||||
/// <summary>
|
||||
/// The target guild is already a member of an alliance.
|
||||
/// </summary>
|
||||
TargetGuildAlreadyInAlliance,
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of guilds allowed in an alliance has been reached.
|
||||
/// </summary>
|
||||
MaximumAllianceSizeReached,
|
||||
|
||||
/// <summary>
|
||||
/// The guild could not be found in the target context.
|
||||
/// </summary>
|
||||
GuildNotFoundInTargetContext,
|
||||
|
||||
/// <summary>
|
||||
/// An unexpected error occurred during alliance creation.
|
||||
/// </summary>
|
||||
Error,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for the guild server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A little note about the guild id:
|
||||
/// The original GMO server uses an 32-bit integer in all of its messages. However, actually it's only using (or used?) 16 bits of it for created guilds (see struct SDHP_GUILDCREATED).
|
||||
/// Some people may remember the "guildbug" on GMO - I guess the keys exceeded these 16 bits and somehow caused a crash... but after restart of the servers it started working again.
|
||||
/// </remarks>
|
||||
public interface IGuildServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the guild with the specified name exists.
|
||||
/// </summary>
|
||||
/// <param name="guildName">Name of the guild.</param>
|
||||
/// <returns>True, if the guild exists; False, otherwise.</returns>
|
||||
ValueTask<bool> GuildExistsAsync(string guildName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the guild by the guild identifier.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <returns>The guild.</returns>
|
||||
ValueTask<Guild?> GetGuildAsync(uint guildId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the guild id by the guild name.
|
||||
/// </summary>
|
||||
/// <param name="guildName">The guild name.</param>
|
||||
/// <returns>The guild id. <c>0</c>, if not found.</returns>
|
||||
ValueTask<uint> GetGuildIdByNameAsync(string guildName);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the guild and sets the guild master online at the guild server. A separate call to <see cref="PlayerEnteredGameAsync"/> is not required.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="masterName">Name of the master.</param>
|
||||
/// <param name="masterId">The master identifier.</param>
|
||||
/// <param name="logo">The logo.</param>
|
||||
/// <param name="serverId">The identifier of the server on which the guild is getting created.</param>
|
||||
/// <returns>A flag, indicating if the guild has been created successfully.</returns>
|
||||
ValueTask<bool> CreateGuildAsync(string name, string masterName, Guid masterId, byte[] logo, byte serverId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the guild member and sets it online at the guild server. A separate call to <see cref="PlayerEnteredGameAsync"/> is not required.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <param name="characterId">The identifier.</param>
|
||||
/// <param name="characterName">The name.</param>
|
||||
/// <param name="role">The role of the member.</param>
|
||||
/// <param name="serverId">The identifier of the server on which the guild member is getting created.</param>
|
||||
ValueTask CreateGuildMemberAsync(uint guildId, Guid characterId, string characterName, GuildPosition role, byte serverId);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the guild member position.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <param name="characterId">The id of the character.</param>
|
||||
/// <param name="role">The role.</param>
|
||||
ValueTask ChangeGuildMemberPositionAsync(uint guildId, Guid characterId, GuildPosition role);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the guild server that a player (potential guild member) entered the game.
|
||||
/// </summary>
|
||||
/// <param name="characterId">The character identifier.</param>
|
||||
/// <param name="characterName">Name of the character.</param>
|
||||
/// <param name="serverId">The identifier of the server on which the guild member entered.</param>
|
||||
ValueTask PlayerEnteredGameAsync(Guid characterId, string characterName, byte serverId);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the guild server that a guild member left the game.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <param name="guildMemberId">The identifier of the guild member.</param>
|
||||
/// <param name="serverId">The identifier of the server from which the guild member left.</param>
|
||||
ValueTask GuildMemberLeftGameAsync(uint guildId, Guid guildMemberId, byte serverId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the guild member list.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <returns>The guild member list.</returns>
|
||||
ValueTask<IImmutableList<GuildListEntry>> GetGuildListAsync(uint guildId);
|
||||
|
||||
/// <summary>
|
||||
/// Kicks a guild member from a guild.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <param name="playerName">Name of the player which is getting kicked.</param>
|
||||
ValueTask KickMemberAsync(uint guildId, string playerName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the guild position of a specific character.
|
||||
/// </summary>
|
||||
/// <param name="characterId">The character identifier.</param>
|
||||
/// <returns>The guild position.</returns>
|
||||
ValueTask<GuildPosition> GetGuildPositionAsync(Guid characterId);
|
||||
|
||||
/// <summary>
|
||||
/// Increases the guild score by one.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The identifier of the guild.</param>
|
||||
ValueTask IncreaseGuildScoreAsync(uint guildId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an alliance between the master guild and the target guild.
|
||||
/// The master guild becomes (or remains) the alliance master.
|
||||
/// </summary>
|
||||
/// <param name="masterGuildId">The identifier of the master guild that initiates the alliance.</param>
|
||||
/// <param name="targetGuildId">The identifier of the target guild to add to the alliance.</param>
|
||||
/// <returns><c>true</c> if the alliance was created successfully; <c>false</c> otherwise.</returns>
|
||||
ValueTask<AllianceCreationResult> CreateAllianceAsync(uint masterGuildId, uint targetGuildId);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a guild from an alliance.
|
||||
/// </summary>
|
||||
/// <param name="targetGuildId">The identifier of the guild to remove from its alliance.</param>
|
||||
/// <returns><c>true</c> if the guild was removed successfully; <c>false</c> otherwise.</returns>
|
||||
ValueTask<bool> RemoveAllianceAsync(uint targetGuildId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of guilds in the alliance of the specified guild.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The identifier of any guild in the alliance.</param>
|
||||
/// <returns>The list of alliance guilds.</returns>
|
||||
ValueTask<IImmutableList<AllianceGuildEntry>> GetAllianceGuildsAsync(uint guildId);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified guild is the alliance master.
|
||||
/// </summary>
|
||||
/// <param name="guildId">The guild identifier.</param>
|
||||
/// <returns><c>true</c> if the guild is the alliance master; <c>false</c> otherwise.</returns>
|
||||
ValueTask<bool> IsAllianceMasterAsync(uint guildId);
|
||||
|
||||
/// <summary>
|
||||
/// Sets or clears the hostility between guilds.
|
||||
/// </summary>
|
||||
/// <param name="guildIdA">The guild identifier of the requesting guild.</param>
|
||||
/// <param name="guildIdB">The identifier of the target guild. Only used when <paramref name="create"/> is <c>true</c>.</param>
|
||||
/// <param name="create"><c>true</c> to set hostility; <c>false</c> to clear any existing hostility.</param>
|
||||
/// <returns><c>true</c> if the hostility state was changed successfully; <c>false</c> otherwise.</returns>
|
||||
ValueTask<bool> SetHostilityAsync(uint guildIdA, uint guildIdB, bool create);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the relationship between two guilds.
|
||||
/// </summary>
|
||||
/// <param name="guild1">The first guild identifier.</param>
|
||||
/// <param name="guild2">The second guild identifier.</param>
|
||||
/// <returns>The relationship between the two guilds.</returns>
|
||||
ValueTask<GuildRelationship> GetGuildRelationshipAsync(uint guild1, uint guild2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The guild list entry.
|
||||
/// </summary>
|
||||
public class GuildListEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the player.
|
||||
/// </summary>
|
||||
public string? PlayerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the server identifier on which the player is playing.
|
||||
/// </summary>
|
||||
public byte ServerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the players position in the guild.
|
||||
/// </summary>
|
||||
public GuildPosition PlayerPosition { get; set; }
|
||||
}
|
||||
34
src/Interfaces/ILoginServer.cs
Normal file
34
src/Interfaces/ILoginServer.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
// -----------------------------------------------------------------------
|
||||
// <copyright file="ILoginServer.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Interface of the login server, which keeps track of all connected accounts.
|
||||
/// </summary>
|
||||
public interface ILoginServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to login the account on the specified server.
|
||||
/// </summary>
|
||||
/// <param name="accountName">Name of the account.</param>
|
||||
/// <param name="serverId">The server identifier.</param>
|
||||
/// <returns>The success.</returns>
|
||||
Task<bool> TryLoginAsync(string accountName, byte serverId);
|
||||
|
||||
/// <summary>
|
||||
/// Logs the account off from the specified server.
|
||||
/// </summary>
|
||||
/// <param name="accountName">Name of the account.</param>
|
||||
/// <param name="serverId">The server identifier.</param>
|
||||
ValueTask LogOffAsync(string accountName, byte serverId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a snapshot of the currently logged in accounts and their corresponding server ids.
|
||||
/// </summary>
|
||||
/// <returns>A snapshot of the currently logged in accounts and their corresponding server ids.</returns>
|
||||
ValueTask<Dictionary<string, byte>> GetSnapshotAsync();
|
||||
}
|
||||
59
src/Interfaces/IManageableServer.cs
Normal file
59
src/Interfaces/IManageableServer.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
// <copyright file="IManageableServer.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// General interface for a server which provides some information and functions to manage it from outside.
|
||||
/// </summary>
|
||||
public interface IManageableServer : INotifyPropertyChanged, IHostedService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the identifier of the server.
|
||||
/// </summary>
|
||||
int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the identifier of the configuration of the server.
|
||||
/// </summary>
|
||||
Guid ConfigurationId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description.
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type.
|
||||
/// </summary>
|
||||
ServerType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current state of the server.
|
||||
/// </summary>
|
||||
ServerState ServerState { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum number of connections the server can handle.
|
||||
/// </summary>
|
||||
int MaximumConnections { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current connection count.
|
||||
/// </summary>
|
||||
int CurrentConnections { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Starts the server.
|
||||
/// </summary>
|
||||
ValueTask StartAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Stops the server.
|
||||
/// </summary>
|
||||
ValueTask ShutdownAsync();
|
||||
}
|
||||
18
src/Interfaces/IServerProvider.cs
Normal file
18
src/Interfaces/IServerProvider.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
// <copyright file="IServerProvider.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
/// <summary>
|
||||
/// An interface for an object which provides a list of <see cref="IManageableServer"/>s.
|
||||
/// </summary>
|
||||
public interface IServerProvider : INotifyPropertyChanged
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the servers.
|
||||
/// </summary>
|
||||
IList<IManageableServer> Servers { get; }
|
||||
}
|
||||
55
src/Interfaces/LetterHeader.cs
Normal file
55
src/Interfaces/LetterHeader.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// <copyright file="LetterHeader.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The header of a letter.
|
||||
/// </summary>
|
||||
public class LetterHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier.
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sender.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The persistence implementation can implement to keep an internal id, too.
|
||||
/// However, it should keep the name, if it should stay available after a sender character got deleted.
|
||||
/// </remarks>
|
||||
public string? SenderName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the receiver.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The persistence implementation can implement to keep an internal id, too.
|
||||
/// In this case, it may not be required to save the name itself.
|
||||
/// </remarks>
|
||||
public string? ReceiverName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the subject.
|
||||
/// </summary>
|
||||
public string? Subject { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the letter date.
|
||||
/// </summary>
|
||||
public DateTime LetterDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the letter has been read.
|
||||
/// </summary>
|
||||
public bool ReadFlag { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{this.SenderName} -> {this.ReceiverName} - {this.Subject} ({this.LetterDate})";
|
||||
}
|
||||
}
|
||||
354
src/Interfaces/LocalizedString.cs
Normal file
354
src/Interfaces/LocalizedString.cs
Normal file
@@ -0,0 +1,354 @@
|
||||
// <copyright file="LocalizedString.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a string which can be translated to different languages and serializes into a single string.
|
||||
/// It's meant for simple usage in database fields and not for complex localization scenarios.
|
||||
/// To keep compatibility with normal strings, we simply assume the first string to be in neutral (usually english) language.
|
||||
/// Example: "Some text||de=Etwas Text||fr=Un peu de texte" where the first part is english, second german and third french.
|
||||
/// </summary>
|
||||
public readonly struct LocalizedString : IEquatable<LocalizedString>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalizedString"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public LocalizedString(string? value)
|
||||
{
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the separator string which separates the different languages.
|
||||
/// </summary>
|
||||
public static string Separator => "||";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the neutral language code.
|
||||
/// </summary>
|
||||
public static string NeutralLanguageCode => "en";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying serialized value of this localized string.
|
||||
/// </summary>
|
||||
public string? Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value in the neutral language as a <see cref="string"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that contains the neutral language text, or an empty string
|
||||
/// if the underlying value is <see langword="null"/>.
|
||||
/// </value>
|
||||
public string ValueInNeutralLanguage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Value?.IndexOf(Separator, StringComparison.OrdinalIgnoreCase) is not >= 0)
|
||||
{
|
||||
return this.Value ?? string.Empty;
|
||||
}
|
||||
|
||||
var span = this.ValueInNeutralLanguageAsSpan;
|
||||
return new(span);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value in the neutral language as a <see cref="ReadOnlySpan{T}"/> of characters.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ReadOnlySpan{T}"/> that contains the neutral language text, or an empty span
|
||||
/// if the underlying value is <see langword="null"/>.
|
||||
/// </value>
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public ReadOnlySpan<char> ValueInNeutralLanguageAsSpan
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Value is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var separatorIndex = this.Value.IndexOf(Separator, StringComparison.OrdinalIgnoreCase);
|
||||
if (separatorIndex == -1)
|
||||
{
|
||||
return this.Value.AsSpan();
|
||||
}
|
||||
|
||||
return this.Value.AsSpan(0, separatorIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an implicit conversion from <see cref="LocalizedString"/> to <see cref="string"/>.
|
||||
/// </summary>
|
||||
/// <param name="localizedString">The localized string.</param>
|
||||
/// <returns>The underlying serialized value of the localized string, or <see langword="null"/> if the instance is <see langword="null"/>.</returns>
|
||||
public static implicit operator string?(LocalizedString? localizedString)
|
||||
{
|
||||
return localizedString?.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an implicit conversion from <see cref="LocalizedString"/> to <see cref="string"/>.
|
||||
/// </summary>
|
||||
/// <param name="localizedString">The localized string.</param>
|
||||
/// <returns>The underlying serialized value of the localized string, or an empty string if the underlying value is <see langword="null"/>.</returns>
|
||||
public static implicit operator string(LocalizedString localizedString)
|
||||
{
|
||||
return localizedString.Value ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an implicit conversion from <see cref="string"/> to a nullable <see cref="LocalizedString"/>.
|
||||
/// </summary>
|
||||
/// <param name="localizedString">The serialized localized string value.</param>
|
||||
/// <returns>A new <see cref="LocalizedString"/> instance, or <see langword="null"/> if <paramref name="localizedString"/> is <see langword="null"/>.</returns>
|
||||
public static implicit operator LocalizedString?(string? localizedString)
|
||||
{
|
||||
if (localizedString is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new LocalizedString(localizedString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an implicit conversion from <see cref="string"/> to <see cref="LocalizedString"/>.
|
||||
/// </summary>
|
||||
/// <param name="localizedString">The serialized localized string value.</param>
|
||||
/// <returns>A new <see cref="LocalizedString"/> instance.</returns>
|
||||
public static implicit operator LocalizedString(string localizedString)
|
||||
{
|
||||
return new LocalizedString(localizedString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="string"/> that represents this instance for the current UI culture.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="string"/> containing the translation for the current UI culture,
|
||||
/// or the neutral language translation if none is available for the current culture.
|
||||
/// </returns>
|
||||
public override string? ToString()
|
||||
{
|
||||
return this.Value is null ? null : this.GetTranslation(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the translation for the specified culture.
|
||||
/// </summary>
|
||||
/// <param name="cultureInfo">The culture for which the translation is requested.</param>
|
||||
/// <param name="fallbackToNeutral">
|
||||
/// If set to <see langword="true"/>, falls back to the neutral language if no translation for
|
||||
/// <paramref name="cultureInfo"/> is available; otherwise returns an empty string.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The translation for the specified culture, the neutral language translation if
|
||||
/// <paramref name="fallbackToNeutral"/> is <see langword="true"/> and no specific translation exists,
|
||||
/// or an empty string if neither is available.
|
||||
/// </returns>
|
||||
public string? GetTranslation(CultureInfo cultureInfo, bool fallbackToNeutral = true)
|
||||
{
|
||||
var span = this.GetTranslationAsSpan(cultureInfo, fallbackToNeutral);
|
||||
return span.IsEmpty
|
||||
? null
|
||||
: new(span);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the translation for the specified culture as a <see cref="ReadOnlySpan{T}"/> of characters.
|
||||
/// </summary>
|
||||
/// <param name="cultureInfo">The culture for which the translation is requested.</param>
|
||||
/// <param name="fallbackToNeutral">
|
||||
/// If set to <see langword="true"/>, falls back to the neutral language if no translation for
|
||||
/// <paramref name="cultureInfo"/> is available; otherwise returns an empty span.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A <see cref="ReadOnlySpan{T}"/> containing the translation for the specified culture,
|
||||
/// the neutral language translation if <paramref name="fallbackToNeutral"/> is <see langword="true"/>
|
||||
/// and no specific translation exists, or an empty span if neither is available.
|
||||
/// </returns>
|
||||
public ReadOnlySpan<char> GetTranslationAsSpan(CultureInfo cultureInfo, bool fallbackToNeutral = true)
|
||||
{
|
||||
// Implementation for retrieving the localized string based on the cultureInfo
|
||||
if (this.Value is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
if (cultureInfo.TwoLetterISOLanguageName == NeutralLanguageCode)
|
||||
{
|
||||
return this.ValueInNeutralLanguageAsSpan;
|
||||
}
|
||||
|
||||
var searchPattern = Separator + cultureInfo.TwoLetterISOLanguageName + "=";
|
||||
var startIndex = this.Value.IndexOf(searchPattern, StringComparison.OrdinalIgnoreCase);
|
||||
if (startIndex == -1)
|
||||
{
|
||||
return fallbackToNeutral ? this.ValueInNeutralLanguageAsSpan : [];
|
||||
}
|
||||
|
||||
var part = this.Value.AsSpan(startIndex + searchPattern.Length);
|
||||
var endIndex = part.IndexOf(Separator);
|
||||
if (endIndex == -1)
|
||||
{
|
||||
return part;
|
||||
}
|
||||
|
||||
return part.Slice(0, endIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="LocalizedString"/> with the specified translation added, updated, or removed.
|
||||
/// </summary>
|
||||
/// <param name="cultureInfo">The culture for which the translation should be added or updated.</param>
|
||||
/// <param name="text">
|
||||
/// The translation text. If <see langword="null"/> or empty, an existing translation for the specified culture
|
||||
/// is removed.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A new <see cref="LocalizedString"/> instance with the modified translation for the specified culture.
|
||||
/// </returns>
|
||||
public LocalizedString WithTranslation(CultureInfo cultureInfo, string? text)
|
||||
{
|
||||
// Plan (pseudocode):
|
||||
// 1. Determine language code from culture (TwoLetterISOLanguageName).
|
||||
// 2. If language is neutral ("en"):
|
||||
// a. If Value is null or empty:
|
||||
// - If text is null or empty: return this (no change).
|
||||
// - Else: create new base + keep all existing non-neutral parts (if any) and return new instance.
|
||||
// b. If Value has separator:
|
||||
// - Replace the part before first separator with the new text (may be null/empty).
|
||||
// c. If Value has no separator:
|
||||
// - Replace whole value with new text.
|
||||
// 3. If language is non-neutral:
|
||||
// a. If Value is null or empty:
|
||||
// - If text is null or empty: return this.
|
||||
// - Else: initialize base as empty string and append "||xx=text".
|
||||
// b. Search for existing "||xx=" section.
|
||||
// - If found:
|
||||
// i. If text is null or empty: remove that section (and possible trailing/leading separators).
|
||||
// ii. Else: replace its content with text.
|
||||
// - If not found and text is not null/empty: append "||xx=text".
|
||||
// 4. Return new LocalizedString with computed value.
|
||||
var languageCode = cultureInfo.TwoLetterISOLanguageName;
|
||||
|
||||
// Work with a mutable string representation
|
||||
var current = this.Value ?? string.Empty;
|
||||
|
||||
if (languageCode == NeutralLanguageCode)
|
||||
{
|
||||
// Handle neutral language as the base string (before first separator)
|
||||
var separatorIndex = current.IndexOf(Separator, StringComparison.OrdinalIgnoreCase);
|
||||
if (separatorIndex == -1)
|
||||
{
|
||||
// Only neutral text present
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
if (string.IsNullOrEmpty(current))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
return new LocalizedString(string.Empty);
|
||||
}
|
||||
|
||||
return new LocalizedString(text);
|
||||
}
|
||||
|
||||
// There are additional translations after the base text
|
||||
var suffix = current.Substring(separatorIndex); // includes the separator
|
||||
var newBase = text ?? string.Empty;
|
||||
return new LocalizedString(newBase + suffix);
|
||||
}
|
||||
|
||||
// Handle non-neutral languages
|
||||
var searchPattern = Separator + languageCode + "=";
|
||||
var startIndex = current.IndexOf(searchPattern, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (startIndex == -1)
|
||||
{
|
||||
// No existing translation for this language
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(current))
|
||||
{
|
||||
// No base text yet, just start with empty base and language entry
|
||||
return new LocalizedString(string.Empty + Separator + languageCode + "=" + text);
|
||||
}
|
||||
|
||||
return new LocalizedString(current + Separator + languageCode + "=" + text);
|
||||
}
|
||||
|
||||
// Existing translation found
|
||||
var partStart = startIndex + searchPattern.Length;
|
||||
var span = current.AsSpan(partStart);
|
||||
var endIndex = span.IndexOf(Separator);
|
||||
var removeLength = endIndex == -1 ? current.Length - partStart : endIndex;
|
||||
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
// Remove this translation entry completely, including "||xx=" prefix
|
||||
var prefix = current.AsSpan(0, startIndex);
|
||||
ReadOnlySpan<char> suffixSpan;
|
||||
if (endIndex == -1)
|
||||
{
|
||||
suffixSpan = ReadOnlySpan<char>.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
suffixSpan = current.AsSpan(partStart + removeLength);
|
||||
}
|
||||
|
||||
var result = string.Concat(prefix, suffixSpan);
|
||||
return new LocalizedString(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replace the content of this translation
|
||||
var prefix = current.AsSpan(0, partStart);
|
||||
ReadOnlySpan<char> suffixSpan;
|
||||
if (endIndex == -1)
|
||||
{
|
||||
suffixSpan = ReadOnlySpan<char>.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
suffixSpan = current.AsSpan(partStart + removeLength);
|
||||
}
|
||||
|
||||
var result = string.Concat(prefix, text, suffixSpan);
|
||||
return new LocalizedString(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(LocalizedString other)
|
||||
{
|
||||
return this.Value == other.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is LocalizedString other && this.Equals(other);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Value != null ? this.Value.GetHashCode() : 0;
|
||||
}
|
||||
}
|
||||
36
src/Interfaces/LocalizedStringJsonConverter.cs
Normal file
36
src/Interfaces/LocalizedStringJsonConverter.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
// <copyright file="LocalizedStringJsonConverter.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// A JSON converter for the <see cref="LocalizedString"/> type which serializes it as a simple JSON string.
|
||||
/// </summary>
|
||||
public class LocalizedStringJsonConverter : JsonConverter<LocalizedString>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override LocalizedString Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.Null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
return new LocalizedString(reader.GetString());
|
||||
}
|
||||
|
||||
throw new Exception($"Unexpected token parsing binary. Expected String, got {reader.TokenType}.");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, LocalizedString value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.Value);
|
||||
}
|
||||
}
|
||||
24
src/Interfaces/MUnique.OpenMU.Interfaces.csproj
Normal file
24
src/Interfaces/MUnique.OpenMU.Interfaces.csproj
Normal file
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<Nullable>enable</Nullable>
|
||||
<WarningsAsErrors>nullable;CS4014;VSTHRD110;VSTHRD100</WarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<OutputPath>..\..\bin\Debug\</OutputPath>
|
||||
<DocumentationFile>..\..\bin\Debug\MUnique.OpenMU.Interfaces.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<OutputPath>..\..\bin\Release\</OutputPath>
|
||||
<DocumentationFile>..\..\bin\Release\MUnique.OpenMU.Interfaces.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
10
src/Interfaces/Properties/AssemblyInfo.cs
Normal file
10
src/Interfaces/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
// <copyright file="AssemblyInfo.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("MUnique.OpenMU.Interfaces")]
|
||||
451
src/Interfaces/Properties/ModelResources.resx
Normal file
451
src/Interfaces/Properties/ModelResources.resx
Normal file
@@ -0,0 +1,451 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
|
||||
<data name="LetterHeader_TypeCaption" xml:space="preserve">
|
||||
<value>Letter Header</value>
|
||||
</data>
|
||||
<data name="LetterHeader_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Letter Headers</value>
|
||||
</data>
|
||||
<data name="LetterHeader_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LetterHeader_Id_Caption" xml:space="preserve">
|
||||
<value>Id</value>
|
||||
</data>
|
||||
<data name="LetterHeader_Id_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LetterHeader_SenderName_Caption" xml:space="preserve">
|
||||
<value>Sender Name</value>
|
||||
</data>
|
||||
<data name="LetterHeader_SenderName_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LetterHeader_ReceiverName_Caption" xml:space="preserve">
|
||||
<value>Receiver Name</value>
|
||||
</data>
|
||||
<data name="LetterHeader_ReceiverName_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LetterHeader_Subject_Caption" xml:space="preserve">
|
||||
<value>Subject</value>
|
||||
</data>
|
||||
<data name="LetterHeader_Subject_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LetterHeader_LetterDate_Caption" xml:space="preserve">
|
||||
<value>Letter Date</value>
|
||||
</data>
|
||||
<data name="LetterHeader_LetterDate_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LetterHeader_ReadFlag_Caption" xml:space="preserve">
|
||||
<value>Read Flag</value>
|
||||
</data>
|
||||
<data name="LetterHeader_ReadFlag_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildListEntry_TypeCaption" xml:space="preserve">
|
||||
<value>Guild List Entry</value>
|
||||
</data>
|
||||
<data name="GuildListEntry_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Guild List Entrys</value>
|
||||
</data>
|
||||
<data name="GuildListEntry_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildListEntry_PlayerName_Caption" xml:space="preserve">
|
||||
<value>Player Name</value>
|
||||
</data>
|
||||
<data name="GuildListEntry_PlayerName_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildListEntry_ServerId_Caption" xml:space="preserve">
|
||||
<value>Server Id</value>
|
||||
</data>
|
||||
<data name="GuildListEntry_ServerId_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildListEntry_PlayerPosition_Caption" xml:space="preserve">
|
||||
<value>Player Position</value>
|
||||
</data>
|
||||
<data name="GuildListEntry_PlayerPosition_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Guild_TypeCaption" xml:space="preserve">
|
||||
<value>Guild</value>
|
||||
</data>
|
||||
<data name="Guild_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Guilds</value>
|
||||
</data>
|
||||
<data name="Guild_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Guild_Name_Caption" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="Guild_Name_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Guild_Logo_Caption" xml:space="preserve">
|
||||
<value>Logo</value>
|
||||
</data>
|
||||
<data name="Guild_Logo_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Guild_Score_Caption" xml:space="preserve">
|
||||
<value>Score</value>
|
||||
</data>
|
||||
<data name="Guild_Score_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Guild_Notice_Caption" xml:space="preserve">
|
||||
<value>Notice</value>
|
||||
</data>
|
||||
<data name="Guild_Notice_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Guild_Hostility_Caption" xml:space="preserve">
|
||||
<value>Hostility</value>
|
||||
</data>
|
||||
<data name="Guild_Hostility_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Guild_AllianceGuild_Caption" xml:space="preserve">
|
||||
<value>Alliance Guild</value>
|
||||
</data>
|
||||
<data name="Guild_AllianceGuild_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Friend_TypeCaption" xml:space="preserve">
|
||||
<value>Friend</value>
|
||||
</data>
|
||||
<data name="Friend_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Friends</value>
|
||||
</data>
|
||||
<data name="Friend_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Friend_Id_Caption" xml:space="preserve">
|
||||
<value>Id</value>
|
||||
</data>
|
||||
<data name="Friend_Id_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Friend_CharacterId_Caption" xml:space="preserve">
|
||||
<value>Character Id</value>
|
||||
</data>
|
||||
<data name="Friend_CharacterId_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Friend_FriendId_Caption" xml:space="preserve">
|
||||
<value>Friend Id</value>
|
||||
</data>
|
||||
<data name="Friend_FriendId_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Friend_Accepted_Caption" xml:space="preserve">
|
||||
<value>Accepted</value>
|
||||
</data>
|
||||
<data name="Friend_Accepted_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="Friend_RequestOpen_Caption" xml:space="preserve">
|
||||
<value>Request Open</value>
|
||||
</data>
|
||||
<data name="Friend_RequestOpen_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildMemberStatus_TypeCaption" xml:space="preserve">
|
||||
<value>Guild Member Status</value>
|
||||
</data>
|
||||
<data name="GuildMemberStatus_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Guild Member Status</value>
|
||||
</data>
|
||||
<data name="GuildMemberStatus_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildMemberStatus_GuildId_Caption" xml:space="preserve">
|
||||
<value>Guild Id</value>
|
||||
</data>
|
||||
<data name="GuildMemberStatus_GuildId_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildMemberStatus_Position_Caption" xml:space="preserve">
|
||||
<value>Position</value>
|
||||
</data>
|
||||
<data name="GuildMemberStatus_Position_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_TypeCaption" xml:space="preserve">
|
||||
<value>Chat Server Authentication Info</value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Chat Server Authentication Infos</value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_Index_Caption" xml:space="preserve">
|
||||
<value>Index</value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_Index_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_RoomId_Caption" xml:space="preserve">
|
||||
<value>Room Id</value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_RoomId_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_ClientName_Caption" xml:space="preserve">
|
||||
<value>Client Name</value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_ClientName_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_AuthenticationToken_Caption" xml:space="preserve">
|
||||
<value>Authentication Token</value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_AuthenticationToken_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_HostAddress_Caption" xml:space="preserve">
|
||||
<value>Host Address</value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_HostAddress_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_AuthenticationRequiredUntil_Caption" xml:space="preserve">
|
||||
<value>Authentication Required Until</value>
|
||||
</data>
|
||||
<data name="ChatServerAuthenticationInfo_AuthenticationRequiredUntil_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="FriendViewItem_TypeCaption" xml:space="preserve">
|
||||
<value>Friend View Item</value>
|
||||
</data>
|
||||
<data name="FriendViewItem_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Friend View Items</value>
|
||||
</data>
|
||||
<data name="FriendViewItem_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="FriendViewItem_CharacterName_Caption" xml:space="preserve">
|
||||
<value>Character Name</value>
|
||||
</data>
|
||||
<data name="FriendViewItem_CharacterName_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="FriendViewItem_FriendName_Caption" xml:space="preserve">
|
||||
<value>Friend Name</value>
|
||||
</data>
|
||||
<data name="FriendViewItem_FriendName_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LocalizableException_TypeCaption" xml:space="preserve">
|
||||
<value>Localizable Exception</value>
|
||||
</data>
|
||||
<data name="LocalizableException_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Localizable Exceptions</value>
|
||||
</data>
|
||||
<data name="LocalizableException_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LocalizableException_InnerException_Caption" xml:space="preserve">
|
||||
<value>Inner Exception</value>
|
||||
</data>
|
||||
<data name="LocalizableException_InnerException_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="SpecialServerId_TypeCaption" xml:space="preserve">
|
||||
<value>Special Server Id</value>
|
||||
</data>
|
||||
<data name="SpecialServerId_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="SpecialServerId_Offline_Caption" xml:space="preserve">
|
||||
<value>Offline</value>
|
||||
</data>
|
||||
<data name="SpecialServerId_Offline_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="SpecialServerId_Invisible_Caption" xml:space="preserve">
|
||||
<value>Invisible</value>
|
||||
</data>
|
||||
<data name="SpecialServerId_Invisible_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="NoneConfigurationChangePublisher_TypeCaption" xml:space="preserve">
|
||||
<value>None Configuration Change Publisher</value>
|
||||
</data>
|
||||
<data name="NoneConfigurationChangePublisher_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>None Configuration Change Publishers</value>
|
||||
</data>
|
||||
<data name="NoneConfigurationChangePublisher_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildPosition_TypeCaption" xml:space="preserve">
|
||||
<value>Guild Position</value>
|
||||
</data>
|
||||
<data name="GuildPosition_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildPosition_Undefined_Caption" xml:space="preserve">
|
||||
<value>Undefined</value>
|
||||
</data>
|
||||
<data name="GuildPosition_Undefined_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildPosition_NormalMember_Caption" xml:space="preserve">
|
||||
<value>Normal Member</value>
|
||||
</data>
|
||||
<data name="GuildPosition_NormalMember_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildPosition_GuildMaster_Caption" xml:space="preserve">
|
||||
<value>Guild Master</value>
|
||||
</data>
|
||||
<data name="GuildPosition_GuildMaster_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="GuildPosition_BattleMaster_Caption" xml:space="preserve">
|
||||
<value>Battle Master</value>
|
||||
</data>
|
||||
<data name="GuildPosition_BattleMaster_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LocalizableExceptionBase_TypeCaption" xml:space="preserve">
|
||||
<value>Localizable Exception Base</value>
|
||||
</data>
|
||||
<data name="LocalizableExceptionBase_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Localizable Exception Bases</value>
|
||||
</data>
|
||||
<data name="LocalizableExceptionBase_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LocalizableExceptionBase_FormatArguments_Caption" xml:space="preserve">
|
||||
<value>Format Arguments</value>
|
||||
</data>
|
||||
<data name="LocalizableExceptionBase_FormatArguments_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="LocalizableExceptionBase_ResourceKey_Caption" xml:space="preserve">
|
||||
<value>Resource Key</value>
|
||||
</data>
|
||||
<data name="LocalizableExceptionBase_ResourceKey_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="SpecialServerIds_TypeCaption" xml:space="preserve">
|
||||
<value>Special Server Ids</value>
|
||||
</data>
|
||||
<data name="SpecialServerIds_TypeCaptionPlural" xml:space="preserve">
|
||||
<value>Special Server Ids</value>
|
||||
</data>
|
||||
<data name="SpecialServerIds_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerType_TypeCaption" xml:space="preserve">
|
||||
<value>Server Type</value>
|
||||
</data>
|
||||
<data name="ServerType_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerType_Undefined_Caption" xml:space="preserve">
|
||||
<value>Undefined</value>
|
||||
</data>
|
||||
<data name="ServerType_Undefined_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerType_GameServer_Caption" xml:space="preserve">
|
||||
<value>Game Server</value>
|
||||
</data>
|
||||
<data name="ServerType_GameServer_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerType_ConnectServer_Caption" xml:space="preserve">
|
||||
<value>Connect Server</value>
|
||||
</data>
|
||||
<data name="ServerType_ConnectServer_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerType_ChatServer_Caption" xml:space="preserve">
|
||||
<value>Chat Server</value>
|
||||
</data>
|
||||
<data name="ServerType_ChatServer_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerState_TypeCaption" xml:space="preserve">
|
||||
<value>Server State</value>
|
||||
</data>
|
||||
<data name="ServerState_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerState_Stopped_Caption" xml:space="preserve">
|
||||
<value>Stopped</value>
|
||||
</data>
|
||||
<data name="ServerState_Stopped_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerState_Starting_Caption" xml:space="preserve">
|
||||
<value>Starting</value>
|
||||
</data>
|
||||
<data name="ServerState_Starting_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerState_Started_Caption" xml:space="preserve">
|
||||
<value>Started</value>
|
||||
</data>
|
||||
<data name="ServerState_Started_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerState_Stopping_Caption" xml:space="preserve">
|
||||
<value>Stopping</value>
|
||||
</data>
|
||||
<data name="ServerState_Stopping_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="ServerState_Timeout_Caption" xml:space="preserve">
|
||||
<value>Timeout</value>
|
||||
</data>
|
||||
<data name="ServerState_Timeout_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="MessageType_TypeCaption" xml:space="preserve">
|
||||
<value>Message Type</value>
|
||||
</data>
|
||||
<data name="MessageType_TypeDescription" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="MessageType_GoldenCenter_Caption" xml:space="preserve">
|
||||
<value>Golden Center</value>
|
||||
</data>
|
||||
<data name="MessageType_GoldenCenter_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="MessageType_BlueNormal_Caption" xml:space="preserve">
|
||||
<value>Blue Normal</value>
|
||||
</data>
|
||||
<data name="MessageType_BlueNormal_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
<data name="MessageType_GuildNotice_Caption" xml:space="preserve">
|
||||
<value>Guild Notice</value>
|
||||
</data>
|
||||
<data name="MessageType_GuildNotice_Description" xml:space="preserve">
|
||||
<value></value>
|
||||
</data>
|
||||
</root>
|
||||
12
src/Interfaces/Readme.md
Normal file
12
src/Interfaces/Readme.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Interfaces
|
||||
|
||||
This project contains the interfaces which are used to communicate between the
|
||||
different sub-systems ("servers") of the whole system.
|
||||
|
||||
The game logic and game server should only use these interfaces instead of the
|
||||
actual implementations.
|
||||
The goal is to make them exchangeable. This can be helpful for tests, and also
|
||||
if we want to move specific systems to other machines or external processes
|
||||
(scale-out).
|
||||
Then there could be an implementation of an interface which forwards the calls
|
||||
over the network (etc.) to another process.
|
||||
16
src/Interfaces/ServerInfo.cs
Normal file
16
src/Interfaces/ServerInfo.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// <copyright file="ServerInfo.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The state info about a server.
|
||||
/// </summary>
|
||||
public record ServerInfo(ushort Id, string Description, int CurrentConnections, int MaximumConnections)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the count of current connections.
|
||||
/// </summary>
|
||||
public int CurrentConnections { get; set; } = CurrentConnections;
|
||||
}
|
||||
31
src/Interfaces/ServerType.cs
Normal file
31
src/Interfaces/ServerType.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
// <copyright file="ServerType.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// The type of a <see cref="IManageableServer"/>.
|
||||
/// </summary>
|
||||
public enum ServerType
|
||||
{
|
||||
/// <summary>
|
||||
/// Undefined type.
|
||||
/// </summary>
|
||||
Undefined = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A game server.
|
||||
/// </summary>
|
||||
GameServer = 1,
|
||||
|
||||
/// <summary>
|
||||
/// A connect server.
|
||||
/// </summary>
|
||||
ConnectServer = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A chat server.
|
||||
/// </summary>
|
||||
ChatServer = 3,
|
||||
}
|
||||
22
src/Interfaces/SpecialServerIds.cs
Normal file
22
src/Interfaces/SpecialServerIds.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
// <copyright file="SpecialServerIds.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Special server ids.
|
||||
/// </summary>
|
||||
/// <remarks>Ids from 0 to 0xFFFF are reserved to game servers.</remarks>
|
||||
public static class SpecialServerIds
|
||||
{
|
||||
/// <summary>
|
||||
/// The connect server special server id.
|
||||
/// </summary>
|
||||
public static readonly int ConnectServer = 0x10000;
|
||||
|
||||
/// <summary>
|
||||
/// The chat server special server id.
|
||||
/// </summary>
|
||||
public static readonly int ChatServer = 0x20000;
|
||||
}
|
||||
Reference in New Issue
Block a user