You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

152 lines
4.5 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Sog;
namespace Game
{
//玩家server patch 机制,
//使用场景:老玩家的一些数据随着版本迭代已经不符合当下的需求,或者一些业务存在bug,导致玩家数据不正确,需要修复
//对应的数据,但是不想把修复代码参合再现有的逻辑中、补丁方式修复,所以建议采用patch 机制,玩家只需要执行一次修复,
//后续将不用再维护相关的修复逻辑。
public static class PatchSvc
{
private class PatchModel
{
public int Id;
public Func<PlayerOnGame, int> Patch;
}
private static readonly ReaderWriterLockSlim Locker = new();
private static int _maxPatch;
private static readonly Dictionary<int, PatchModel> AllPatchMethods = new();
public static void RegisterAll()
{
try
{
Locker.EnterUpgradeableReadLock();
try
{
//写锁线程只有一个
Locker.EnterWriteLock();
AllPatchMethods.Clear();
Register(PatchCode.PATCH_CODE_FIX_TEST, FixTest);
}
catch (Exception e)
{
TraceLog.Error("Patch.Register register method failed,e={0}", e.Message);
}
finally
{
Locker.ExitWriteLock();
}
}
catch (Exception e)
{
TraceLog.Error("Patch.Register register method failed,e={0}", e.Message);
}
finally
{
Locker.ExitUpgradeableReadLock();
}
}
private static void Register(int id, Func<PlayerOnGame, int> method)
{
if (method == null)
{
return;
}
TraceLog.Trace("PatchSvc.Register register method,id={0},name={1}", id, method.Method.Name);
AllPatchMethods[id] = new PatchModel() { Id = id, Patch = method };
_maxPatch = Math.Max(_maxPatch, id);
}
public static void PatchAll(PlayerOnGame player)
{
_Patch(player);
player.MakeDirty();
}
private static void _Patch(PlayerOnGame player)
{
try
{
Locker.EnterReadLock();
int position = player.RoleData.ExtData.Patch;
if (position == _maxPatch)
{
return;
}
if (AllPatchMethods.Count == 0)
{
return;
}
foreach (var patch in AllPatchMethods.Where(patch => patch.Key > position))
{
try
{
patch.Value.Patch(player);
}
catch (Exception e)
{
TraceLog.Trace("PatchSvc.PatchAll patch failed. id={0},name={1},error info={2}", patch.Key,
patch.Value.Patch.Method.Name, e.Message);
break;
}
position = Math.Max(patch.Key, position);
}
player.RoleData.ExtData.Patch = position;
}
catch (Exception e)
{
TraceLog.Trace("PatchSvc.PatchAll patch failed,e={0}", e.Message);
}
finally
{
Locker.ExitReadLock();
}
}
public static void OnPlayerBorn(PlayerOnGame player)
{
int position = 0;
try
{
Locker.EnterReadLock();
position = _maxPatch;
}
catch (Exception e)
{
TraceLog.Error("PatchSvc.OnPlayerBorn error: {0}", e.Message);
}
finally
{
Locker.ExitReadLock();
}
player.RoleData.ExtData.Patch = position;
}
//---------------------------------------------------------------- 需要修复的逻辑
public static int FixTest(PlayerOnGame player)
{
TraceLog.Trace("test fix data player uid={0}", player.UserID);
return 0;
}
}
}