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.
164 lines
5.9 KiB
C#
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;
|
|
}
|
|
}
|