Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Maple2.Database/Model/Account.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using Maple2.Database.Extensions;
using Maple2.Model.Enum;
using Maple2.Model.Metadata;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
Expand Down Expand Up @@ -34,6 +35,7 @@ internal class Account {
public DateTime LastModified { get; set; }

public bool Online { get; set; }
public string Permissions { get; set; }

public ICollection<Character>? Characters { get; set; }

Expand Down Expand Up @@ -72,6 +74,7 @@ internal class Account {
SurvivalGoldLevelRewardClaimed = other.SurvivalGoldLevelRewardClaimed,
ActiveGoldPass = other.ActiveGoldPass,
Online = other.Online,
Permissions = other.AdminPermissions.ToString(),
};
}

Expand Down Expand Up @@ -106,6 +109,7 @@ internal class Account {
SurvivalGoldLevelRewardClaimed = other.SurvivalGoldLevelRewardClaimed,
ActiveGoldPass = other.ActiveGoldPass,
Online = other.Online,
AdminPermissions = Enum.TryParse<AdminPermissions>(other.Permissions, true, out AdminPermissions permissions) ? permissions : AdminPermissions.None,
};
}

Expand Down
3 changes: 2 additions & 1 deletion Maple2.Model/Enum/Admin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public enum PetReportFlag {

[Flags]
public enum AdminPermissions {
None = 0,
Alert = 1,
StringBoard = 2,
EventManagement = 4,
Expand All @@ -77,6 +78,6 @@ public enum AdminPermissions {
Find = 512,
PlayerCommands = 1024,

Spawn = SpawnNpc | SpawnItem,
GameMaster = Warp | Ban | Alert | StringBoard | EventManagement | PlayerCommands,
Admin = int.MaxValue,
}
6 changes: 5 additions & 1 deletion Maple2.Model/Game/User/Account.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Maple2.Model.Game;
using Maple2.Model.Enum;

namespace Maple2.Model.Game;

public class Account {
#region Immutable
Expand Down Expand Up @@ -27,10 +29,12 @@ public class Account {
public int SurvivalGoldLevelRewardClaimed { get; set; }
public bool ActiveGoldPass { get; set; }
public bool Online { get; set; }
public AdminPermissions AdminPermissions { get; set; }

public Account() {
PremiumRewardsClaimed = new List<int>();
PrestigeMissions = new List<PrestigeMission>();
PrestigeRewardsClaimed = new List<int>();
AdminPermissions = AdminPermissions.None;
}
}
190 changes: 190 additions & 0 deletions Maple2.Server.Game/Commands/AdminPermissionCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.CommandLine.IO;
using System.Text;
using Maple2.Database.Storage;
using Maple2.Model.Enum;
using Maple2.Model.Game;
using Maple2.Server.Core.Packets;
using Maple2.Server.Game.Model;
using Maple2.Server.Game.Session;

namespace Maple2.Server.Game.Commands;

public class AdminPermissionCommand : GameCommand {
private const string NAME = "perm";
private const string DESCRIPTION = "Set/Remove admin permissions.";
public const AdminPermissions RequiredPermission = AdminPermissions.Admin;

public AdminPermissionCommand(GameSession session) : base(RequiredPermission, NAME, DESCRIPTION) {
AddCommand(new SetCommand(session));
AddCommand(new RemoveCommand(session));
AddCommand(new ViewCommand(session));
}

private class SetCommand : Command {
private readonly GameSession session;

public SetCommand(GameSession session) : base("set", "Set permission on a player.") {
this.session = session;

var player = new Argument<string>("player", "Player Name.");
var permFlag = new Argument<int>("flag", $"Permission Flag. Possible flags:\n"
+ $"{GetFlagsString()}");

AddArgument(player);
AddArgument(permFlag);
this.SetHandler<InvocationContext, string, int>(Handle, player, permFlag);
}

private void Handle(InvocationContext ctx, string playerName, int permFlag) {
if (permFlag == 0) {
ctx.Console.Out.WriteLine("Flag cannot be 0.");
return;
}

if (string.IsNullOrEmpty(playerName)) {
ctx.Console.Out.WriteLine("Player name cannot be empty.");
return;
}

var flag = (AdminPermissions) permFlag;
if (!Enum.IsDefined<AdminPermissions>(flag)) {
ctx.Console.Out.WriteLine($"Invalid flag: {permFlag}");
return;
}

FieldPlayer? player = session.Field.GetPlayers().Values
.FirstOrDefault(player => string.Equals(player.Value.Character.Name, playerName, StringComparison.OrdinalIgnoreCase));
if (player is null) {
ctx.Console.Out.WriteLine($"Player {playerName} not found in field.");
return;
}
// Set this to get correct casing
playerName = player.Value.Character.Name;

player.AdminPermissions |= flag;
player.Session.CommandHandler.RegisterCommands();
ctx.Console.Out.WriteLine($"Permission {flag} set on {playerName}.");
player.Session.Send(NoticePacket.Notice(NoticePacket.Flags.MessageBox | NoticePacket.Flags.Message, new InterfaceText($"<FONT size='18'>Granted admin permission: <FONT color='#73eafd'>{flag.ToString()}</FONT></FONT>", true)));
}
}

private class RemoveCommand : Command {
private readonly GameSession session;

public RemoveCommand(GameSession session) : base("remove", "Remove permission on a player.") {
this.session = session;

var player = new Argument<string>("player", "Player Name.");
var permFlag = new Argument<int>("flag", $"Permission Flag. Possible flags:\n"
+ $"{GetFlagsString()}");

AddArgument(player);
AddArgument(permFlag);
this.SetHandler<InvocationContext, string, int>(Handle, player, permFlag);
}

private void Handle(InvocationContext ctx, string playerName, int permFlag) {
if (permFlag == 0) {
ctx.Console.Out.WriteLine("Flag cannot be 0.");
return;
}

if (string.IsNullOrEmpty(playerName)) {
ctx.Console.Out.WriteLine("Player name cannot be empty.");
return;
}

var flag = (AdminPermissions) permFlag;
if (!Enum.IsDefined<AdminPermissions>(flag)) {
ctx.Console.Out.WriteLine($"Invalid flag: {permFlag}");
return;
}

FieldPlayer? player = session.Field.GetPlayers().Values
.FirstOrDefault(player => string.Equals(player.Value.Character.Name, playerName, StringComparison.OrdinalIgnoreCase));
if (player is null) {
ctx.Console.Out.WriteLine($"Player {playerName} not found in field.");
return;
}
// Set this to get correct casing
playerName = player.Value.Character.Name;

if (player.AdminPermissions == AdminPermissions.Admin) {
ctx.Console.Out.WriteLine($"Cannot remove admin permissions from {playerName}.");
return;
}

player.AdminPermissions &= ~flag;
player.Session.CommandHandler.RegisterCommands();
ctx.Console.Out.WriteLine($"Permission {flag} removed from {playerName}.");
}
}

private class ViewCommand : Command {
private readonly GameSession session;

public ViewCommand(GameSession session) : base("view", "View permissions on a player.") {
this.session = session;

var player = new Argument<string>("player", "Player Name.");

AddArgument(player);
this.SetHandler<InvocationContext, string>(Handle, player);
}

private void Handle(InvocationContext ctx, string playerName) {
if (string.IsNullOrEmpty(playerName)) {
ctx.Console.Out.WriteLine("Player name cannot be empty.");
return;
}

using GameStorage.Request db = session.GameStorage.Context();
long characterId = db.GetCharacterId(playerName);
if (characterId == 0) {
ctx.Console.Out.WriteLine($"Player '{playerName}' not found.");
return;
}

if (!session.PlayerInfo.GetOrFetch(characterId, out PlayerInfo? playerInfo)) {
ctx.Console.Out.WriteLine($"Player '{playerName}' not found.");
return;
}

// Set this to get correct casing
playerName = playerInfo.Name;
long accountId = playerInfo.AccountId;
if (accountId == 0) {
ctx.Console.Out.WriteLine($"Player '{playerName}' not found.");
return;
}

Account? account = db.GetAccount(accountId);
if (account is null) {
ctx.Console.Out.WriteLine($"Player '{playerName}' not found.");
return;
}

ctx.Console.Out.WriteLine($"Permissions for {playerName}: \n"
+ $"{account.AdminPermissions}");
}
}

private static string GetFlagsString() {
var result = new StringBuilder();
foreach (AdminPermissions flag in Enum.GetValues(typeof(AdminPermissions))) {
if (flag == AdminPermissions.GameMaster || flag == AdminPermissions.Admin) {
continue; // Skip composite permissions
}

result.AppendLine($"{flag} ({(int) flag})");
}

// Add composite flags at the end
result.AppendLine($"GameMaster ({(int) AdminPermissions.GameMaster})");
result.AppendLine($"Admin ({(int) AdminPermissions.Admin})");

return result.ToString().TrimEnd();
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using Maple2.Model.Enum;
using Maple2.Model.Game;
using Maple2.Server.Game.Packets;
using Maple2.Server.Game.Session;

namespace Maple2.Server.Game.Commands;

public class AlertCommand : Command {
public class AlertCommand : GameCommand {
private const string NAME = "alert";
private const string DESCRIPTION = "Send alert to the entire server.";
public const AdminPermissions RequiredPermission = AdminPermissions.Alert;

private readonly GameSession session;

public AlertCommand(GameSession session) : base(NAME, DESCRIPTION) {
public AlertCommand(GameSession session) : base(RequiredPermission, NAME, DESCRIPTION) {
this.session = session;

var message = new Argument<string[]>("message", () => [], "Message to display");
Expand Down
6 changes: 4 additions & 2 deletions Maple2.Server.Game/Commands/BuffCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@
using System.CommandLine.Invocation;
using System.CommandLine.IO;
using Maple2.Database.Storage;
using Maple2.Model.Enum;
using Maple2.Model.Metadata;
using Maple2.Server.Game.Model;
using Maple2.Server.Game.Packets;
using Maple2.Server.Game.Session;

namespace Maple2.Server.Game.Commands;

public class BuffCommand : Command {
public class BuffCommand : GameCommand {
private const string NAME = "buff";
private const string DESCRIPTION = "Add buff to player.";
public const AdminPermissions RequiredPermission = AdminPermissions.GameMaster;

private readonly GameSession session;
private readonly SkillMetadataStorage skillStorage;

public BuffCommand(GameSession session, SkillMetadataStorage skillStorage) : base(NAME, DESCRIPTION) {
public BuffCommand(GameSession session, SkillMetadataStorage skillStorage) : base(RequiredPermission, NAME, DESCRIPTION) {
this.session = session;
this.skillStorage = skillStorage;

Expand Down
Loading
Loading