mirror of
https://github.com/MikuLeaks/MikuSB.git
synced 2026-06-04 05:23:59 +00:00
Compare commits
5 Commits
5af23a8113
...
720f56c708
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
720f56c708 | ||
|
|
5fa42bdb23 | ||
|
|
2f8d0c6afc | ||
|
|
f6204134a9 | ||
|
|
57ce0e183b |
@@ -20,6 +20,9 @@ public class InventoryData : BaseDatabaseDataHelper
|
||||
|
||||
[SugarColumn(IsJson = true)]
|
||||
public Dictionary<uint, GameSupportCardInfo> SupportCards { get; set; } = []; // Key: UniqueId
|
||||
|
||||
[SugarColumn(IsJson = true)]
|
||||
public Dictionary<uint, uint> SkinTypesBySkinId { get; set; } = []; // Key: nSkinId, Value: client nType
|
||||
}
|
||||
|
||||
public class BaseGameItemInfo
|
||||
@@ -88,7 +91,7 @@ public class GameSkinInfo : BaseGameItemInfo
|
||||
Count = ItemCount,
|
||||
Flag = (uint)Flag,
|
||||
};
|
||||
proto.Slots[11] = SkinType;
|
||||
proto.Slots[11] = Math.Min(SkinType, 1);
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ public class CommandTextCHS
|
||||
public HelpTextCHS Help { get; } = new();
|
||||
public GirlTextCHS Girl { get; } = new();
|
||||
public GiveAllTextCHS GiveAll { get; } = new();
|
||||
public DebugTextCHS Debug { get; } = new();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -244,6 +245,21 @@ public class GiveAllTextCHS
|
||||
public string GiveAllItems => "已向玩家添加 {0} 个 {1}!";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// path: Game.Command.Debug
|
||||
/// </summary>
|
||||
public class DebugTextCHS
|
||||
{
|
||||
public string Desc => "调试包输出开关";
|
||||
public string Usage => "用法: /debug [on|off|simple|detail|file]";
|
||||
public string Enabled => "已启用调试包输出。";
|
||||
public string Disabled => "已禁用调试包输出。";
|
||||
public string SimpleEnabled => "已启用简单调试包输出。";
|
||||
public string DetailEnabled => "已启用详细调试包输出。";
|
||||
public string FileEnabled => "个人调试文件输出已启用。";
|
||||
public string FileDisabled => "个人调试文件输出已禁用。";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
@@ -124,6 +124,7 @@ public class CommandTextCHT
|
||||
public HelpTextCHT Help { get; } = new();
|
||||
public GirlTextCHT Girl { get; } = new();
|
||||
public GiveAllTextCHT GiveAll { get; } = new();
|
||||
public DebugTextCHT Debug { get; } = new();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -244,6 +245,21 @@ public class GiveAllTextCHT
|
||||
public string GiveAllItems => "已向玩家添加 {0} 個 {1}!";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// path: Game.Command.Debug
|
||||
/// </summary>
|
||||
public class DebugTextCHT
|
||||
{
|
||||
public string Desc => "切換調試封包輸出";
|
||||
public string Usage => "用法: /debug [on|off|simple|detail|file]";
|
||||
public string Enabled => "已啟用調試封包輸出。";
|
||||
public string Disabled => "已停用調試封包輸出。";
|
||||
public string SimpleEnabled => "已啟用簡易調試封包輸出。";
|
||||
public string DetailEnabled => "已啟用詳細調試封包輸出。";
|
||||
public string FileEnabled => "個人調試檔案輸出已啟用。";
|
||||
public string FileDisabled => "個人調試檔案輸出已停用。";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
@@ -83,6 +83,7 @@ public class CommandTextEN
|
||||
public HelpTextEN Help { get; } = new();
|
||||
public GirlTextEN Girl { get; } = new();
|
||||
public GiveAllTextEN GiveAll { get; } = new();
|
||||
public DebugTextEN Debug { get; } = new();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -210,6 +211,21 @@ public class GiveAllTextEN
|
||||
public string GiveAllItems => "Added {0} {1} to player!";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// path: Game.Command.Debug
|
||||
/// </summary>
|
||||
public class DebugTextEN
|
||||
{
|
||||
public string Desc => "Toggle debug packet output";
|
||||
public string Usage => "Usage: /debug [on|off|simple|detail|file]";
|
||||
public string Enabled => "Debug packet output enabled.";
|
||||
public string Disabled => "Debug packet output disabled.";
|
||||
public string SimpleEnabled => "Simple debug packet output enabled.";
|
||||
public string DetailEnabled => "Detailed debug packet output enabled.";
|
||||
public string FileEnabled => "Personal debug file output enabled.";
|
||||
public string FileDisabled => "Personal debug file output disabled.";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
69
GameServer/Command/Commands/CommandDebug.cs
Normal file
69
GameServer/Command/Commands/CommandDebug.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using MikuSB.Configuration;
|
||||
using MikuSB.Enums.Player;
|
||||
using MikuSB.Util;
|
||||
using MikuSB.Internationalization;
|
||||
|
||||
namespace MikuSB.GameServer.Command.Commands;
|
||||
|
||||
[CommandInfo("debug", "Game.Command.Debug.Desc", "Game.Command.Debug.Usage", ["dbg"], [PermEnum.Admin, PermEnum.Support])]
|
||||
public class CommandDebug : ICommands
|
||||
{
|
||||
private static readonly Logger Logger = new("CommandManager");
|
||||
|
||||
[CommandDefault]
|
||||
public async ValueTask ToggleDebug(CommandArg arg)
|
||||
{
|
||||
var option = arg.Args.FirstOrDefault()?.ToLowerInvariant() ?? "on";
|
||||
var serverOption = ConfigManager.Config.ServerOption;
|
||||
var message = option switch
|
||||
{
|
||||
"on" => EnableDebug(serverOption),
|
||||
"off" => DisableDebug(serverOption),
|
||||
"simple" => EnableSimpleDebug(serverOption),
|
||||
"detail" => EnableDetailDebug(serverOption),
|
||||
"file" => ToggleDebugFile(serverOption),
|
||||
_ => I18NManager.Translate("Game.Command.Debug.Usage")
|
||||
};
|
||||
|
||||
Logger.Info(message);
|
||||
await arg.SendMsg(message);
|
||||
}
|
||||
|
||||
private static string EnableDebug(ServerOption serverOption)
|
||||
{
|
||||
serverOption.EnableDebug = true;
|
||||
serverOption.DebugMessage = true;
|
||||
serverOption.DebugDetailMessage = true;
|
||||
return I18NManager.Translate("Game.Command.Debug.Enabled");
|
||||
}
|
||||
|
||||
private static string DisableDebug(ServerOption serverOption)
|
||||
{
|
||||
serverOption.EnableDebug = false;
|
||||
return I18NManager.Translate("Game.Command.Debug.Disabled");
|
||||
}
|
||||
|
||||
private static string EnableSimpleDebug(ServerOption serverOption)
|
||||
{
|
||||
serverOption.EnableDebug = true;
|
||||
serverOption.DebugMessage = true;
|
||||
serverOption.DebugDetailMessage = false;
|
||||
return I18NManager.Translate("Game.Command.Debug.SimpleEnabled");
|
||||
}
|
||||
|
||||
private static string EnableDetailDebug(ServerOption serverOption)
|
||||
{
|
||||
serverOption.EnableDebug = true;
|
||||
serverOption.DebugMessage = true;
|
||||
serverOption.DebugDetailMessage = true;
|
||||
return I18NManager.Translate("Game.Command.Debug.DetailEnabled");
|
||||
}
|
||||
|
||||
private static string ToggleDebugFile(ServerOption serverOption)
|
||||
{
|
||||
serverOption.SavePersonalDebugFile = !serverOption.SavePersonalDebugFile;
|
||||
return serverOption.SavePersonalDebugFile
|
||||
? I18NManager.Translate("Game.Command.Debug.FileEnabled")
|
||||
: I18NManager.Translate("Game.Command.Debug.FileDisabled");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
using MikuSB.Proto;
|
||||
using MikuSB.Data;
|
||||
using MikuSB.Database;
|
||||
using MikuSB.Database.Inventory;
|
||||
using MikuSB.Enums.Item;
|
||||
using MikuSB.GameServer.Game.Player;
|
||||
using MikuSB.Proto;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
@@ -11,9 +16,10 @@ public class GirlSkin_ChangeSkinType : ICallGSHandler
|
||||
public async Task Handle(Connection connection, string param, ushort seqNo)
|
||||
{
|
||||
var req = JsonSerializer.Deserialize<ChangeSkinTypeParam>(param);
|
||||
var skinType = ClampClientSkinType(req?.Type ?? 0);
|
||||
var response = new JsonObject
|
||||
{
|
||||
["nType"] = req?.Type ?? 1,
|
||||
["nType"] = skinType,
|
||||
["nSkinId"] = req?.SkinId
|
||||
};
|
||||
if (req == null)
|
||||
@@ -23,14 +29,20 @@ public class GirlSkin_ChangeSkinType : ICallGSHandler
|
||||
}
|
||||
|
||||
var player = connection.Player!;
|
||||
var skinData = player.InventoryManager.GetSkinItem(req.SkinId);
|
||||
var skinData = GetOrCreateSkinItem(player, req.SkinId);
|
||||
if (skinData != null)
|
||||
skinData.SkinType = skinType;
|
||||
|
||||
player.InventoryManager.InventoryData.SkinTypesBySkinId ??= [];
|
||||
player.InventoryManager.InventoryData.SkinTypesBySkinId[req.SkinId] = skinType;
|
||||
DatabaseHelper.SaveDatabaseType(player.InventoryManager.InventoryData);
|
||||
|
||||
if (skinData == null)
|
||||
{
|
||||
await CallGSRouter.SendScript(connection, "GirlSkin_ChangeSkinType", response.ToJsonString());
|
||||
return;
|
||||
}
|
||||
|
||||
skinData.SkinType = req.Type;
|
||||
var sync = new NtfSyncPlayer
|
||||
{
|
||||
Items = { skinData.ToProto() }
|
||||
@@ -38,6 +50,42 @@ public class GirlSkin_ChangeSkinType : ICallGSHandler
|
||||
|
||||
await CallGSRouter.SendScript(connection, "GirlSkin_ChangeSkinType", response.ToJsonString(), sync);
|
||||
}
|
||||
|
||||
internal static uint ClampClientSkinType(uint skinType)
|
||||
{
|
||||
return Math.Min(skinType, 1);
|
||||
}
|
||||
|
||||
internal static GameSkinInfo? GetOrCreateSkinItem(PlayerInstance player, uint skinId)
|
||||
{
|
||||
var inventoryData = player.InventoryManager.InventoryData;
|
||||
if (inventoryData.Skins.TryGetValue(skinId, out var skinInfo))
|
||||
return skinInfo;
|
||||
|
||||
if (!GameData.CardSkinData.TryGetValue(skinId, out var skinData))
|
||||
return null;
|
||||
|
||||
var templateId = GameResourceTemplateId.FromGdpl(skinData.Genre, skinData.Detail, skinData.Particular, skinData.Level);
|
||||
skinInfo = player.InventoryManager.GetSkinItemByTemplateId(templateId);
|
||||
if (skinInfo != null)
|
||||
{
|
||||
inventoryData.Skins.Remove(skinInfo.UniqueId);
|
||||
skinInfo.UniqueId = skinId;
|
||||
}
|
||||
else
|
||||
{
|
||||
skinInfo = new GameSkinInfo
|
||||
{
|
||||
UniqueId = skinId,
|
||||
TemplateId = templateId,
|
||||
ItemType = ItemTypeEnum.TYPE_CARD_SKIN,
|
||||
ItemCount = 1
|
||||
};
|
||||
}
|
||||
|
||||
inventoryData.Skins[skinId] = skinInfo;
|
||||
return skinInfo;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ChangeSkinTypeParam
|
||||
|
||||
@@ -4,12 +4,14 @@ using MikuSB.Database.Account;
|
||||
using MikuSB.Database.Player;
|
||||
using MikuSB.GameServer.Game.Player;
|
||||
using MikuSB.GameServer.Server.CallGS;
|
||||
using MikuSB.GameServer.Server.CallGS.Handlers.Girl;
|
||||
using MikuSB.GameServer.Server.Packet.Send.Friend;
|
||||
using MikuSB.GameServer.Server.Packet.Send.Login;
|
||||
using MikuSB.GameServer.Server.Packet.Send.Misc;
|
||||
using MikuSB.Proto;
|
||||
using MikuSB.TcpSharp;
|
||||
using MikuSB.Util;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace MikuSB.GameServer.Server.Packet.Recv.Login;
|
||||
|
||||
@@ -54,6 +56,66 @@ public class HandlerReqLogin : Handler
|
||||
|
||||
await connection.Player.OnHeartBeat();
|
||||
await connection.SendPacket(new PacketNtfUpdateFriend(connection.Player!));
|
||||
ApplySavedGirlSkinTypes(connection.Player!);
|
||||
await connection.SendPacket(new PacketNtfCallScript(connection.Player!.InventoryManager.InventoryData));
|
||||
await SendGirlSkinTypeOnLogin(connection);
|
||||
}
|
||||
|
||||
private static void ApplySavedGirlSkinTypes(PlayerInstance player)
|
||||
{
|
||||
var inventoryData = player.InventoryManager.InventoryData;
|
||||
inventoryData.SkinTypesBySkinId ??= [];
|
||||
var changed = false;
|
||||
|
||||
foreach (var (skinId, skinType) in inventoryData.SkinTypesBySkinId.ToArray())
|
||||
{
|
||||
var clamped = GirlSkin_ChangeSkinType.ClampClientSkinType(skinType);
|
||||
if (clamped != skinType)
|
||||
{
|
||||
inventoryData.SkinTypesBySkinId[skinId] = clamped;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
var skinData = GirlSkin_ChangeSkinType.GetOrCreateSkinItem(player, skinId);
|
||||
if (skinData != null && skinData.SkinType != clamped)
|
||||
{
|
||||
skinData.SkinType = clamped;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
DatabaseHelper.SaveDatabaseType(inventoryData);
|
||||
}
|
||||
|
||||
private static async Task SendGirlSkinTypeOnLogin(Connection connection)
|
||||
{
|
||||
var player = connection.Player;
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
var inventoryData = player.InventoryManager.InventoryData;
|
||||
inventoryData.SkinTypesBySkinId ??= [];
|
||||
foreach (var (skinId, skinType) in inventoryData.SkinTypesBySkinId)
|
||||
{
|
||||
var clamped = GirlSkin_ChangeSkinType.ClampClientSkinType(skinType);
|
||||
var skinData = GirlSkin_ChangeSkinType.GetOrCreateSkinItem(player, skinId);
|
||||
var response = new JsonObject
|
||||
{
|
||||
["nType"] = clamped,
|
||||
["nSkinId"] = skinId
|
||||
};
|
||||
|
||||
if (skinData == null)
|
||||
{
|
||||
await CallGSRouter.SendScript(connection, "GirlSkin_ChangeSkinType", response.ToJsonString());
|
||||
continue;
|
||||
}
|
||||
|
||||
await CallGSRouter.SendScript(connection, "GirlSkin_ChangeSkinType", response.ToJsonString(), new NtfSyncPlayer
|
||||
{
|
||||
Items = { skinData.ToProto() }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user