mirror of
https://github.com/MikuLeaks/MikuSB.git
synced 2026-06-04 17:04:13 +00:00
Rewrite girl skin type handling
This commit is contained in:
@@ -17,6 +17,9 @@ public class InventoryData : BaseDatabaseDataHelper
|
|||||||
|
|
||||||
[SugarColumn(IsJson = true)]
|
[SugarColumn(IsJson = true)]
|
||||||
public Dictionary<uint, GameSkinInfo> Skins { get; set; } = []; // Key: UniqueId
|
public Dictionary<uint, GameSkinInfo> Skins { get; set; } = []; // Key: UniqueId
|
||||||
|
|
||||||
|
[SugarColumn(IsJson = true)]
|
||||||
|
public Dictionary<uint, uint> SkinTypesBySkinId { get; set; } = []; // Key: nSkinId, Value: client nType
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BaseGameItemInfo
|
public class BaseGameItemInfo
|
||||||
@@ -67,7 +70,9 @@ public class GameWeaponInfo : GrowableItemInfo
|
|||||||
};
|
};
|
||||||
return proto;
|
return proto;
|
||||||
}
|
}
|
||||||
}public class GameSkinInfo : BaseGameItemInfo
|
}
|
||||||
|
|
||||||
|
public class GameSkinInfo : BaseGameItemInfo
|
||||||
{
|
{
|
||||||
public uint SkinType { get; set; }
|
public uint SkinType { get; set; }
|
||||||
public override Item ToProto()
|
public override Item ToProto()
|
||||||
@@ -79,7 +84,7 @@ public class GameWeaponInfo : GrowableItemInfo
|
|||||||
Count = ItemCount,
|
Count = ItemCount,
|
||||||
Flag = (uint)Flag,
|
Flag = (uint)Flag,
|
||||||
};
|
};
|
||||||
proto.Slots[11] = SkinType;
|
proto.Slots[11] = Math.Min(SkinType, 1);
|
||||||
return proto;
|
return proto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
60
GameServer/Command/Commands/CommandDebug.cs
Normal file
60
GameServer/Command/Commands/CommandDebug.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using MikuSB.Configuration;
|
||||||
|
using MikuSB.Enums.Player;
|
||||||
|
using MikuSB.Util;
|
||||||
|
|
||||||
|
namespace MikuSB.GameServer.Command.Commands;
|
||||||
|
|
||||||
|
[CommandInfo("debug", "Debug packet output", "/debug [on|off|simple|detail|file]", ["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" => EnableDebug(serverOption),
|
||||||
|
"file" => ToggleDebugFile(serverOption),
|
||||||
|
_ => "Usage: /debug [on|off|simple|detail|file]"
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.Info(message);
|
||||||
|
await arg.SendMsg(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string EnableDebug(ServerOption serverOption)
|
||||||
|
{
|
||||||
|
serverOption.EnableDebug = true;
|
||||||
|
serverOption.DebugMessage = true;
|
||||||
|
serverOption.DebugDetailMessage = true;
|
||||||
|
return "Debug packet output enabled.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string DisableDebug(ServerOption serverOption)
|
||||||
|
{
|
||||||
|
serverOption.EnableDebug = false;
|
||||||
|
return "Debug packet output disabled.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string EnableSimpleDebug(ServerOption serverOption)
|
||||||
|
{
|
||||||
|
serverOption.EnableDebug = true;
|
||||||
|
serverOption.DebugMessage = true;
|
||||||
|
serverOption.DebugDetailMessage = false;
|
||||||
|
return "Simple debug packet output enabled.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ToggleDebugFile(ServerOption serverOption)
|
||||||
|
{
|
||||||
|
serverOption.SavePersonalDebugFile = !serverOption.SavePersonalDebugFile;
|
||||||
|
return serverOption.SavePersonalDebugFile
|
||||||
|
? "Personal debug file output enabled."
|
||||||
|
: "Personal debug file output disabled.";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
using System.Text.Json.Nodes;
|
using System.Text.Json.Nodes;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
@@ -11,9 +16,10 @@ public class GirlSkin_ChangeSkinType : ICallGSHandler
|
|||||||
public async Task Handle(Connection connection, string param, ushort seqNo)
|
public async Task Handle(Connection connection, string param, ushort seqNo)
|
||||||
{
|
{
|
||||||
var req = JsonSerializer.Deserialize<ChangeSkinTypeParam>(param);
|
var req = JsonSerializer.Deserialize<ChangeSkinTypeParam>(param);
|
||||||
|
var skinType = ClampClientSkinType(req?.Type ?? 0);
|
||||||
var response = new JsonObject
|
var response = new JsonObject
|
||||||
{
|
{
|
||||||
["nType"] = req?.Type ?? 1,
|
["nType"] = skinType,
|
||||||
["nSkinId"] = req?.SkinId
|
["nSkinId"] = req?.SkinId
|
||||||
};
|
};
|
||||||
if (req == null)
|
if (req == null)
|
||||||
@@ -23,14 +29,20 @@ public class GirlSkin_ChangeSkinType : ICallGSHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
var player = connection.Player!;
|
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)
|
if (skinData == null)
|
||||||
{
|
{
|
||||||
await CallGSRouter.SendScript(connection, "GirlSkin_ChangeSkinType", response.ToJsonString());
|
await CallGSRouter.SendScript(connection, "GirlSkin_ChangeSkinType", response.ToJsonString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
skinData.SkinType = req.Type;
|
|
||||||
var sync = new NtfSyncPlayer
|
var sync = new NtfSyncPlayer
|
||||||
{
|
{
|
||||||
Items = { skinData.ToProto() }
|
Items = { skinData.ToProto() }
|
||||||
@@ -38,6 +50,42 @@ public class GirlSkin_ChangeSkinType : ICallGSHandler
|
|||||||
|
|
||||||
await CallGSRouter.SendScript(connection, "GirlSkin_ChangeSkinType", response.ToJsonString(), sync);
|
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
|
internal sealed class ChangeSkinTypeParam
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ using MikuSB.Database.Account;
|
|||||||
using MikuSB.Database.Player;
|
using MikuSB.Database.Player;
|
||||||
using MikuSB.GameServer.Game.Player;
|
using MikuSB.GameServer.Game.Player;
|
||||||
using MikuSB.GameServer.Server.CallGS;
|
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.Friend;
|
||||||
using MikuSB.GameServer.Server.Packet.Send.Login;
|
using MikuSB.GameServer.Server.Packet.Send.Login;
|
||||||
using MikuSB.GameServer.Server.Packet.Send.Misc;
|
using MikuSB.GameServer.Server.Packet.Send.Misc;
|
||||||
using MikuSB.Proto;
|
using MikuSB.Proto;
|
||||||
using MikuSB.TcpSharp;
|
using MikuSB.TcpSharp;
|
||||||
using MikuSB.Util;
|
using MikuSB.Util;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
|
|
||||||
namespace MikuSB.GameServer.Server.Packet.Recv.Login;
|
namespace MikuSB.GameServer.Server.Packet.Recv.Login;
|
||||||
|
|
||||||
@@ -52,6 +54,66 @@ public class HandlerReqLogin : Handler
|
|||||||
|
|
||||||
await connection.Player.OnHeartBeat();
|
await connection.Player.OnHeartBeat();
|
||||||
await connection.SendPacket(new PacketNtfUpdateFriend(connection.Player!));
|
await connection.SendPacket(new PacketNtfUpdateFriend(connection.Player!));
|
||||||
|
ApplySavedGirlSkinTypes(connection.Player!);
|
||||||
await connection.SendPacket(new PacketNtfCallScript(connection.Player!.InventoryManager.InventoryData));
|
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