yuanshen/Yuanshen.Gameserver/Controllers/AccountController.cs
wisedev a4b3b669a8 Use the named retcode and reason constants
Half the handlers were still answering with a bare 0 or -1 even though the whole
retcode table is generated. Values on the wire are unchanged, they just read
properly now.

Same for the item hint reasons. ActionReasonType is a generated enum and we were
redeclaring six of its members as private consts in four different files.
2026-09-04 11:21:12 +03:00

164 lines
5.9 KiB
C#

using Yuanshen.Gameserver.Controllers.Attributes;
using Yuanshen.Gameserver.Controllers.Result;
using Yuanshen.Gameserver.Game;
using Yuanshen.Gameserver.Network.Session;
using Yuanshen.Protocol;
using Yuanshen.Gameserver.Database;
using Microsoft.Extensions.Logging;
namespace Yuanshen.Gameserver.Controllers;
[NetController]
internal sealed class AccountController : ControllerBase
{
[NetCommand(CmdType.GetPlayerTokenReq)]
public async ValueTask<IResult> OnGetPlayerTokenReq(Player player, IAccountRepository accounts)
{
GetPlayerTokenReq req = Packet!.DecodeBody<GetPlayerTokenReq>();
uint uid = await accounts.GetOrCreateUidAsync(req.AccountUid);
player.AssignUid(uid);
GetPlayerTokenRsp rsp = new()
{
PlayerUid = player.Uid,
AccountToken = req.AccountToken,
AccountType = (int)req.AccountType,
SecretKey = 1337
};
return Response(CmdType.GetPlayerTokenRsp, rsp);
}
[NetCommand(CmdType.PingReq)]
public async ValueTask<IResult> OnPingReq(SceneManager scene)
{
PingReq req = Packet!.DecodeBody<PingReq>();
await scene.SyncPendingMonsterLevelsAsync();
PingRsp rsp = new()
{
Seq = (uint)req.Seq,
ClientTime = (uint)req.ClientTime
};
return Response(CmdType.PingRsp, rsp);
}
[NetCommand(CmdType.PlayerLoginReq)]
public async ValueTask<IResult> OnPlayerLoginReq(NetSession session, Player player, GameState state, PlayerPersistence persistence, OpenStateTable openStates, ILogger<AccountController> logger)
{
player.InitDefault();
persistence.Acquire();
PlayerRecord? record = await persistence.LoadAsync();
if (record is not null)
{
player.ApplyRecord(record);
if (record.PosX != 0f || record.PosY != 0f || record.PosZ != 0f)
state.UpdatePosition(new Vector { X = record.PosX, Y = record.PosY, Z = record.PosZ });
logger.LogInformation("Loaded player {uid}: pos=({x}, {y}, {z}), team={team}, killed={killed}",
player.Uid, state.CurrentPos.X, state.CurrentPos.Y, state.CurrentPos.Z,
player.TeamAvatarGuids.Count, record.KilledNodes.Count);
}
else
{
logger.LogInformation("No saved record for player {uid}, starting fresh", player.Uid);
}
await session.NotifyAsync(CmdType.PlayerDataNotify, new PlayerDataNotify
{
NickName = player.Nickname,
PropMap =
{
{ 4001u, new PropValue { Type = 4001, Ival = 1, Val = 1 } },
{ 10006u, new PropValue { Type = 10006, Ival = 1, Val = 1 } },
{ 10009u, new PropValue { Type = 10009, Ival = 1, Val = 1 } },
{ 10010u, new PropValue { Type = 10010, Ival = 24000, Val = 24000 } },
{ 10011u, new PropValue { Type = 10011, Ival = 24000, Val = 24000 } },
{ 10013u, new PropValue { Type = 10013, Ival = 60, Val = 60 } },
{ 10015u, new PropValue { Type = 10015, Ival = player.Hcoin, Val = player.Hcoin } },
{ 10016u, new PropValue { Type = 10016, Ival = player.Scoin, Val = player.Scoin } },
{ 10019u, new PropValue { Type = 10019, Ival = 8, Val = 8 } },
{ 10020u, new PropValue { Type = 10020, Ival = 160, Val = 160 } }
}
});
await session.NotifyAsync(CmdType.AvatarDataNotify, BuildAvatarData(player));
await session.NotifyAsync(CmdType.PlayerStoreNotify, BuildStore(player));
OpenStateUpdateNotify openStateNotify = new();
foreach (uint openStateId in openStates.Ids)
openStateNotify.OpenStateMap[openStateId] = 1;
await session.NotifyAsync(CmdType.OpenStateUpdateNotify, openStateNotify);
await session.NotifyAsync(CmdType.PlayerEnterSceneNotify, new PlayerEnterSceneNotify
{
SceneId = GameState.SceneId,
Pos = state.CurrentPos,
SceneBeginTime = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
Type = EnterType.EnterSelf,
TargetUid = player.Uid,
EnterSceneToken = state.NextEnterSceneToken(),
IsFirstLoginEnterScene = true,
WorldLevel = 0,
EnterReason = 1
});
return Response(CmdType.PlayerLoginRsp, new PlayerLoginRsp
{
Retcode = Retcode.RET_SUCC,
GameBiz = "hk4e_global"
});
}
private static AvatarDataNotify BuildAvatarData(Player player)
{
AvatarDataNotify data = new()
{
CurAvatarTeamId = player.CurrentTeamId,
ChooseAvatarGuid = player.CurrentAvatarGuid
};
foreach (uint flycloak in Player.Flycloaks)
data.OwnedFlycloakList.Add(flycloak);
foreach (GameAvatar avatar in player.Avatars)
data.AvatarList.Add(avatar.AsAvatarInfo());
AvatarTeam team = new() { TeamName = "Team " + player.CurrentTeamId };
team.AvatarGuidList.AddRange(player.TeamAvatarGuids);
data.AvatarTeamMap.Add(player.CurrentTeamId, team);
return data;
}
private static PlayerStoreNotify BuildStore(Player player)
{
PlayerStoreNotify store = new()
{
StoreType = StoreType.StorePack,
WeightLimit = 30000
};
foreach (GameWeapon weapon in player.Weapons)
store.ItemList.Add(weapon.AsItem());
foreach (GameReliquary reliquary in player.Reliquaries)
store.ItemList.Add(reliquary.AsItem());
foreach ((uint itemId, uint count) in player.Materials)
store.ItemList.Add(new Item
{
ItemId = itemId,
Guid = ((ulong)player.Uid << 32) | itemId,
Material = new Material { Count = count }
});
return store;
}
}