mirror of
https://github.com/EggLinks/DanhengServer-OpenSource.git
synced 2026-01-02 20:26:03 +08:00
feat: skin system
This commit is contained in:
@@ -234,7 +234,8 @@ public class CommandGiveall : ICommand
|
||||
if (material.ItemMainType == ItemMainTypeEnum.Usable)
|
||||
if (material.ItemSubType == ItemSubTypeEnum.HeadIcon ||
|
||||
material.ItemSubType == ItemSubTypeEnum.PhoneTheme ||
|
||||
material.ItemSubType == ItemSubTypeEnum.ChatBubble)
|
||||
material.ItemSubType == ItemSubTypeEnum.ChatBubble ||
|
||||
material.ItemSubType == ItemSubTypeEnum.AvatarSkin)
|
||||
await player.InventoryManager!.AddItem(material.ID, 1, false);
|
||||
|
||||
await arg.SendMsg(I18NManager.Translate("Game.Command.GiveAll.GiveAllItems",
|
||||
|
||||
18
Common/Data/Excel/AvatarSkinExcel.cs
Normal file
18
Common/Data/Excel/AvatarSkinExcel.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace EggLink.DanhengServer.Data.Excel;
|
||||
|
||||
[ResourceEntity("AvatarSkin.json")]
|
||||
public class AvatarSkinExcel : ExcelResource
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public int AvatarID { get; set; }
|
||||
|
||||
public override int GetId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public override void Loaded()
|
||||
{
|
||||
GameData.AvatarSkinData[ID] = this;
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ public static class GameData
|
||||
public static Dictionary<int, AvatarPromotionConfigExcel> AvatarPromotionConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, AvatarExpItemConfigExcel> AvatarExpItemConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, AvatarSkillTreeConfigExcel> AvatarSkillTreeConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, AvatarSkinExcel> AvatarSkinData { get; private set; } = [];
|
||||
public static Dictionary<int, AvatarDemoConfigExcel> AvatarDemoConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, ExpTypeExcel> ExpTypeData { get; private set; } = [];
|
||||
|
||||
|
||||
@@ -10,4 +10,6 @@ public class PlayerUnlockData : BaseDatabaseDataHelper
|
||||
[SugarColumn(IsJson = true)] public List<int> ChatBubbles { get; set; } = [];
|
||||
|
||||
[SugarColumn(IsJson = true)] public List<int> PhoneThemes { get; set; } = [];
|
||||
|
||||
[SugarColumn(IsJson = true)] public Dictionary<int, List<int>> Skins { get; set; } = [];
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using EggLink.DanhengServer.Enums.Item;
|
||||
using EggLink.DanhengServer.Enums.Mission;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Avatar;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lineup;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Player;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.PlayerSync;
|
||||
@@ -77,6 +78,16 @@ public class InventoryManager(PlayerInstance player) : BasePlayerManager(player)
|
||||
case ItemSubTypeEnum.PhoneTheme:
|
||||
Player.PlayerUnlockData!.PhoneThemes.Add(itemId);
|
||||
break;
|
||||
case ItemSubTypeEnum.AvatarSkin:
|
||||
var avatarId = GameData.AvatarSkinData[itemId].AvatarID;
|
||||
if (!Player.PlayerUnlockData!.Skins.TryGetValue(avatarId, out var value))
|
||||
{
|
||||
value = [];
|
||||
Player.PlayerUnlockData.Skins[avatarId] = value;
|
||||
}
|
||||
value.Add(itemId);
|
||||
await Player.SendPacket(new PacketUnlockAvatarSkinScNotify(itemId));
|
||||
break;
|
||||
case ItemSubTypeEnum.Food:
|
||||
case ItemSubTypeEnum.Book:
|
||||
case ItemSubTypeEnum.FindChest:
|
||||
|
||||
@@ -305,6 +305,17 @@ public class PlayerInstance(PlayerData data)
|
||||
await SendPacket(new PacketPlayerSyncScNotify(avatar));
|
||||
}
|
||||
|
||||
public async ValueTask ChangeAvatarSkin(int avatarId, int skinId)
|
||||
{
|
||||
PlayerUnlockData!.Skins.TryGetValue(avatarId, out var skins);
|
||||
if (skins != null && (skins.Contains(skinId) || skinId == 0))
|
||||
{
|
||||
var avatar = AvatarManager!.GetAvatar(avatarId)!;
|
||||
avatar.GetPathInfo(avatarId)!.Skin = skinId;
|
||||
await SendPacket(new PacketPlayerSyncScNotify(avatar));
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<AvatarInfo> MarkAvatar(int avatarId, bool isMarked, bool sendPacket = true)
|
||||
{
|
||||
var avatar = AvatarManager!.GetAvatar(avatarId)!;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using EggLink.DanhengServer.Kcp;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Avatar;
|
||||
|
||||
[Opcode(CmdIds.DressAvatarSkinCsReq)]
|
||||
public class HandlerDressAvatarSkinCsReq : Handler
|
||||
{
|
||||
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
var req = DressAvatarSkinCsReq.Parser.ParseFrom(data);
|
||||
await connection.Player!.ChangeAvatarSkin((int)req.AvatarId, (int)req.SkinId);
|
||||
await connection.SendPacket(CmdIds.DressAvatarSkinScRsp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using EggLink.DanhengServer.Kcp;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Avatar;
|
||||
|
||||
[Opcode(CmdIds.SetMultipleAvatarPathsCsReq)]
|
||||
public class HandlerSetMultipleAvatarPathsCsReq : Handler
|
||||
{
|
||||
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
var req = SetMultipleAvatarPathsCsReq.Parser.ParseFrom(data);
|
||||
|
||||
foreach (var targetAvatarType in req.AvatarIdList)
|
||||
{
|
||||
var avatarId = (int)targetAvatarType;
|
||||
var baseAvatarId = connection.Player!.AvatarManager!.GetAvatar(avatarId)!.BaseAvatarId;
|
||||
if (avatarId % 2 == 0) avatarId--;
|
||||
await connection.Player!.ChangeAvatarPathType(baseAvatarId, (MultiPathAvatarType)avatarId);
|
||||
}
|
||||
|
||||
await connection.SendPacket(CmdIds.SetMultipleAvatarPathsScRsp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using EggLink.DanhengServer.Kcp;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Avatar;
|
||||
|
||||
[Opcode(CmdIds.TakeOffAvatarSkinCsReq)]
|
||||
public class HandlerTakeOffAvatarSkinCsReq : Handler
|
||||
{
|
||||
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
var req = TakeOffAvatarSkinCsReq.Parser.ParseFrom(data);
|
||||
await connection.Player!.ChangeAvatarSkin((int)req.AvatarId, 0);
|
||||
await connection.SendPacket(CmdIds.TakeOffAvatarSkinScRsp);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,9 @@ public class PacketGetAvatarDataScRsp : BasePacket
|
||||
IsGetAll = true
|
||||
};
|
||||
|
||||
player.PlayerUnlockData!.Skins.Values.ToList().ForEach(skin =>
|
||||
proto.SkinList.AddRange(skin.Select(x => (uint)x)));
|
||||
|
||||
player.AvatarManager?.AvatarData?.Avatars?.ForEach(avatar =>
|
||||
{
|
||||
GameData.MultiplePathAvatarConfigData.TryGetValue(avatar.BaseAvatarId, out var multiPathAvatar);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using EggLink.DanhengServer.Kcp;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Avatar;
|
||||
|
||||
public class PacketUnlockAvatarSkinScNotify : BasePacket
|
||||
{
|
||||
public PacketUnlockAvatarSkinScNotify(int skinId) : base(CmdIds.UnlockAvatarSkinScNotify)
|
||||
{
|
||||
var proto = new UnlockAvatarSkinScNotify
|
||||
{
|
||||
SkinId = (uint)skinId
|
||||
};
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
|
||||
new pbr::FileDescriptor[] { global::EggLink.DanhengServer.Proto.BCMLJCFOEFMReflection.Descriptor, global::EggLink.DanhengServer.Proto.AvatarReflection.Descriptor, },
|
||||
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::EggLink.DanhengServer.Proto.GetAvatarDataScRsp), global::EggLink.DanhengServer.Proto.GetAvatarDataScRsp.Parser, new[]{ "IsGetAll", "Retcode", "ANKHENIIACH", "JPNLPOPMKEJ", "AvatarList", "PNKCFEALAMI" }, null, null, null, null)
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::EggLink.DanhengServer.Proto.GetAvatarDataScRsp), global::EggLink.DanhengServer.Proto.GetAvatarDataScRsp.Parser, new[]{ "IsGetAll", "Retcode", "SkinList", "JPNLPOPMKEJ", "AvatarList", "PNKCFEALAMI" }, null, null, null, null)
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
@@ -77,7 +77,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
public GetAvatarDataScRsp(GetAvatarDataScRsp other) : this() {
|
||||
isGetAll_ = other.isGetAll_;
|
||||
retcode_ = other.retcode_;
|
||||
aNKHENIIACH_ = other.aNKHENIIACH_.Clone();
|
||||
skinList_ = other.skinList_.Clone();
|
||||
jPNLPOPMKEJ_ = other.jPNLPOPMKEJ_;
|
||||
avatarList_ = other.avatarList_.Clone();
|
||||
pNKCFEALAMI_ = other.pNKCFEALAMI_.Clone();
|
||||
@@ -114,15 +114,15 @@ namespace EggLink.DanhengServer.Proto {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "ANKHENIIACH" field.</summary>
|
||||
public const int ANKHENIIACHFieldNumber = 9;
|
||||
private static readonly pb::FieldCodec<uint> _repeated_aNKHENIIACH_codec
|
||||
/// <summary>Field number for the "skin_list" field.</summary>
|
||||
public const int SkinListFieldNumber = 9;
|
||||
private static readonly pb::FieldCodec<uint> _repeated_skinList_codec
|
||||
= pb::FieldCodec.ForUInt32(74);
|
||||
private readonly pbc::RepeatedField<uint> aNKHENIIACH_ = new pbc::RepeatedField<uint>();
|
||||
private readonly pbc::RepeatedField<uint> skinList_ = new pbc::RepeatedField<uint>();
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public pbc::RepeatedField<uint> ANKHENIIACH {
|
||||
get { return aNKHENIIACH_; }
|
||||
public pbc::RepeatedField<uint> SkinList {
|
||||
get { return skinList_; }
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "JPNLPOPMKEJ" field.</summary>
|
||||
@@ -176,7 +176,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
}
|
||||
if (IsGetAll != other.IsGetAll) return false;
|
||||
if (Retcode != other.Retcode) return false;
|
||||
if(!aNKHENIIACH_.Equals(other.aNKHENIIACH_)) return false;
|
||||
if(!skinList_.Equals(other.skinList_)) return false;
|
||||
if (JPNLPOPMKEJ != other.JPNLPOPMKEJ) return false;
|
||||
if(!avatarList_.Equals(other.avatarList_)) return false;
|
||||
if(!pNKCFEALAMI_.Equals(other.pNKCFEALAMI_)) return false;
|
||||
@@ -189,7 +189,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
int hash = 1;
|
||||
if (IsGetAll != false) hash ^= IsGetAll.GetHashCode();
|
||||
if (Retcode != 0) hash ^= Retcode.GetHashCode();
|
||||
hash ^= aNKHENIIACH_.GetHashCode();
|
||||
hash ^= skinList_.GetHashCode();
|
||||
if (JPNLPOPMKEJ != 0) hash ^= JPNLPOPMKEJ.GetHashCode();
|
||||
hash ^= avatarList_.GetHashCode();
|
||||
hash ^= pNKCFEALAMI_.GetHashCode();
|
||||
@@ -220,7 +220,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
output.WriteRawTag(64);
|
||||
output.WriteUInt32(JPNLPOPMKEJ);
|
||||
}
|
||||
aNKHENIIACH_.WriteTo(output, _repeated_aNKHENIIACH_codec);
|
||||
skinList_.WriteTo(output, _repeated_skinList_codec);
|
||||
pNKCFEALAMI_.WriteTo(output, _repeated_pNKCFEALAMI_codec);
|
||||
if (IsGetAll != false) {
|
||||
output.WriteRawTag(104);
|
||||
@@ -245,7 +245,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
output.WriteRawTag(64);
|
||||
output.WriteUInt32(JPNLPOPMKEJ);
|
||||
}
|
||||
aNKHENIIACH_.WriteTo(ref output, _repeated_aNKHENIIACH_codec);
|
||||
skinList_.WriteTo(ref output, _repeated_skinList_codec);
|
||||
pNKCFEALAMI_.WriteTo(ref output, _repeated_pNKCFEALAMI_codec);
|
||||
if (IsGetAll != false) {
|
||||
output.WriteRawTag(104);
|
||||
@@ -267,7 +267,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
if (Retcode != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Retcode);
|
||||
}
|
||||
size += aNKHENIIACH_.CalculateSize(_repeated_aNKHENIIACH_codec);
|
||||
size += skinList_.CalculateSize(_repeated_skinList_codec);
|
||||
if (JPNLPOPMKEJ != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(JPNLPOPMKEJ);
|
||||
}
|
||||
@@ -291,7 +291,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
if (other.Retcode != 0) {
|
||||
Retcode = other.Retcode;
|
||||
}
|
||||
aNKHENIIACH_.Add(other.aNKHENIIACH_);
|
||||
skinList_.Add(other.skinList_);
|
||||
if (other.JPNLPOPMKEJ != 0) {
|
||||
JPNLPOPMKEJ = other.JPNLPOPMKEJ;
|
||||
}
|
||||
@@ -326,7 +326,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
}
|
||||
case 74:
|
||||
case 72: {
|
||||
aNKHENIIACH_.AddEntriesFrom(input, _repeated_aNKHENIIACH_codec);
|
||||
skinList_.AddEntriesFrom(input, _repeated_skinList_codec);
|
||||
break;
|
||||
}
|
||||
case 90:
|
||||
@@ -367,7 +367,7 @@ namespace EggLink.DanhengServer.Proto {
|
||||
}
|
||||
case 74:
|
||||
case 72: {
|
||||
aNKHENIIACH_.AddEntriesFrom(ref input, _repeated_aNKHENIIACH_codec);
|
||||
skinList_.AddEntriesFrom(ref input, _repeated_skinList_codec);
|
||||
break;
|
||||
}
|
||||
case 90:
|
||||
|
||||
Reference in New Issue
Block a user