Skip to content

Commit

Permalink
更新Framework:添加数据同步和长期存储
Browse files Browse the repository at this point in the history
  • Loading branch information
Yuancheng Zhang committed May 18, 2021
1 parent 8557cbb commit 9172e71
Show file tree
Hide file tree
Showing 12 changed files with 812 additions and 67 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,18 @@ end

--- 加载的时候运行的代码
function ClientBase:InitDefault(_module)
-- print(string.format('[ClientBase][%s] InitDefault()', self.name))
-- --print(string.format('[ClientBase][%s] InitDefault()', self.name))
-- 初始化默认监听事件
EventUtil.LinkConnects(localPlayer.C_Event, _module, self)
end

--- Debug模式下打印日志
-- self.debug 针对模块本身的debug开关
-- FrameworkConfig.DebugMode 框架中的全局debug开关
function ClientBase:Log(...)
if self.debug and FrameworkConfig.DebugMode then
--print(string.format('[%s]', self.name), ...)
end
end

return ClientBase
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
--- 游戏客户端数据同步
--- @module Client Sync Data, Client-side
--- @copyright Lilith Games, Avatar Team
--- @author Yuancheng Zhang
local ClientDataSync = {}

-- Localize global vars
local FrameworkConfig, MetaData = FrameworkConfig, MetaData

-- 客户端私有数据
local rawDataGlobal = {}
local rawDataPlayer = {}

--- 打印数据同步日志
local PrintLog = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowDataSyncLog and function(...)
--print('[DataSync][Client]', ...)
end or function()
end

--! 初始化

--- 数据初始化
function ClientDataSync.Init()
--print('[DataSync][Client] Init()')
InitEventsAndListeners()
InitDataDefines()
end

--- 初始化事件和绑定Handler
function InitEventsAndListeners()
if localPlayer.C_Event == nil then
world:CreateObject('FolderObject', 'S_Event', localPlayer)
end

-- 数据同步事件
world:CreateObject('CustomEvent', 'DataSyncS2CEvent', localPlayer.C_Event)
localPlayer.C_Event.DataSyncS2CEvent:Connect(DataSyncS2CEventHandler)

-- 长期存储成功事件
if not localPlayer.C_Event.LoadPlayerDataSuccessEvent then
world:CreateObject('CustomEvent', 'LoadPlayerDataSuccessEvent', localPlayer.C_Event)
end
end

--- 校验数据定义
function InitDataDefines()
--* 客户端全局数据
Data.Global = Data.Global or MetaData.New(rawDataGlobal, MetaData.Enum.GLOBAL, MetaData.Enum.CLIENT)
-- 默认赋值
for k, v in pairs(Data.Default.Global) do
Data.Global[k] = v
end

--* 客户端玩家数据
local uid = localPlayer.UserId
local path = MetaData.Enum.PLAYER .. uid
Data.Player = Data.Player or MetaData.New(rawDataPlayer, path, uid)
-- 默认赋值
for k, v in pairs(Data.Default.Player) do
Data.Player[k] = v
end
end

--- 开始同步
function ClientDataSync.Start()
--print('[DataSync][Client] 客户端数据同步开启')
MetaData.ClientSync = true
end

--! Event handler

--- 数据同步事件Handler
function DataSyncS2CEventHandler(_path, _value)
if not MetaData.ClientSync then
return
end

PrintLog(string.format('收到 _path = %s, _value = %s', _path, table.dump(_value)))

local uid = localPlayer.UserId

--* 收到服务器数据
if string.startswith(_path, MetaData.Enum.GLOBAL) then
--* Data.Global 全局数据
MetaData.Set(rawDataGlobal, _path, _value, uid, false)
elseif string.startswith(_path, MetaData.Enum.PLAYER .. uid) then
--* Data.Player 玩家数据
MetaData.Set(rawDataPlayer, _path, _value, uid, false)
else
error(
string.format(
'[DataSync][Client] _path错误 _player = %s, _path = %s, _value = %s',
localPlayer,
_path,
table.dump(_value)
)
)
end
end

return ClientDataSync
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
local ClientHeartbeat = {}

-- Localize global vars
local Setting = FrameworkConfig.Client
local FrameworkConfig = FrameworkConfig

-- 心跳包间隔时间,单位:秒
local HEARTBEAT_DELTA = Setting.HeartbeatDelta
local HEARTBEAT_DELTA = FrameworkConfig.Client.HeartbeatDelta

-- 心跳阈值,单位:秒,范围定义如下:
-- 0s -> threshold_1 : connected
-- threshold_1 -> threshold_2 : disconnected, weak network
-- threshold_2 -> longer : disconnected, quit server
local HEARTBEAT_THRESHOLD_1 = Setting.HeartbeatThreshold1 * 1000 -- second => ms
local HEARTBEAT_THRESHOLD_2 = Setting.HeartbeatThreshold2 * 1000 -- second => ms
local HEARTBEAT_THRESHOLD_1 = FrameworkConfig.Client.HeartbeatThreshold1 * 1000 -- second => ms
local HEARTBEAT_THRESHOLD_2 = FrameworkConfig.Client.HeartbeatThreshold2 * 1000 -- second => ms

-- 玩家心跳连接状态
local HeartbeatEnum = {
Expand All @@ -37,23 +37,23 @@ local diff -- 时间戳插值
local sTmpTs, cTmpTs -- 时间戳缓存

--- 打印心跳日志
local PrintHb = Setting.ShowHeartbeatLog and function(...)
print('[Heartbeat][Client]', ...)
local PrintHb = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowHeartbeatLog and function(...)
--print('[Heartbeat][Client]', ...)
end or function()
end

--! 外部接口

--- 初始化心跳包
function ClientHeartbeat.Init()
print('[Heartbeat][Client] Init()')
--print('[Heartbeat][Client] Init()')
CheckSetting()
InitEventsAndListeners()
end

--- 开始发出心跳
function ClientHeartbeat.Start()
print('[Heartbeat][Client] Start()')
--print('[Heartbeat][Client] Start()')
local cTimestamp
running = true
while (running) do
Expand All @@ -64,7 +64,7 @@ end

-- 停止心跳
function ClientHeartbeat.Stop()
print('[Heartbeat][Client] Stop()')
--print('[Heartbeat][Client] Stop()')
running = false
end

Expand Down Expand Up @@ -127,12 +127,12 @@ end
function CheckPlayerJoin(_player, _sTimestamp)
if not cache.sTimestamp then
--* 玩家新加入 OnPlayerJoinEvent
print('[Heartbeat][Client] OnPlayerJoinEvent, 新玩家加入,', localPlayer)
--print('[Heartbeat][Client] OnPlayerJoinEvent, 新玩家加入,', localPlayer, localPlayer.UserId)
NetUtil.Fire_C('OnPlayerJoinEvent', localPlayer)
cache.state = HeartbeatEnum.CONNECT
elseif cache.state == HeartbeatEnum.DISCONNECT then
--* 玩家断线重连 OnPlayerReconnectEvent
print('[Heartbeat][Client] OnPlayerReconnectEvent, 玩家断线重连,', localPlayer)
--print('[Heartbeat][Client] OnPlayerReconnectEvent, 玩家断线重连,', localPlayer, localPlayer.UserId)
NetUtil.Fire_C('OnPlayerReconnectEvent', localPlayer)
cache.state = HeartbeatEnum.CONNECT
end
Expand All @@ -150,7 +150,7 @@ function CheckPlayerState(_player, _cTimestamp)
cache.state = HeartbeatEnum.CONNECT
elseif cache.state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then
--* 玩家断线,弱网环境
print('[Heartbeat][Client] OnPlayerDisconnectEvent, 玩家离线, 弱网环境,', localPlayer)
--print('[Heartbeat][Client] OnPlayerDisconnectEvent, 玩家离线, 弱网环境,', localPlayer)
NetUtil.Fire_C('OnPlayerDisconnectEvent', localPlayer)
cache.state = HeartbeatEnum.DISCONNECT
elseif cache.state == HeartbeatEnum.DISCONNECT and diff >= HEARTBEAT_THRESHOLD_2 then
Expand All @@ -162,7 +162,7 @@ end

--- 退出游戏
function QuitGame()
print('[Heartbeat][Client] Game.Quit(), 玩家退出游戏')
--print('[Heartbeat][Client] Game.Quit(), 玩家退出游戏', localPlayer, localPlayer.UserId)
Game.Quit()
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ local initDefaultList, initList, updateList = {}, {}, {}

--- 运行客户端
function Client:Run()
print('[Client] Run()')
--print('[Client] Run()')
InitClient()
StartUpdate()
end

--- 停止Update
function Client:Stop()
print('[Client] Stop()')
--print('[Client] Stop()')
running = false
ClientHeartbeat.Stop()
end
Expand All @@ -33,11 +33,11 @@ function InitClient()
if initialized then
return
end
print('[Client] InitClient()')
--print('[Client] InitClient()')
InitRandomSeed()
InitHeartbeat()
InitDataSync()
InitClientCustomEvents()
PreloadCsv()
GenInitAndUpdateList()
RunInitDefault()
InitOtherModules()
Expand All @@ -50,6 +50,12 @@ function InitHeartbeat()
ClientHeartbeat.Init()
end

--- 初始化数据同步
function InitDataSync()
assert(ClientDataSync, '[Server][DataSync] 找不到ClientDataSync,请联系张远程')
ClientDataSync.Init()
end

--- 初始化客户端的CustomEvent
function InitClientCustomEvents()
if localPlayer.C_Event == nil then
Expand Down Expand Up @@ -77,9 +83,18 @@ end

--- 生成需要Init和Update的模块列表
function GenInitAndUpdateList()
-- TODO: 改成在FrameworkConfig中配置
-- Init Default
ModuleUtil.GetModuleListWithFunc(Module.UI_Module, 'InitDefault', initDefaultList)
ModuleUtil.GetModuleListWithFunc(Module.C_Module, 'InitDefault', initDefaultList)
-- Init
ModuleUtil.GetModuleListWithFunc(Define, 'Init', initList)
ModuleUtil.GetModuleListWithFunc(Module.UI_Module, 'Init', initList)
ModuleUtil.GetModuleListWithFunc(Module.C_Module, 'Init', initList)
-- Update
ModuleUtil.GetModuleListWithFunc(Module.UI_Module, 'Update', updateList)
ModuleUtil.GetModuleListWithFunc(Module.C_Module, 'Update', updateList)
-- Plugin
for _, m in pairs(Config.PluginModules) do
ModuleUtil.GetModuleListWithFunc(m, 'InitDefault', initDefaultList)
ModuleUtil.GetModuleListWithFunc(m, 'Init', initList)
Expand All @@ -99,14 +114,6 @@ function InitRandomSeed()
math.randomseed(os.time())
end

--- 预加载所有的CSV表格
function PreloadCsv()
print('[Client] PreloadCsv()')
if Config.ClientPreload and #Config.ClientPreload > 0 then
CsvUtil.PreloadCsv(Config.ClientPreload, Csv, Config)
end
end

--- 初始化包含Init()方法的模块
function InitOtherModules()
for _, m in ipairs(initList) do
Expand All @@ -116,7 +123,7 @@ end

--- 开始Update
function StartUpdate()
print('[Client] StartUpdate()')
--print('[Client] StartUpdate()')
assert(not running, '[Client] StartUpdate() 正在运行')

running = true
Expand All @@ -126,6 +133,9 @@ function StartUpdate()
invoke(ClientHeartbeat.Start)
end

-- 开启数据同步
ClientDataSync.Start()

local dt = 0 -- delta time 每帧时间
local tt = 0 -- total time 游戏总时间
local now = Timer.GetTimeMillisecond --时间函数缓存
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--- 游戏数据
--- @module Game Data, Both-side
--- @copyright Lilith Games, Avatar Team
--- @author Yuancheng Zhang
local Data = {}

-- 客户端
-- 1. Data.Global
-- 2. Data.Player

-- 服务器
-- 1. Data.Global
-- 2. Data.Players

--! 这个Module为空
--! 数据定义在:ClientDataSyncModule、ServerDataSyncModule

return Data
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
--- @copyright Lilith Games, Avatar Team
--- @author Yuancheng Zhang
local FrameworkConfig = {
--! Debug模式
DebugMode = true,
-- 启动心跳
HeartbeatStart = true,
-- 长期存储:玩家数据定时保存时间间隔(秒)
DatabaseAutoSaveTime = 30,
-- 长期存储:重新读取游戏数据时间间隔(秒)
DatabaseReloadTimeAfterFailed = 1,
-- 服务器配置
Server = {
-- 心跳包间隔时间,单位:秒
HeartbeatDelta = 1,
Expand All @@ -14,13 +21,12 @@ local FrameworkConfig = {
-- threshold_2 -> longer : disconnected, remove player
HeartbeatThreshold1 = 5,
HeartbeatThreshold2 = 10,
-- 显示心跳日志
ShowHeartbeatLog = false,
-- 插件中需要使用声明周期的服务器模块目录
PluginModules = {},
-- 插件中服务器需要生成的CustomEvent, 模块中必须得有ServerEvents
PluginEvents = {}
},
-- 客户端配置
Client = {
-- 心跳包间隔时间,单位:秒
HeartbeatDelta = 1,
Expand All @@ -30,12 +36,17 @@ local FrameworkConfig = {
-- threshold_2 -> longer : disconnected, quit server
HeartbeatThreshold1 = 5,
HeartbeatThreshold2 = 10,
-- 显示心跳日志
ShowHeartbeatLog = false,
-- 插件中需要使用声明周期的客户端模块目录
PluginModules = {},
-- 插件中客户端需要生成的CustomEvent,模块中必须得有ClientEvents
PluginEvents = {}
},
--! Debug相关
Debug = {
-- 显示心跳日志
ShowHeartbeatLog = false,
-- 显示数据同步日志
ShowDataSyncLog = false
}
}

Expand Down
Loading

0 comments on commit 9172e71

Please sign in to comment.