KCP gameserver with packet dispatch, scene streaming, combat, gacha and the shop, plus a small HTTP server for the login flow and the wish history page. Game data under assets is pulled out of the client instead of being typed by hand. The excel tables come from the packed bin container and the spawn points from the compiled scene scripts.
61 lines
1.9 KiB
C#
61 lines
1.9 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using Yuanshen.Gameserver.Game;
|
|
|
|
namespace Yuanshen.Gameserver.Database;
|
|
|
|
internal sealed class PlayerPersistence
|
|
{
|
|
private readonly Player _player;
|
|
private readonly GameState _state;
|
|
private readonly IPlayerRepository _repository;
|
|
private readonly PlayerSessionRegistry _registry;
|
|
private readonly ILogger _logger;
|
|
|
|
private long _sessionId;
|
|
|
|
public PlayerPersistence(Player player, GameState state, IPlayerRepository repository,
|
|
PlayerSessionRegistry registry, ILogger<PlayerPersistence> logger)
|
|
{
|
|
_player = player;
|
|
_state = state;
|
|
_repository = repository;
|
|
_registry = registry;
|
|
_logger = logger;
|
|
}
|
|
|
|
public uint PlayerUid => _player.Uid;
|
|
|
|
public void Bind(long sessionId) => _sessionId = sessionId;
|
|
|
|
public void Acquire() => _registry.Acquire(_player.Uid, _sessionId);
|
|
|
|
public void Release() => _registry.Release(_player.Uid, _sessionId);
|
|
|
|
public ValueTask<PlayerRecord?> LoadAsync() => _repository.LoadAsync(_player.Uid);
|
|
|
|
public async ValueTask<bool> SaveAsync()
|
|
{
|
|
if (!_player.IsInitialized)
|
|
return false;
|
|
|
|
if (!_registry.IsOwner(_player.Uid, _sessionId))
|
|
{
|
|
_logger.LogDebug("Skipped save for player {uid}: session {sessionId} is stale", _player.Uid, _sessionId);
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
bool saved = await _repository.SaveAsync(_player.ToRecord(_state.CurrentPos));
|
|
if (saved)
|
|
_logger.LogDebug("Persisted player {uid} at ({x}, {y}, {z}), killed={killed}",
|
|
_player.Uid, _state.CurrentPos.X, _state.CurrentPos.Y, _state.CurrentPos.Z, _player.KilledNodeIds.Count);
|
|
return saved;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
_logger.LogError("Failed to persist player {uid}: {message}", _player.Uid, exception.Message);
|
|
return false;
|
|
}
|
|
}
|
|
}
|