help, character, inventory and setaccount cmd

This commit is contained in:
raphaeIl 2024-05-15 11:55:44 -04:00
parent 3bdcfd22a0
commit abe0581f7b
8 changed files with 266 additions and 115 deletions

View File

@ -2,6 +2,7 @@
using SCHALE.Common.Database;
using SCHALE.Common.Database.ModelExtensions;
using SCHALE.Common.FlatData;
using SCHALE.Common.Utils;
using SCHALE.GameServer.Controllers.Api.ProtocolHandlers;
using SCHALE.GameServer.Services;
using SCHALE.GameServer.Services.Irc;
@ -28,13 +29,13 @@ namespace SCHALE.GameServer.Commands
case "add":
if (Target == "all")
{
AddAllCharacters(connection);
InventoryUtils.AddAllCharacters(connection);
connection.SendChatMessage("All Characters Added!");
}
else if (uint.TryParse(Target, out uint characterId))
{
var newChar = CreateMaxCharacterFromId(characterId);
var newChar = InventoryUtils.CreateMaxCharacterFromId(characterId);
if (characterDB.Any(x => x.UniqueId == newChar.UniqueId))
{
@ -51,14 +52,13 @@ namespace SCHALE.GameServer.Commands
}
break;
case "clear":
var defaultCharacters = connection.ExcelTableService.GetTable<DefaultCharacterExcelTable>().UnPack().DataList.Select(x => x.CharacterId).ToList();
InventoryUtils.RemoveAllCharacters(connection);
var removed = characterDB.Where(x => x.AccountServerId == connection.AccountServerId && !defaultCharacters.Contains(x.UniqueId));
characterDB.RemoveRange(removed);
connection.SendChatMessage($"Removed {removed.Count()} characters!");
connection.SendChatMessage($"Removed all characters!");
break;
default:
connection.SendChatMessage($"Usage: /character unlock=<all|clear|characterId>");
throw new InvalidOperationException("Invalid operation!");
@ -66,42 +66,5 @@ namespace SCHALE.GameServer.Commands
connection.Context.SaveChanges();
}
private void AddAllCharacters(IrcConnection connection)
{
var account = connection.Account;
var context = connection.Context;
var characterExcel = connection.ExcelTableService.GetTable<CharacterExcelTable>().UnPack().DataList;
var allCharacters = characterExcel.Where(x => x.IsPlayable && x.IsPlayableCharacter && x.CollectionVisible && !account.Characters.Any(c => c.UniqueId == x.Id)).Select(x =>
{
return CreateMaxCharacterFromId(x.Id);
}).ToList();
account.AddCharacters(context, [.. allCharacters]);
connection.Context.SaveChanges();
}
private CharacterDB CreateMaxCharacterFromId(long characterId)
{
return new CharacterDB()
{
UniqueId = characterId,
StarGrade = 5,
Level = 90,
Exp = 0,
PublicSkillLevel = 10,
ExSkillLevel = 5,
PassiveSkillLevel = 10,
ExtraPassiveSkillLevel = 10,
LeaderSkillLevel = 1,
FavorRank = 500,
IsNew = true,
IsLocked = true,
PotentialStats = { { 1, 0 }, { 2, 0 }, { 3, 0 } },
EquipmentServerIds = [0, 0, 0]
};
}
}
}

View File

@ -1,19 +1,55 @@
using SCHALE.Common.Database;
using Microsoft.Extensions.FileSystemGlobbing.Internal;
using SCHALE.Common.Database;
using SCHALE.GameServer.Services.Irc;
using Serilog;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
using static System.Net.Mime.MediaTypeNames;
namespace SCHALE.GameServer.Commands
{
[CommandHandler("help", "Show this help.", "/help")]
[CommandHandler("help", "Show this help.", "/help [command]")]
internal class HelpCommand : Command
{
[Argument(0, @"^[a-zA-Z]+$", "The command to display the help message", ArgumentFlags.IgnoreCase | ArgumentFlags.Optional)]
public string Command { get; set; } = string.Empty;
public HelpCommand(IrcConnection connection, string[] args, bool validate = true) : base(connection, args, validate) { }
public override void Execute()
{ // can't use newline, not gonna print args help for now
{
if (Command != string.Empty)
{
if (CommandFactory.commands.ContainsKey(Command))
{
var cmdAtr = (CommandHandlerAttribute?)Attribute.GetCustomAttribute(CommandFactory.commands[Command], typeof(CommandHandlerAttribute));
Command? cmd = CommandFactory.CreateCommand(Command, connection, args, false);
if (cmd is not null)
{
connection.SendChatMessage($"{Command} - {cmdAtr.Hint} (Usage: {cmdAtr.Usage})");
List<PropertyInfo> argsProperties = cmd.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.GetCustomAttribute(typeof(ArgumentAttribute)) is not null).ToList();
foreach (var argProp in argsProperties)
{
ArgumentAttribute attr = (ArgumentAttribute)argProp.GetCustomAttribute(typeof(ArgumentAttribute))!;
var arg = Regex.Replace(attr.Pattern.ToString(), @"[\^\$\+]", "");
connection.SendChatMessage($"<{arg}> - {attr.Description}");
}
}
} else
{
throw new ArgumentException("Invalid Argument.");
}
return;
}
foreach (var command in CommandFactory.commands.Keys)
{
var cmdAtr = (CommandHandlerAttribute?)Attribute.GetCustomAttribute(CommandFactory.commands[command], typeof(CommandHandlerAttribute));

View File

@ -0,0 +1,41 @@
using SCHALE.Common.Database;
using SCHALE.Common.FlatData;
using SCHALE.Common.Utils;
using SCHALE.GameServer.Services;
using SCHALE.GameServer.Services.Irc;
namespace SCHALE.GameServer.Commands
{
[CommandHandler("inventory", "Command to manage inventory (chars, weapons, equipment, items)", "/inventory <addall|clearall>")]
internal class InventoryCommand : Command
{
public InventoryCommand(IrcConnection connection, string[] args, bool validate = true) : base(connection, args, validate) { }
[Argument(0, @"^addall$|^clearall$", "The operation selected (addall, clearall)", ArgumentFlags.IgnoreCase)]
public string Op { get; set; } = string.Empty;
public override void Execute()
{
var context = connection.Context;
switch (Op.ToLower())
{
case "addall":
InventoryUtils.AddAllCharacters(connection);
InventoryUtils.AddAllWeapons(connection);
InventoryUtils.AddAllEquipment(connection);
InventoryUtils.AddAllItems(connection);
break;
case "clearall":
InventoryUtils.RemoveAllCharacters(connection);
context.Weapons.RemoveRange(context.Weapons.Where(x => x.AccountServerId == connection.AccountServerId));
context.Equipment.RemoveRange(context.Equipment.Where(x => x.AccountServerId == connection.AccountServerId));
context.Items.RemoveRange(context.Items.Where(x => x.AccountServerId == connection.AccountServerId));
break;
}
context.SaveChanges();
}
}
}

View File

@ -0,0 +1,47 @@
using SCHALE.Common.Database;
using SCHALE.GameServer.Services.Irc;
using System.ComponentModel;
using System.Reflection;
namespace SCHALE.GameServer.Commands
{
[CommandHandler("setaccount", "Command to change player's account data", "/setaccount <|Level|Nickname|RaidSeasonId|Property|...> <Value>")]
internal class SetAccountCommand : Command
{
public SetAccountCommand(IrcConnection connection, string[] args, bool validate = true) : base(connection, args, validate) { }
[Argument(0, @"^[a-zA-Z]+$", "The Account Property you want to change.", ArgumentFlags.IgnoreCase)]
public string Property { get; set; } = string.Empty;
[Argument(1, @"", "The value you want to change it to, must match the property type.", ArgumentFlags.IgnoreCase)]
public string Value { get; set; } = string.Empty;
public override void Execute()
{
PropertyInfo? targetProperty = typeof(AccountDB).GetProperty(Property);
if (targetProperty != null)
{
TypeConverter converter = TypeDescriptor.GetConverter(targetProperty.PropertyType);
if (converter != null && converter.CanConvertFrom(typeof(string)))
{
try
{
object targetValue = converter.ConvertFromString(Value);
targetProperty.SetValue(connection.Account, targetValue);
} catch (Exception)
{
throw new ArgumentException("Invalid Value");
}
}
} else
{
throw new ArgumentException("Invalid Player Property!");
}
}
}
}

View File

@ -218,13 +218,6 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
{
var account = sessionKeyService.GetAccount(req.SessionKey);
// add everything manually
//AddAllCharacters(account);
//AddAllEquipment(account);
//AddAllItems(account);
//AddAllWeapons(account);
SetRaidSeason(account, 63);
return new AccountLoginSyncResponse()
{
AccountCurrencySyncResponse = new AccountCurrencySyncResponse()
@ -454,59 +447,6 @@ namespace SCHALE.GameServer.Controllers.Api.ProtocolHandlers
}
// these will probably be commands
private void AddAllEquipment(AccountDB account)
{
var equipmentExcel = excelTableService.GetTable<EquipmentExcelTable>().UnPack().DataList;
var allEquipment = equipmentExcel.Select(x =>
{
return new EquipmentDB()
{
UniqueId = x.Id,
Level = 1,
StackCount = 100, // ~ 90,000 cap, auto converted if over
};
}).ToList();
account.AddEquipment(context, [.. allEquipment]);
context.SaveChanges();
}
private void AddAllItems(AccountDB account)
{
var itemExcel = excelTableService.GetTable<ItemExcelTable>().UnPack().DataList;
var allItems = itemExcel.Select(x =>
{
return new ItemDB()
{
IsNew = true,
UniqueId = x.Id,
StackCount = 5555,
};
}).ToList();
account.AddItems(context, [.. allItems]);
context.SaveChanges();
}
private void AddAllWeapons(AccountDB account)
{
// only for current characters
var allWeapons = account.Characters.Select(x =>
{
return new WeaponDB()
{
UniqueId = x.UniqueId,
BoundCharacterServerId = x.ServerId,
IsLocked = false,
StarGrade = 5,
Level = 200
};
});
account.AddWeapons(context, [.. allWeapons]);
context.SaveChanges();
}
private void SetRaidSeason(AccountDB account, long seasonId)
{
account.RaidSeasonId = seasonId;

View File

@ -22,10 +22,15 @@ namespace SCHALE.GameServer.Services.Irc
public void SendChatMessage(string text)
{
SendChatMessage(text, "Shiroko", 10010, IrcMessageType.Chat);
SendChatMessage(text, "Shiroko", 10010, 0, IrcMessageType.Chat);
}
public void SendChatMessage(string text, string nickname, long pfpCharacterId, IrcMessageType messageType)
public void SendEmote(long stickerId)
{
SendChatMessage("", "Shiroko", 10010, stickerId, IrcMessageType.Sticker);
}
public void SendChatMessage(string text, string nickname, long pfpCharacterId, long stickerId, IrcMessageType messageType)
{
var reply = new Reply()
{
@ -38,11 +43,11 @@ namespace SCHALE.GameServer.Services.Irc
AccountNickname = nickname,
Text = text,
SendTicks = DateTimeOffset.Now.Ticks,
StickerId = stickerId,
}, typeof(IrcMessage)),
}.ToString();
StreamWriter.WriteLine(reply);
StreamWriter.Flush();
}
}
}

View File

@ -129,12 +129,16 @@ namespace SCHALE.GameServer.Services.Irc
channels[channel] = new List<long>();
}
var userClient = clients[client];
var connection = clients[client];
channels[channel].Add(userClient.AccountServerId);
userClient.CurrentChannel = channel;
channels[channel].Add(connection.AccountServerId);
connection.CurrentChannel = channel;
logger.LogDebug($"User {userClient.AccountServerId} joined {channel}");
logger.LogDebug($"User {connection.AccountServerId} joined {channel}");
// custom welcome
connection.SendChatMessage("Welcome to SCHALE!");
connection.SendEmote(2);
}
private async Task HandlePrivMsg(string parameters, TcpClient client) // player sends msg
@ -215,7 +219,7 @@ namespace SCHALE.GameServer.Services.Irc
public string AccountNickname { get; set; }
[JsonPropertyName("StickerId")]
public long StickerId { get; }
public long StickerId { get; set; }
[JsonPropertyName("Text")]
public string Text { get; set; }

View File

@ -0,0 +1,115 @@
using SCHALE.Common.Database;
using SCHALE.Common.Database.ModelExtensions;
using SCHALE.Common.FlatData;
using SCHALE.GameServer.Services;
using SCHALE.GameServer.Services.Irc;
using System;
using System.Data;
namespace SCHALE.Common.Utils
{
public static class InventoryUtils
{
public static void AddAllCharacters(IrcConnection connection)
{
var account = connection.Account;
var context = connection.Context;
var characterExcel = connection.ExcelTableService.GetTable<CharacterExcelTable>().UnPack().DataList;
var allCharacters = characterExcel.Where(x => x.IsPlayable && x.IsPlayableCharacter && x.CollectionVisible && !account.Characters.Any(c => c.UniqueId == x.Id)).Select(x =>
{
return CreateMaxCharacterFromId(x.Id);
}).ToList();
account.AddCharacters(context, [.. allCharacters]);
context.SaveChanges();
}
public static void AddAllEquipment(IrcConnection connection)
{
var equipmentExcel = connection.ExcelTableService.GetTable<EquipmentExcelTable>().UnPack().DataList;
var allEquipment = equipmentExcel.Select(x =>
{
return new EquipmentDB()
{
UniqueId = x.Id,
Level = 1,
StackCount = 77777, // ~ 90,000 cap, auto converted if over
};
}).ToList();
connection.Account.AddEquipment(connection.Context, [.. allEquipment]);
connection.Context.SaveChanges();
}
public static void AddAllItems(IrcConnection connection)
{
var itemExcel = connection.ExcelTableService.GetTable<ItemExcelTable>().UnPack().DataList;
var allItems = itemExcel.Select(x =>
{
return new ItemDB()
{
IsNew = true,
UniqueId = x.Id,
StackCount = 5555,
};
}).ToList();
connection.Account.AddItems(connection.Context, [.. allItems]);
connection.Context.SaveChanges();
}
public static void AddAllWeapons(IrcConnection connection)
{
var account = connection.Account;
var context = connection.Context;
// only for current characters
var allWeapons = account.Characters.Select(x =>
{
return new WeaponDB()
{
UniqueId = x.UniqueId,
BoundCharacterServerId = x.ServerId,
IsLocked = false,
StarGrade = 5,
Level = 200
};
});
account.AddWeapons(context, [.. allWeapons]);
context.SaveChanges();
}
public static void RemoveAllCharacters(IrcConnection connection) // removing default characters breaks game
{
var characterDB = connection.Context.Characters;
var defaultCharacters = connection.ExcelTableService.GetTable<DefaultCharacterExcelTable>().UnPack().DataList.Select(x => x.CharacterId).ToList();
var removed = characterDB.Where(x => x.AccountServerId == connection.AccountServerId && !defaultCharacters.Contains(x.UniqueId));
characterDB.RemoveRange(removed);
}
public static CharacterDB CreateMaxCharacterFromId(long characterId)
{
return new CharacterDB()
{
UniqueId = characterId,
StarGrade = 5,
Level = 200,
Exp = 0,
PublicSkillLevel = 10,
ExSkillLevel = 5,
PassiveSkillLevel = 10,
ExtraPassiveSkillLevel = 10,
LeaderSkillLevel = 1,
FavorRank = 500,
IsNew = true,
IsLocked = true,
PotentialStats = { { 1, 25 }, { 2, 25 }, { 3, 25 } },
EquipmentServerIds = [0, 0, 0]
};
}
}
}