baseline: OpenMU upstream b5a0961 (fresh source)
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
// <copyright file="AddAgilityStatChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.AttributeSystem;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the command to add agility stat points.
|
||||
/// </summary>
|
||||
[Guid("43156A52-03EE-42C0-88BF-CA9665DC8E1E")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.AddAgilityStatChatCommandPlugIn_Name), Description = nameof(PlugInResources.AddAgilityStatChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, null, MinimumStatus)]
|
||||
public class AddAgilityStatChatCommandPlugIn : AddStatChatCommandPlugIn, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/addagi";
|
||||
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
command = command.Insert(4, " ");
|
||||
await base.HandleCommandAsync(player, command).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// <copyright file="AddCommandStatChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.AttributeSystem;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the command to add command stat points.
|
||||
/// </summary>
|
||||
[Guid("EFE421FB-BE79-4656-AF39-D22A105D1455")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.AddCommandStatChatCommandPlugIn_Name), Description = nameof(PlugInResources.AddCommandStatChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, null, MinimumStatus)]
|
||||
public class AddCommandStatChatCommandPlugIn : AddStatChatCommandPlugIn, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/addcmd";
|
||||
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
command = command.Insert(4, " ");
|
||||
await base.HandleCommandAsync(player, command).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// <copyright file="AddEnergyStatChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.AttributeSystem;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the command to add energy stat points.
|
||||
/// </summary>
|
||||
[Guid("A597B6E7-9395-4CF4-8439-A1D60134B63E")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.AddEnergyStatChatCommandPlugIn_Name), Description = nameof(PlugInResources.AddEnergyStatChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, null, MinimumStatus)]
|
||||
public class AddEnergyStatChatCommandPlugIn : AddStatChatCommandPlugIn, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/addene";
|
||||
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
command = command.Insert(4, " ");
|
||||
await base.HandleCommandAsync(player, command).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// <copyright file="AddStatChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlayerActions.Character;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the command to add stat points.
|
||||
/// </summary>
|
||||
[Guid("042EC5C6-27C8-4E00-A48B-C5458EDEA0BC")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.AddStatChatCommandPlugIn_Name), Description = nameof(PlugInResources.AddStatChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(Arguments), MinimumStatus)]
|
||||
public class AddStatChatCommandPlugIn : ChatCommandPlugInBase<AddStatChatCommandPlugIn.Arguments>
|
||||
{
|
||||
private const string Command = "/add";
|
||||
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.Normal;
|
||||
|
||||
private readonly IncreaseStatsAction _action = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
if (player.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var attribute = await this.TryGetAttributeAsync(player, arguments.StatType).ConfigureAwait(false);
|
||||
if (attribute is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedCharacter = player.SelectedCharacter;
|
||||
|
||||
if (!selectedCharacter.CanIncreaseStats(arguments.Amount))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.CurrentMiniGame is not null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(PlayerMessage.AddingMultiplePointsWhileMiniGameNotAllowed).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await this._action.IncreaseStatsAsync(player, attribute, arguments.Amount).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for this command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the stat.
|
||||
/// </summary>
|
||||
[ValidValues("str", "agi", "vit", "ene", "cmd")]
|
||||
public string? StatType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the amount.
|
||||
/// </summary>
|
||||
public ushort Amount { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// <copyright file="AddStrengthStatChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.AttributeSystem;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the command to add strength stat points.
|
||||
/// </summary>
|
||||
[Guid("21B15D95-BA2F-40A3-AB7D-8BD886FAEAE5")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.AddStrengthStatChatCommandPlugIn_Name), Description = nameof(PlugInResources.AddStrengthStatChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, null, MinimumStatus)]
|
||||
public class AddStrengthStatChatCommandPlugIn : AddStatChatCommandPlugIn, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/addstr";
|
||||
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
command = command.Insert(4, " ");
|
||||
await base.HandleCommandAsync(player, command).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// <copyright file="AddVitalityStatChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.AttributeSystem;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the command to add vitality stat points.
|
||||
/// </summary>
|
||||
[Guid("370CE86C-E382-4E0F-93F4-AD75FA079129")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.AddVitalityStatChatCommandPlugIn_Name), Description = nameof(PlugInResources.AddVitalityStatChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, null, MinimumStatus)]
|
||||
public class AddVitalityStatChatCommandPlugIn : AddStatChatCommandPlugIn, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/addvit";
|
||||
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
command = command.Insert(4, " ");
|
||||
await base.HandleCommandAsync(player, command).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
43
src/GameLogic/PlugIns/ChatCommands/ArgumentAttribute.cs
Normal file
43
src/GameLogic/PlugIns/ChatCommands/ArgumentAttribute.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
// <copyright file="ArgumentAttribute.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
/// <summary>
|
||||
/// Attribute used in the arguments of the commands.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class ArgumentAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArgumentAttribute"/> class
|
||||
/// which is a required argument.
|
||||
/// </summary>
|
||||
/// <param name="shortName">The short name.</param>
|
||||
public ArgumentAttribute(string shortName)
|
||||
: this(shortName, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArgumentAttribute" /> class.
|
||||
/// </summary>
|
||||
/// <param name="shortName">The short name.</param>
|
||||
/// <param name="isRequired">If set to <c>true</c>, this argument is required to execute the command.</param>
|
||||
public ArgumentAttribute(string shortName, bool isRequired)
|
||||
{
|
||||
this.ShortName = shortName;
|
||||
this.IsRequired = isRequired;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the short name of the argument to be used in chat.
|
||||
/// </summary>
|
||||
public string ShortName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the argument is required to execute the command.
|
||||
/// </summary>
|
||||
public bool IsRequired { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="BanAccChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by BanAccChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class BanAccChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the account name.
|
||||
/// </summary>
|
||||
[Argument("acc")]
|
||||
public string? AccountName { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="BanCharChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by BanCharChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class BanCharChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("char")]
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="ChangeLanguageChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by <see cref="ChangeLanguageChatCommandArgs"/>>.
|
||||
/// </summary>
|
||||
public class ChangeLanguageChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the iso 2/3 language code of the requested language.
|
||||
/// </summary>
|
||||
[Argument("isoCode")]
|
||||
public string? IsoLanguageCode { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="CharInfoChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by CharInfoChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class CharInfoChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("char")]
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// <copyright file="ChatBanCharChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by the <see cref="ChatBanCharChatCommandPlugIn"/>.
|
||||
/// </summary>
|
||||
public class ChatBanCharChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("characterName")]
|
||||
public string? CharacterName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the duration.
|
||||
/// </summary>
|
||||
[Argument("durationMinutes")]
|
||||
public int DurationMinutes { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="ChatUnbanCharChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by the <see cref="ChatUnbanCharChatCommandPlugIn"/>.
|
||||
/// </summary>
|
||||
public class ChatUnbanCharChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("characterName")]
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// <copyright file="CoordinatesCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
using MUnique.OpenMU.Pathfinding;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by <see cref="TeleportChatCommandPlugIn"/> and others which just require an X and Y coordinate of a game map.
|
||||
/// </summary>
|
||||
public class CoordinatesCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the coordinate X.
|
||||
/// </summary>
|
||||
[Argument("x", true)]
|
||||
public byte X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the coordinate Y.
|
||||
/// </summary>
|
||||
[Argument("y", true)]
|
||||
public byte Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the coordinates X and Y.
|
||||
/// </summary>
|
||||
public Point Coordinates => new(this.X, this.Y);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// <copyright file="CreateMonsterChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by <see cref="CreateMonsterChatCommand"/>.
|
||||
/// </summary>
|
||||
public class CreateMonsterChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("number")]
|
||||
public short MonsterNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the created monster should be intelligent (walking, attacking), or should do nothing at all.
|
||||
/// </summary>
|
||||
[Argument("intelligence", false)]
|
||||
public bool IsIntelligent { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="DisconnectChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by DisconnectChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class DisconnectChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("char")]
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// <copyright file="EmptyChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by any ChatCommandPlugIn which don't need any arguments.
|
||||
/// </summary>
|
||||
public class EmptyChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="GuildDisconnectChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by GuildDisconnectChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class GuildDisconnectChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the guild name.
|
||||
/// </summary>
|
||||
[Argument("guild")]
|
||||
public string? GuildName { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// <copyright file="GuildMoveChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
using MUnique.OpenMU.Pathfinding;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by GuildMoveChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class GuildMoveChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the guild name.
|
||||
/// </summary>
|
||||
[Argument("guild")]
|
||||
public string? GuildName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name or id of the map.
|
||||
/// </summary>
|
||||
[Argument("mapIdOrName")]
|
||||
public string? MapIdOrName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the coordinate X.
|
||||
/// </summary>
|
||||
[Argument("x", false)]
|
||||
public byte X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the coordinate Y.
|
||||
/// </summary>
|
||||
[Argument("y", false)]
|
||||
public byte Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the coordinates X and Y.
|
||||
/// </summary>
|
||||
public Point Coordinates => new(this.X, this.Y);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="GuildWarChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by <see cref="GuildWarChatCommandPlugIn"/> and <see cref="GuildBattleSoccerChatCommandPlugIn"/>.
|
||||
/// </summary>
|
||||
public class GuildWarChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the guild name.
|
||||
/// </summary>
|
||||
[Argument("guildname")]
|
||||
public string GuildName { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="IdCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by <see cref="RemoveNpcChatCommand"/> and others which just require an id of an object.
|
||||
/// </summary>
|
||||
public class IdCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the npc id.
|
||||
/// </summary>
|
||||
[Argument("id", true)]
|
||||
public short Id { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// <copyright file="ItemChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by ItemChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class ItemChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the group.
|
||||
/// </summary>
|
||||
[Argument("group")]
|
||||
public byte Group { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number.
|
||||
/// </summary>
|
||||
[Argument("number")]
|
||||
public short Number { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level.
|
||||
/// </summary>
|
||||
[Argument("lvl", false)]
|
||||
public byte Level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the excellent number.
|
||||
/// </summary>
|
||||
[Argument("ex", false)]
|
||||
public byte ExcellentNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the item contains skill.
|
||||
/// </summary>
|
||||
[Argument("sk", false)]
|
||||
public bool Skill { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the item contains luck.
|
||||
/// </summary>
|
||||
[Argument("lu", false)]
|
||||
public bool Luck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the option.
|
||||
/// </summary>
|
||||
[Argument("opt", false)]
|
||||
public byte Opt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ancient set discriminator.
|
||||
/// When 0, it's not an ancient.
|
||||
/// When 1, the first ancient type of an item is applied; When 2, the second, if available.
|
||||
/// Example for a Dragon Set item: 1 will be Hyon, 2 will be Vicious..
|
||||
/// </summary>
|
||||
[Argument("anc", false)]
|
||||
[ValidValues("0", "1", "2")]
|
||||
public byte Ancient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ancient bonus option; Should be 1 or 2. Only applies, when <see cref="Ancient"/> is bigger than 0.
|
||||
/// </summary>
|
||||
[Argument("ancBonuslvl", false)]
|
||||
[ValidValues("1", "2")]
|
||||
public byte AncientBonusLevel { get; set; } = 1;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// <copyright file="MoveChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
using MUnique.OpenMU.Pathfinding;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by MoveChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class MoveChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the target.
|
||||
/// The target can be the map name, map id or character name.
|
||||
/// </summary>
|
||||
[Argument("target")]
|
||||
public string? Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name or id of the map.
|
||||
/// </summary>
|
||||
[Argument("mapIdOrName", false)]
|
||||
public string? MapIdOrName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the coordinate X.
|
||||
/// </summary>
|
||||
[Argument("x", false)]
|
||||
public byte X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the coordinate Y.
|
||||
/// </summary>
|
||||
[Argument("y", false)]
|
||||
public byte Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the coordinates X and Y.
|
||||
/// </summary>
|
||||
public Point Coordinates => new(this.X, this.Y);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="MoveMonsterCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by <see cref="MoveMonsterChatCommand"/> and others which just require an X and Y coordinate of a game map.
|
||||
/// </summary>
|
||||
public class MoveMonsterCommandArgs : CoordinatesCommandArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the monster id.
|
||||
/// </summary>
|
||||
[Argument("id", true)]
|
||||
public short Id { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// <copyright file="PKChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by PKChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class PkChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("char")]
|
||||
public string? CharacterName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pk level.
|
||||
/// </summary>
|
||||
[Argument("pk_lvl")]
|
||||
[ValidValues("1", "2", "3")]
|
||||
public int Level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pk count.
|
||||
/// </summary>
|
||||
[Argument("pk_count")]
|
||||
public int Count { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="PKClearChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by PKClearChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class PkClearChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("char", false)]
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="SkinChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by the <see cref="SkinChatCommandPlugIn"/>.
|
||||
/// </summary>
|
||||
public class SkinChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the skin number, which is mostly equivalent to the <see cref="MonsterDefinition.Number"/>.
|
||||
/// </summary>
|
||||
[Argument("skin", true)]
|
||||
public short SkinNumber { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="TraceChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by TraceChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class TraceChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("char")]
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="UnBanAccChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by UnBanAccChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class UnBanAccChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the account name.
|
||||
/// </summary>
|
||||
[Argument("acc")]
|
||||
public string? AccountName { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// <copyright file="UnBanCharChatCommandArgs.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Arguments used by UnBanCharChatCommandPlugIn.
|
||||
/// </summary>
|
||||
public class UnBanCharChatCommandArgs : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name.
|
||||
/// </summary>
|
||||
[Argument("char")]
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
34
src/GameLogic/PlugIns/ChatCommands/ArgumentsBase.cs
Normal file
34
src/GameLogic/PlugIns/ChatCommands/ArgumentsBase.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
// <copyright file="ArgumentsBase.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
/// <summary>
|
||||
/// The base of every arguments class used in the commands.
|
||||
/// </summary>
|
||||
public class ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// This makes it easier to print the arguments and its values for debugging.
|
||||
/// </summary>
|
||||
/// <returns>String.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var properties = this.GetType().GetProperties();
|
||||
var stringBuilder = new StringBuilder();
|
||||
bool isFirst = true;
|
||||
foreach (var property in properties)
|
||||
{
|
||||
if (!isFirst)
|
||||
{
|
||||
stringBuilder.Append(" ");
|
||||
}
|
||||
|
||||
stringBuilder.Append($"{property.Name}:{property.GetValue(this)}");
|
||||
isFirst = false;
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// <copyright file="BanAccChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles banacc commands.
|
||||
/// </summary>
|
||||
[Guid("EF869270-847E-48D5-9012-F5D111D9C8EB")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.BanAccChatCommandPlugIn_Name), Description = nameof(PlugInResources.BanAccChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(BanAccChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class BanAccChatCommandPlugIn : ChatCommandPlugInBase<BanAccChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/banacc";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, BanAccChatCommandArgs arguments)
|
||||
{
|
||||
await this.ChangeAccountStateByLoginNameAsync(gameMaster, arguments.AccountName ?? string.Empty, AccountState.Banned).ConfigureAwait(false);
|
||||
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.AccountHasBeenBanned), this.Key, arguments.AccountName).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// <copyright file="BanCharChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles banchar commands.
|
||||
/// </summary>
|
||||
[Guid("7AD1E5F4-4B07-4165-B9A4-188614F00F7C")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.BanCharChatCommandPlugIn_Name), Description = nameof(PlugInResources.BanCharChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(BanCharChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class BanCharChatCommandPlugIn : ChatCommandPlugInBase<BanCharChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/banchar";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, BanCharChatCommandArgs arguments)
|
||||
{
|
||||
if (!await this.TryChangeAccountStateByCharacterNameAsync(gameMaster, arguments.CharacterName ?? string.Empty, AccountState.Banned).ConfigureAwait(false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.AccountOfHasBeenBanned), this.Key, arguments.CharacterName).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// <copyright file="ChangeLanguageChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the language change command.
|
||||
/// </summary>
|
||||
[Guid("06870B25-3240-49CF-ADD4-F3060EA1FA7D")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.ChangeLanguageChatCommandPlugIn_Name), Description = nameof(PlugInResources.ChangeLanguageChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(ChangeLanguageChatCommandArgs), CharacterStatus.Normal)]
|
||||
public class ChangeLanguageChatCommandPlugIn : ChatCommandPlugInBase<ChangeLanguageChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/language";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, ChangeLanguageChatCommandArgs arguments)
|
||||
{
|
||||
var languages = CultureHelper.GetAvailableCultures<PlayerMessage>();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(arguments.IsoLanguageCode))
|
||||
{
|
||||
await ShowAvailableLanguagesAsync(player, languages).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var requestedCulture = languages.FirstOrDefault(cu => cu.TwoLetterISOLanguageName == arguments.IsoLanguageCode
|
||||
|| cu.ThreeLetterISOLanguageName == arguments.IsoLanguageCode);
|
||||
if (requestedCulture is null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.RequestedLanguageNotFound), arguments.IsoLanguageCode).ConfigureAwait(false);
|
||||
await ShowAvailableLanguagesAsync(player, languages).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.Culture = requestedCulture;
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.LanguageChanged), requestedCulture.NativeName, requestedCulture.TwoLetterISOLanguageName).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static async ValueTask ShowAvailableLanguagesAsync(Player player, IEnumerable<CultureInfo> languages)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.AvailableLanguagesCaption)).ConfigureAwait(false);
|
||||
foreach (var lang in languages.OrderBy(l => l.TwoLetterISOLanguageName))
|
||||
{
|
||||
await player.ShowBlueMessageAsync($" {lang.TwoLetterISOLanguageName} - {lang.NativeName} / {lang.EnglishName}").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// <copyright file="CharInfoChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.DataModel.Entities;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles charinfo commands.
|
||||
/// </summary>
|
||||
[Guid("0C7162BC-C74E-4A65-82E3-12811E4BE170")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.CharInfoChatCommandPlugIn_Name), Description = nameof(PlugInResources.CharInfoChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(CharInfoChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class CharInfoChatCommandPlugIn : ChatCommandPlugInBase<CharInfoChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/charinfo";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, CharInfoChatCommandArgs arguments)
|
||||
{
|
||||
var player = await this.GetPlayerByCharacterNameAsync(gameMaster, arguments.CharacterName ?? string.Empty).ConfigureAwait(false);
|
||||
|
||||
if (player?.Account is not { } account
|
||||
|| player.SelectedCharacter is not { } character)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await gameMaster.ShowBlueMessageAsync($"Account Name: {account.LoginName}").ConfigureAwait(false);
|
||||
|
||||
await this.ShowAllLinesMessageToAsync(gameMaster, GetCharacterInfo(gameMaster, character)).ConfigureAwait(false);
|
||||
|
||||
await this.ShowAllLinesMessageToAsync(gameMaster, player.Attributes?.ToString()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static string GetCharacterInfo(Player gameMaster, Character character)
|
||||
{
|
||||
var stringBuilder = new StringBuilder()
|
||||
.AppendLine($"Id: {character.Id}")
|
||||
.AppendLine($"Name: {character.Name}")
|
||||
.AppendLine($"Class: {character.CharacterClass?.Name.GetTranslation(gameMaster.Culture)}")
|
||||
.AppendLine($"Slot: {character.CharacterSlot}")
|
||||
.AppendLine($"Create Date: {character.CreateDate}")
|
||||
.AppendLine($"Exp: {character.Experience}")
|
||||
.AppendLine($"Level Up Points: {character.LevelUpPoints}")
|
||||
.AppendLine($"Master Exp: {character.MasterExperience}")
|
||||
.AppendLine($"Master Lv Up Points: {character.MasterLevelUpPoints}")
|
||||
.AppendLine($"Location: {character.CurrentMap?.Name}({character.PositionX}, {character.PositionY})")
|
||||
.AppendLine($"Kill Count: {character.PlayerKillCount}")
|
||||
.AppendLine($"State Remaining Seconds: {character.StateRemainingSeconds}")
|
||||
.AppendLine($"State: {Enum.GetName(character.State)}")
|
||||
.AppendLine($"Status: {Enum.GetName(character.CharacterStatus)}")
|
||||
.AppendLine($"Used Fruit Points: {character.UsedFruitPoints}")
|
||||
.AppendLine($"Used Neg Fruit Points: {character.UsedNegFruitPoints}")
|
||||
.AppendLine($"Inventory Extensions: {character.InventoryExtensions}");
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
private async ValueTask ShowAllLinesMessageToAsync(Player gameMaster, string? message)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var reader = new StringReader(message);
|
||||
|
||||
while (true)
|
||||
{
|
||||
var line = await reader.ReadLineAsync().ConfigureAwait(false);
|
||||
if (line == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
await gameMaster.ShowBlueMessageAsync(line).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// <copyright file="ChatBanCharChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles chatban command.
|
||||
/// </summary>
|
||||
[Guid("287AE9A6-E434-4E52-A791-8AAD267A8E05")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.ChatBanCharChatCommandPlugIn_Name), Description = nameof(PlugInResources.ChatBanCharChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(ChatBanCharChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class ChatBanCharChatCommandPlugIn : ChatCommandPlugInBase<ChatBanCharChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/chatban";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, ChatBanCharChatCommandArgs arguments)
|
||||
{
|
||||
if (string.IsNullOrEmpty(arguments.CharacterName))
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNameIsRequired)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (arguments.DurationMinutes == 0)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.DurationMustBeLongerThan0)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var player = gameMaster.GameContext.GetPlayerByCharacterName(arguments.CharacterName);
|
||||
if (player == null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), arguments.CharacterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await this.ChangeAccountChatBanUntilAsync(player, DateTime.UtcNow.AddMinutes(arguments.DurationMinutes)).ConfigureAwait(false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Send ban notice to Game Master
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.AccountChatBannedResult), this.Key, arguments.CharacterName, arguments.DurationMinutes).ConfigureAwait(false);
|
||||
|
||||
// Send ban notice to character
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.YouAreChatBanned), arguments.DurationMinutes).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// <copyright file="ChatCommandHelpAttribute.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
/// <summary>
|
||||
/// An attribute which decorates an <see cref="IChatCommandPlugIn"/> with help information.
|
||||
/// This information is then used in the <see cref="HelpCommand"/>.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class ChatCommandHelpAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatCommandHelpAttribute" /> class.
|
||||
/// </summary>
|
||||
/// <param name="command">The command.</param>
|
||||
public ChatCommandHelpAttribute(string command)
|
||||
: this(command, CharacterStatus.Normal)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatCommandHelpAttribute" /> class.
|
||||
/// </summary>
|
||||
/// <param name="command">The command.</param>
|
||||
/// <param name="minimumCharacterStatus">The minimum character status.</param>
|
||||
public ChatCommandHelpAttribute(string command, CharacterStatus minimumCharacterStatus)
|
||||
: this(command, (Type?)null, minimumCharacterStatus)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatCommandHelpAttribute" /> class.
|
||||
/// </summary>
|
||||
/// <param name="command">The command.</param>
|
||||
/// <param name="description">The description of the command.</param>
|
||||
/// <param name="argumentsType">Type of the arguments.</param>
|
||||
public ChatCommandHelpAttribute(string command, string description, Type? argumentsType)
|
||||
: this(command, argumentsType, CharacterStatus.Normal)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatCommandHelpAttribute" /> class.
|
||||
/// </summary>
|
||||
/// <param name="command">The command.</param>
|
||||
/// <param name="argumentsType">Type of the arguments.</param>
|
||||
/// <param name="minimumCharacterStatus">The minimum character status.</param>
|
||||
public ChatCommandHelpAttribute(string command, Type? argumentsType, CharacterStatus minimumCharacterStatus)
|
||||
{
|
||||
this.Command = command;
|
||||
this.ArgumentsType = argumentsType;
|
||||
this.MinimumCharacterStatus = minimumCharacterStatus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the command.
|
||||
/// </summary>
|
||||
public string Command { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minimum character status.
|
||||
/// </summary>
|
||||
public CharacterStatus MinimumCharacterStatus { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the arguments of the chat command.
|
||||
/// </summary>
|
||||
public Type? ArgumentsType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the usage text for the chat command.
|
||||
/// </summary>
|
||||
public string Usage => this.ArgumentsType is null ? this.Command : CommandExtensions.CreateUsage(this.ArgumentsType, this.Command);
|
||||
}
|
||||
263
src/GameLogic/PlugIns/ChatCommands/ChatCommandPlugInBase.cs
Normal file
263
src/GameLogic/PlugIns/ChatCommands/ChatCommandPlugInBase.cs
Normal file
@@ -0,0 +1,263 @@
|
||||
// <copyright file="ChatCommandPlugInBase.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using MUnique.OpenMU.AttributeSystem;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.Pathfinding;
|
||||
|
||||
/// <summary>
|
||||
/// The base of every chat command plug in.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of arguments base.</typeparam>
|
||||
public abstract class ChatCommandPlugInBase<T> : IChatCommandPlugIn
|
||||
where T : ArgumentsBase, new()
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public abstract string Key { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract CharacterStatus MinCharacterStatusRequirement { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
var arguments = await command.TryParseArgumentsAsync<T>(player).ConfigureAwait(false);
|
||||
if (arguments is not null)
|
||||
{
|
||||
await this.DoHandleCommandAsync(player, arguments).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
player.Logger.LogError(ex, $"Unexpected error handling the chat command '{this.Key}'.", command);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the chat command safely.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <param name="arguments">The arguments.</param>
|
||||
protected abstract ValueTask DoHandleCommandAsync(Player player, T arguments);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a player by his character name.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <param name="characterName">The character name.</param>
|
||||
/// <returns>The target player.</returns>
|
||||
protected async ValueTask<Player?> GetPlayerByCharacterNameAsync(Player player, string characterName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(characterName))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNameIsRequired)).ConfigureAwait(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (result is null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a guild id by name.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <param name="guildName">The guild name.</param>
|
||||
/// <returns>The guild id.</returns>
|
||||
protected async ValueTask<uint?> GetGuildIdByNameAsync(Player player, string guildName)
|
||||
{
|
||||
var guildServer = (player.GameContext as IGameServerContext)!.GuildServer;
|
||||
var guildId = await guildServer.GetGuildIdByNameAsync(guildName).ConfigureAwait(false);
|
||||
|
||||
if (guildId == 0)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.GuildNotFound), guildName).ConfigureAwait(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
return guildId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a exit gate.
|
||||
/// </summary>
|
||||
/// <param name="gameMaster">The game master.</param>
|
||||
/// <param name="map">The name or id of the map.</param>
|
||||
/// <param name="coordinates">The coordinates X and Y.</param>
|
||||
/// <returns>The ExitGate.</returns>
|
||||
protected async ValueTask<ExitGate?> GetExitGateAsync(Player gameMaster, string map, Point coordinates)
|
||||
{
|
||||
if (coordinates == default)
|
||||
{
|
||||
var result = this.GetWarpInfo(gameMaster, map)?.Gate;
|
||||
if (result is null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MapNotFound), map).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var mapDefinition = ushort.TryParse(map, out var mapId)
|
||||
? (await gameMaster.GameContext.GetMapAsync(mapId).ConfigureAwait(false))?.Definition
|
||||
: gameMaster.GameContext.Configuration.Maps.FirstOrDefault(x =>
|
||||
x.Name.GetTranslationAsSpan(gameMaster.Culture).Equals(map, StringComparison.OrdinalIgnoreCase)
|
||||
|| x.Name.ValueInNeutralLanguageAsSpan.Equals(map, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (mapDefinition is null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MapNotFound), map).ConfigureAwait(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ExitGate
|
||||
{
|
||||
Map = mapDefinition,
|
||||
X1 = coordinates.X,
|
||||
X2 = coordinates.X,
|
||||
Y1 = coordinates.Y,
|
||||
Y2 = coordinates.Y,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a warp info.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <param name="map">The name or id of the map.</param>
|
||||
/// <returns>The WarpInfo.</returns>
|
||||
protected WarpInfo? GetWarpInfo(Player player, string map)
|
||||
{
|
||||
var warpList = player.GameContext.Configuration.WarpList;
|
||||
return ushort.TryParse(map, out var mapId)
|
||||
? warpList.FirstOrDefault(info => info.Gate?.Map?.Number == mapId)
|
||||
: warpList.FirstOrDefault(info => map.Equals(info.Name.GetTranslationAsSpan(player.Culture), StringComparison.CurrentCultureIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change <see cref="AccountState"/> from Account by character name.
|
||||
/// </summary>
|
||||
/// <param name="gameMaster">GameMaster Player.</param>
|
||||
/// <param name="name">Name of character to be changed.</param>
|
||||
/// <param name="accountState">New <see cref="AccountState"/>.</param>
|
||||
/// <returns>Flag, if successful.</returns>
|
||||
protected async ValueTask<bool> TryChangeAccountStateByCharacterNameAsync(Player gameMaster, string? name, AccountState accountState)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNameIsRequired)).ConfigureAwait(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return await this.ChangeAccountStateAsync(gameMaster, context => context.GetAccountByCharacterNameAsync(name), accountState).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change <see cref="AccountState"/> from Account by login name.
|
||||
/// </summary>
|
||||
/// <param name="gameMaster">GameMaster Player.</param>
|
||||
/// <param name="loginName">Login from account to be changed.</param>
|
||||
/// <param name="accountState">New <see cref="AccountState"/>.</param>
|
||||
protected async ValueTask<bool> ChangeAccountStateByLoginNameAsync(Player gameMaster, string? loginName, AccountState accountState)
|
||||
{
|
||||
if (string.IsNullOrEmpty(loginName))
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.LoginNameRequired)).ConfigureAwait(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return await this.ChangeAccountStateAsync(gameMaster, context => context.GetAccountByLoginNameAsync(loginName), accountState).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes ChatBanUntil value from Account.
|
||||
/// </summary>
|
||||
/// <param name="player">Player to be banned/unbanned.</param>
|
||||
/// <param name="chatBanUntil">Date and time until which the chat ban is in effect.</param>
|
||||
protected async ValueTask<bool> ChangeAccountChatBanUntilAsync(Player player, DateTime? chatBanUntil)
|
||||
{
|
||||
if (player.Account == null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.AccountNotFound)).ConfigureAwait(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
player.Account.ChatBanUntil = chatBanUntil;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the stat attribute of the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <param name="statType">Type of the stat.</param>
|
||||
/// <returns>The found stat attribute, or <see langword="null"/>.</returns>
|
||||
protected async ValueTask<AttributeDefinition?> TryGetAttributeAsync(Player player, string? statType)
|
||||
{
|
||||
if (player.SelectedCharacter is not { } selectedCharacter)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var attribute = statType switch
|
||||
{
|
||||
"str" => Stats.BaseStrength,
|
||||
"agi" => Stats.BaseAgility,
|
||||
"vit" => Stats.BaseVitality,
|
||||
"ene" => Stats.BaseEnergy,
|
||||
"cmd" => Stats.BaseLeadership,
|
||||
_ => null,
|
||||
};
|
||||
if (attribute is null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(PlayerMessage.UnknownAttribute, statType).ConfigureAwait(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (selectedCharacter.Attributes.All(sa => sa.Definition != attribute))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(PlayerMessage.CharacterHasNoStatAttribute, statType).ConfigureAwait(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
return attribute;
|
||||
}
|
||||
|
||||
private async ValueTask<bool> ChangeAccountStateAsync(Player gameMaster, Func<MUnique.OpenMU.Persistence.IPlayerContext, ValueTask<Account?>> accountSelector, AccountState accountState)
|
||||
{
|
||||
using var context = gameMaster.GameContext.PersistenceContextProvider.CreateNewPlayerContext(gameMaster.GameContext.Configuration);
|
||||
var account = await accountSelector(context).ConfigureAwait(false);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.AccountNotFound)).ConfigureAwait(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var character in account.Characters)
|
||||
{
|
||||
var player = gameMaster.GameContext.GetPlayerByCharacterName(character.Name ?? string.Empty);
|
||||
|
||||
// disconnect to change account
|
||||
if (player != null)
|
||||
{
|
||||
await player.DisconnectAsync().ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
account.State = accountState;
|
||||
await context.SaveChangesAsync().ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// <copyright file="ChatCommandTypeExtensions.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods regarding chat command types.
|
||||
/// </summary>
|
||||
public static class ChatCommandTypeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the available chat commands of the player.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <returns>The available chat commands of the player.</returns>
|
||||
public static IEnumerable<ChatCommandHelpAttribute> GetAvailableChatCommands(this Player player)
|
||||
{
|
||||
return player.GameContext?.PlugInManager
|
||||
.GetKnownPlugInsOf<IChatCommandPlugIn>()
|
||||
.Select(CustomAttributeExtensions.GetCustomAttribute<ChatCommandHelpAttribute>)
|
||||
.Where(attribute => attribute is { })
|
||||
.Where(attribute => player.SelectedCharacter?.CharacterStatus >= attribute!.MinimumCharacterStatus)
|
||||
.Select(attribute => attribute!) ?? Enumerable.Empty<ChatCommandHelpAttribute>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// <copyright file="ChatUnbanCharChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles chatunban command.
|
||||
/// </summary>
|
||||
[Guid("82E74664-7700-433B-9428-90C17CC71350")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.ChatUnbanCharChatCommandPlugIn_Name), Description = nameof(PlugInResources.ChatUnbanCharChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(ChatUnbanCharChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class ChatUnbanCharChatCommandPlugIn : ChatCommandPlugInBase<ChatUnbanCharChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/chatunban";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, ChatUnbanCharChatCommandArgs arguments)
|
||||
{
|
||||
if (string.IsNullOrEmpty(arguments.CharacterName))
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNameIsRequired)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var player = gameMaster.GameContext.GetPlayerByCharacterName(arguments.CharacterName);
|
||||
if (player == null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), arguments.CharacterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await this.ChangeAccountChatBanUntilAsync(player, null).ConfigureAwait(false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Send unban notice to Game Master
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.ChatBanRemoved), this.Key, arguments.CharacterName).ConfigureAwait(false);
|
||||
|
||||
// Send unban notice to character
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.YourChatBanRemovedByGameMaster)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
// <copyright file="ClearInventoryChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.Interfaces;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which clears a character's inventory.
|
||||
/// </summary>
|
||||
[Guid("1E895A6F-3056-4A78-BA64-96E24363B8BC")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.ClearInventoryChatCommandPlugIn_Name), Description = nameof(PlugInResources.ClearInventoryChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, null, MinimumStatus)]
|
||||
public class ClearInventoryChatCommandPlugIn : ChatCommandPlugInBase<ClearInventoryChatCommandPlugIn.Arguments>, ISupportCustomConfiguration<ClearInventoryChatCommandPlugIn.ClearInventoryConfiguration>, ISupportDefaultCustomConfiguration, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/clearinv";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.Normal;
|
||||
private const int ConfirmationTimeoutSeconds = 10;
|
||||
private readonly Dictionary<Guid, DateTime> pendingConfirmations = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration.
|
||||
/// </summary>
|
||||
public ClearInventoryConfiguration? Configuration { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
public object CreateDefaultConfig() => new ClearInventoryConfiguration();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
if (player.SelectedCharacter is not { } selectedCharacter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var configuration = this.Configuration ??= (ClearInventoryConfiguration)this.CreateDefaultConfig();
|
||||
bool removeMoney = configuration.MoneyCost > 0;
|
||||
var targetPlayer = player;
|
||||
bool isGameMaster = selectedCharacter?.CharacterStatus >= CharacterStatus.GameMaster;
|
||||
if (isGameMaster)
|
||||
{
|
||||
removeMoney = false;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.Inventory is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isGameMaster && configuration.RequireConfirmation)
|
||||
{
|
||||
var playerId = selectedCharacter!.Id;
|
||||
if (!this.pendingConfirmations.TryGetValue(playerId, out var confirmationTime) || (DateTime.UtcNow - confirmationTime).TotalSeconds > ConfirmationTimeoutSeconds)
|
||||
{
|
||||
this.pendingConfirmations[playerId] = DateTime.UtcNow;
|
||||
if (configuration.ConfirmationMessage.GetTranslation(player.Culture) is { Length: > 0 } message)
|
||||
{
|
||||
await player.ShowBlueMessageAsync(message).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.pendingConfirmations.Remove(playerId);
|
||||
}
|
||||
|
||||
var itemsToRemove = targetPlayer.Inventory.Items
|
||||
.Where(item => item is not null &&
|
||||
(item.ItemSlot < InventoryConstants.FirstEquippableItemSlotIndex ||
|
||||
item.ItemSlot > InventoryConstants.LastEquippableItemSlotIndex))
|
||||
.ToList();
|
||||
if (itemsToRemove.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (removeMoney && !player.TryRemoveMoney(configuration.MoneyCost))
|
||||
{
|
||||
if (configuration.NotEnoughMoneyMessage.GetTranslation(player.Culture) is { Length: > 0 } notEnoughMoneyMessage)
|
||||
{
|
||||
await player.ShowBlueMessageAsync(notEnoughMoneyMessage).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in itemsToRemove)
|
||||
{
|
||||
await targetPlayer.DestroyInventoryItemAsync(item).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (configuration.InventoryClearedMessage.GetTranslation(player.Culture) is { Length: > 0 } clearedMessage)
|
||||
{
|
||||
await player.ShowBlueMessageAsync(clearedMessage).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Clear Inventory chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to clear inventory for (GM only).
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The configuration of a <see cref="ClearInventoryChatCommandPlugIn"/>.
|
||||
/// </summary>
|
||||
public class ClearInventoryConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to clear inventory for (GM only).
|
||||
/// </summary>
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.ClearInventoryConfiguration_MoneyCost_Name), Description = nameof(PlugInResources.ClearInventoryConfiguration_MoneyCost_Description))]
|
||||
public int MoneyCost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the player needs to run the command again within 10 seconds to confirm the inventory clearing (excluding GM).
|
||||
/// </summary>
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.ClearInventoryConfiguration_RequireConfirmation_Name), Description = nameof(PlugInResources.ClearInventoryConfiguration_RequireConfirmation_Description))]
|
||||
public bool RequireConfirmation { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message to show the confirmation message.
|
||||
/// </summary>
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.ClearInventoryConfiguration_ConfirmationMessage_Name), Description = nameof(PlugInResources.ClearInventoryConfiguration_ConfirmationMessage_Description))]
|
||||
public LocalizedString ConfirmationMessage { get; set; } = "Confirmation: run again within 10 seconds to confirm inventory clearing";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message to show when the player does not have enough money to run the command.
|
||||
/// </summary>
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.ClearInventoryConfiguration_NotEnoughMoneyMessage_Name), Description = nameof(PlugInResources.ClearInventoryConfiguration_NotEnoughMoneyMessage_Description))]
|
||||
public LocalizedString NotEnoughMoneyMessage { get; set; } = "Not enough money to run command";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message to show when the inventory is cleared.
|
||||
/// </summary>
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.ClearInventoryConfiguration_InventoryClearedMessage_Name), Description = nameof(PlugInResources.ClearInventoryConfiguration_InventoryClearedMessage_Description))]
|
||||
public LocalizedString InventoryClearedMessage { get; set; } = "Inventory cleared";
|
||||
}
|
||||
}
|
||||
208
src/GameLogic/PlugIns/ChatCommands/CommandExtensions.cs
Normal file
208
src/GameLogic/PlugIns/ChatCommands/CommandExtensions.cs
Normal file
@@ -0,0 +1,208 @@
|
||||
// <copyright file="CommandExtensions.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
/// <summary>
|
||||
/// Extensions to make the process of creating more commands easier.
|
||||
/// </summary>
|
||||
public static class CommandExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse the arguments of a command string.
|
||||
/// </summary>
|
||||
/// <param name="command">The command.</param>
|
||||
/// <param name="player">The player which issued the command.</param>
|
||||
/// <typeparam name="T">The type.</typeparam>
|
||||
/// <returns>Returns the parsed object, if successful; Otherwise <see langword="null"/>.</returns>
|
||||
public static async ValueTask<T?> TryParseArgumentsAsync<T>(this string command, Player? player)
|
||||
where T : class, new()
|
||||
{
|
||||
var instance = new T();
|
||||
var properties = typeof(T).GetProperties()
|
||||
.Where(property => property.SetMethod is { })
|
||||
.ToList();
|
||||
var arguments = command.Split(' ').Where(x => !x.Contains("/")).ToList();
|
||||
|
||||
if (command.Contains('='))
|
||||
{
|
||||
// [Short argument parsing]
|
||||
// If the command string contains = it means it is using the short version
|
||||
if (await ReadNamedArgumentsAsync(instance, properties, arguments, player).ConfigureAwait(false))
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var attributedArguments = properties
|
||||
.Select(p => p.GetCustomAttribute<ArgumentAttribute>(inherit: true))
|
||||
.Where(a => a is { })
|
||||
.Select(a => a!)
|
||||
.ToList();
|
||||
var requiredArgumentCount = attributedArguments.Any()
|
||||
? attributedArguments.Count(a => a.IsRequired)
|
||||
: arguments.Count;
|
||||
|
||||
if (arguments.Count < requiredArgumentCount)
|
||||
{
|
||||
if (player is not null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CommandExtensionsInvalidArgumentCount), requiredArgumentCount, arguments.Count).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var success = true;
|
||||
for (var i = 0; i < Math.Min(arguments.Count, properties.Count); i++)
|
||||
{
|
||||
var property = properties[i];
|
||||
var argument = arguments[i];
|
||||
|
||||
success = await TrySetPropertyValueAsync(instance, property, argument, player).ConfigureAwait(false) && success;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the usage string for the command using the argument class.
|
||||
/// </summary>
|
||||
/// <param name="argumentsType">Type of the arguments.</param>
|
||||
/// <param name="commandName">The command name.</param>
|
||||
/// <returns>
|
||||
/// The usage string.
|
||||
/// </returns>
|
||||
public static string CreateUsage(Type argumentsType, string commandName)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
|
||||
stringBuilder.Append($"{commandName} ");
|
||||
foreach (var parameter in GetParameters(argumentsType).ToList())
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(parameter.ValidValues))
|
||||
{
|
||||
stringBuilder.Append($"{{{parameter.Name}:{parameter.ValidValues}}}");
|
||||
}
|
||||
else if (parameter.Type == nameof(String))
|
||||
{
|
||||
stringBuilder.Append($"{{{parameter.Name}}}");
|
||||
}
|
||||
else
|
||||
{
|
||||
stringBuilder.Append($"{{{parameter.Name}:{parameter.Type}}}");
|
||||
}
|
||||
|
||||
stringBuilder.Append(" ");
|
||||
}
|
||||
|
||||
stringBuilder.ToString().TrimEnd(' ');
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parameters for an argument class.
|
||||
/// </summary>
|
||||
/// <param name="argumentsType">Type of the arguments.</param>
|
||||
/// <returns>A list of parameters with name, type, and valid values.</returns>
|
||||
public static IEnumerable<(string Name, string Type, string ValidValues)> GetParameters(Type argumentsType)
|
||||
{
|
||||
var properties = argumentsType.GetProperties().Where(p => p.CanWrite);
|
||||
foreach (var property in properties)
|
||||
{
|
||||
string validValues = string.Empty;
|
||||
|
||||
if (property.GetCustomAttribute<ValidValuesAttribute>() is { } validValuesAttribute)
|
||||
{
|
||||
validValues = string.Join('|', validValuesAttribute.ValidValues);
|
||||
}
|
||||
else if (property.PropertyType == typeof(bool))
|
||||
{
|
||||
validValues = "0|1";
|
||||
}
|
||||
else if (property.PropertyType == typeof(byte) || property.PropertyType == typeof(ushort) || property.PropertyType == typeof(uint))
|
||||
{
|
||||
// todo: ranges in ParameterAttribute
|
||||
// validValues = "";
|
||||
}
|
||||
|
||||
yield return (property.Name, property.PropertyType.Name, validValues);
|
||||
}
|
||||
}
|
||||
|
||||
private static async ValueTask<bool> ReadNamedArgumentsAsync(object instance, IList<PropertyInfo> properties, IList<string> arguments, Player? player)
|
||||
{
|
||||
var argumentProperties = properties.Where(property => property.GetCustomAttribute<ArgumentAttribute>() is { }).ToList();
|
||||
var requiredProperties = argumentProperties.Where(prop => prop.GetCustomAttribute<ArgumentAttribute>() is { IsRequired: true }).ToList();
|
||||
|
||||
foreach (var property in argumentProperties)
|
||||
{
|
||||
var attribute = property.GetCustomAttributes<ArgumentAttribute>().First();
|
||||
var argument = arguments.FirstOrDefault(x => x.Split('=').First().Trim() == attribute.ShortName);
|
||||
|
||||
if (argument is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cleans the argument from the short name
|
||||
var argumentValue = argument.Replace($"{attribute.ShortName}=", string.Empty);
|
||||
|
||||
if (!await TrySetPropertyValueAsync(instance, property, argumentValue, player).ConfigureAwait(false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
requiredProperties.Remove(property);
|
||||
}
|
||||
|
||||
if (!requiredProperties.Any())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// One or many required properties were not used
|
||||
foreach (var requiredProperty in requiredProperties)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CommandExtensions_RequiredArgumentMissing), requiredProperty.Name).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static async ValueTask<bool> TrySetPropertyValueAsync(object instance, PropertyInfo propertyInfo, string stringValue, Player? player)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Special handling of booleans; we want to allow 0 and 1 as valid values.
|
||||
if (propertyInfo.PropertyType == typeof(bool) && int.TryParse(stringValue, out var intBool))
|
||||
{
|
||||
stringValue = intBool == 1 ? bool.TrueString : bool.FalseString;
|
||||
}
|
||||
|
||||
propertyInfo.SetValue(instance, Convert.ChangeType(stringValue, propertyInfo.PropertyType, CultureInfo.InvariantCulture));
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (player is not null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CommandExtensionsArgumentInvalidType), propertyInfo.Name, propertyInfo.PropertyType.Name).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// <copyright file="CreateMonsterChatCommand.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.NPC;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command to create a new monster which can be remote controlled.
|
||||
/// </summary>
|
||||
[Guid("BF4DA282-8CFE-4110-B1C5-A01D3F224FAB")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.CreateMonsterChatCommand_Name), Description = nameof(PlugInResources.CreateMonsterChatCommand_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(CreateMonsterChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
internal class CreateMonsterChatCommand : ChatCommandPlugInBase<CreateMonsterChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/createmonster";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, CreateMonsterChatCommandArgs arguments)
|
||||
{
|
||||
var monsterDef = gameMaster.GameContext.Configuration.Monsters.FirstOrDefault(m => m.Number == arguments.MonsterNumber);
|
||||
if (monsterDef is null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MonsterNotFoundByNumber), arguments.MonsterNumber).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var gameMap = gameMaster.CurrentMap;
|
||||
var area = new MonsterSpawnArea
|
||||
{
|
||||
GameMap = gameMap!.Definition,
|
||||
MonsterDefinition = monsterDef,
|
||||
SpawnTrigger = SpawnTrigger.OnceAtEventStart,
|
||||
Quantity = 1,
|
||||
X1 = (byte)Math.Max(gameMaster.Position.X - 3, byte.MinValue),
|
||||
X2 = (byte)Math.Min(gameMaster.Position.X + 3, byte.MaxValue),
|
||||
Y1 = (byte)Math.Max(gameMaster.Position.Y - 3, byte.MinValue),
|
||||
Y2 = (byte)Math.Min(gameMaster.Position.Y + 3, byte.MaxValue),
|
||||
};
|
||||
|
||||
INpcIntelligence intelligence = arguments.IsIntelligent ? new BasicMonsterIntelligence() : new NullMonsterIntelligence();
|
||||
var monster = new Monster(area, monsterDef, gameMap, gameMaster.GameContext.DropGenerator, intelligence, gameMaster.GameContext.PlugInManager, gameMaster.GameContext.PathFinderPool);
|
||||
intelligence.Npc = monster;
|
||||
|
||||
monster.Initialize();
|
||||
await gameMap.AddAsync(monster).ConfigureAwait(false);
|
||||
monster.OnSpawn();
|
||||
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MonsterCreatedByGameMaster), arguments.MonsterNumber, monster.Id).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// <copyright file="DisconnectChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles disconnect commands.
|
||||
/// </summary>
|
||||
[Guid("B5E0F108-9E55-48F6-A7A8-220BFAEF2F3E")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.DisconnectChatCommandPlugIn_Name), Description = nameof(PlugInResources.DisconnectChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(DisconnectChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class DisconnectChatCommandPlugIn : ChatCommandPlugInBase<DisconnectChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/disconnect";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, DisconnectChatCommandArgs arguments)
|
||||
{
|
||||
var player = await this.GetPlayerByCharacterNameAsync(gameMaster, arguments.CharacterName ?? string.Empty).ConfigureAwait(false);
|
||||
if (player is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await player.DisconnectAsync().ConfigureAwait(false);
|
||||
|
||||
if (!player.Name.Equals(gameMaster.Name))
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CommandResultPlayerDisconnected), this.Key, player.Name).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// <copyright file="GetLevelChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin to get a character's level.
|
||||
/// </summary>
|
||||
[Guid("9D5C8FFE-EC32-48AC-8B6F-BB361AD184E5")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GetLevelChatCommandPlugIn_Name), Description = nameof(PlugInResources.GetLevelChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Gets level of a player. Usage: /getlevel (optional:character)", null)]
|
||||
public class GetLevelChatCommandPlugIn : ChatCommandPlugInBase<GetLevelChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/getlevel";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.LevelInformation), targetPlayer.SelectedCharacter.Name, targetPlayer.Attributes![Stats.Level]).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Get Level chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to get level for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// <copyright file="GetLevelUpPointsChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin to get a character's level-up points.
|
||||
/// </summary>
|
||||
[Guid("E4D65354-CCD2-4960-BDCA-D4582A57BBCB")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GetLevelUpPointsChatCommandPlugIn_Name), Description = nameof(PlugInResources.GetLevelUpPointsChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Gets level up points of a player. Usage: /getleveluppoints (optional:character)", null)]
|
||||
public class GetLevelUpPointsChatCommandPlugIn : ChatCommandPlugInBase<GetLevelUpPointsChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/getleveluppoints";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.LevelUpPointsInfo), targetPlayer.SelectedCharacter.Name, targetPlayer.SelectedCharacter.LevelUpPoints).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Get Level-Up Points chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to get level-up points for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// <copyright file="GetMasterLevelChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.Interfaces;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin to get a character's master level.
|
||||
/// </summary>
|
||||
[Guid("4CED4BF8-9D91-47F9-82DE-51E2646F77C8")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GetMasterLevelChatCommandPlugIn_Name), Description = nameof(PlugInResources.GetMasterLevelChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Gets master level of a player. Usage: /getmasterlevel (optional:character)", null)]
|
||||
public class GetMasterLevelChatCommandPlugIn : ChatCommandPlugInBase<GetMasterLevelChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/getmasterlevel";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MasterLevelInfo), targetPlayer.SelectedCharacter.Name, targetPlayer.Attributes![Stats.MasterLevel]).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Get Master Level chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to get master level for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// <copyright file="GetMasterLevelUpPointsChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin to get a character's master level-up points.
|
||||
/// </summary>
|
||||
[Guid("8ACCF267-F5F3-4003-B4C3-536ACCB5181D")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GetMasterLevelUpPointsChatCommandPlugIn_Name), Description = nameof(PlugInResources.GetMasterLevelUpPointsChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Gets master level up points of a player. Usage: /getmasterleveluppoints (optional:character)", null)]
|
||||
public class GetMasterLevelUpPointsChatCommandPlugIn : ChatCommandPlugInBase<GetMasterLevelUpPointsChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/getmasterleveluppoints";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MasterLevelUpPointsInfo), targetPlayer.SelectedCharacter.Name, targetPlayer.SelectedCharacter.MasterLevelUpPoints).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Get Master Level-Up Points chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to get master level-up points for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// <copyright file="GetMoneyChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin to get a character's money.
|
||||
/// </summary>
|
||||
[Guid("207F5872-33AB-4764-B67F-95AB7C6313E3")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GetMoneyChatCommandPlugIn_Name), Description = nameof(PlugInResources.GetMoneyChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Gets money of a player. Usage: /getmoney (optional:character)", null)]
|
||||
public class GetMoneyChatCommandPlugIn : ChatCommandPlugInBase<GetMoneyChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/getmoney";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter?.Inventory is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MoneyInfo), targetPlayer.SelectedCharacter.Name, targetPlayer.Money).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Get Money chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to get money for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// <copyright file="GetResetsChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.Resets;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which sets a character's resets.
|
||||
/// </summary>
|
||||
[Guid("26ACF6A9-346A-49DF-8583-EA610F6E3AEA")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GetResetsChatCommandPlugIn_Name), Description = nameof(PlugInResources.GetResetsChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Gets resets of a player. Usage: /getresets (optional:character)", null)]
|
||||
public class GetResetsChatCommandPlugIn : ChatCommandPlugInBase<GetResetsChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/getresets";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var configuration = player.GameContext.FeaturePlugIns.GetPlugIn<ResetFeaturePlugIn>()?.Configuration;
|
||||
if (configuration is null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.ResetSystemInactive)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.ResetsInfo), targetPlayer.SelectedCharacter.Name, targetPlayer.Attributes![Stats.Resets]).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Get Resets chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to get resets for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// <copyright file="GetStatChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the command to get stat points.
|
||||
/// </summary>
|
||||
[Guid("F8CACA47-D486-45AE-814F-C6218AD87652")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GetStatChatCommandPlugIn_Name), Description = nameof(PlugInResources.GetStatChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(Arguments), MinimumStatus)]
|
||||
public class GetStatChatCommandPlugIn : ChatCommandPlugInBase<GetStatChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/get";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (await this.TryGetAttributeAsync(targetPlayer, arguments.StatType).ConfigureAwait(false) is not { } attribute)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.StatPointInfo), targetPlayer.SelectedCharacter?.Name, targetPlayer.Attributes![attribute]).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Get Stat chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the stat type to get.
|
||||
/// </summary>
|
||||
[ValidValues("str", "agi", "vit", "ene", "cmd")]
|
||||
public string? StatType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to get stat for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// <copyright file="GuildBattleSoccerChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlayerActions.Guild;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles guild battle soccer requests.
|
||||
/// </summary>
|
||||
[Guid("A456F032-CE7D-4EA5-8EB2-96C2B04C70D1")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GuildBattleSoccerChatCommandPlugIn_Name), Description = nameof(PlugInResources.GuildBattleSoccerChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(GuildWarChatCommandArgs), CharacterStatus.Normal)]
|
||||
public class GuildBattleSoccerChatCommandPlugIn : ChatCommandPlugInBase<GuildWarChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/battlesoccer";
|
||||
|
||||
private readonly GuildWarRequestAction _action = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player guildMaster, GuildWarChatCommandArgs arguments)
|
||||
{
|
||||
await this._action.RequestBattleSoccerAsync(guildMaster, arguments.GuildName).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// <copyright file="GuildDisconnectChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles gm disconnect commands.
|
||||
/// </summary>
|
||||
[Guid("F23262E6-0D7C-4B9C-8CD5-7E44AF4EE469")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GuildDisconnectChatCommandPlugIn_Name), Description = nameof(PlugInResources.GuildDisconnectChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(GuildDisconnectChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class GuildDisconnectChatCommandPlugIn : ChatCommandPlugInBase<GuildDisconnectChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/guilddisconnect";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, GuildDisconnectChatCommandArgs arguments)
|
||||
{
|
||||
var guildId = await this.GetGuildIdByNameAsync(gameMaster, arguments.GuildName!).ConfigureAwait(false);
|
||||
if (guildId is null || gameMaster.GameContext is not IGameServerContext gameServerContext)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await gameServerContext.ForEachGuildPlayerAsync(guildId.Value, async guildPlayer =>
|
||||
{
|
||||
await guildPlayer.DisconnectAsync().ConfigureAwait(false);
|
||||
|
||||
if (!guildPlayer.Name.Equals(gameMaster.Name))
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.GuildDisconnectResult), this.Key, guildPlayer.Name).ConfigureAwait(false);
|
||||
}
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// <copyright file="GuildMoveChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles gm move commands.
|
||||
/// </summary>
|
||||
[Guid("9163C3EA-6722-4E55-A109-20C163C05266")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GuildMoveChatCommandPlugIn_Name), Description = nameof(PlugInResources.GuildMoveChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(GuildMoveChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class GuildMoveChatCommandPlugIn : ChatCommandPlugInBase<GuildMoveChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/guildmove";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, GuildMoveChatCommandArgs arguments)
|
||||
{
|
||||
var guildId = await this.GetGuildIdByNameAsync(gameMaster, arguments.GuildName!).ConfigureAwait(false);
|
||||
|
||||
if (guildId is null || gameMaster.GameContext is not IGameServerContext gameServerContext)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var exitGate = await this.GetExitGateAsync(gameMaster, arguments.MapIdOrName!, arguments.Coordinates).ConfigureAwait(false);
|
||||
if (exitGate is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await gameServerContext.ForEachGuildPlayerAsync(guildId.Value, async guildPlayer =>
|
||||
{
|
||||
await guildPlayer.WarpToAsync(exitGate).ConfigureAwait(false);
|
||||
|
||||
if (!guildPlayer.Name.Equals(gameMaster.Name))
|
||||
{
|
||||
await guildPlayer.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MovedByGameMaster)).ConfigureAwait(false);
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MovedPlayerResult), this.Key, guildPlayer.Name, exitGate!.Map!.Name.GetTranslation(gameMaster.Culture), guildPlayer.Position.X, guildPlayer.Position.Y).ConfigureAwait(false);
|
||||
}
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// <copyright file="GuildWarChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlayerActions.Guild;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles guild war requests.
|
||||
/// </summary>
|
||||
[Guid("12A6E159-0D5E-44DE-8CF8-012A7278D42C")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.GuildWarChatCommandPlugIn_Name), Description = nameof(PlugInResources.GuildWarChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(GuildWarChatCommandArgs), CharacterStatus.Normal)]
|
||||
public class GuildWarChatCommandPlugIn : ChatCommandPlugInBase<GuildWarChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/war";
|
||||
|
||||
private readonly GuildWarRequestAction _action = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player guildMaster, GuildWarChatCommandArgs arguments)
|
||||
{
|
||||
await this._action.RequestWarAsync(guildMaster, arguments.GuildName).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
59
src/GameLogic/PlugIns/ChatCommands/HelpCommand.cs
Normal file
59
src/GameLogic/PlugIns/ChatCommands/HelpCommand.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
// <copyright file="HelpCommand.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// The help command which shows the usage of a command.
|
||||
/// </summary>
|
||||
[Guid("EFE9399A-9A14-4B94-BBC1-20718584C4C2")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.HelpCommand_Name), Description = nameof(PlugInResources.HelpCommand_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Shows information about the requested command.", typeof(Arguments))]
|
||||
public class HelpCommand : IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/help";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await command.TryParseArgumentsAsync<Arguments>(player).ConfigureAwait(false) is not { } arguments)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var commandName = arguments.CommandName;
|
||||
var commandPluginAttribute = player.GetAvailableChatCommands()
|
||||
.FirstOrDefault(x => x.Command.Equals("/" + commandName, StringComparison.InvariantCultureIgnoreCase));
|
||||
if (commandPluginAttribute is null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CommandDoesNotExist), commandName ?? string.Empty).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await player.ShowBlueMessageAsync(commandPluginAttribute.Usage).ConfigureAwait(false);
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
// Should not happen, as we don't throw them anymore. But just in case...
|
||||
await player.ShowBlueMessageAsync(e.Message).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class Arguments
|
||||
{
|
||||
public string? CommandName { get; set; }
|
||||
}
|
||||
}
|
||||
32
src/GameLogic/PlugIns/ChatCommands/HideChatCommandPlugIn.cs
Normal file
32
src/GameLogic/PlugIns/ChatCommands/HideChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
// <copyright file="HideChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles hide commands.
|
||||
/// </summary>
|
||||
[Guid("7CE1CA66-C6B1-4840-9997-EF15C49FAB49")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.HideChatCommandPlugIn_Name), Description = nameof(PlugInResources.HideChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, CharacterStatus.GameMaster)]
|
||||
public class HideChatCommandPlugIn : IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/hide";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
await player.AddInvisibleEffectAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
28
src/GameLogic/PlugIns/ChatCommands/IChatCommandPlugIn.cs
Normal file
28
src/GameLogic/PlugIns/ChatCommands/IChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
// <copyright file="IChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A plugin interface for chat commands.
|
||||
/// </summary>
|
||||
[Guid("6CABB847-AE91-4F2B-9FD2-296990950EA3")]
|
||||
[PlugInPoint("Chat commands", "Plugins which will be executed when a chat message arrives with a slash prefix.")]
|
||||
public interface IChatCommandPlugIn : IStrategyPlugIn<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets min Status Requirement to run a command.
|
||||
/// </summary>
|
||||
public CharacterStatus MinCharacterStatusRequirement { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Handles the chat command.
|
||||
/// </summary>
|
||||
/// <param name="player">The player.</param>
|
||||
/// <param name="command">The command.</param>
|
||||
ValueTask HandleCommandAsync(Player player, string command);
|
||||
}
|
||||
178
src/GameLogic/PlugIns/ChatCommands/ItemChatCommandPlugIn.cs
Normal file
178
src/GameLogic/PlugIns/ChatCommands/ItemChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
// <copyright file="ItemChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.DataModel.Configuration.Items;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles gm item command.
|
||||
/// </summary>
|
||||
/// <seealso cref="MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.IChatCommandPlugIn" />
|
||||
[Guid("ABFE2440-E765-4F17-A588-BD9AE3799887")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.ItemChatCommandPlugIn_Name), Description = nameof(PlugInResources.ItemChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(ItemChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class ItemChatCommandPlugIn : ChatCommandPlugInBase<ItemChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/item";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, ItemChatCommandArgs arguments)
|
||||
{
|
||||
if (gameMaster.CurrentMap != null)
|
||||
{
|
||||
var (isValid, itemDefinition) = await TryParseArgumentsAsync(gameMaster, arguments).ConfigureAwait(false);
|
||||
if (!isValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var item = CreateItem(itemDefinition!, arguments);
|
||||
var dropCoordinates = gameMaster.CurrentMap.Terrain.GetRandomCoordinate(gameMaster.Position, 1);
|
||||
var droppedItem = new DroppedItem(item, dropCoordinates, gameMaster.CurrentMap, gameMaster);
|
||||
await gameMaster.CurrentMap.AddAsync(droppedItem).ConfigureAwait(false);
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.ItemCreatedResult), this.Key, item).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static async ValueTask<(bool Success, ItemDefinition? Definition)> TryParseArgumentsAsync(Player gameMaster, ItemChatCommandArgs arguments)
|
||||
{
|
||||
var itemDefinition = gameMaster.GameContext.Configuration.Items
|
||||
.FirstOrDefault(def => def.Group == arguments.Group && def.Number == arguments.Number);
|
||||
if (itemDefinition is null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.ItemGroupNumberNotExists), arguments.Group, arguments.Number).ConfigureAwait(false);
|
||||
return (false, null);
|
||||
}
|
||||
|
||||
if (arguments.Level > itemDefinition.MaximumItemLevel)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.ItemLevelExceeded), itemDefinition.MaximumItemLevel).ConfigureAwait(false);
|
||||
return (false, null);
|
||||
}
|
||||
|
||||
return (true, itemDefinition);
|
||||
}
|
||||
|
||||
private static Item CreateItem(DataModel.Configuration.Items.ItemDefinition itemDefinition, ItemChatCommandArgs arguments)
|
||||
{
|
||||
var item = new TemporaryItem();
|
||||
item.Definition = itemDefinition;
|
||||
item.Durability = item.IsStackable() ? 1 : item.Definition.Durability;
|
||||
item.HasSkill = item.Definition.Skill != null && arguments.Skill;
|
||||
item.Level = arguments.Level;
|
||||
item.SocketCount = item.Definition.MaximumSockets;
|
||||
|
||||
AddOption(item, arguments);
|
||||
AddLuckOption(item, arguments);
|
||||
AddExcellentOptions(item, arguments);
|
||||
AddAncientBonusOption(item, arguments);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private static void AddOption(TemporaryItem item, ItemChatCommandArgs arguments)
|
||||
{
|
||||
if (item.Definition != null && arguments.Opt > 0)
|
||||
{
|
||||
var allOptions = item.Definition.PossibleItemOptions
|
||||
.SelectMany(o => o.PossibleOptions)
|
||||
.Where(o => o.OptionType == ItemOptionTypes.Option);
|
||||
IncreasableItemOption itemOption;
|
||||
|
||||
// Dinorant.
|
||||
if (item.Definition.Skill?.Number == 49)
|
||||
{
|
||||
if ((arguments.Opt & 1) > 0)
|
||||
{
|
||||
itemOption = allOptions.First(o => o.PowerUpDefinition!.TargetAttribute == Stats.DamageReceiveDecrement);
|
||||
var dinoOptionLink = new ItemOptionLink { ItemOption = itemOption, Level = 1 };
|
||||
item.ItemOptions.Add(dinoOptionLink);
|
||||
}
|
||||
|
||||
if ((arguments.Opt & 2) > 0)
|
||||
{
|
||||
itemOption = allOptions.First(o => o.PowerUpDefinition!.TargetAttribute == Stats.MaximumAbility);
|
||||
var dinoOptionLink = new ItemOptionLink { ItemOption = itemOption, Level = 2 };
|
||||
item.ItemOptions.Add(dinoOptionLink);
|
||||
}
|
||||
|
||||
if ((arguments.Opt & 4) > 0)
|
||||
{
|
||||
itemOption = allOptions.First(o => o.PowerUpDefinition!.TargetAttribute == Stats.AttackSpeedAny);
|
||||
var dinoOptionLink = new ItemOptionLink { ItemOption = itemOption, Level = 4 };
|
||||
item.ItemOptions.Add(dinoOptionLink);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
itemOption = allOptions.First();
|
||||
var level = arguments.Opt;
|
||||
var optionLink = new ItemOptionLink { ItemOption = itemOption, Level = level };
|
||||
item.ItemOptions.Add(optionLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddLuckOption(TemporaryItem item, ItemChatCommandArgs arguments)
|
||||
{
|
||||
if (item.Definition != null && arguments.Luck)
|
||||
{
|
||||
var optionLink = new ItemOptionLink
|
||||
{
|
||||
ItemOption = item.Definition.PossibleItemOptions
|
||||
.SelectMany(o => o.PossibleOptions)
|
||||
.First(o => o.OptionType == ItemOptionTypes.Luck),
|
||||
};
|
||||
|
||||
item.ItemOptions.Add(optionLink);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddExcellentOptions(TemporaryItem item, ItemChatCommandArgs arguments)
|
||||
{
|
||||
if (item.Definition != null && arguments.ExcellentNumber > 0)
|
||||
{
|
||||
var excellentOptions = item.Definition.PossibleItemOptions
|
||||
.SelectMany(o => o.PossibleOptions)
|
||||
.Where(o => o.OptionType == ItemOptionTypes.Excellent)
|
||||
.Where(o => ((1 << (o.Number - 1)) & arguments.ExcellentNumber) > 0)
|
||||
.ToList();
|
||||
|
||||
ushort appliedOptions = 0;
|
||||
foreach (var excellentOption in excellentOptions)
|
||||
{
|
||||
var optionLink = new ItemOptionLink { ItemOption = excellentOption };
|
||||
item.ItemOptions.Add(optionLink);
|
||||
appliedOptions++;
|
||||
}
|
||||
|
||||
// every excellent item has skill (if is in item definition)
|
||||
item.HasSkill = appliedOptions > 0 && item.Definition.Skill != null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddAncientBonusOption(TemporaryItem item, ItemChatCommandArgs arguments)
|
||||
{
|
||||
if (item.Definition != null && arguments.Ancient > 0
|
||||
&& item.Definition.PossibleItemSetGroups.FirstOrDefault(g => g.Items.Any(i => i.ItemDefinition == item.Definition && i.AncientSetDiscriminator == arguments.Ancient)) is { } ancientSet
|
||||
&& ancientSet.Items.FirstOrDefault(i => i.ItemDefinition == item.Definition) is { } itemOfItemSet)
|
||||
{
|
||||
var optionLink = new ItemOptionLink { ItemOption = itemOfItemSet.BonusOption, Level = arguments.AncientBonusLevel };
|
||||
item.ItemOptions.Add(optionLink);
|
||||
item.ItemSetGroups.Add(itemOfItemSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/GameLogic/PlugIns/ChatCommands/ListCommand.cs
Normal file
37
src/GameLogic/PlugIns/ChatCommands/ListCommand.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
// <copyright file="ListCommand.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A command which lists all available chat commands with their usage.
|
||||
/// </summary>
|
||||
[Guid("a5b0a3e5-bb2a-4287-821a-cd97714fe209")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.ListCommand_Name), Description = nameof(PlugInResources.ListCommand_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Lists all the commands.", null)]
|
||||
public class ListCommand : IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/list";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
var commands = player.GetAvailableChatCommands();
|
||||
|
||||
foreach (var commandUsage in commands.Select(x => x.Usage))
|
||||
{
|
||||
await player.ShowBlueMessageAsync(commandUsage).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
src/GameLogic/PlugIns/ChatCommands/MoveChatCommandPlugIn.cs
Normal file
61
src/GameLogic/PlugIns/ChatCommands/MoveChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
// <copyright file="MoveChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlayerActions;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles move commands.
|
||||
/// </summary>
|
||||
[Guid("4564AE2B-4819-4155-B5B2-FE2ED0CF7A7F")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.MoveChatCommandPlugIn_Name), Description = nameof(PlugInResources.MoveChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(MoveChatCommandArgs), CharacterStatus.Normal)]
|
||||
public class MoveChatCommandPlugIn : ChatCommandPlugInBase<MoveChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/move";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player sender, MoveChatCommandArgs arguments)
|
||||
{
|
||||
var senderIsGameMaster = sender.SelectedCharacter?.CharacterStatus == CharacterStatus.GameMaster;
|
||||
var isGameMasterWarpingCharacter = senderIsGameMaster && !string.IsNullOrWhiteSpace(arguments.MapIdOrName);
|
||||
|
||||
if (isGameMasterWarpingCharacter)
|
||||
{
|
||||
var targetPlayer = await this.GetPlayerByCharacterNameAsync(sender, arguments.Target!).ConfigureAwait(false);
|
||||
var exitGate = await this.GetExitGateAsync(sender, arguments.MapIdOrName!, arguments.Coordinates).ConfigureAwait(false);
|
||||
if (targetPlayer is null || exitGate is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await targetPlayer.WarpToAsync(exitGate).ConfigureAwait(false);
|
||||
|
||||
if (!targetPlayer.Name.Equals(sender.Name))
|
||||
{
|
||||
await targetPlayer.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MovedByGameMaster)).ConfigureAwait(false);
|
||||
await sender.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MovedPlayerResult), this.Key, targetPlayer.Name, exitGate!.Map!.Name.GetTranslation(sender.Culture), targetPlayer.Position.X, targetPlayer.Position.Y).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var warpInfo = this.GetWarpInfo(sender, arguments.Target!);
|
||||
if (warpInfo != null)
|
||||
{
|
||||
await new WarpAction().WarpToAsync(sender, warpInfo).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/GameLogic/PlugIns/ChatCommands/MoveMonsterChatCommand.cs
Normal file
41
src/GameLogic/PlugIns/ChatCommands/MoveMonsterChatCommand.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
// <copyright file="MoveMonsterChatCommand.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.NPC;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// Chat command to instantly move a monster to specific coordinates.
|
||||
/// </summary>
|
||||
[Guid("B3DE58F3-B604-4F59-9122-E686AD90BE7B")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.MoveMonsterChatCommand_Name), Description = nameof(PlugInResources.MoveMonsterChatCommand_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(MoveMonsterCommandArgs), CharacterStatus.GameMaster)]
|
||||
internal class MoveMonsterChatCommand : ChatCommandPlugInBase<MoveMonsterCommandArgs>
|
||||
{
|
||||
private const string Command = "/movemonster";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, MoveMonsterCommandArgs arguments)
|
||||
{
|
||||
var monster = gameMaster.ObservingBuckets.SelectMany(b => b).OfType<Monster>().FirstOrDefault(m => m.Id == arguments.Id);
|
||||
if (monster is null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MonsterNotFoundById), arguments.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await monster.MoveAsync(arguments.Coordinates).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// <copyright file="NoticeChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles post commands by sending a golden notice message to all players.
|
||||
/// </summary>
|
||||
[Guid("2BFC9464-4B76-4D76-8CE1-69B712B65E6C")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.NoticeChatCommandPlugIn_Name), Description = nameof(PlugInResources.NoticeChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
public class NoticeChatCommandPlugIn : IChatCommandPlugIn
|
||||
{
|
||||
private const string CommandKey = "/goldnotice";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => CommandKey;
|
||||
|
||||
/// <inheritdoc />
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
var regex = new Regex(Regex.Escape(CommandKey));
|
||||
var message = regex.Replace(command, string.Empty, 1)?.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await player.GameContext.SendGlobalMessageAsync(message, Interfaces.MessageType.GoldenCenter).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
132
src/GameLogic/PlugIns/ChatCommands/NpcChatCommandPlugIn.cs
Normal file
132
src/GameLogic/PlugIns/ChatCommands/NpcChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
// <copyright file="NpcChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.DataModel.Configuration;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.NPC;
|
||||
using MUnique.OpenMU.GameLogic.PlayerActions;
|
||||
using MUnique.OpenMU.Interfaces;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which opens NPC windows.
|
||||
/// </summary>
|
||||
[Guid("D8AC2F15-AB30-4432-A042-A41ACA1B274D")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.NpcChatCommandPlugIn_Name), Description = nameof(PlugInResources.NpcChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Opens the NPC store.", null)]
|
||||
public class NpcChatCommandPlugIn : ChatCommandPlugInBase<NpcChatCommandPlugIn.Arguments>, ISupportCustomConfiguration<NpcChatCommandPlugIn.NpcChatCommandConfiguration>, ISupportDefaultCustomConfiguration, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/npc";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.Normal;
|
||||
|
||||
private readonly TalkNpcAction _talkNpcAction = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration.
|
||||
/// </summary>
|
||||
public NpcChatCommandConfiguration? Configuration { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
public object CreateDefaultConfig() => new NpcChatCommandConfiguration();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
if (player.CurrentMap is not { } currentMap)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var configuration = this.Configuration ??= (NpcChatCommandConfiguration)this.CreateDefaultConfig();
|
||||
var npcDefinition = configuration.OpenMerchantNpc;
|
||||
|
||||
if (player.SelectedCharacter?.CharacterStatus >= CharacterStatus.GameMaster && arguments?.NpcId is { } npcIdStr)
|
||||
{
|
||||
if (int.TryParse(npcIdStr, out var npcId) && player.GameContext.Configuration.Monsters.FirstOrDefault(m => m.Number == npcId) is { } definition)
|
||||
{
|
||||
npcDefinition = definition;
|
||||
}
|
||||
else
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidMerchantId), npcIdStr).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (npcDefinition is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (npcDefinition.MerchantStore is null)
|
||||
{
|
||||
if (player.SelectedCharacter?.CharacterStatus >= CharacterStatus.GameMaster)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.NpcIsNotMerchant)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (configuration.MinimumVipLevel > 0 && (player.Attributes?[Stats.IsVip] ?? 0) < configuration.MinimumVipLevel)
|
||||
{
|
||||
if (configuration.InsufficientVipLevelMessage.GetTranslation(player.Culture) is { Length: > 0 } message)
|
||||
{
|
||||
await player.ShowBlueMessageAsync(message).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var npc = new NonPlayerCharacter(new MonsterSpawnArea { MonsterDefinition = npcDefinition }, npcDefinition, currentMap);
|
||||
await this._talkNpcAction.TalkToNpcAsync(player, npc).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the NPC chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the NPC ID to open the merchant store for (GM only).
|
||||
/// </summary>
|
||||
public string? NpcId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The configuration of a <see cref="NpcChatCommandPlugIn"/>.
|
||||
/// </summary>
|
||||
public class NpcChatCommandConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the NPC ID of the NPC to open the merchant store.
|
||||
/// </summary>
|
||||
// TODO: Change to a list of possible NPCs merchants
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.NpcChatCommandConfiguration_OpenMerchantNpc_Name), Description = nameof(PlugInResources.NpcChatCommandConfiguration_OpenMerchantNpc_Description))]
|
||||
public MonsterDefinition? OpenMerchantNpc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum VIP level to use the command.
|
||||
/// </summary>
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.NpcChatCommandConfiguration_MinimumVipLevel_Name), Description = nameof(PlugInResources.NpcChatCommandConfiguration_MinimumVipLevel_Description))]
|
||||
public int MinimumVipLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message to show when the player does not have the required VIP level for this command (excluding GM).
|
||||
/// </summary>
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.NpcChatCommandConfiguration_InsufficientVipLevelMessage_Name), Description = nameof(PlugInResources.NpcChatCommandConfiguration_InsufficientVipLevelMessage_Description))]
|
||||
public LocalizedString InsufficientVipLevelMessage { get; set; } = "Insufficient VIP level to use this command";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// <copyright file="OfflineLevelingChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.MuHelper;
|
||||
using MUnique.OpenMU.GameLogic.Offline;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <c>/offlevel</c> chat command.
|
||||
/// <list type="bullet">
|
||||
/// <item>Logs the login-server entry off so the real player can re-connect at any time.</item>
|
||||
/// <item>Disconnects the real client connection.</item>
|
||||
/// <item>Creates a silent ghost player on the current map using the character's MU Helper config.</item>
|
||||
/// <item>On next login the ghost is automatically stopped before character selection.</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[Guid("A1C4E7F2-3B8D-4A09-8E5C-2D6F0B3A7E14")]
|
||||
[PlugIn]
|
||||
[Display(
|
||||
Name = nameof(PlugInResources.OfflineLevelingChatCommandPlugIn_Name),
|
||||
Description = nameof(PlugInResources.OfflineLevelingChatCommandPlugIn_Description),
|
||||
ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, CharacterStatus.Normal)]
|
||||
public sealed class OfflineLevelingChatCommandPlugIn : IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/offlevel";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
if (player.SelectedCharacter is null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.OfflineLevelingNoCharacterSelected)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player.IsAlive)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.OfflineLevelingMustBeAlive)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.CurrentMap is null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.OfflineLevelingNotOnMap)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.Attributes?[Stats.IsMuHelperActive] <= 0)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.OfflineLevelingMuHelperNotRunning)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var loginName = player.Account?.LoginName;
|
||||
if (loginName is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var manager = player.GameContext.OfflinePlayerManager;
|
||||
|
||||
if (manager.IsActive(loginName))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.OfflineLevelingAlreadyActive)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.OfflineLevelingStarted)).ConfigureAwait(false);
|
||||
|
||||
if (!await manager.StartAsync(player, loginName).ConfigureAwait(false))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.OfflineLevelingFailed)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// <copyright file="OnlineChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles online commands.
|
||||
/// </summary>
|
||||
[Guid("6693ABA3-7B35-4800-815B-096F3420E998")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.OnlineChatCommandPlugIn_Name), Description = nameof(PlugInResources.OnlineChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(EmptyChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class OnlineChatCommandPlugIn : ChatCommandPlugInBase<EmptyChatCommandArgs>, IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/online";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMasterPlayer, EmptyChatCommandArgs arguments)
|
||||
{
|
||||
var totalCharactersCount = 0;
|
||||
var totalGameMastersCount = 0;
|
||||
await gameMasterPlayer.GameContext.ForEachPlayerAsync(player =>
|
||||
{
|
||||
switch (player.SelectedCharacter?.CharacterStatus)
|
||||
{
|
||||
case CharacterStatus.Normal:
|
||||
Interlocked.Increment(ref totalCharactersCount);
|
||||
break;
|
||||
case CharacterStatus.GameMaster:
|
||||
Interlocked.Increment(ref totalGameMastersCount);
|
||||
break;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
await gameMasterPlayer.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.OnlineCountInfo), this.Key, totalGameMastersCount, totalCharactersCount).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// <copyright file="OpenWarehouseChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.DataModel.Configuration;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.NPC;
|
||||
using MUnique.OpenMU.GameLogic.PlayerActions;
|
||||
using MUnique.OpenMU.Interfaces;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which opens the warehouse NPC window.
|
||||
/// </summary>
|
||||
[Guid("62027B6B-D8E7-4DDB-A16B-7070D1BC4A56")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.OpenWarehouseChatCommandPlugIn_Name), Description = nameof(PlugInResources.OpenWarehouseChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Opens the warehouse.", null)]
|
||||
public class OpenWarehouseChatCommandPlugIn : ChatCommandPlugInBase<OpenWarehouseChatCommandPlugIn.Arguments>, ISupportCustomConfiguration<OpenWarehouseChatCommandPlugIn.OpenWarehouseChatCommandConfiguration>, ISupportDefaultCustomConfiguration, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/openware";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.Normal;
|
||||
|
||||
private readonly TalkNpcAction _talkNpcAction = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration.
|
||||
/// </summary>
|
||||
public OpenWarehouseChatCommandConfiguration? Configuration { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
public object CreateDefaultConfig() => new OpenWarehouseChatCommandConfiguration();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
if (player.CurrentMap is not { } currentMap)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var configuration = this.Configuration ??= (OpenWarehouseChatCommandConfiguration)this.CreateDefaultConfig();
|
||||
|
||||
if (configuration.MinimumVipLevel > 0 && (player.Attributes?[Stats.IsVip] ?? 0) < configuration.MinimumVipLevel)
|
||||
{
|
||||
if (configuration.InsufficientVipLevelMessage.GetTranslation(player.Culture) is { Length: > 0 } message)
|
||||
{
|
||||
await player.ShowBlueMessageAsync(message).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.GameContext.Configuration.Monsters.FirstOrDefault(m => m.NpcWindow == NpcWindow.VaultStorage) is not { } definition)
|
||||
{
|
||||
if (player.SelectedCharacter?.CharacterStatus >= CharacterStatus.GameMaster)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.NoWarehouseNpcFound)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var npc = new NonPlayerCharacter(new MonsterSpawnArea { MonsterDefinition = definition }, definition, currentMap);
|
||||
await this._talkNpcAction.TalkToNpcAsync(player, npc).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Open Warehouse chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The configuration of a <see cref="OpenWarehouseChatCommandPlugIn"/>.
|
||||
/// </summary>
|
||||
public class OpenWarehouseChatCommandConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum VIP level to use the command (excluding GM).
|
||||
/// </summary>
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.OpenWarehouseChatCommandConfiguration_MinimumVipLevel_Name), Description = nameof(PlugInResources.OpenWarehouseChatCommandConfiguration_MinimumVipLevel_Description))]
|
||||
public int MinimumVipLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message to show when the player does not have the required VIP level for this command (excluding GM).
|
||||
/// </summary>
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = nameof(PlugInResources.OpenWarehouseChatCommandConfiguration_InsufficientVipLevelMessage_Name), Description = nameof(PlugInResources.OpenWarehouseChatCommandConfiguration_InsufficientVipLevelMessage_Description))]
|
||||
public LocalizedString InsufficientVipLevelMessage { get; set; } = "Insufficient VIP level to use this command";
|
||||
}
|
||||
}
|
||||
67
src/GameLogic/PlugIns/ChatCommands/PKChatCommandPlugIn.cs
Normal file
67
src/GameLogic/PlugIns/ChatCommands/PKChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
// <copyright file="PKChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles pk commands.
|
||||
/// </summary>
|
||||
[Guid("30B7EFF0-33EE-4136-BEB0-BE503B748DC6")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.PkChatCommandPlugIn_Name), Description = nameof(PlugInResources.PkChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(PkChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class PkChatCommandPlugIn : ChatCommandPlugInBase<PkChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/pk";
|
||||
private const int MinPkLevel = HeroState.PlayerKillWarning - HeroState.Normal;
|
||||
private const int MaxPkLevel = HeroState.PlayerKiller2ndStage - HeroState.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, PkChatCommandArgs arguments)
|
||||
{
|
||||
if (arguments.Level < MinPkLevel || arguments.Level > MaxPkLevel)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.PlayerKillLevelRangeError), MinPkLevel, MaxPkLevel).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (arguments.Count <= 0)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.PlayerKillCountMustBePositive)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var targetPlayer = await this.GetPlayerByCharacterNameAsync(gameMaster, arguments.CharacterName ?? string.Empty).ConfigureAwait(false);
|
||||
var character = targetPlayer?.SelectedCharacter;
|
||||
if (character is null)
|
||||
{
|
||||
// logged out in the mean time ...
|
||||
return;
|
||||
}
|
||||
|
||||
character.State = HeroState.Normal + arguments.Level;
|
||||
character.StateRemainingSeconds = (int)TimeSpan.FromHours(arguments.Count).TotalSeconds;
|
||||
character.PlayerKillCount = arguments.Count;
|
||||
await targetPlayer!.ForEachWorldObserverAsync<IUpdateCharacterHeroStatePlugIn>(p => p.UpdateCharacterHeroStateAsync(targetPlayer!), true).ConfigureAwait(false);
|
||||
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(
|
||||
nameof(PlayerMessage.PlayerKillStateChangeResult),
|
||||
this.Key,
|
||||
character.Name,
|
||||
character.State,
|
||||
character.PlayerKillCount,
|
||||
Math.Round(TimeSpan.FromSeconds(character!.StateRemainingSeconds).TotalMinutes)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
141
src/GameLogic/PlugIns/ChatCommands/PKClearChatCommandPlugIn.cs
Normal file
141
src/GameLogic/PlugIns/ChatCommands/PKClearChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
// <copyright file="PKClearChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles pk clear commands.
|
||||
/// </summary>
|
||||
[Guid("EB97A8F6-F6BD-460A-BCBE-253BF679361A")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.PkClearChatCommandPlugIn_Name), Description = nameof(PlugInResources.PkClearChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(PkClearChatCommandArgs), CharacterStatus.Normal)]
|
||||
public class PkClearChatCommandPlugIn : ChatCommandPlugInBase<PkClearChatCommandArgs>, ISupportCustomConfiguration<PkClearChatCommandPlugIn.PKClearConfiguration>, ISupportDefaultCustomConfiguration
|
||||
{
|
||||
private const string Command = "/pkclear";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the configuration.
|
||||
/// </summary>
|
||||
public PKClearConfiguration? Configuration { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public object CreateDefaultConfig() => new PKClearConfiguration();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, PkClearChatCommandArgs arguments)
|
||||
{
|
||||
var selectedCharacter = player.SelectedCharacter;
|
||||
if (selectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var configuration = this.Configuration ?? (PKClearConfiguration)this.CreateDefaultConfig();
|
||||
var isGameMaster = selectedCharacter.CharacterStatus >= CharacterStatus.GameMaster;
|
||||
|
||||
Player? targetPlayer;
|
||||
if (isGameMaster)
|
||||
{
|
||||
targetPlayer = await this.GetPlayerByCharacterNameAsync(player, arguments.CharacterName ?? string.Empty).ConfigureAwait(false);
|
||||
if (targetPlayer is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!configuration.AllowRegularPlayers)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.PkClearCommandOnlyForGameMasters)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(arguments.CharacterName) && !arguments.CharacterName.Equals(player.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.PkClearOnlyClearOwnPk)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer = player;
|
||||
}
|
||||
|
||||
var targetCharacter = targetPlayer.SelectedCharacter;
|
||||
if (targetCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetCharacter.PlayerKillCount == 0 && targetCharacter.State < HeroState.PlayerKillWarning)
|
||||
{
|
||||
if (isGameMaster)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.PkClearTargetNotPlayerKiller), targetCharacter.Name).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.PkClearYouAreNotPlayerKiller)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isGameMaster)
|
||||
{
|
||||
var cost = (long)targetCharacter.PlayerKillCount * configuration.ZenCostPerKill;
|
||||
if (cost > int.MaxValue)
|
||||
{
|
||||
cost = int.MaxValue;
|
||||
}
|
||||
|
||||
if (cost > 0 && !player.TryRemoveMoney((int)cost))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.NotEnoughMoney)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
targetCharacter.State = HeroState.Normal;
|
||||
targetCharacter.StateRemainingSeconds = 0;
|
||||
targetCharacter.PlayerKillCount = 0;
|
||||
await targetPlayer.ForEachWorldObserverAsync<IUpdateCharacterHeroStatePlugIn>(p => p.UpdateCharacterHeroStateAsync(targetPlayer), true).ConfigureAwait(false);
|
||||
|
||||
if (!targetPlayer.Name.Equals(player.Name))
|
||||
{
|
||||
await targetPlayer.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.PkStatusClearedByGameMaster)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.PkClearedResult), this.Key, targetPlayer.Name).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for the <see cref="PkClearChatCommandPlugIn"/>.
|
||||
/// </summary>
|
||||
public class PKClearConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Zen cost per kill.
|
||||
/// </summary>
|
||||
[Display(Name = "Zen Cost Per Kill", Description = "The amount of Zen required to clear one PK count.")]
|
||||
public int ZenCostPerKill { get; set; } = 10_000_000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether regular players are allowed to clear their PK status.
|
||||
/// </summary>
|
||||
[Display(Name = "Allow Regular Players", Description = "Allows regular players to use this command to clear their own PK status for Zen.")]
|
||||
public bool AllowRegularPlayers { get; set; } = true;
|
||||
}
|
||||
}
|
||||
42
src/GameLogic/PlugIns/ChatCommands/PostChatCommandPlugIn.cs
Normal file
42
src/GameLogic/PlugIns/ChatCommands/PostChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
// <copyright file="PostChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using MUnique.OpenMU.GameLogic.Views;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles post commands by sending a blue system message to all players.
|
||||
/// </summary>
|
||||
[Guid("ED2523C1-F66D-4B53-814E-D2FC0C1F46C0")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.PostChatCommandPlugIn_Name), Description = nameof(PlugInResources.PostChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
public class PostChatCommandPlugIn : IChatCommandPlugIn
|
||||
{
|
||||
private const string CommandKey = "/post";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => CommandKey;
|
||||
|
||||
/// <inheritdoc />
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.Normal;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
var regex = new Regex(Regex.Escape(CommandKey));
|
||||
var message = regex.Replace(command, string.Empty, 1)?.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
message = $"{player.SelectedCharacter?.Name}: {message}";
|
||||
await player.GameContext.SendGlobalChatMessageAsync("[POST]", message, ChatMessageType.Gens).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
42
src/GameLogic/PlugIns/ChatCommands/RemoveNpcChatCommand.cs
Normal file
42
src/GameLogic/PlugIns/ChatCommands/RemoveNpcChatCommand.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
// <copyright file="RemoveNpcChatCommand.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.NPC;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// Chat command to remove a npc with a specific id.
|
||||
/// </summary>
|
||||
[Guid("34FAAD0A-FCA4-42E2-8F37-CEF48783BD78")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.RemoveNpcChatCommand_Name), Description = nameof(PlugInResources.RemoveNpcChatCommand_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(IdCommandArgs), CharacterStatus.GameMaster)]
|
||||
internal class RemoveNpcChatCommand : ChatCommandPlugInBase<IdCommandArgs>
|
||||
{
|
||||
private const string Command = "/removenpc";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, IdCommandArgs arguments)
|
||||
{
|
||||
var monster = gameMaster.ObservingBuckets.SelectMany(b => b).OfType<NonPlayerCharacter>().FirstOrDefault(m => m.Id == arguments.Id);
|
||||
if (monster is null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.NpcNotFoundById), arguments.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
monster.Dispose();
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.NpcRemovedById), arguments.Id).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// <copyright file="SetLevelChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which sets a character's level.
|
||||
/// </summary>
|
||||
[Guid("4BE779C9-E6B6-47F2-BC23-2E71D82A6C1D")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.SetLevelChatCommandPlugIn_Name), Description = nameof(PlugInResources.SetLevelChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Sets level of a player. Usage: /setlevel (level) (optional:character)", null)]
|
||||
public class SetLevelChatCommandPlugIn : ChatCommandPlugInBase<SetLevelChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/setlevel";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (arguments is null || arguments.Level < 1 || arguments.Level > targetPlayer.GameContext.Configuration.MaximumLevel)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidCharacterLevel), targetPlayer.GameContext.Configuration.MaximumLevel).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer.Attributes![Stats.Level] = checked(arguments.Level);
|
||||
await targetPlayer.InvokeViewPlugInAsync<IUpdateLevelPlugIn>(p => p.UpdateLevelAsync()).ConfigureAwait(false);
|
||||
await targetPlayer.ForEachWorldObserverAsync<IShowEffectPlugIn>(p => p.ShowEffectAsync(targetPlayer, IShowEffectPlugIn.EffectType.LevelUp), true).ConfigureAwait(false);
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.SetLevelResult), arguments.Level).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Set Level chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the level to set.
|
||||
/// </summary>
|
||||
public int Level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to set level for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// <copyright file="SetLevelUpPointsChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.Interfaces;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which sets a character's level-up points.
|
||||
/// </summary>
|
||||
[Guid("50EF670A-DF7A-4FEE-8E42-7C7A18A68941")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.SetLevelUpPointsChatCommandPlugIn_Name), Description = nameof(PlugInResources.SetLevelUpPointsChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Sets level up points of a player. Usage: /setleveluppoints (points) (optional:character)", null)]
|
||||
public class SetLevelUpPointsChatCommandPlugIn : ChatCommandPlugInBase<SetLevelUpPointsChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/setleveluppoints";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (arguments is null || arguments.LevelUpPoints < 0)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidLevelUpPoints)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer.SelectedCharacter.LevelUpPoints = checked(arguments.LevelUpPoints);
|
||||
await targetPlayer.InvokeViewPlugInAsync<IUpdateLevelPlugIn>(p => p.UpdateLevelAsync()).ConfigureAwait(false);
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.SetLevelUpPointsResult), arguments.LevelUpPoints).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Set Level-Up Points chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the level-up points to set.
|
||||
/// </summary>
|
||||
public int LevelUpPoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to set level-up points for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// <copyright file="SetMasterLevelChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which sets a character's master level.
|
||||
/// </summary>
|
||||
[Guid("E401CA16-7827-495B-9DD0-EABDFF39901E")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.SetMasterLevelChatCommandPlugIn_Name), Description = nameof(PlugInResources.SetMasterLevelChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Sets master level of a player. Usage: /setmasterlevel (level) (optional:character)", null)]
|
||||
public class SetMasterLevelChatCommandPlugIn : ChatCommandPlugInBase<SetMasterLevelChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/setmasterlevel";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (arguments is null || arguments.MasterLevel < 1 || arguments.MasterLevel > targetPlayer.GameContext.Configuration.MaximumMasterLevel)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidCharacterLevel), targetPlayer.GameContext.Configuration.MaximumMasterLevel).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer.Attributes![Stats.MasterLevel] = checked(arguments.MasterLevel);
|
||||
await targetPlayer.InvokeViewPlugInAsync<IUpdateLevelPlugIn>(p => p.UpdateMasterLevelAsync()).ConfigureAwait(false);
|
||||
await targetPlayer.ForEachWorldObserverAsync<IShowEffectPlugIn>(p => p.ShowEffectAsync(targetPlayer, IShowEffectPlugIn.EffectType.LevelUp), true).ConfigureAwait(false);
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.SetMasterLevelResult), arguments.MasterLevel).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Set Master Level chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the master level to set.
|
||||
/// </summary>
|
||||
public int MasterLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to set master level for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// <copyright file="SetMasterLevelUpPointsChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which sets a character's master level-up points.
|
||||
/// </summary>
|
||||
[Guid("69AC0B9E-1063-448E-ABD6-C5837A1E8A4B")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.SetMasterLevelUpPointsChatCommandPlugIn_Name), Description = nameof(PlugInResources.SetMasterLevelUpPointsChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Sets master level up points of a player. Usage: /setmasterleveluppoints (points) (optional:character)", null)]
|
||||
public class SetMasterLevelUpPointsChatCommandPlugIn : ChatCommandPlugInBase<SetMasterLevelUpPointsChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/setmasterleveluppoints";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
if (arguments is null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidMasterLevelUpPoints)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var targetPlayer = player;
|
||||
if (arguments.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer?.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (arguments.MasterLevelUpPoints < 0)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidMasterLevelUpPoints)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer.SelectedCharacter.MasterLevelUpPoints = checked(arguments.MasterLevelUpPoints);
|
||||
await targetPlayer.InvokeViewPlugInAsync<IUpdateLevelPlugIn>(p => p.UpdateMasterLevelAsync()).ConfigureAwait(false);
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.SetMasterLevelUpPointsResult), arguments.MasterLevelUpPoints).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Set Master Level-Up Points chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the master level-up points to set.
|
||||
/// </summary>
|
||||
public int MasterLevelUpPoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to set master level-up points for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// <copyright file="SetMoneyChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which sets a character's money.
|
||||
/// </summary>
|
||||
[Guid("00AA4F0E-911D-49FE-8D88-114C7496D383")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.SetMoneyChatCommandPlugIn_Name), Description = nameof(PlugInResources.SetMoneyChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Sets money of a player. Usage: /setmoney (amount) (optional:character)", null)]
|
||||
public class SetMoneyChatCommandPlugIn : ChatCommandPlugInBase<SetMoneyChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/setmoney";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer.SelectedCharacter?.Inventory is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetPlayer.GameContext?.Configuration?.MaximumInventoryMoney is not int maxMoney)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (arguments is null || arguments.Amount < 0 || arguments.Amount > maxMoney)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidMoneyAmount), maxMoney).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer.Money = checked(arguments.Amount);
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.SetMoneyResult), arguments.Amount).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Set Money chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the amount of money to set.
|
||||
/// </summary>
|
||||
public int Amount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to set money for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
// <copyright file="SetResetsChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.Resets;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which sets a character's resets.
|
||||
/// </summary>
|
||||
[Guid("47A8644C-B6C5-439E-BAB0-C1A7AE72691C")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.SetResetsChatCommandPlugIn_Name), Description = nameof(PlugInResources.SetResetsChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, "Sets resets of a player. Usage: /setresets (resets) (optional:character)", null)]
|
||||
public class SetResetsChatCommandPlugIn : ChatCommandPlugInBase<SetResetsChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/setresets";
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var configuration = player.GameContext.FeaturePlugIns.GetPlugIn<ResetFeaturePlugIn>()?.Configuration;
|
||||
if (configuration is null)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.ResetSystemInactive)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var targetPlayer = player;
|
||||
if (arguments?.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPlayer?.SelectedCharacter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (configuration.ResetLimit is null)
|
||||
{
|
||||
if (arguments is null || arguments.Resets < 0)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidResetsAmount)).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arguments is null || arguments.Resets < 0 || arguments.Resets > configuration.ResetLimit)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidResetsWithLimits), configuration.ResetLimit).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
targetPlayer.Attributes![Stats.Resets] = checked(arguments.Resets);
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.SetResetsResult), arguments.Resets).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Set Resets chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the resets to set.
|
||||
/// </summary>
|
||||
public int Resets { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to set resets for (GM only).
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// <copyright file="SetStatChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.AttributeSystem;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the command to add stat points.
|
||||
/// </summary>
|
||||
[Guid("D074E8AB-9D6E-49A4-956F-1F4818188AF1")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.SetStatChatCommandPlugIn_Name), Description = nameof(PlugInResources.SetStatChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(Arguments), MinimumStatus)]
|
||||
public class SetStatChatCommandPlugIn : ChatCommandPlugInBase<SetStatChatCommandPlugIn.Arguments>, IDisabledByDefault
|
||||
{
|
||||
private const string Command = "/set";
|
||||
|
||||
private const CharacterStatus MinimumStatus = CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override CharacterStatus MinCharacterStatusRequirement => MinimumStatus;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player player, Arguments arguments)
|
||||
{
|
||||
var targetPlayer = player;
|
||||
if (arguments.CharacterName is { } characterName)
|
||||
{
|
||||
targetPlayer = player.GameContext.GetPlayerByCharacterName(characterName);
|
||||
if (targetPlayer?.SelectedCharacter is null ||
|
||||
!targetPlayer.SelectedCharacter.Name.Equals(characterName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.CharacterNotFound), characterName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var attribute = await this.TryGetAttributeAsync(targetPlayer, arguments.StatType).ConfigureAwait(false);
|
||||
if (attribute is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (attribute.MaximumValue is null && arguments.Amount < 1)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidStatValue), arguments.StatType).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (attribute.MaximumValue < 0 || arguments.Amount > attribute.MaximumValue)
|
||||
{
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.InvalidStatValueRange), arguments.StatType, attribute.MaximumValue).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer.Attributes![attribute] = arguments.Amount;
|
||||
await targetPlayer.InvokeViewPlugInAsync<IUpdateCharacterBaseStatsPlugIn>(p => p.UpdateCharacterBaseStatsAsync()).ConfigureAwait(false);
|
||||
await player.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.SetStatResult), arguments.StatType, arguments.Amount, targetPlayer.SelectedCharacter?.Name).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the Get Stat chat command.
|
||||
/// </summary>
|
||||
public class Arguments : ArgumentsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the stat type to set.
|
||||
/// </summary>
|
||||
[ValidValues("str", "agi", "vit", "ene", "cmd")]
|
||||
public string? StatType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the amount to set.
|
||||
/// </summary>
|
||||
public ushort Amount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the character name to set stat for.
|
||||
/// </summary>
|
||||
public string? CharacterName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// <copyright file="ShowFireworksEffectChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.Pathfinding;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles fireworks effect commands.
|
||||
/// </summary>
|
||||
[Guid("658F7F9D-B8FF-4D52-A835-5B3D658B6B9F")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.ShowFireworksEffectChatCommandPlugIn_Name), Description = nameof(PlugInResources.ShowFireworksEffectChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(CoordinatesCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class ShowFireworksEffectChatCommandPlugIn : ChatCommandPlugInBase<CoordinatesCommandArgs>
|
||||
{
|
||||
private const string Command = "/fireworks";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, CoordinatesCommandArgs arguments)
|
||||
{
|
||||
var coordinates = arguments.X == 0 ? gameMaster.Position : new Point(arguments.X, arguments.Y);
|
||||
await gameMaster.ForEachWorldObserverAsync<IShowItemDropEffectPlugIn>(p => p.ShowEffectAsync(ItemDropEffect.Fireworks, coordinates), true).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
38
src/GameLogic/PlugIns/ChatCommands/ShowNpcIdsChatCommand.cs
Normal file
38
src/GameLogic/PlugIns/ChatCommands/ShowNpcIdsChatCommand.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
// <copyright file="ShowNpcIdsChatCommand.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.NPC;
|
||||
using MUnique.OpenMU.GameLogic.Views.NPC;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// Chat command to request the ids of all NPCs in the range of the player.
|
||||
/// </summary>
|
||||
[Guid("498D0205-388F-410A-A7C7-49069A64D3A9")]
|
||||
[PlugIn]
|
||||
[Display(ResourceType = typeof(PlugInResources), Name = "ShowNpcIdsChatCommand_ShowNpcIdsChatCommand_Name", Description = "ShowNpcIdsChatCommand_ShowNpcIdsChatCommand_Description")]
|
||||
[ChatCommandHelp(Command, CharacterStatus.GameMaster)]
|
||||
internal sealed class ShowNpcIdsChatCommand : IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/showids";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
var monsters = player.ObservingBuckets.SelectMany(b => b).OfType<NonPlayerCharacter>().ToList();
|
||||
foreach (var monster in monsters)
|
||||
{
|
||||
await player.InvokeViewPlugInAsync<IShowMessageOfObjectPlugIn>(p => p.ShowMessageOfObjectAsync($"{monster.Id}", monster)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// <copyright file="ShowXmasFireworksEffectChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.GameLogic.Views.Character;
|
||||
using MUnique.OpenMU.Pathfinding;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles xmas fireworks effect commands.
|
||||
/// </summary>
|
||||
[Guid("0E23E4CE-6E7B-4F29-92D8-04A1335EC722")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.ShowXmasFireworksEffectChatCommandPlugIn_Name), Description = nameof(PlugInResources.ShowXmasFireworksEffectChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(CoordinatesCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class ShowXmasFireworksEffectChatCommandPlugIn : ChatCommandPlugInBase<CoordinatesCommandArgs>
|
||||
{
|
||||
private const string Command = "/xmasfireworks";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, CoordinatesCommandArgs arguments)
|
||||
{
|
||||
var coordinates = arguments.X == 0 ? gameMaster.Position : new Point(arguments.X, arguments.Y);
|
||||
await gameMaster.ForEachWorldObserverAsync<IShowItemDropEffectPlugIn>(p => p.ShowEffectAsync(ItemDropEffect.ChristmasFireworks, coordinates), true).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
43
src/GameLogic/PlugIns/ChatCommands/SkinChatCommandPlugIn.cs
Normal file
43
src/GameLogic/PlugIns/ChatCommands/SkinChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
// <copyright file="SkinChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.AttributeSystem;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.Persistence.BasicModel;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles skin commands.
|
||||
/// </summary>
|
||||
[Guid("4735CC2C-9E5D-457A-92CB-9D765F74FDFB")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.SkinChatCommandPlugIn_Name), Description = nameof(PlugInResources.SkinChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(SkinChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class SkinChatCommandPlugIn : ChatCommandPlugInBase<SkinChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/skin";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, SkinChatCommandArgs arguments)
|
||||
{
|
||||
if (gameMaster?.Attributes is { } attributes
|
||||
&& attributes.GetComposableAttribute(Stats.TransformationSkin) is { } attribute)
|
||||
{
|
||||
attribute.Elements.ToList().ForEach(attribute.RemoveElement);
|
||||
attribute.AddElement(attributes.CreateElement(new PowerUpDefinitionValue { AggregateType = AggregateType.AddRaw, Value = arguments.SkinNumber }, Stats.TransformationSkin));
|
||||
|
||||
attributes[Stats.TransformationSkin] = arguments.SkinNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// <copyright file="StartBloodCastleEventChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.PeriodicTasks;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the startds command.
|
||||
/// </summary>
|
||||
[Guid("7177533A-F147-407E-97B0-C4D8E1AC1AF4")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.StartBloodCastleEventChatCommandPlugIn_Name), Description = nameof(PlugInResources.StartBloodCastleEventChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, CharacterStatus.GameMaster)]
|
||||
public class StartBloodCastleEventChatCommandPlugIn : IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/startbc";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
var bloodCastle = player.GameContext.PlugInManager.GetStrategy<MiniGameType, IPeriodicMiniGameStartPlugIn>(MiniGameType.BloodCastle);
|
||||
bloodCastle?.ForceStart();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// <copyright file="StartChaosCastleEventChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.PeriodicTasks;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the startcc command.
|
||||
/// </summary>
|
||||
[Guid("A990270E-B9C6-4445-BBA9-56367A90D31D")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.StartChaosCastleEventChatCommandPlugIn_Name), Description = nameof(PlugInResources.StartChaosCastleEventChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, CharacterStatus.GameMaster)]
|
||||
public class StartChaosCastleEventChatCommandPlugIn : IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/startcc";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
var chaosCastle = player.GameContext.PlugInManager.GetStrategy<MiniGameType, IPeriodicMiniGameStartPlugIn>(MiniGameType.ChaosCastle);
|
||||
chaosCastle?.ForceStart();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// <copyright file="StartDevilSquareEventChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.PeriodicTasks;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles the startds command.
|
||||
/// </summary>
|
||||
[Guid("3684DC79-D81E-4033-AB2C-537334CF0BB6")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.StartDevilSquareEventChatCommandPlugIn_Name), Description = nameof(PlugInResources.StartDevilSquareEventChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, CharacterStatus.GameMaster)]
|
||||
public class StartDevilSquareEventChatCommandPlugIn : IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/startds";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
var devilSquare = player.GameContext.PlugInManager.GetStrategy<MiniGameType, IPeriodicMiniGameStartPlugIn>(MiniGameType.DevilSquare);
|
||||
devilSquare?.ForceStart();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// <copyright file="TeleportChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles teleport commands.
|
||||
/// </summary>
|
||||
[Guid("ABFE2440-E765-4F17-A588-BD9AE3799886")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.TeleportChatCommandPlugIn_Name), Description = nameof(PlugInResources.TeleportChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(CoordinatesCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class TeleportChatCommandPlugIn : ChatCommandPlugInBase<CoordinatesCommandArgs>
|
||||
{
|
||||
private const string Command = "/teleport";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, CoordinatesCommandArgs arguments)
|
||||
{
|
||||
await gameMaster.MoveAsync(arguments.Coordinates).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
50
src/GameLogic/PlugIns/ChatCommands/TraceChatCommandPlugIn.cs
Normal file
50
src/GameLogic/PlugIns/ChatCommands/TraceChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
// <copyright file="TraceChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles trace commands.
|
||||
/// </summary>
|
||||
[Guid("F22C989B-A2A1-4991-B6C2-658337CC19CE")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.TraceChatCommandPlugIn_Name), Description = nameof(PlugInResources.TraceChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(TraceChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class TraceChatCommandPlugIn : ChatCommandPlugInBase<TraceChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/trace";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, TraceChatCommandArgs arguments)
|
||||
{
|
||||
var player = await this.GetPlayerByCharacterNameAsync(gameMaster, arguments.CharacterName ?? string.Empty).ConfigureAwait(false);
|
||||
var character = player?.SelectedCharacter;
|
||||
|
||||
if (character is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var characterLocation = new ExitGate
|
||||
{
|
||||
Map = character.CurrentMap,
|
||||
X1 = character.PositionX,
|
||||
X2 = (byte)(character.PositionX + 2),
|
||||
Y1 = character.PositionY,
|
||||
Y2 = (byte)(character.PositionY + 2),
|
||||
};
|
||||
|
||||
await gameMaster.WarpToAsync(characterLocation).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
49
src/GameLogic/PlugIns/ChatCommands/TrackChatCommandPlugIn.cs
Normal file
49
src/GameLogic/PlugIns/ChatCommands/TrackChatCommandPlugIn.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
// <copyright file="TrackChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles track commands.
|
||||
/// </summary>
|
||||
[Guid("7F12326A-9B84-4A56-A013-8C485D7B2EF6")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.TrackChatCommandPlugIn_Name), Description = nameof(PlugInResources.TrackChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(TraceChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class TrackChatCommandPlugIn : ChatCommandPlugInBase<TraceChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/track";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, TraceChatCommandArgs arguments)
|
||||
{
|
||||
var player = await this.GetPlayerByCharacterNameAsync(gameMaster, arguments.CharacterName ?? string.Empty).ConfigureAwait(false);
|
||||
|
||||
if (gameMaster.SelectedCharacter is null || player is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var gameMasterLocation = new ExitGate
|
||||
{
|
||||
Map = gameMaster.SelectedCharacter.CurrentMap,
|
||||
X1 = gameMaster.SelectedCharacter.PositionX,
|
||||
X2 = (byte)(gameMaster.SelectedCharacter.PositionX + 2),
|
||||
Y1 = gameMaster.SelectedCharacter.PositionY,
|
||||
Y2 = (byte)(gameMaster.SelectedCharacter.PositionY + 2),
|
||||
};
|
||||
|
||||
await player.WarpToAsync(gameMasterLocation).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// <copyright file="UnBanAccChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles banacc commands.
|
||||
/// </summary>
|
||||
[Guid("FCBC9CC0-3C8F-45E2-96DF-9C55BE30C5D9")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.UnBanAccChatCommandPlugIn_Name), Description = nameof(PlugInResources.UnBanAccChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(UnBanAccChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class UnBanAccChatCommandPlugIn : ChatCommandPlugInBase<UnBanAccChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/unbanacc";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, UnBanAccChatCommandArgs arguments)
|
||||
{
|
||||
await this.ChangeAccountStateByLoginNameAsync(gameMaster, arguments.AccountName ?? string.Empty, AccountState.Normal).ConfigureAwait(false);
|
||||
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.UnbanAccountResult), this.Key, arguments.AccountName).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// <copyright file="UnBanCharChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles unbanchar commands.
|
||||
/// </summary>
|
||||
[Guid("2830B01B-57A4-4925-AB6B-242C242B96C9")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.UnBanCharChatCommandPlugIn_Name), Description = nameof(PlugInResources.UnBanCharChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(UnBanCharChatCommandArgs), CharacterStatus.GameMaster)]
|
||||
public class UnBanCharChatCommandPlugIn : ChatCommandPlugInBase<BanCharChatCommandArgs>
|
||||
{
|
||||
private const string Command = "/unbanchar";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, BanCharChatCommandArgs arguments)
|
||||
{
|
||||
if (!await this.TryChangeAccountStateByCharacterNameAsync(gameMaster, arguments.CharacterName ?? string.Empty, AccountState.Normal).ConfigureAwait(false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.UnbanAccountOfCharacterResult), this.Key, arguments.CharacterName).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// <copyright file="UnHideChatCommandPlugIn.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A chat command plugin which handles unhide commands.
|
||||
/// </summary>
|
||||
[Guid("0F0ADAC6-88C7-4EC0-94A2-A289173DEDA7")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.UnHideChatCommandPlugIn_Name), Description = nameof(PlugInResources.UnHideChatCommandPlugIn_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, CharacterStatus.GameMaster)]
|
||||
public class UnHideChatCommandPlugIn : IChatCommandPlugIn
|
||||
{
|
||||
private const string Command = "/unhide";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask HandleCommandAsync(Player player, string command)
|
||||
{
|
||||
await player.RemoveInvisibleEffectAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
31
src/GameLogic/PlugIns/ChatCommands/ValidValuesAttribute.cs
Normal file
31
src/GameLogic/PlugIns/ChatCommands/ValidValuesAttribute.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
// <copyright file="ValidValuesAttribute.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
/// <summary>
|
||||
/// Describes valid values for string argument properties.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class ValidValuesAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// The valid values.
|
||||
/// </summary>
|
||||
private readonly ISet<string> _validValues;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ValidValuesAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="values">The values.</param>
|
||||
public ValidValuesAttribute(params string[] values)
|
||||
{
|
||||
this._validValues = new SortedSet<string>(values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the valid values.
|
||||
/// </summary>
|
||||
public IEnumerable<string> ValidValues => this._validValues;
|
||||
}
|
||||
41
src/GameLogic/PlugIns/ChatCommands/WalkMonsterChatCommand.cs
Normal file
41
src/GameLogic/PlugIns/ChatCommands/WalkMonsterChatCommand.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
// <copyright file="WalkMonsterChatCommand.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.PlugIns.ChatCommands;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MUnique.OpenMU.GameLogic.NPC;
|
||||
using MUnique.OpenMU.GameLogic.PlugIns.ChatCommands.Arguments;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// Chat command to let a monster walk to specific coordinates.
|
||||
/// </summary>
|
||||
[Guid("1852FED5-8184-431E-8C5F-5131356D348F")]
|
||||
[PlugIn]
|
||||
[Display(Name = nameof(PlugInResources.WalkMonsterChatCommand_Name), Description = nameof(PlugInResources.WalkMonsterChatCommand_Description), ResourceType = typeof(PlugInResources))]
|
||||
[ChatCommandHelp(Command, typeof(MoveMonsterCommandArgs), CharacterStatus.GameMaster)]
|
||||
internal class WalkMonsterChatCommand : ChatCommandPlugInBase<MoveMonsterCommandArgs>
|
||||
{
|
||||
private const string Command = "/walkmonster";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Key => Command;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CharacterStatus MinCharacterStatusRequirement => CharacterStatus.GameMaster;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask DoHandleCommandAsync(Player gameMaster, MoveMonsterCommandArgs arguments)
|
||||
{
|
||||
var monster = gameMaster.ObservingBuckets.SelectMany(b => b).OfType<Monster>().FirstOrDefault(m => m.Id == arguments.Id);
|
||||
if (monster is null)
|
||||
{
|
||||
await gameMaster.ShowLocalizedBlueMessageAsync(nameof(PlayerMessage.MonsterNotFoundById), arguments.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await monster.WalkToAsync(arguments.Coordinates).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user