From 88985ed2fbfe2bb8da0ea4aaf917b07d8eeccb2d Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Thu, 14 Jan 2021 21:28:06 +0800 Subject: [PATCH 01/39] Update ['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复一个心跳的bug --- ...bal']['Framework']['ClientHeartbeatModule'].ModuleScript.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua index 99f36a4..ec73b18 100644 --- a/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua +++ b/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua @@ -83,7 +83,7 @@ end --- 初始化事件和绑定Handler function InitEventsAndListeners() if localPlayer.C_Event == nil then - world:CreateObject('FolderObject', 'C_Event', localPlayer) + world:CreateObject('FolderObject', 'C_Event', localPlayer.C_Event) end world:CreateObject('CustomEvent', 'HeartbeatS2CEvent', localPlayer.C_Event) localPlayer.C_Event.HeartbeatS2CEvent:Connect(HeartbeatS2CEventHandler) From 38e6bb3030cc58d4e2d86fea26089b52e695704f Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Thu, 14 Jan 2021 21:33:15 +0800 Subject: [PATCH 02/39] Update ['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改错了,我傻逼了 --- ...bal']['Framework']['ClientHeartbeatModule'].ModuleScript.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua index ec73b18..99f36a4 100644 --- a/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua +++ b/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua @@ -83,7 +83,7 @@ end --- 初始化事件和绑定Handler function InitEventsAndListeners() if localPlayer.C_Event == nil then - world:CreateObject('FolderObject', 'C_Event', localPlayer.C_Event) + world:CreateObject('FolderObject', 'C_Event', localPlayer) end world:CreateObject('CustomEvent', 'HeartbeatS2CEvent', localPlayer.C_Event) localPlayer.C_Event.HeartbeatS2CEvent:Connect(HeartbeatS2CEventHandler) From a6a29548c9c9ab70ca358dc05d1e557a3070e492 Mon Sep 17 00:00:00 2001 From: Xinwu Zhang <64084648+lilith-avatar-sidzhang@users.noreply.github.com> Date: Fri, 5 Mar 2021 12:49:52 +0800 Subject: [PATCH 03/39] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9F=8B=E7=82=B9?= =?UTF-8?q?=E5=87=BD=E6=95=B0,=E9=80=82=E5=BA=94=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=88=86=E6=9E=90=E5=B8=88=E7=9A=84=E6=A0=BC=E5=BC=8F=E8=A6=81?= =?UTF-8?q?=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...al']['Utility']['CloudLogUtilModule'].ModuleScript.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua index 702cfd9..b7d35be 100644 --- a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua +++ b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua @@ -12,13 +12,13 @@ end ---触发埋点相应的事件调用 ---@param _key string 埋点的键 -function CloudLogUtil.UploadLog(_key, ...) +function CloudLogUtil.UploadLog(_key, _table) local tableName = CloudLogUtil.gameId .. '_' .. _key - local args = { ... } + local arg = LuaJsonUtil:encode(_table) if localPlayer then - TrackService.CloudLogFromClient({ tableName, CloudLogUtil.gameId, table.unpack(args) }) + TrackService.CloudLogFromClient({ tableName, CloudLogUtil.gameId, arg}) else - TrackService.CloudLogFromServer({ tableName, CloudLogUtil.gameId, table.unpack(args) }) + TrackService.CloudLogFromServer({ tableName, CloudLogUtil.gameId, arg}) end end From 57a86bb4e3695318aea9655f59441a72f7b8f621 Mon Sep 17 00:00:00 2001 From: Xinwu Zhang <64084648+lilith-avatar-sidzhang@users.noreply.github.com> Date: Thu, 22 Apr 2021 16:32:14 +0800 Subject: [PATCH 04/39] =?UTF-8?q?Lua=20function=E5=86=85=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E8=AE=A1=E6=95=B0=E5=99=A8=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...['World']['Global']['LuaFunctionScript'].Script.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/code/['World']['Global']['LuaFunctionScript'].Script.lua b/code/['World']['Global']['LuaFunctionScript'].Script.lua index 8dfae50..02fe3c5 100644 --- a/code/['World']['Global']['LuaFunctionScript'].Script.lua +++ b/code/['World']['Global']['LuaFunctionScript'].Script.lua @@ -956,3 +956,13 @@ function Stack:PrintElement() str = str .. '}' print(str) end + + +--- uid递增计数器 +function UidCounter() + local num = 0 + return function() + num = num + 1 + return tostring(os.clock())..'-'..tostring(num) + end +end From 5636d4abd70cd1a3192088d4d54c28cbc0a57fd6 Mon Sep 17 00:00:00 2001 From: Xinwu Zhang <64084648+lilith-avatar-sidzhang@users.noreply.github.com> Date: Thu, 22 Apr 2021 17:05:42 +0800 Subject: [PATCH 05/39] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E6=97=B6=E8=84=9A=E6=9C=AC,=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E5=92=8C=E7=8E=B0=E5=9C=A8=E6=A8=A1=E5=9D=97=E5=8C=96?= =?UTF-8?q?=E7=9A=84=E7=BE=8E=E6=9C=AF=E5=AF=B9=E6=8E=A5=E6=97=B6=E5=BF=AB?= =?UTF-8?q?=E9=80=9F=E5=8F=A0=E4=BB=A3=E8=B5=84=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...['SceneMeshEditorModule'].ModuleScript.lua | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua diff --git a/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua b/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua new file mode 100644 index 0000000..b123b06 --- /dev/null +++ b/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua @@ -0,0 +1,29 @@ +--- 用于场景mesh的一些快捷编辑功能 +--- @module SceneMeshEditor +--- @copyright Lilith Games, Avatar Team +--- @author Sidzhang +local SceneMeshEditor = {} + +--- 将当前选中节点下的所有特定名称的mesh节点更改其引用 +--- @param _NodeName string 需要被替换资源的节点名字 +--- @param _MeshResource string FBX资源路径 +--- @param _root object 执行该操作的根节点,缺省则为选中的第一个节点 +function SceneMeshEditor:ChangeMesh(_NodeName,_MeshResource,_root) + if not _root then + _root = Editor.Selections[1] + end + if not _root then + print('没有选中或输入任何节点') + return + end + for _,v in pairs(_root:GetChildren()) do + if v.Name == _NodeName and v.ClassName == 'MeshObject' then + v.Mesh = ResourceManager.GetMesh(_MeshResource) + end + self:ChangeMesh(_NodeName,_MeshResource,v) + end +end + +return SceneMeshEditor + +-- require(Module.Editor_Module.SceneMeshEditorModule):ChangeMesh() \ No newline at end of file From c08ddfdf18df182fbd0267572ad349eb549f96b7 Mon Sep 17 00:00:00 2001 From: Xinwu Zhang <64084648+lilith-avatar-sidzhang@users.noreply.github.com> Date: Mon, 26 Apr 2021 14:14:06 +0800 Subject: [PATCH 06/39] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9F=8B=E7=82=B9?= =?UTF-8?q?=E5=B0=81=E8=A3=85=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...lobal']['Utility']['CloudLogUtilModule'].ModuleScript.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua index b7d35be..e49275c 100644 --- a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua +++ b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua @@ -13,12 +13,11 @@ end ---触发埋点相应的事件调用 ---@param _key string 埋点的键 function CloudLogUtil.UploadLog(_key, _table) - local tableName = CloudLogUtil.gameId .. '_' .. _key local arg = LuaJsonUtil:encode(_table) if localPlayer then - TrackService.CloudLogFromClient({ tableName, CloudLogUtil.gameId, arg}) + TrackService.CloudLogFromClient({ (_key, CloudLogUtil.gameId, arg}) else - TrackService.CloudLogFromServer({ tableName, CloudLogUtil.gameId, arg}) + TrackService.CloudLogFromServer({ (_key, CloudLogUtil.gameId, arg}) end end From b2917cd9f0a0c1a3abebd01070420662307e557c Mon Sep 17 00:00:00 2001 From: Xinwu Zhang <64084648+lilith-avatar-sidzhang@users.noreply.github.com> Date: Wed, 28 Apr 2021 10:57:52 +0800 Subject: [PATCH 07/39] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=9F=8B=E7=82=B9=E6=8E=A5=E5=8F=A3bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua index e49275c..acc5fc9 100644 --- a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua +++ b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua @@ -15,9 +15,9 @@ end function CloudLogUtil.UploadLog(_key, _table) local arg = LuaJsonUtil:encode(_table) if localPlayer then - TrackService.CloudLogFromClient({ (_key, CloudLogUtil.gameId, arg}) + TrackService.CloudLogFromClient(_key, CloudLogUtil.gameId, arg) else - TrackService.CloudLogFromServer({ (_key, CloudLogUtil.gameId, arg}) + TrackService.CloudLogFromServer(_key, CloudLogUtil.gameId, arg) end end From f54315ba693dc2802c04d2997ccd466228f67f27 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Fri, 7 May 2021 15:43:41 +0800 Subject: [PATCH 08/39] Update ['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改框架心跳的一个bug --- ...amework']['ServerHeartbeatModule'].ModuleScript.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua index 516c596..4219788 100644 --- a/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua +++ b/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua @@ -159,14 +159,16 @@ function CheckPlayerStates(_player, _sTimestam) end diff = _sTimestam - cache[_player].sTimestamp PrintHb(string.format('==========================================> diff = %s, %s', diff * .001, _player)) - - if cache[_player].state == HeartbeatEnum.CONNECT and diff > HEARTBEAT_THRESHOLD_1 then - --* 玩家断线 OnPlayerReconnectEvent + if diff < HEARTBEAT_THRESHOLD_1 then + --* 玩家在线 + cache[_player].state = HeartbeatEnum.CONNECT + elseif cache[_player].state == HeartbeatEnum.CONNECT and diff > HEARTBEAT_THRESHOLD_1 then + --* 玩家断线 OnPlayerDisconnectEvent print('[Heartbeat][Server] OnPlayerDisconnectEvent, 玩家离线, 等待断线重连,', _player) NetUtil.Fire_S('OnPlayerDisconnectEvent', _player) cache[_player].state = HeartbeatEnum.DISCONNECT elseif cache[_player].state == HeartbeatEnum.DISCONNECT and diff > HEARTBEAT_THRESHOLD_2 then - --* 玩家彻底断线,剔除玩家 + --* 玩家彻底断线,剔除玩家 OnPlayerLeaveEvent print('[Heartbeat][Server] OnPlayerLeaveEvent, 剔除离线玩家,', _player) NetUtil.Fire_S('OnPlayerLeaveEvent', _player) print('[Heartbeat][Server] OnPlayerLeave, 发送客户端离线事件,', _player) From c4ae073410d6a7b68c07dd9f2509c78f3fe4461c Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Fri, 7 May 2021 15:44:35 +0800 Subject: [PATCH 09/39] Update ['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua --- ...l']['Framework']['ServerHeartbeatModule'].ModuleScript.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua index 4219788..d79c0bf 100644 --- a/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua +++ b/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua @@ -162,12 +162,12 @@ function CheckPlayerStates(_player, _sTimestam) if diff < HEARTBEAT_THRESHOLD_1 then --* 玩家在线 cache[_player].state = HeartbeatEnum.CONNECT - elseif cache[_player].state == HeartbeatEnum.CONNECT and diff > HEARTBEAT_THRESHOLD_1 then + elseif cache[_player].state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then --* 玩家断线 OnPlayerDisconnectEvent print('[Heartbeat][Server] OnPlayerDisconnectEvent, 玩家离线, 等待断线重连,', _player) NetUtil.Fire_S('OnPlayerDisconnectEvent', _player) cache[_player].state = HeartbeatEnum.DISCONNECT - elseif cache[_player].state == HeartbeatEnum.DISCONNECT and diff > HEARTBEAT_THRESHOLD_2 then + elseif cache[_player].state == HeartbeatEnum.DISCONNECT and diff >= HEARTBEAT_THRESHOLD_2 then --* 玩家彻底断线,剔除玩家 OnPlayerLeaveEvent print('[Heartbeat][Server] OnPlayerLeaveEvent, 剔除离线玩家,', _player) NetUtil.Fire_S('OnPlayerLeaveEvent', _player) From f42a4a02765ada12fabb45ae2aa207b28a7cd495 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Fri, 7 May 2021 15:47:07 +0800 Subject: [PATCH 10/39] Update ['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua --- ...['Framework']['ClientHeartbeatModule'].ModuleScript.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua index 99f36a4..07f4be4 100644 --- a/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua +++ b/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua @@ -145,12 +145,15 @@ function CheckPlayerState(_player, _cTimestamp) end diff = _cTimestamp - cache.cTimestamp PrintHb(string.format('==========================================> diff = %s, %s', diff * .001, localPlayer)) - if cache.state == HeartbeatEnum.CONNECT and diff > HEARTBEAT_THRESHOLD_1 then + if diff < HEARTBEAT_THRESHOLD_1 then + --* 玩家在线 + cache.state = HeartbeatEnum.CONNECT + elseif cache.state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then --* 玩家断线,弱网环境 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 + elseif cache.state == HeartbeatEnum.DISCONNECT and diff >= HEARTBEAT_THRESHOLD_2 then --* 玩家断线, 退出游戏 -- QuitGame() NetUtil.Fire_C('OnPlayerLeaveEvent', localPlayer) From 97476dfe8a48e934131d7be2d17ee028f114d595 Mon Sep 17 00:00:00 2001 From: Xinwu Zhang <64084648+lilith-avatar-sidzhang@users.noreply.github.com> Date: Tue, 11 May 2021 12:08:13 +0800 Subject: [PATCH 11/39] =?UTF-8?q?=E4=BF=AE=E6=94=B9log=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua index acc5fc9..7abcdde 100644 --- a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua +++ b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua @@ -15,9 +15,9 @@ end function CloudLogUtil.UploadLog(_key, _table) local arg = LuaJsonUtil:encode(_table) if localPlayer then - TrackService.CloudLogFromClient(_key, CloudLogUtil.gameId, arg) + TrackService.CloudLogFromClient({_key, CloudLogUtil.gameId, arg}) else - TrackService.CloudLogFromServer(_key, CloudLogUtil.gameId, arg) + TrackService.CloudLogFromServer({_key, CloudLogUtil.gameId, arg}) end end From e6129dbbcff8716cc24c19a4bf66457436ab5633 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 18:01:19 +0800 Subject: [PATCH 12/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0CloudLogUtil=EF=BC=9A?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BF=83=E6=82=9F=E7=9A=84=E7=BD=B2=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua index 7abcdde..fc2e27b 100644 --- a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua +++ b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua @@ -1,7 +1,7 @@ --- 埋点数据工具 --- @module CloudLogUtil --- @copyright Lilith Games, Avatar Team ---- @author Sharif Ma +--- @author Sharif Ma, Xinwu Zhang local CloudLogUtil = {} ---埋点工具初始化 From da6d22dc47faacd9416b229d2a318deb895d278d Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 18:17:36 +0800 Subject: [PATCH 13/39] Git ignore .vscode --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 92d5dad..84eb89b 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ code/*.xlsx *.smap.storage *.iso ~$* -*.idea/ \ No newline at end of file +*.idea/ +*.vscode/ \ No newline at end of file From affbfee127a8aeaed31979ea09bf6157a68dea5e Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 18:18:14 +0800 Subject: [PATCH 14/39] Code format --- ...odule']['SceneMeshEditorModule'].ModuleScript.lua | 12 ++++++------ ...'Utility']['CloudLogUtilModule'].ModuleScript.lua | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua b/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua index b123b06..b26b366 100644 --- a/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua +++ b/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua @@ -1,29 +1,29 @@ --- 用于场景mesh的一些快捷编辑功能 --- @module SceneMeshEditor --- @copyright Lilith Games, Avatar Team ---- @author Sidzhang +--- @author Sid Zhang local SceneMeshEditor = {} --- 将当前选中节点下的所有特定名称的mesh节点更改其引用 --- @param _NodeName string 需要被替换资源的节点名字 --- @param _MeshResource string FBX资源路径 --- @param _root object 执行该操作的根节点,缺省则为选中的第一个节点 -function SceneMeshEditor:ChangeMesh(_NodeName,_MeshResource,_root) +function SceneMeshEditor:ChangeMesh(_NodeName, _MeshResource, _root) if not _root then _root = Editor.Selections[1] end if not _root then - print('没有选中或输入任何节点') + print('[SceneMeshEditor] 没有选中或输入任何节点') return end - for _,v in pairs(_root:GetChildren()) do + for _, v in pairs(_root:GetChildren()) do if v.Name == _NodeName and v.ClassName == 'MeshObject' then v.Mesh = ResourceManager.GetMesh(_MeshResource) end - self:ChangeMesh(_NodeName,_MeshResource,v) + self:ChangeMesh(_NodeName, _MeshResource, v) end end return SceneMeshEditor --- require(Module.Editor_Module.SceneMeshEditorModule):ChangeMesh() \ No newline at end of file +-- require(Module.Editor_Module.SceneMeshEditorModule):ChangeMesh() diff --git a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua index fc2e27b..65f6636 100644 --- a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua +++ b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua @@ -21,4 +21,4 @@ function CloudLogUtil.UploadLog(_key, _table) end end -return CloudLogUtil \ No newline at end of file +return CloudLogUtil From 60bed06c07b98fa415f5fbb9adce70c6d007bf31 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 18:19:32 +0800 Subject: [PATCH 15/39] Update avatar-ava.smap --- Smap/avatar-ava.smap | Bin 321328 -> 67653 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Smap/avatar-ava.smap b/Smap/avatar-ava.smap index 6beeceae3646c0e7027cb783b1c1c1d71182e7dc..c484c0f9a1c2a644e35824d9a346794f072d9cea 100644 GIT binary patch literal 67653 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 literal 321328 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ℜ^a0KlW~jQ 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

GYH~^n5Xb-&mpaEF^TNH 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 Date: Tue, 18 May 2021 18:30:25 +0800 Subject: [PATCH 16/39] =?UTF-8?q?=E5=B0=86=E6=A1=86=E6=9E=B6=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=E7=89=88=E6=9C=AC=E5=8D=87=E7=BA=A7=E5=88=B0?= =?UTF-8?q?v0.11.0.53772?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Smap/avatar-ava.smap | Bin 67653 -> 67356 bytes ...'PlayerGuiDefaultModule'].ModuleScript.lua | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Smap/avatar-ava.smap b/Smap/avatar-ava.smap index c484c0f9a1c2a644e35824d9a346794f072d9cea..6de308a17405157aa2df3240bc7aade6137562a6 100644 GIT binary patch literal 67356 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 diff --git a/code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua b/code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua index 5a96144..cb06367 100644 --- a/code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua +++ b/code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua @@ -28,8 +28,7 @@ end -- 姓名板 function PlayerGuiDefault:InitNameGui() nameGUI = player.NameGui - nameGUI.NameBarTxt1.Text = player.Name - nameGUI.NameBarTxt2.Text = player.Name + nameGUI.NameBarTxt.Text = player.Name end -- 血条 From a842760623b8e4a652df19240c205b071e9de7d2 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 18:34:11 +0800 Subject: [PATCH 17/39] remove all folder --- Smap/avatar-ava.smap | Bin 67356 -> 0 bytes ...ickGuide']['GuideEffectScript'].Script.lua | 20 - ...]['C_Code']['ClientMainScript'].Script.lua | 4 - ...lobal']['AutoAssignTeamScript'].Script.lua | 31 - ...'Define']['ConfigModule'].ModuleScript.lua | 18 - ...['Define']['ConstModule'].ModuleScript.lua | 17 - ...'Define']['EventsModule'].ModuleScript.lua | 14 - ...ine']['GlobalDataModule'].ModuleScript.lua | 9 - ...ork']['ClientBaseModule'].ModuleScript.lua | 18 - ...['ClientHeartbeatModule'].ModuleScript.lua | 169 --- ...amework']['ClientModule'].ModuleScript.lua | 151 --- ...['FrameworkConfigModule'].ModuleScript.lua | 42 - ...ork']['ServerBaseModule'].ModuleScript.lua | 18 - ...['ServerHeartbeatModule'].ModuleScript.lua | 180 --- ...amework']['ServerModule'].ModuleScript.lua | 154 --- ...['Global']['LuaFunctionScript'].Script.lua | 968 --------------- ...e']['LanguageUtilModule'].ModuleScript.lua | 32 - ...']['PlayerControlModule'].ModuleScript.lua | 182 --- ...'PlayerGuiDefaultModule'].ModuleScript.lua | 92 -- ...['SceneMeshEditorModule'].ModuleScript.lua | 29 - ...Global']['ModuleRequireScript'].Script.lua | 40 - ...de']['GuideSystemModule'].ModuleScript.lua | 47 - ...tility']['CamUtilModule'].ModuleScript.lua | 41 - ...y']['CloudLogUtilModule'].ModuleScript.lua | 24 - ...tility']['CsvUtilModule'].ModuleScript.lua | 244 ---- ...lity']['EventUtilModule'].ModuleScript.lua | 53 - ...ity']['GlobalFuncModule'].ModuleScript.lua | 26 - ...ity']['LinkedListModule'].ModuleScript.lua | 444 ------- ...tility']['LogUtilModule'].ModuleScript.lua | 45 - ...ty']['LuaJsonUtilModule'].ModuleScript.lua | 1042 ----------------- ...ity']['ModuleUtilModule'].ModuleScript.lua | 68 -- ...tility']['NetUtilModule'].ModuleScript.lua | 123 -- ...ty']['ObjPoolUtilModule'].ModuleScript.lua | 65 - ...lity']['SoundUtilModule'].ModuleScript.lua | 65 - ...ility']['TimeUtilModule'].ModuleScript.lua | 149 --- ...['TweenControllerModule'].ModuleScript.lua | 38 - ...['Utility']['UuidModule'].ModuleScript.lua | 229 ---- ...['ValueChangeUtilModule'].ModuleScript.lua | 137 --- ...tility']['XlsUtilModule'].ModuleScript.lua | 162 --- ...ls']['Example1XlsModule'].ModuleScript.lua | 110 -- ...ls']['Example2XlsModule'].ModuleScript.lua | 83 -- ...'GlobalSettingXlsModule'].ModuleScript.lua | 31 - ...['LanguagePackXlsModule'].ModuleScript.lua | 81 -- ...['Xls']['SoundXlsModule'].ModuleScript.lua | 21 - ...]['S_Code']['ServerMainScript'].Script.lua | 5 - xls/ExampleTable1.xls | 3 - xls/ExampleTable1.xlsx | 3 - xls/GlobalSetting.xls | 3 - xls/LanguagePack.xls | 3 - xls/Sound.xls | 3 - 50 files changed, 5536 deletions(-) delete mode 100644 Smap/avatar-ava.smap delete mode 100644 code/['Archetypes']['GuideArchetype']['ClickGuide']['GuideEffectScript'].Script.lua delete mode 100644 code/['Archetypes']['Player']['Local']['C_Code']['ClientMainScript'].Script.lua delete mode 100644 code/['World']['Global']['AutoAssignTeamScript'].Script.lua delete mode 100644 code/['World']['Global']['Define']['ConfigModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Define']['EventsModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['LuaFunctionScript'].Script.lua delete mode 100644 code/['World']['Global']['Module']['C_Module']['LanguageUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Module']['C_Module']['PlayerControlModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['ModuleRequireScript'].Script.lua delete mode 100644 code/['World']['Global']['Plugin']['FUNC_Guide']['GuideSystemModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['CamUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['CsvUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['EventUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['LinkedListModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['LuaJsonUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['TweenControllerModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['UuidModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['ValueChangeUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Utility']['XlsUtilModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua delete mode 100644 code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua delete mode 100644 code/['World']['S_Code']['ServerMainScript'].Script.lua delete mode 100644 xls/ExampleTable1.xls delete mode 100644 xls/ExampleTable1.xlsx delete mode 100644 xls/GlobalSetting.xls delete mode 100644 xls/LanguagePack.xls delete mode 100644 xls/Sound.xls diff --git a/Smap/avatar-ava.smap b/Smap/avatar-ava.smap deleted file mode 100644 index 6de308a17405157aa2df3240bc7aade6137562a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67356 zcmV(x*sMwv&l%+qP}nwr$%s_djp#ZBMVNPkrgCey@=wSuuY)D8ta) zvUF5sY;o8SY3B;)fdvqwf(ao52#(}YIZ#`Y5Kbw^@5L;dLyp;H05BO+5>ahO0Y{oC zzIwjuyK$QC$&(2}4yHR@gk~?jxd_#EB~99Grer5o%0K!F6R?x93lfDop~*YikhC<9 zL|k{7f=#Nf2ji)#%(Pl&Q;i_g4)>So_tlcudkN=N4Dl({NHjE5Fn`LGr_B9R#(;-SS%#dtTHF{8kELG|0Vt#zy z=-OP(`jYKH0N5p4)HP|25J4{(=`0UP1muO1%Ww}#IK{wkFqRXB6I&PB^}(KrrIK_h zx);MPgIe!NceNumxb9Y46fHG7?Pv!YTiCPah1sR>jSKPj zbk~xym#qY)!0}L-4&de*&>@rwsyTFH?UxHdJd(ZX{s{JIrRj6#npliNR`68}2nne&?p;i~#OEJ1OEVg&ewc z;jD?Z7gAHo>ypvHj=LT@uQDj|XCv~#j=LJVCAh35IM|();EtKR8m6^Hj%ujE!wx$| zjEl7pXRE=EMT710x*I2TS5EHlatY=0DQBvO^K2CVq4gFG+b7njC;n->>0&(_TD z-D%z{)6&j$u`RorC_U)auzwezG=G-w@Ac)dU+fyCTd?exn9Q!o-jgtV5@YH`Hv&x1 z?i}MsapE!;0G=xBN(l@9Ts_lYh73ptCUI|n!~m!2mm&Z@8y!P9lJ?{!|02;h_yhW= z!A{fnicEy`35+4kl8) zoJlZ;_c}A>Ez`P7d#7%xuR#63f3dkd+ z<{wNpCi`4B9bWd(LlMH)gidbU4bk}d1suE)WZQaMt*qM=?S6!y(ZcModnbR^J?W=R zdxO!3A_VER45Y+er>?dWZ#w}AWjpV@5$|yA;2Ms8Ynr-Rs>}yATutH6u-{?;pWS1c zr-HV%{dpTMg+FYkqM2Vze8NwB_|doa~h3wusZXGO-nH; zKzJ9`SnK}FYWtvV43F(7JyN|AhOgv_e%431E1Yfw07&dQf4wF$aF6p)%)?)e0HYuu ztDFQbB4Xo$;8A9U5rt^u3iXDWm(dH&i{!d+C`BOrpMaW%9gC({@)tg<`|+QXIk27- zV7IL6ZV2w>+fP29kZv}KP-9bLGn2`bD&>Lx@to19sD!`q@}{Pu4dWLi)Pj@=3Sr8k zqQXPJ&QY!jOTVw~ukYMFu@JGZ-VYu;wVxfetB*Z5mw2m}Zbtrfbp(izcmDqUL!cMv zEAbDbGM4%GXf*D0(IIzscKmMiz(gb5RCh>-kU?~N(Sm|16V1ZxF!uxWHj7{UIh6#W{>23ZDy9SD|5=_@nKn;b%$)bD^@w&3K}%`wf$EYRS6Aw?@=7u_s>y|=py%@4=>J3`>> z%OLNrn-$nmEhIbY+hirP-V1(kdz$&bIviseoz~)$L?@ zr}j=Oh=B5C!NS^1fSHZuI3EhVaraJ>(m60bFtyW5$ZeZo6j$Mt61&O2<|L4!qsacH z?isKEc^+!S@{;z}xF$3Sf?N8KJWu)uLjhm*5}|ZnH(rhd-OxSo{&w%BxaLY<_;;Z` zD?~FB7i~Pe&{hpxd&v9#tmjVRN=uHqA7KpV!d6u_w8&lXS#xGt4~^v0Zn4}TOP|U^ zQ^gBd`da8JkHA6^`r7lMYy6c)X*)09)5nju{;<*e{?DPFHp*s2!(jp}KK}4^U0!t!hwp2-C+lIW1(z!RoL= zZ}|R=?tFR_>H{t0xWz%T>Fp8};#-mB3Em9;p*I|-Gd{GlITTG-s=5kTaSx+pDY}77 z9iUiH%JIs{<8e%#4aZ%c*KfY79uj&+XhwR(9(!Q}s^yBFH9A>R`^xhdaK4~h2{}7h zd8lSuufa1{*j>v4%b!>&2HL0X-}~`-FxU<>Igqzs5g2P8avl~H1r#nEo3`?7hJelK z5xlwTLhmdo%qJ!yFBZazUDlY;fzi61dD*cMakN;SS0}R|YwDBrnL~VQgeR(F!I@MG zO6(1J&mxsoWW*C$)Jumr7Ky5+d8w!cQZyK%m=#^gRZ9-9WB=8L+$Gpx|A5ctRJP7c z)8V!UGE4T(Pbih3VGIESGp>T{bq)q=S<6q1#?o^~1J0=OP{uCu=QiC>FXW?j2Vts0 zOjLne0sdQCCrg1e3I~e|On7DOAHrdM#AYOo?0-eGY~};=D@ubgkLbCYWXzK=k{WiP z%R6|aY+nTGm8j`c1Q5Oe#Yw&Ot@-4~qkN>S;5~PP@)B8x+sCIIyoilJHE4tC4!GPL zxm|8A#o>utoUpk5t2s)pQ!~RtPyt2-%3wG!n-U{6n9OQD@rn?(ki}%`85+O^3s;E_ zkE+JP&zF|~yeZhQJ&u4wBjXKu>T;!qjbb;uc6GeW;P*T`;;K_FPC_JctcwfYl(&x} zob2JL6s;Nmpb5YXFnA~;gV8Tv<5z`W|K*^ZghiM7@HPh{88CH*jeBITbDV~8j!T86 z?E26lE=Wo&-N@o0tnH)`CT7Y(ovX=s*okc~_Wab`ziExwc3r7f%G1m#)!|K?yxO!T>wpvD8uP-b zoZ|1Pq`W)Vxw4CKxY5T!;Gp!aP>s10l;mOdi)>zIRqpu{9=+Qg)!kub#KXuOQ|%Y+ zUn*_cRdaSW9Vjh^XBlHCY1A|`JFlDt%swunC)V^Y(JbrP)yNfhQVMoL-<9u4KKD8CEK z7^hZ^yjSF?%I_;=HONneV->31JY#%{4UP7n{B?hoOGh1hk!H&m?U5{tZ1ZT}47rms ztCq^<{N9Bo#?)?5S^l=&o_iX>XnUxCaJ1fT%fW=>C1$+`jPm6bOYU=fJ4rTpr|i)v z?U9zMj)reQwCx@MwELT4r*esne0(drrit$>0DL#A6^L{NSQ&wU=YYom%?WtC%51&m zCJZkNSDRl*#h+s?@7I7%P#boqitU;cwT5ju3AMT-6&~1UZ;2lh;9fBee0k@Uj4zqw ziRW75h!0IT)*;c8h>xhxF+|56wg@W8<`sdG~fUNG_rNV zhSAlDl@ItJ~Kf8d$(TfeFyw${)?^PT6UVWdrS^y&cXmOOsMm#%w6xK zEmQcsabv&kKj+(oK`GlMuJ!GvIu?JUy)2Af9Md4E%6vW4-s<`Gn^szC% zwfqKpX$KXf56s9zNi#dC&?+Kl2MkWRJ8HRg(1l)b06l+rh%89=wesWe@)nwZdv` zE!^d`=-WrQI@pUY!YOA4sN${KVI46}l8VW!6Mc`~b;6ddo)#pPxuXmL!D82k;h(%! zln0^EO%EeaA<-Zj!MDp2@&DRU2CyST#fh<}S#qCw5{4cQV9CrF(|KdkDeBe`HPmox zTkMS#m)+`PQzutfYq~?Vp21&mvl!IMVM#40pxQ+oo4=R6Bx^GwnCBBHXf1`yL>`Ns}o+=khMa=dgnGW z9CyPQ>Z!LoL1!o->Xq8om_LL^%6+ncQEIwQYlMDN07(dC8y+maY?sYdnOwvC1<*?VBC1mt+PU`ow|gN99J zFJDg^oFuEYvbH+2;;@1*xcvX7Q-JpR?lke0(F~oLAOz zbQ#YY;oU;ZBV~swH_R3> zi;o5G8cYenwSEtv&j_dvsOEZ2=Qk|d_M)w;EYZB;4taveiE(d5|MF0#sbS; zOL;>X;lsiAdXBG9Ig9;>jhYH-fw}r7(^b&=-iH5v}q$&;JIRyB0Re z*ZDl|+I_O@)ms~SS_8~J&#gLvv%WmTnHI9pw+kzdUIRs<6elg=FLHU`D6RsnD|C0P zWN92BJ26nuFWQ8Fee649C6yx&%IXq$YxbFr-aX7}N_E!aGH#t~oP!EZQ9HP!0cC{$GId7R-Z|SsG;X<)RyjIRF z(+jM;_oae8v5gjp8E{V%#Y3iy`zcQ6x}~_A4Gc{de!R(Eam4{$+gzN>4lDwuF?7?%6CK{O z&$na0;+k{wSX{e;m8J?ZOwQv!cVghu<7OsEQ{)6m>n(>Y%(U%b(kv;GaO|mYDitF2 zz7gIh>(>c#XgVOu)u|~jP%w_X;xR*(#a0=fy(61Xb*n^|eZ7RKCMi(aJh|k}l@AM% zYprbB>EKx^L%L;?rGws1MYkqKe0ajf1iF;ug8$`oA6l964UA;J65L(YpBVLLknW6h z>{m9VSKT7R*kWdCPmFtc1tjce%k9sB!FnGYc-u+tceqVIg>V%Ac|B6S@t5q1^rx>z z&V|XxJ9ro{S!Raid?t-EL3aGv7?cnQ3|!Xk;QYuVX;4@T^lXjgK2(&AJ5*F{&K=D2 z5dS{QSNBbc_<_=c*UJ|Y;%E)*0*3_SN^kexuovwW^_WxWzHw7{a7S?uUBzQJ}L}jzdvnzRLc$^%4D9s8#Y^64D#aiCdlEnhlTL40MB9SE9WP_d8PH zeRMcJ2*2<#EtyuDqN$ED{UXzkklKyl1j(nVPn2WWR#lgPIK<`Lj~v&o=kA^_&N0-| z2M8n1%H!$?lv;W_Jb0j$i$Har1xR}xvZw}U3ym5au^-=kUKs>%E0d#iW$t7Z9IAD! zV5rQ@xxl74JX)$pv|+{$iVGB|V<8S>yeVqNa;vhZU5~LGyW2DCjPGk(rwu5&Vv43Z zrs34lkEfHUR>rBx!$I~0#PMfZr7KHO~y&;_;}LH1%D-=C#KJ8Lu_z zci1&@9AnAz-eMW!bk(C)NA4<>*rFOyPEMRD%X{=i@@M^A%P_2l#t?xUZ{6hNzbvMa zhj$C)(vf616Yr!>&vE{dPZMOgX+<%1R0`0wLmH({`!)tFTe#mQyttLMJix6e-Vg^D zm#^{SpdMnn6pr#?y|J8`8qy8T%tL~lAD~&er~9n-I_%0; z+ULMc+geTBewBQI_CD||`>QZI$D=twc-;|Pz7NLVCBalZo}WfM4>A|!A}L3hobckf zqv;o7?uBynqKb+fJE`&k*1w*=n%lnbA3i@3kMk|GM~ni}s+2zYP;;C$_a;3Ug+im) ziGP=~*@HR=2m6z~2>Erd4v!r|#_ur`=N6Zx05xWHmX68w9HU2I*Zd~ZRb4*VTWXng0$UbGp$)r&RG z!Gi%ClAbkGiT5)ttsI8Rgk+LSsm7E9NULs6SDi&Idkc63L-F#lN`f5w;8@jsAzpW* zccLiSUXGZJ&6r#3(btwk&&~Vp>$e>jFI%pj*1x;|NBra3dPqWF@%-dbFYY@jL5c_Q ztPoT6nGXT&D_*-g6WEWcj|i#La`ZS<Om@G+6^h+EopQ-E5u-b;I5BK50#ITKCPtZy+Y zs&bHG4s3)>uL~Wz%4d-3H5NY8&r@-fc}8AvacgpMH!V?gVX}_MBiiBhoAM;gYx^ec zMh`(JYzh^M*rG8=7<@`w!~^2o9+F>uUaGejKA#=9nINNpErDKt)f^k99w7#?**Sd} ze~7%$UBWHWE-~*i#pa(PBun0=%rR_DXbzln?`&1+aW%(Z4%AJ*W+W5@Va(hR3cS}x zBrV4|c4c5C$PCbk$My&dVFUY+5;%oAXHJ8A#Q7nOQr*`2*tRVzk`%ywMPzZROI{dK z<~j^uf)QN||A_J>Vt6chyxpl6@8ls~tv0_yxgd%Nf+1O?#<0<^Jby{wf~x)vp3Q>C z4lM~qD^)W}mIOONR&9UqXHBHsE@n`|rYLGB`cQ@0QTu=xT19W#jeUZ}LC`U8f}MXd z8_yU*LxuXdf_&o0Z1t?3DE)%1ngo%~^W$oG5@^XMY58zrsdP3=oIY8tCqTCT$s+dC z6r&ZN)i76)j=S%ih&z?=xlL#7OgbMs6{pmmS(tP|^g3SxovEaOyjLzpPF6tFU|)?h zw#93r{_)!Y1FXZA?semYZhHUprgQ=>y>x7vau}bQ8_|uy!nf>^K*5{He&8~yNJvdf zfvOB$d7@ZU2EL2Jz!$N%R^>=X79-Ko^-N~QWcb+8wdJDwOC2S5Rf=!Lg<#5^23BQ% zV@G~}=RweAr7f=VCILQIw1JY(`U>vy@~sZN(FSL>;B>fli@GASC|kzurlp%V_g#YB zwOo20J_7%rBNBZEijsyCYQ&R!F}chivm4G8rWq&M9ry53BEGyv6>lIuUk5)1jK{xE zkY^~(e!h*S4*^u7c+9msExoIPb(ei=1#~sFE%vWFYl=9zmBp+auV>b^r)+{tG|=v5 z!i?wxUqjY=mF3IjmWNo`dpY)5KWtd43>FDy@Jr1haP7D-ZeYlv#bw^C%=4{GQK?LmO&{DYu_)YxZ{&4z!IEN42S(|C#&5*TlGm7L>ij0tX0TC*x4XB~o%IM7sqRV~Vp7Js@3KhoS1ws^ zE&#Xk`rur8=1SDn75y;s<>t@9dTcv$|wYB z3VM?2<0hAeRovdx`%u39N1ZlQa~31VJ0c7MaK7ePMX*1V^)>7Yt@cH11=*7VEQOBp z+D<1vSR}X}2j#Vv7Qk>?@v-VYo*1^yZ}mrQcRpbg2g@H3K?;RGF1mE|SM!oRN@bk7 zOV-K*Mim+uYA1BfBKLH#C$c_W47C|`4mHcV_`#Q~s?Lq`9qE|UNo4>qgcyt?QzuC? z24k=+8gv;3%I}RBI1n6dXUoN@7x9?UvrYr+fiypo+XGG1w&axbRiIm6m!-1aKsF3$ zCBSt)XDZO&e4I39IDeE~Qje%Gb0d7Dj)Kj%b)o`mg~B_cVTf6$=~P9w`V2+Jwy0mF~*iwUJ234 z&?!l~5$%!ND!;!6HSD=I%=j_`x;>KAyk2sw8oA~i7F{|bV@1CfZ;yeadGWQ(4xYUi z=sS(Gr5bx_9do2I>Cf}4_kKLxaWP0}K0clX;h{v4aDeA z>iS7r8}lNmaQOp0y@N!xM~6eA^Br7X27;YczmFT|t!x)dJD=M}`L0AM=4ro?yF?t^83 zpf{XTD&a!ZVwG>uc}DGSUCidgocl~GHlZR?k`edCwrG?=Z#zy2fBcRU^O;9%vaNk; zu4YLM8H2a$t1^GtX8(KHAbpRf)_qZSSW7?*-p;16ob$^6ti6AgU>3-SCkRzx{QDRG>G` z*B7yjLyORgI%uPKW%TJVol>@mBWuO>DtvP&HrJ(oz;({>y`|WdxH0a%fcB&(;;?xP z3#IZwZqcpFt2XRH{-aOvNl_|CWUIF zTAwDmIq3SMwADprNcg|}xGfAP zH8b-J*M{2c)fB38zJFL1^>RWy)&}z2P$H zGm?*od5z<19OT>}jLi@hu<%c3aJGb_22}glURkuzm@_&(v@W(L?3tx_Fv~hC`uyeS z&fTGWdpu<_7v4K?6nBqo$*Qf4M5-dwuG`z#Hl6?-32Qcu9uXG=Wcpr;c)&*?;LEouFIhiJR>G z{}#`fzXmW9C12(r8==T<7nnJNDiFb}nXua&2r)Yp)b3oAx4-IK zG!;|$MM1)5$@$!|vi^D2*L+}A87h+LE;c#YTtn*)7p6i%B4S6AIdUf`x18EGWUu8&4- zpZ|*ex4!dnBWGUqpaGXhB4bF)&ZH%q@whKSsQS1CjHZI%gw@Gq+7VD+_)xI34F$pJ zL&O|5uPr8U9bJmSw>+_kl<)b2p49z!WDAA2{D2tMg!+I&RbtVaMcF`1C>@9db>LD-5z6s;z^Ns2Uk|I{?TTyDmVSBdUoY+D#1t&PP} z{vy}jqNd(MW_B2B#sce$@t@kYmYE&u`7fWXCQ~@~w(p6zE=R)XM>Budoi^E4w23Z-lT<b|UPi!ZWLJ0 z!V+PkYGHP14Br4Lp%L(}4LoyGV|1z3I#Z{f{!#@?| zvW5tS(8bvq(n|!G-I$VssRG`7QGB8Guw@!Hg2k}U5&Nt_dt>HH5TAaO{d=48Pm0ii znU*-j;o%Ev7l;t0_Z=50+LWGT%lq$;l~!(BMTfn^Y;qZ6tK6VdN@8BwZab(~=b;LB z+~Q7qp4fiMlSJsJ=lY8BQ#IQ>szJd3wCqYj&TZiK!KVn(%%Yd*WCXV$og}$V0=hF& znic=$F3DEZD)v)Tjb-X)z`lF;7P!M?tI!VZ`eLp~Bu%BF*sTpv^v0CKIB$z`ZfMWi zD?FVMV}hy4)91G5u-u}h##4m>!j_>|HnD~ylH7fP_+TDj zc#dqQ>n#GruhhGqTpRZ2sG&LruBEa`Z$XBP0G%!LxiR??t3LrvLU@=~|zISC8-Q0g$Gf<{!E6CsbA++L5*nuRbh^ zTE3uPQKqKamjc%@&wJ5$gt{fVGaKj`j+4=02^uE{-+*P?2cX~EJQX2v2Z4x!u(ZO( z22rSfI#+WKHJAZm_aT!_NBo&`hpr&JK%q=wOZpts=Kk$NHxA>Fcul@?*@HpL^Ov3D zej&*=ue{wjCg(~>#=*WlR>oq91u7w;lQY?J%NVAJZE<1&wVW#6z4QB77Qh?X>8f=P`Q)2ruHk z`Q1qJJg&&iDf&YQ3ZK&VL|aZKh!`Jk>u~2Q69+BJoW3Mog8{@KxKhFix*2?3%it)W zKwf~EmV(7K=r#rQ8_;*uOJaWT-@<4V?UVFCVFks|o8enc@RQqpjDpL-|U@QPQ;A{uy=orwSP z1vcAgC_U?2_jL1I+)P30HH?C6^W{y&5j{X@H#>`vME8C1O2Fhy~m#4Fjz@x2oV%v6N8%ln4nm?O`E;J%~1O9>$xO0U5X zfD2(s9i>c8&DVLu%V7E@F6UZz=r7kn!|+ZJh@*f*I5^F{iSdPywswTf@&gC=Jelrg!$`a;H4B!|StdgSZ;RkNR? z#oajP}QFvxI1Z`$nJOk<*-HQB*#}Wv;8gQ4SeNknp8} zyl`MR#D-5dOr|^)v!UtCHuWztsem$UG+=8D5}uXLi`_!bJTlvyEErZh68eGte*%@} zr&Bz1S~_AD&*w~$Kyz7>>^*azz)wN8=8WB%{8_H|!i?lYegCu*SX~M>#fi4C!PS&V&m6OiK)nc+;=V$`Ds4dE6aeEyRo0giuqE{lI3NDuhEOb< zriRqT$SB%dQt@1XoHg_HQIkYiWQ4b&=)Stu2YeW4ufh^G`{L2k#s5^GdrGOjvEE*3 zxdAo`U-MEGEk*7$#e#>-$P%tUM@wHNbi>e_rE&u1D~r6`GMN(D<>P^Bl3?>6g`i!9 z8>=elaPuu5gpo68$!q!jsjLV%7_<(5tx@;6I9tLLOJ1SdR$1$n4lW2FTn#$eBbbnv z$R{W2)Z9A!s}85Z&t(M;U?#kb2~xW${<~(ucCUj(+n%qbraE|PoDysJ0-@C4{#F%` za)#~y%*fiW@}~;&xe%2@qsM^k@h(Af1w4*{EGI|f_n8$%zn)gkRU^JR;ZA1Tk+{Fj zDn^k(m!hQEn}~&VO*JQwVof=YK9r-&xF6o(kGhPQkl7&)R2{j37|tR{Bov+|tBPh! z#A%Kk9A}@Y)4Stz7rPIKFHqe=4+-n_cO6iZWUu6om-rx9Lxc(ywywku)ieW1n{V>Z zwN7_sV*aS%Fk#wCMt3w+G-w*jP`*Hd6Ox%Zz%|4t{L9xXSF9qh@k*7aKmK37sK z192GSTa8l)XWSt;4#{+UMZHdpsA}r*37-rDFWz*!EK4{0=Ji&ZscFiVIWg_MF1!udTRo(+Gd>tk&;w<|OO-T^^4gPKEvEpEm5=R`I3 zOG^pE+yU<;+0Hz#>ju<(p&fbmgTiFu+n`umutxAfN0p%$97(%j)@|v}MPd@J{FXi6 zpl}?-@s3&6XN-8x4~hLOFDoLCTeFP{t^ivxOWeZ`B97p0}A!Zq4ipu97Dx7H$QCVpW z9g3D8IYYPj{2TL6n`JIqZH?+NB2uMK5TJ%#}>bb^t@-8yX{5&qEYqH!SN;+7& z9iv>t&j67H(G{g=Hfg!mvXgu|4^KdOxS5D;7S&!1z=*H?n6Nx%$)obL0E=(SXLF# z4LVc{Rz$Uw^#RuzD;)jf^;)#E_h==v^*FoZ!K$!TF|JZ$ zWpS2>=@UBz{KcRtm#{3UA-dBphV^v(C-*iuT<^jQwZt4bi|qy`pYzMFm`~unUBWf; zakJKd!geZvG3cFf5Lg+_$Dlrl1n~0MwKmDxq6rX;ZIjhf{ zW;@khI`H73DE8&b+eA6>%xo6F(N|<>S}M(C?8Tm#i5sf)io;BaG8jHi&VCN>8q#Y8 z7x*d5aciBS7d0Dv_Nf_gWBpynvjizZHVe*ba}Q2Az4vU+G{d#N>qOXPT>f&v!4I(7 z5p;3*NYG6fs#{bol^5>%M07=evv!2T>X2`at(h+#;Z6*jk5c&dUZdoNn4Y-Wc9*Jw z=Ut$;*>Ml&(-D(!PuVgiBK91MgC)NMi?Z?oxsD+u(s19RCx;tR-B@L|{ob@4nrh99 z<;))hWr~@zYQGi3?bpGGF2I~IHyScA?Ez~QfnI@Y=rK%pcdqH2{*}%TJn*qxQ$klI z@A^II%598l1AlKVlVf1cyGT6c;y^f}XLwZ?8tSSM;nO~8SMTct$}@@nz27RWmbjd$ z+Cv;RWEoCq-pd#FnUH*hXk@wj^*2#HgyW#~Y7X%kGlVAj(5s_e9)aFf8R=+u$>_|`h8WyE#4 zsKz?E0;xy&ptFDB_o(9-HG)nUipgr5Gu{t4$bODI>C1S~nho>wPBpHPY-(!3+CT!+ zt5MVrEc-txi+aQT^K4*XhbW0BjGG9eHRMMu`DOoM-UiV{`vY`Y;!=Ym9q-|766IkY zhGS`(<5SS~?k*!k=I`1sKnooX29?YyW%5qd=gPJgEH*WBn1@sD;fo`Msf}%arHDbk zG_^jQpGh3BPIFNcdJ9HVsnZ!&4UHf^aO?1C_Rw%-geny}PaE@vlS=W6+oA<1Y9=nbY*`|eWN4(?m5C8oH8%EAP}~`!rO+f@b!BvW;E7r^{7W1R2>5zy=38 zn-f#kUGI1jdS%m8Kaw0}`m3O=#L6GZr*Y@73bZ<+i3d}$&0eM>-8NBocoaAZ<&wI8 z9r`P*E&d?T9H}RmTO=}nXg-BaZGSJzS9y&6 zOzjuGopwPeJ2sARj6$5EK~#+@MN^}6e^2SW#f+63r<;m{ts6LR+hKT_kS+drHFZkA zTlq`NtqoHze?^*nZ!5>ic}(fFkJW6-VpxdTx~D6K&8R zI^5n_F>;=}knN|S^U{#8cB?;yR9qm}g^uMu^u z9t(tkjYc3(8%T7lLJO82t|A9WTZ`A2N}siNS1*&hdx6KGyJ~9hJRj=@dQoQM5VD(K zo!~K$l?<21m>^N`ZT+^9kRQE?Cs~qnD3g=>bA16kbcBV?*Y85^1%s*N5h6SX$QD4m z^ixFr$~|YGe6FKYN7^g-UNKstRkrs^@ z*}a?j@i?bbOmZBt*gi_}eD8|XyDghA&zR0jttD?=L74D=%fKs3(9ti@j=sDabWIV{ zH!lOO88!LYSLX2BabF8O(Ihb)B5voUN^Z9GBzGqbZjb9;9o9TKuDWqwbm2V#q1~y2 zJO97<(>HOD%zs`!&Y!SJodEJLI%J3l5MiIbg=`nKHL2(R$i2a+LyRV!H#a5-F^c&n z0t$Q>=*R##NTeq{(SA$Gh>J~#ofwKE3`S5s%mC6q1G7mAsxeQbIoH_)ge;=j*OhG( ziX)Io+>6x@_}_S5&gu**u64OV`t&#)X83>PKGm_0Y#%W-=bJyYF5H-Z4&|ch_xXVu ze9Z9qG7oRzJ#oYGZK%`U8t0`ws_+{Pm&w`lQ84m4d1hgA+Sj zh_}$)cV^~AA%T&}{^SdY7KOBPEewECLbwJ@4#-R)S*jD_VH*qO(6ipe5vN$zw1_Q5X%wv!(N(nCv?oK2c*udL=EA*Rv(sV{YqRgXP zz_ST>Ln`Gj+!EK|+I&Pe#X+}e<_DGvfeiv%zd`2vflQRI-mI??MKQ4a2>gpkNkhqa zXX_IrVNRc>TGt-9bbO*b(n%jtCGdF-s?W&xNem^8yN3&|aVmmhaAF1L`t?eY`q@gc z+C<+-pIp!6yc>}Cw^W2L;9#Sa5nebsO3?e-6%JAu1*RzaM@JIlt&5;Ev~iuUKwQJI zjd*JaYCEYqu`s*&86ny*OF%7gNz7LgCb2I65?9nheQ+BoMpM?VwAwqy1V~&$0*m3f z7|ZP@k&aUo#ulNL_wTJ)6bKU8JWxeO4Nven9co*(XD8>D$OdfND={WC_}rsqZ%Do` z7>swT?(__p!J|_25eviqt)XN~-{^a;S2JeU%;g60zxK@xtKvRfn9vt7w)^-d5~0?$$irW}^mnKIRWk(15&GVPwXXqSVUVXN-Q&Rd5Wbj9j zKoMsv+BiryA!{)%GZMsCSbs}`AFPMFJK*1I_(%WY*1=N0I(-AvRt;~AEQDy7^8RY1 zT?Japws5ouwYYuxO(U4wmm0~64>L0`X`X6jdBsz9KQU$Jj5UjpJg z2*!Z_@C3mqw(VE*q<5*z;Z%yZlc)37CYYXuJBFV<|F{nrr`3M~vM8TsYXvN3tLSJI zbC(YDmoBZ3E^Uu4ZH{hjUWa~Phdy4FAD^C93zR?ekZS)gOT`<|B_ zVH+mob@ARqbB0?T^c`O`g*u4RgUh1ppWfFc@V4nUy@JdYwd!?#@Gn&mQGd&R=RI&c zls2p{zaW$G(}n;vO`fP$65r41PkOD=Lp{!Z3~t%3P-`~lza`|E)F+W@Gm z04N)2CO)H$1?XL~e7!y|oX4rzx{9w?4RbT6&qWFl6ygI68mnQK%GT`Q>NOYi7Q+A> zrhBrI;|QP?)7`)4s|33?1iv$dwf&OGS6E4KP=rGi+I6m0kGeFfA=u-pR#M3xlrqFZY_nd`mp?T zikAUIV;gWV@0Md^h5pb_C zsBbvrw_jF6W25NWjd5mGcICY*+b+`nCuze7>n^%5nt{KQi?9`bhq?G7yp4sGwOPaX z5yG=EE^QV~+{xxDmt{`)55Euj3w}1FCC=W>OuZq*-KT{S$k(vNA-R+HR&*da8&L|r z8#Fh_4{Qzuz^^wTwVzraAJSvX3b(F~pxBz$Y9;G?ROWRBL4mCTw_84tp50KRPtQ!tmGLd^*xm+Il^D^ zHd1*s^=kztq$g@s!QUV>m=!Y?5FqMeVw|cd5G(UPR#SKxWj}%^#6P+9$So%M|C-&isE+XyNYEgj^?zMh$n0KR z__7Doe0!_bR5u35kbf$u414(1Y;rTuRWcu_RcU{ss9v0@lcJjU;xYw5sMXXvykf=} zJY6zVA z4-iTZe>q6nIM{^mh~(0)8L34!8u0HpJn#7+w{UxH?PZpo>Khuhg1PG5kETu3F`ut4 zY{`^A8}nj?v%8roc&)p3^qlA_L%aY!YbMBK?V-z=&S=LUE|~_JJ`m*ZW{9YtRF5Qx z@TIRKt=(&1zjQRRC;KL!oI{KgS%B>9#q~2#DBth^sD!+bayJ^O|^LwHz zH`s^*{dTP@^Fx`Q${k||u1k`>#-C+wi-%reQWXAUfCMOiBuP46(>OlI?ix8Ue0+~DRkul}WBXhG<)3ceu56Kh}OAZLhb@eSQ z9XE|U8)<_M(sr#`wn{?8ENn;>g36j>xAx-H8#YUZtC6O02_Zw!W<*>?yb#;&9S%E? z;T?xgOgh3q)n=AJ9UWcGjjAe@Jn+_?buhsNO*lkNsOlTM~ zj=vfnhU~`$mhg-=ylZpq_doWemLCqB7~EOZ8|@_7w6azH&b3qeKYzP(gaZt6aW6D2 z9{Qm)u@Y1_50-GS*ua^rz;xDpf&T`&R!1%IQfQp0c%rk!;~g@{>|-{n!QOI4H&xSp z?mBHAvE!QT@Mr_$|i!@=JQX6&5=H7N2f=%jE@cSub z0$%kYRJOOs2KC(T?dbV_t>v8Hsh%jkSDO!Cax0wJo19DrsdE~YuerPXKtFfjojmM4 zz)=Zs5Hu%byyaoUz`z)g)F1EcYnaRO8AvWK9P1&`n3w2Rfw}_{g>Em26k1*fneF?x z;&o=6*S0o6@W~e-LVdJtM7-#pX0X1a|mXla_=!Jaz#=6mamR!@%Q*PZ$M z+BbvO&W!+>+1_5|hhPw2bo--Wg7<}zNeN~|Y4TA0eh3jK!Zn>@k^H`Wp|p^XIQ8uU z0ot@CBzyUd<*j^0NOer@gY}HV^^R+BLn$NeyTz+a=ba_e>q})BJ$+taP0~Mir8y+P zlpnQm5oLh#)bA*gAft;2!&fiS$xfJ@qCXkQg*m<%AvjKHFEbLNsE@U=5vM=>5kRgN znv`pOQ~sWnk1L=U{-sVr9iAVN;*IW+i?JX31n*`hNw_e2o#DUAu;b-7sN?IO3XFY7 zu$<&GJI#vwPRdi|DUpvkD|ZI|Dj%kAyNf_S1y6AGWQ&8I#G)s9LQM1-5Q{Vk%Ew`*A=7zai3}!vfl>ngj>hkZ?t%Tt-ithAqrHu@g+Lo(P`u=aPe&48aD@2wzMLc;8p=7i|#7+X)hB2;aJD=D*b zItx~{21;qAa*y*$2z~J**0ZszYqu+d2(!P|BR?%GSO06ta<}|@hL&4*B362ng63#E zwfIiQirtGCav$CI1&YG>Pj}==croU?Ve#uoq{IOKjceBL-_SL9#R{i&s28~kyi@>> z#nP`@alXIDkHo?Br(~Q7WuRq*?4He9iG_{DMh@E`j%kUI^%EX0JE2;(R?)_k$yhfLrbFjFQ3L|_k68{^&?P^XbGep7$h9QKQr zQ}+#!K(ir_2X%`IcnaZt>1A5=m`wgck@ssk9`|iI9G}Iw5IZqS5?xo1jIPGuF(33V z`>?>OhpPQ@TBlIve9@!ovhz50Tk;mS^_fWk%KBP*&3x(o-D`?-r=bh3=dZmj(B^rR z8=5ln(vbdqzlL15!e$G4d9`z~h5XgGrla#YVNYe9r*!GkMsv{M1qRLFAOJJuiPN;CaLDSJI&wFB3xiZl?W85m(7Jw?%4fk*m;qpDxaJbqz&F;{cv;Be(Ms9yIk>-bn_0V7AQfEs zR-2*vG>}L&)N*|rbGbHv`&c+_s4*HaYWYD6!Yi2Q_%wJ<_&*Cf;;KmDmT{yJ_AHBF zb#r)^7=CC7s6IQRg7$y53Jgu~2+2a}aqt&F9}SWwW1~P^_jycgk}s>(zJr_lNbIi4 zjjV7*1faTGH63lfBz=7d5`bL4mbNK>9Act!x7F4!2|)fCj*nc=UO;HMfqv5RW+)D3 z0izP~`St+RwcY$<@9u>g7ZqhwbUr-VT`^ZMJ~vKU17M!IaoE9vn~*4tZ)bOzv>9e3 zT&~iB_@-=)Mi1fPN#EdNw$w^v&SDDR$Uxdh+Se-VO!+%EJsr7+IpB@5iR~!SwbuSoM=L zN;r+eA3S;l95{NvlLMKE)?dJzy`H}ILeIH}D|W}*=Jf%L6u|+v48I=gOq8#H#CTlpF3*-3Z<++;Wml!|Z-N>7z6+PYQG z2tBkhx&zr$n~ zOD1!BuX>b{!1SDosEE-n5O%J%%P`>9l$}afesdfqwvJythMk7#eyg_&c>lF8G~PHa z{8^K+!D)VHx4C+xUJjeQ_=mpjxE}x3M%B0=!-K<|l*tTuCZ1G4|DLRBLq57S*QdCs0L z;V`|n9siuux)LwGoRa3j!?zzjtQl*HhAkHM;1^tvpV(MzUQqgbysDWbC67tlzvI=} zMx@bJZc`dF876yIGATcC0hd0{hDAV7p1op%qkNQ^;hq7{Zt9)}{4HRvb^D?y0|6-k zfnqT#4FvS?uPOe&8dz}utAQmarYdA$KyU5hVE>;CR;9YMl$;Fh6cv=b{FIDZgEIA~ zl&rj31=v3z2*_-lX-VvVvoQa){~s9UAF!jXk%<|-i;0=N*?+J=G=hu0FHt2~vB2Nx z{ji={da4`N8-j?%io%e?m?Y6iC9nAi#fL<8y?IV1t&37}hqFDAPuH5;)(qwh?whsO z6t3dhBT@!MT#YV#JdFSYy~}D9<6Dy_9M4+=O+&0!ZyUI@U4}N}?Od3}o|J+@nE_Va zPtv%!jze{-vtl+Di-YHsH}49~qn!)oF>92f@_8Z0`@62+%BHw}Hoa!J4RkJP#$oF& zzt_{LI*lt7&`|$!W1c47qvHh3u8_I-l6Wv4D}dXLwdYE(bE)$VZi31Q#yzj&$+7#jW&Uv$ntcPYv5I{=1=pScX7-~sUwyoc!>ZPr zpdPXTbQj3>lR~YDzL6et2=5n@yN21uW?U;tQWtfq{6V3K#oJ`IT94xD%-Mo}JE1HR zqZrw%Dnnpp@fOQA<3yz$MFczax2`O;@+zHZuI>SmyZ8e|3F5MM1sKO6@y0!Xs?6_H zyabv?SoaDEV42qoa?u=@OwCX3!2*uM1b<}5oedr+NpF+Uvz`^e%0T-Iys+Zb4IXYI z))^=Oy;5mm*eCT3?lNeI6G9Kt=~!p;OjoEHN5p+=0zgQc=6m{+lwNB8OWPf3P1DY@ z;up-^LYQ%}jjZ6w3+7wf7-sPyY$tNDiBHENzPdQhr35eA8vPVdBy=K1(+J7u_0*=b z_#Ll$wW2!A1sPTB>vq^Mp#!JBCPrFE2lll*Wnj1)l7^4FrZkxUAxx8>vGpW|ymggxYEB}NTmE5g$?SxxXArALljj#1 za<3_kn{Tcow-6jQbRoNk(o4iWA9NY4siZ8tvgIp$_yZ44UKGwy0d%3y?bPTyxn<7w zp80~FIgV(IYo^3Q=IF)YYWxoZcmrkr=_f|OHkfDDWjBl??npABrBC;7tSN6}`+g1% zCXW-ER$31cYgXV}5@_^ha3RH@p|}(vG9MyX-P0OyXZo*V7yr^*;4DI6g1@>00S(S~1{I z*1Vn9@qO17lc@{_J-%<-6R8Znx9tqRcQ7ki-=7#YU;Au;+fbXDxABu+bokUR>j4Ma z=;bYIP55(`-iOc`y$^`ofz9f#ThA^JZFrHKNQa2~98HioiFa^5zcPMd&Nw8M^|2w{tX*V7yh!X8%IXR%?&m_ETH-zB166 zZ?EYRmGkyJ@!En255CkOK*qSp^crl_^0RkR^VWZ|?qBm2EMUxwImutE&3yaXPoV!W zCGh!4oon;68`t~U47imtcb|Bs%l){+`?=)m<#`#h>A9Bxd^UT!06w!^;4!7q^E?8D{Ru_r%GUYuwkg<%1RIhs zpoaIfiFLi&F}r&)D|k(l`$GWe?d;sp;=gmhn1ra7FtEb&Kag4J4|WJs-THfsm%4s( zGL+Y%_)=PeGfm&S&ry=Sv5Cbn$@8l*z;{cCwAYmm9W0L^SO4wsZn@Dxuj6)dJbfiq z9?qSEJ?C;<(p^E4abNi#bV}xu@c=?aY$bQj#ru3Syf3xTTs7xV-n!#g zg@#89*X)~gIiS>l&ZskA%W=3?I6?nQ>6dg2_zU>s@h;JqTJ=7?=aaJ{l~_EC$NWJ2 z#NPmJe&I=;6)Mtu`C1j|HX#2`=aAhr0ewu{?x~R&GA|U)=ah z{R#t_<-o2sc4}_HNjh-8sZi*M<4C7E5rp>5gLGd&-1BBa!AkYRd)Q_;UxkthFIIkJE@(F3+f8Pu7 zD%MiNc16rB@aXFp+K{>;E0am>uy}Lb;yRa~oWD@i`m@wjr%m9W+Y{jpKVRDfKl)z; z+jp-&@3s8zBUUy6YJ>($WQ4zhtVf|Pb!gR6Qp7X?+3VA z?ETi?0$LsyJ%7IQBIJY5SHvGtBxhVoaALGqdyNLN0DTOqWuK_%45-2Ba1S`xBoOWh zvQk%`XCp5R-JjwYg$UXf2D)B1<;hVuw0HnGb@Ee*i|@F6n(Ew7$FpLLlpKGsCUgG{ z?)%H}QiYZrz}VTIxDEXzr()`HcOpwv!Kl{T*e_U2Z&<@eV-x@8J-NTp>8>IUn_6#= zZ_5b?d3ejyPIA28Kmv!_$_Q2k#^qGUeK146K3OGVj-d)>U5ipsG^IHOhw<|#PDM4n zkGq%4bNhCRF=FZY+&~pi#wP@NXT8sux)GpEKM_Ui4Auu?)RNzEh~l70PnAh2DysZ+ z6zgIJJ|>kfIN(93nBbif`%Owx*1(qOg3X)%$SC$yRu@cu9= z6+I0ym0kv2M`rVW{@o8loCTr|ydy{4GN1eo)0CO1%3;2HUVsvKdC(I$;pzyJBhaOJ~ z%kdA$o0coGoAWycC!`nCBF*7;b9irif8`&kAOuI~yuDS9!Gk8fB(xsO%bj20`z%buIJ}I@@a1oWC`~rkHKDHa6#+7 zkG=#J%W*7V;Cw|)pjaJ{(#Al8Wck!hnjl>Wo)&XP;h2D#2g}?2@d9zaA+*wdx|Ou+ zooWhJ$nUKDY4LnOWl8Zt@_^|wCBtMCa^`q^@_f|YH4id>Z40L@<#LF4j0cAc0DWdpQN zYsT?F4S_685|2|lkd_MH!)T`Cx)_WJ%{A~K!P$=EM7Ff1@E`=f9SfhkAXH>F$<6mc9We|+#M@3{-p5E=aR#^K%bLhR)z_@2_eX&$my3zXiI z{ER!GU|iub6D_uJ_O>7^V#<0Wh5m*(@*b99q{?W#S#hQwNm{?xhvm0i-;}~X9OKx0j#SpQr^1PG1LU#IIPnaBOd17M^)}0Kg_|h?_{mBD0!V%8DU0cw|rFPm3Rve?n z8>R;FD?obIK^!{ht4S<@;t);@R$PD4fufe5Xc~nSOx$!0bP!oad9#GIExC;rFIeP* zx(RDXkSrLorDSi}2Z2Qd6uz=8qLS8A?8zrWhMa`|$x(#E{sigMA0cZY1D2Zgd}g8|W`Pfd2(e~&IZ!O^I+*#B<-?kLJ4MV^0-`!j6%J)!t5 zN<&F%2|DTRettfZ1AV5uMmB3ghj-AWEC9!z%wfBsgmdLdJ0;mNQlW}6^M3lct5M8A z)>9K(DDz1aXp%?#iIdt-0~n1mDHd*29GqPeS${x({}oi&_D!6LsTBi*tgK?#rCq!D&ID?k)wF z5#R4M5GO&GpI(TJP&u^~3L`|1Ugo~a3Wbf?0tG%Z0&LW7z^27GWCB}rZk;3Pnw-3f z<0d?2HqT~KBVGEZrl|FHbML5irjdq-DjY7$#1a*_of~bJoEuwp;aA@PR(E#hvykY$ z&SqL{91Dl;i+PZi!gG}L2>KZ7Yq>U#3b5@wDHN;7k~olA51Fhmp{QwLiLHLv`(Mn7J8;i@5I2O*JV88a!;K-s6Pa7Wo|fzCgj;%XSZ;EnV&h8pH_F zj<5t7p+Cam+xn|F@u7q~deo1=cQfrnyVP=LEOm@@lsBJb$ zS+}L8NV!HX&V(8CO}sB+AdiL}xfJ?L#Jc*f`^?8V$1@A14yuU3YT%+j#t)KiIxOvZ zSC9<4W9|7xsOW!XuXzh=e0{dO{Y(-{wHxYQoh!kC^)BXW39;8q8~f5W``8=Vlv;VV zt8_zL6KOEn#kLjqhdimIYq-26>WT?_{nYbuUKS&l?<9UY%+)g6lln(DFvL+)q)K|Q zCpVdDv1BYqP#m6sFBEk|YppA4B$);HwJAN5f{)ZOXsN+~Jc9nEwLo<;G@5_kVQvVf zv297O(RpL(+EJA;sASpWLsqDuQ$g4T%;)bO7B(bQiBPgTv}h@<*mCPr2ill#oCPEz z<4tlCdyFHt#CAEKt*y|BNY0q>(6}p?*5I)(WxC~zft{x)_tkUSn~VR^dpneuKKtgC`KTVA0Ik1Z-=c|5H*>{4fc`S zc;coN{4LUI)xC`qwYGQ`;busA|9PaZia*ra}!Lux}qxFFP=fRzOc)Q(OPLESwTv%0iXg_a~|3)MnTDQXc zj%VkX%N_)4I~sCPIG2~Vd^6bo8CZ@?)nVWRXLi5aH0k|*<+7$+mvy&6v3}5yMMRY2 z9bi2d75+nMnzW*7g(gJVQ!wWxK{Ai0r9&6sYkWMEs6ry? z>!B9V2KNtX?PnB$K&mP_KMF8~$)7CO?Kf)QJOW&bV4Mem-k$#x^3f#A0 zE${c>WCa4Pj@$S7$U@HJf}Py*-9!ASYjX3@<)he>P{p9b$GS698)y1@JLAdXT>9RJ zq~&swyeQOCCR=p6DGUQW|LuqtDJI79MC`v^xJ`3#Ja8o7%^bD+Q=UuWqi$Ww+f-g= zty;jHtfaM~LE206g2lv3vY|Qow*QKs1!W!%S4S_9aPI%8&VRs?s`WW5Uot|TJ7VVFW zi&aTl@lderE6UueZ*buYTAWi2_!?i&qAvd)iPb!jikCS%sI3g=?aZ#(ttkCEkZ(K( z)Si*0@Wite)(%7EoF@WZ%zm=tj}=Id}bYFa(e0D+#K*o*R!i82Yeb8aU(b zU;8^hK~k7zz`02?hxz?(qWS1I7i)t8aSR&1>qnXT5yqJ(nG=MmqP>}4$4oYdKl?%5o zX;6R(GMk4~ck%0YVJeUGljq&o-{{4f=0hYwWfhp2hVn6N(FTd3#8H_;ttzXyq^cKvN4ep|$mdP>sU%-TsujlYrm zP?Ssi@3HMm+mAsYrpbOjx$HIidvPZV3T2dhn7+xdOQ;U&cV#K$n15VttScs_-6l-WZ2EU)w=P z+%j@Fa6c6i<)>qu&uC&jWRsxX;Y+;q_=BW-Znr+!d?LhQYN}Ylf&hFY_3?_k zGHGDw*1@_#>PuX-NF=h7j_)$JPuiz}2uy`nO~pkm_L8D~M0p68PBIc6WxrR`x2JzG zJ;HjKj`j4SGbF3Sa!fiH5hl7<6)|lvZO`O-u{ri=mx|NCupzCcP%N3crdUdbnA7e6 zc-6H^O9QK7M;OIN{FEu(UC465;_=jy3l?~2S zB$OJz$15YMqSRB``KvI#juJU-A;^YX+X80>M~@D8bk= znaqw)eaWsp@?2_2Bkzjratm_%)X}|=BTe1=o+RXEiQ*cWLv5up;xLsl&$KDm9zc}W z$&s@ydD^aKQO>ua&W+w)B4b+q%3+~BACLDu0$SY88NIYQA7U4y1J#ASf|;MUIOj&F z%7XCF^o_oI5;6?keJ6q@^*lSK^k7;VHte|I!y|H7In}mfm9H%R1C=~L-}5dC!cq&n zhhN{KpjlXoGj#SY%&k6of+sh_xQJL+e%Y~uPD!D4>UTI?6^S0qZ_&SXcaJOd1OK zFYt4#Psxs8t@5YM1!aiV(%jBOr@`GJl9vUh4RJd@z7}H`6!ulDaNYc!ry;2AdS*Gj z`gi9zSs~09>Zo8r9 z7`%^Jd8;YJ7H*T6JPv+P#XL0txWVnVRk}<0{Y}{8R62r@ct6GrCLsGQIb+R0FKqDs z7GqqWz%4u?MK3hEVz2SOUTDf7*DBMZ4YpdAG$PgxPBLZt_eOcKYN^Ycp6XTzC+z8$ zTFYT)PlWFsczOGrVQ+|aOQgcPm0<(G+m9@hBR+zx8Oe+5IqrJ%{Iqaj0utP4G!J#t zjrR)@by=c%ARp=P`jBG5EfeW6$E!0#gUnG zf^)FQ7o0*v4x8xEY(WY5yX=f_!ngNh>m;Ccey2dujng#Q@W)VR5*iuD4b_-fF;myl zGm)vIUY)pX6GI}p;A9h&w|`Y*f{M*{ciFBXU`tm$o1w7gfC8opy-3=QjKnmCS$4vB z;}3Ox2(`=%;CFe!qV%8JY3;W9!UxVasaPoaZm*6HA3Gek7 zIoT~*7x;bJA*pp5>v;OHCCl;WMq0#hkPi4YWLC0A!L16B4qsn^GA;IwTPcAJ9O7s$ zKvMWmQCoilk^PU;%9)2S$hf`!NUf3(YE0F7A&kSIH>eCqRiZ|%L_oqa!7CWT6#N~_ zvNK+TWLxl7`-P~}IT3(EqwgfwfXmtU?lXxRp($cTF?|I#tgy*+tjJb-yrC(?{7Cv= zSYqDC!xuVLGD|Q3`F^)t|B#yF|DP8X--Wuo0xUlSJ!;DUN8`P*kokKh+CYqd_vYHS zMk1$@@m8ez@={8ke#v_u^V|1J?wjiVZ8Sg?){W=c@Z#-dfhl#ZlhFYrZGJ(h*c2RT zYQ(^Gbw$XRCfk}N4G-8*44oO}2Ys$#h&|`7l1Zu5dW(9tVafUA3WPa*>~el4M~nMQ z{{jP{k8(n_%N)brCDW)aF8DEqtQIS3mqUNL#m6hx7t0@Ea`T%11pHeIs>E3?4Rhau z3DV_UZz|k@xfv8>bPGbavwmW2*ESO0`0k@X3^W^2bt45c zL`iS6L6I}kAFC5hoMk-@hXKYNMCdBK9AkZ~ENv@KpEZSPA4=duu^WH!<1RaG!T&V= zK<4H6f+*VBa=}rJcpMl1YbEA*2#Q(8EKya}w<{(uZcb2c2lMEO(fZ-;uSm-F<0|*8 zovX~$3ahF(kScu%w74B+yR`}1!F@?#J7L&E-ueZTmYS$|QH+Rck#U{#C*7$xR2rHG zHImCni3XNjrztApV`zS;rI<=K7gocRq%Q{i|-E5cP49(@i8rxS1Ix2Xx)eMcppe;18gRZA@P_ zW$vGc)8?Gn6Kz-<3sM&g#-COl;uO%J&61fi)g%V#>sj4xmw)o7u=t|IrwgVc-TD;g zgyBf}HIsfX2PO`$7E@V8&%IMwt$Pl!HL0Ny)|(TBxE@gy3*nwkA8UJXut#NUz_WJ+IuEvNhJ2= zgACf?{@gtG79OJbXQXk)1|@7_&%mZ1d##p`78UpwShEp2)YhX#QL(mQgOs>AxW?dZ zBN=dq@DcWM`MHl#!?pY~WAKqXUt>_O8}^TFtm(E+tv#&$tVm`6TwVN}-|XsdVO68_?z!%)S}w@O&BcMn0hZ?%%?Ft`i3ujY{6( znRje>6ySrxNdTg14kZ9>pCTqGR>YvJd=NlJi+$xNGzfgHkNrHD432kTvLyHS6YGDZ z+xsIj#$gnL4!}0;?qTrjyJ8I5iNGKuwb$w)&)XU)D7^?}yJpuKJr?sPqsE(NUtr6b zD=vc#!&1(3GTKvk`&igmK(%n)XQt4f`&#Mi<0dsvjeuSw3((+L>tDX$*Bl__D*LwZ z21?5qMx!#!QGx^s1{`j%k)-@r*rTm}6>j;Ejg(N<_H-m7#Xn(cc9HMYJgu;JSB%^N z>mHms%`9{JW+5vk; z+R8yOt`@#wo6TLLegTC`UdWmImR7bqNk7 zzQjAAoof{=w9;}bVp&Q9FJJRMd2M(A`2)KoIVmy71RqFG@rZ@jg|*^AlZTU%_`t+a zx@bYB5~xFAkD>yrA~jB6A_(a(T#6Sx;(ILwpMP~2jO0sANi5{rf0$+>h!2kn^Oc^8 zF5q>!LO`$=1=89{L}wC=Mz9F_`E(H%x4s754Lz6@0HUwU4q4%BIgeK;bZceJRc>*N zhn<9^nCp`8O|va-2R(JagMbG(8Q%N3cLBV80p80$9Cl_7)Ry+wrI+0`P2LYeGM*{& zSoGv#Y$v#FOc`Jm<9~)mH28hv*c#yeIf6P}w}E1OD0KSe{v|aQqa$i;p1W#i`KoIL zm1@O3$A%plaSAQ5+323i%K2R^zkUBH9XP~XZjsPD1jYa(&gwo@#_F4$C2KHzJz|D? zyqG*rl)t~9idUnR4oy%_*RJekSn{&8|CP=U* zJD91pXK`qzp*bMTH7K5Rn-c?j)oEi%P_6xG=(ut_o1?UOhK|s3v%ynm;%Eq(Yxg~eoll0K+rN4#W#haytR5c`lV z+SaDW-3!9tjEh+)1V5@G=7nT3OBPG$9e6oq?s53E$;Mz)QP6G53?Gs<$uRO`lOc0* zSbIjJaDrza8}9=_|RnX$!J1m)WBj@ zs$gu>A6N!QyO_=PvO60MpAhh=eVQwkQRw=>l8?M{o281fU)5ZwQheCHH2N)`m4@em zOw{kc#ECT9XIKrY@OPA3t>>J!_YKH;khn;e5|RDwyV!=rsD{Tv(jv+vtKF>#gK8R&I$+0wUE%(qQju!bjBe**Trew)FPbja2|I^sVlnH8 zM#i6bQx+L@#`I4WZp7?G0q-P9_Ku_k#Jl2lW<-L1El3-eX$(>?>aX21&q}zK3Gn>L zpE!&SDDspGc2FE$k03Wm$_FCl`g$1?^!oRySNY`M?1e8pe} zcL1pHSyo4CdGz(l>Fb6enZ2uwQ!p1We#FJS#}k&cG!odz(>Dh&&vU z^^MvF>X~R`FRyd&RmY=k?079&oetr}bEL%q{N@s49 zcqYkiUz!tHomLC#W%M9Kdwg#XHsU|01_<_mgDb$-;*9xx{vJp+!PO|v&Kbt+@0}XlG588TW9%Qq;`rO9qwnri&vFHg3f?c z8-Azg&25auspep>DpQZ`;?W&^^@I|OxR7+5~6axLfWE8SvbOzy^ z;1%0SOr)yCv7hD)6V|ql0&(kkZ)IDjPucCjE8J`bQyf^j_dZ0X9$uzV2ZRE`_X^v)}{^b zyht1YCzWTLIzWva&GdlnjA-Vh7+fgCD~TYv3^{)`b6ZG>5EVrk%q~_CvT8gf-7x|k z8Mq!MlCO_DK9X^Bk@wakpAm=gJ7dSxP9NT_^H?lhK4T|snYT{f`{BxmVcd28v!v-b zkgV|dOoui;N!|~BBes(%%q|B#94OjyeG1JyK}A7GX*_`>~B_h#xJr!#x$Y=MT&mGV1m1x zJjE=$NZ7mZN8wlmaUsPmOo)9694@AGy3i6ECM={(D(4p0Fmc}&(m6rRa!cFTe51?` z<5!d-=q-4uX71Q4$>uwbVAafhOUZeb{R66(Wv10%nU-ZZNX(TC60q4PaUdSlcmkfj!yI7eDvgUs7|v1<4r=bK)d)$DWNn z>XbOiI7+=DWpE`3X3pqq-GuH*WtzO`hx2KeYm`PA<@1}ORd2-WpBg*aAd9UD6MF!$ zN}myOh!i%am$KEUEteZz9O<G zwq`zkhOSraiifw{%n0j``)7tp`0||HV{5G1n04@qW6yU~ZXCvzLJtn|H_?*<3 zeis{ETns-qN`&;?&;8?b2BL(v*dRO^u6#yx)F9BQr_T45OR{`)I4D5EDHFdYOJjT%-%|b?5RYu)a?d&E3DJ1-mZVbI)(%l(JUpZXry*Qx5Rhcq8FsZ?x#kcnp2K{&CzJ$@ zS%=#+wZA32jwN=v?caeD=OrQ5k{6@739qr^gIjH{BNzl#GO-tX5Uf^53P{@{pE>$h z6%1N}=VesP$7)Ht}NXDN|2GVCsDW zmc)oc2X>U}!@^?A`DvB z?CHl_XafT1ZlDP$R2Iv-mvX88tzva6*Js7RsAqP>j2G9(%~Va^!M#s+-wr%oWuom%6D&*k#68bXOrPB~bb7*H)K4?h?D#-X`dJ zqaX`sjlMg?eJD+7SoZGzU1XvZAKfGn7>}Sg2#aTE?)BPU=(kquwTc5L6$GyaKIws2 zRZ?1@Ngh}3s0?$xwR&QtsXTJF@p89mm|RiZb-2C!vH8QlqNRmyt`=Uoh(j{(pu|K8 zC}~7-3M%PnF-PJQzLWW1BRUlL;<<}35`hh_`<#=FXaXc^0`hSS+-|;aQ;mw284$!f z9ghBQ7IBg7#}xRHYvO}Vx?F$T?yz9o zLL`V~z9ie8h+RPi2>GMm)2d{x%hOud+6XGEsK4{FRq}bHMR1Tglxcq4RqMfL^3@W@mQseIgk`jS-D z^9)SWZP>swpSaJd>6`d2oUkBV0OQ)9#**XEHI%x{Q`Ty>sN(JF@>P3*fgy7s@unkrZd0K5X3U2FsmIR`;-R4TPdf-tpUtt^_Dco2hANN4YC8=2tu;UYlGK-HvP-YGVf2Mq4jn z4tRAoI3W66C`WgaBq(DJuis_w*?yW;me>YRe)*m352G*Vr;f8)2i5%0aI(xN{8&jw z&A5Ie7ftCDw1;KxWEauZG%P8>3RptIRS&6KIaANv2ck6UX%djCgODQe6kX>dMnof- z*}zBxCQthoqAPb2@=pUah{DW`2FWcqQ1^4fnpgD8zPd5i3Chk)B!WUdyw(gohb}t7 zc7rB#$(iwBK`Eg$tks$E^hLud*Mk{}kfHWs3CElFicKyjD*zziqKZ+LX8foxQ-Vv) zAH}8Pmn>mJb905cjbU*b3_^|>x;LzQTPOhOXy@mBMmP9U}}e6aHA%d9h8qLUS1EiAu# z6#n)|*q8`P!cD*WZPliPSK()mwT}OC>FAp)uO2h9elzb*!~{v3tD0zASX-);0EK}B zWM_dM$Ok(A>D6a&!PjDsR2Of+fE1b6Apx%wEF0#h*7L%#8MnunI9!Rm- z9rG8K`SK=a6!R6aHQ^O|VXlO#3khGN>9FuiZD%^>m`C3oh>#ErJeYehVZ)GwKtr4V zK3=Q?1w$w2SB){~Vj+O@Tg>`7cuP0V`_-mL^Oi0%*9Abcin<^PjbQ;9I0{T&EbW!@ zh!<9v66x?^*{K(PlO%Cuo`aqWnj3~N=Ba0JJ@gT3T`rFovEfzLLu1jOP_Zq-Y3RlLFV-zl z7`_rNLWFIKRgqN455yGm$-3tr=s??UPfcxRFgf$6+JL1O#?+h3q^2n|Oe)H@g~68~ zujUVt?}a<$wcoq_(YJ>_{liRc;+KE*_?b&&Of>Q)bg^J$~*? z>(RHDpL+=8|Am#GJiuOH3|l|>_{yh`Kn09e;PCcy_b;A*e&y3sppbDJjKPkf?fY+Y zqRSZ&Bg*uTKI&gQ%}8;77SBDp{L=?;qxa+UfR~OGdb0^Mw;F-c+Frc)%F;tGw+_F* z^1+WWOyYvqK!SZ#RE&b>}_J%xyE zdFI68$IoHgC(bTid;!SAIi9iZgNIueUvpqUu$w%96znFlKy%jwCLg_w9lr1^ccJz8 zGYbEulc$znKObX^m1i$5KZI8>03GzC(g<$x!f|+qiJLF}y!E5w%fGy^eBotEI`-!B zg?E`cv7ulPcuM2r9|8{v)Hn+f;{4z*#a{mFKh^2th4A({h}M+rA^;&Y-vjHtG`fQ1kLGOAX>X}lXRSBj2TsD(!s8ih4h^I5|(lB|xK z6(%mXq#~1M01b_dqSxKnYEE9NDS?s%`V7#bcWc0lf<)E_Et)TOtngJjQex>65XH(h zapBE>GBD8d@BWiN3*R~R(yec=VdeVfRb9EZuk*_F@RxzrmmYtp_29{+7tZtIwfyr7 zGy_x~T~OJyV^iIou3g=U>xx8m%!Q9oncyNzF8|aQGQ8|fVfMmXOK0D2ee}yqFTMtA zz{mYy!*w>z3-?NmS1=b z0HEYL`u5_*9~o7P@COj|>aN2rqfn9+jgqLoNskm4<<$rUEXhm^?*(D`>d#t7o?U+F z9WZaWn0~mMNl_RL_5~GhXHdtCZn-EEJ7AONmed&vR`K~?Ab5{%yOey|3lurN?+ikp zTInW0>bG8_%uQ;w1QL27w^EzNo8?9DQemJvRq=B2;1D!gn9pO|h5Nel>O7HvjIZR^ z`??HEtKyX#TEn~GrxFe#3Q9DEC8>ojuqtnkyNV=w8@Kd8SLs*GwS&GUCS20dgrw=` z5#J38{%}>C6_WiRczLI%Yc>Co@HIuHZ1?*{y)QPUxz=O8W=Aw7_K2TZ&_)_5N4{js z=BF&O1EDi@ZonEFm*qtXFh+~33NJ0 zuQR9?hrXWPK4+g>JP_7gkhHmg(#*IOkO%N;qcb|~-y1q3#p$}|-wX0G2kVVr_KUQ= z5t1oO5O?`SuZq@gvx;#aXc7<9kbLqD%9lDh2Kx#9B2Roh>!c(6c<8((Sr+N}X*MGBg#xN|7tU7U-w zjRBa<)qRY9%sXLFZh%x}Z(_;ED3Zx$!yui+6Z)?gK(A`m$qbBi507M=?E@pjBkVoB zdwBHrz57R}h)j5@q2`72ez;^sYM9#QdaF=vSp(Azj zD=11zKZqCr-)oeK{Pl7X|KHTx*H>uFM+3GeXdr%WgZTq5I|Y7mS?6t}OGTebqldU!S#WwCb`a(rzv0XU%?gaGM>!kWM;$oO zZ-CqIkQ#2$2Vvc;`rm7MRV3sbNJR%`zcU?#jnJ8br*(`BaGhooFR7wku}Kf<1)VOz zfR>td>Dvy`Rn5%6_{67X5Q>x#&R8TiFt~0!C%suyz+cTta$_9; z0lVQozdjXgn5+bo8@Be`)VH~3vezwdfiIJ8Y12(NZ7JTovA4MOX7{G8n~J^O#!aQk zz76P!*??p#RGMxV`p{e^DDWR<7GSlP8FrsH1w$lB<4yusIx{HYaf70&kNG#44!Q^v zk_K2K42lQ5Mq!Hg@sLBz4M%8pgo^OMlpS~0^(!1C3HA>RK2QQ=L9;0MvsT9(Z!=B~ zzRdbK-UpG*~?Sh|vqqh!7oa1!fsd6Y`7_S!bG+hL2f}0ay`O(+hmu zt6>x90#gqm@iYy9(0M6tX?*5@x&>#TO0pKk!L*A!kbn$&84V2!9v=(1RWE3U05w_h*F{0;U~a|SyJV31?)+Fc;g z%7mfbDE^xCD#2VqLIjSVkkeVq$S`r&(7q9n=KV8nqd1+*USGPtaKrVb8?s$=Bx|bf zPEtd%Dw0@3dth|m@V6%h_Uu6X5B7jocqs4SzrBYJ#R`#+<{-a=GQCEb+lRgl%gZ(= z3!1~mO`Ese1T%NCSn|r*s4?8JnV=mTWBbNSMU+#~U9``Inl*hzzK_a~mI9P+!5M0I2$j2xtB(iE?-}g_e#)6d2=fkJZ;d>b1=ibQ7|KaX=mbD}7&}e%jSwnJ zZ?KTop-?dta#xP{9Bfzkk4}omkJd8^*WnTWJ_Co4CP&s*N2UYOca_#zv#)!+7w=TP zIa*E%&JgQ+ViiJlgme~IvF1gGX~SHTw$rSfYBC%Z5dZ*l07PX7%OofWo>+y&fe4U$ zUZso$T|9?VZxoxfx7(1qj2w1Uft~NpEKHDEw2iR@baBZAeHx<#VsGJ1v?%Tj>H-zH zcGvNkg6C|6IZA8#H&of)0%%F~upt$7=erFMt&_V?Y~zvbrs zO}+iaE#C#x7q}J_f6`GfAOvhquvt)*m$ncZf53m=)mAcHVJtZN(aO{{ZmJ5Zyk8P$ zqQinSTy_Gmks27WfQn9!f%0PqH>evz!_O2(l~o!+3H^ljd(=id13+rN=-`Q;&bEFMp} z@SKi$i#be*j?fAI(ht$$shfGw%#gYCm2C>l0a}dpirTU-;yS9$nxpJAS(kNqeHzo+ zMJMpsdYJ?pm?UITz~IodIWIfwQPaJBPH`Fp72s75qgGYeJ?FobB~TTL z9?F1i)P5)xfhctgwib6i3#T2nUV-B;DqzmR<>WhU`W$rWw z+bKaW&~y~b2F5Rq567ti%PUU+Wl2#j)OA&SoU69l_T$yf9>aU8pyAB`Wo$R@#_%Hlmn|f!eZv<4D}`iD$O6bpqdR60TDdJUio0w~TjPJ@3cx461Oj zEL)tc>{Uhw>E;4wVccBkb0!1aM65S4cO35nP^Bq<7VIlbr`Mp(N00OA(K!ZrJ{H=T z^2mrIFZ?tqJYhZpB271P)^U?`>XUHe9V1^HH9!L|sG?Qs7N-r@HlW6U)OM1#TZB7L zMcN3E{!`Q+*!zge0~v&P^?FxvfqYGoXcBEok5t5bZd~eXTC(V)06LE0}#Ax*g0jDBfxe)|Li^>sf9QLJ#`b0yj8RZaJwV@PmJJarJiP#Y(3&kWBaw!l8tZ&gz2Luod1|<=J$;YuV{#=NbroLPK_hb}Y^9U$uX$B0$_q-E&I|h0jQ` z7~STs(u|_5M5p3cJw{)x7A}96LWa-KMhvCN8SVF4Wr?gR=X}}06gohP0;4#VH8)Mz48v{F{$F@V{*M%MWL# ze(%{eM8)m6s!?&D&uBTA7@>8JlY8RNzSxbE;RZZSh#?^TPP0+&-il91_=%J5KJh%} z$pQ*;Nn$|C3xz-MtQoq{0pWsH(Fm05!8nXf&bPdBx$Z4EJL{lQRJfc7V5-9kH(&6p zWeRth+Mq$&h1+rssdx3K)d2Cd0kc$THA!*92pe?e*FA~?k-=gvZ}_2p1cbuq3})Tj>VZ@434FC$m z0=9sf7o`I%Q`n)buVH|W*zPf6Bn(WF0*tcP7;NF>RvF+f)wqt-cz0H;+H&mU6i|uT zym=p^%tDT6aj*s4DWjv;lR;A`=s~ky6jTy1kP>A~5T@uxhhAlTC3IaG2)IktK+z8h zDuV%ysM0Kve&X!i{;eHDJH>FI0Rf99tkkf=;n_%+Vgo~gPP0nfBJmHkX(kUb2x%ed zE}*LoplBS$Hz91z@zH)or;ILJ4CtYWIBYaa6i5+4N&sb8Ne-7GidxM`Hpz75C`1S3 zST`+elxtXwM;(X*LlA24v@jsrtK3E{$Ru`kcWwevnP_Y$4Lzq4a# zaPN-cJ-0bI5!6V86>}c=$|dui+U+tb{>BW!FasoPh=UO;uM;pNSJ6ITZfLS)~RufYqK?eFtzbRv7td3#@rLlwTR}9Tcp@-q>$Lbms-AC zpK4+pr@Z4l<28!V%G|VHoR)FFBvV8ft(ww6V>zQ)p>Ki;;du4B!XKkqkXKM`516^= zwM3$TbefSc*c)3{55h}WKhwqZqbn^QAU5VW8IK`w#HD&Ry^p?=FwN}?(P zIXOWtSF&jq$eoo?1j_;+mDoO1d&@?lamZ50N{A46U20lz5SE}wC}lu^(;k-b$);avbmQ)(sz;mGD3U5?w7zA z(8;_r3Wm+&DhU+^O2H(?^Mh(v4?tYkD$OY$7>J@$Na1UeHi*d(kkK)|*5qmYDC6;R z7+g15U*9DQZ#(nTAJsJuER!MSmu_hAFp;Qlt^Wp88WOjU?%pNaL`jO};yAU(1tD1Z!G;Zr17tg~vX?=0z&xiZ8cj}UG?)ufu>jc* zR#Y(v@ce*C*+y_C!92z3t29IGCNB{nyn;F(m?oK=iv3q}KFKVS4b*-*m_!Kxc+(5U+#qx`oJi~7 zWY_ShP@4`|;8hbf9Y?lH|6s&~2zn8r{75a-t7w`iVEt2GW2cN4-0d}7#4DFYO%PM- zW|MssbE%^_im0@mit5vEeGnTbJa(0LmJs8Biq4}Dwa%jpoz5})bgZK zP{SNX#b(8=M-8xQmOyO?Uc%{ArT2iSS?3fw`IQuYj;PryOzTO_p z!6F077)%6!J}B2kXiyz*#}M6F9o@;;*mN*c6Xv`33M!J0Mcb8>6A z6Iu6hyHt&;PP^Qwc6LzLLMH_a1{5-{j1+k+6oHz8ZWnpv!`eOJc@{+s1baH3QCVI!Ck@H;`9RzZ@5T!kkB zD!V1le4F_`n4q99SNy3eURx5%T&O}`istu1TMKMa zNqwEtrIDq?{nw^o++1R9NNm|NuCztri`^pA`X<|0Of^mAGsmxsgdk?5=a`8(-iMRM zk6|V|ckUY+9sN%Co%@FOjG8v`faU}MYSlF#fFoxB@T)lHk(Y{`i@Uw>LO|hbkD7Je z89L2rrz0N$9-{;$70pm{Ak^^d>;fDj`NO8HqUZ($G#+{u4K|52+ z^!IMbXFy2$B`%A*%1|_{26KRL1)j|KRj5|U9Llq!v5v*Q<<{IPl*7a?Apq&sJ0i7p zEB2E7opwU!5YZt=_Q-rEdl#R5T4x>TZR};#cSm$SRv;pUqiCTQITS-f(#VlSGF}UU zIlaBnW1V)RWRIf6;-l&?8)=_DjBKT(r)9?Qbnd9RJ-Jb}jQtor@--1_}=hW&o@K87ptS+isRJ~V+wZy!?jkcRb+D02!ooM)eWWTbMU6=^(* zQ#~R37PM2Otj$(I$;8wm$X%5ErHmf>s>qZ>_p5~{pIzPz5{fk{aCLOKOP51bfb3kL z8OO@HyumeboMiaaEPvMs8{0cBYf?Xv>WW{(Oo#?m&OU99NB80RIraUM)~&QC_W}oXY`$ZI^i!;V=HD{ z$KX^MHX=lmkVF$|70EhIHl>WT3br{1*P_N)Thda)_~8J#yHo_r#6%+yvwoX3%b?H% zvyrbXs|EQ2XaTY?L9Jm@3-KgslcVu2w^1JQM5_$cXm+od(^>#1N9^E86Hd9tWTh(> zo2-RQ!dt$&I4?WVl}tk$f#mkq0+VZWrDY#!R()Es@J}u9tBnaaoM<-6TXX7(ivLt` zpz0MzQ^*W6dMV79s7l>}XHRd6g_ujsIeiVDEKM{iu8cMS_4RCuLy~O@?0S2978Vxf z=bhf3dHN_l;FfN>X{X$zEgd&XYb64lylP?2Kj7EAlJ8QG6aLz;AE;q(Ox$A#dJQ_s zjWj<|Uz`ne`mrls4QwD$D=OOU2b{jHo*}Qq< z=GEv(gj{g=AB~__N)7GWil}1U!%(~uWi8Sv!o@X`#4Cb^nQSnEwkr9fqTP<5z5uBo zO4j<-Ge4wLT|1zlFcIUR;6!cDnI*&n^Z2uQFdy&ek^xk5$59=`#w?O9hKvqWOAF4v z0)}tWu4z}nfIYtm(}gDU3mj?i130cwYuTZrINcHy8Q}JsXPCJsS(P zQu(^u`nLAm)MLjQy*rNf$wkBy)I-fgQtK9YG|F(Mm(XSVeZWym@*7?*?BpmNiXf{n_$WpL-*#nfP0)c9kw4FD zLwl1G`f(Jtlq5jglG^Aqc7>$b1D%Pz6V^?lhBAjztJs*V%?8|mz~qi;##8m+fXt`C zr@n*g~IPAgrq^pGNt98cK_Y6-tL>nF{`C$jn>9k znI830qZw|`8=#Yfi^-6zC-VhySF@?z)J7+|J(aTn-Dou0U*Vg??bOj@oJ(F2y?m)u z67Q{4y1sCI>BcN(@j>Ebvx*81-yEyg?HnVZ1|78W+h8TjSkW5uhQ`ObZyf)-?Xfdp znCMA1tW*T|$&dkKU}4@E)WHxi9i|QoEV@KK&|JKMI2%QkR_7r+t-J>IkqPc(3qYo} zlaQB)_LER7bd>T&ycAOh#8ftuUA-3>H4{WKtq{|lQtG_#HG>8^{w`-`^dg_#*h}g3 z7BC)E$OpP2mm%v_v55)b2gz50HKGD{4eZ)Kq~*fWE-qGe_4HR!>MKPb-@J|)O+!i| zmY|Y0Sk!Dj^-g952dRC}JvKlRasC(hwP?P#UHQz0t1-duxo48+RR=9(p{%`;zSSBj zuc49h-D@Vn@=|Fn~#!t=CD8Zq;irdTR3wh2@X1&H0MzeKE-_LmWcd7@w+`4 zf+tM($S~t0Ju<65UM*C@!#^H{E@9Y`Er&@w51nX+_wmKO4^@ugq1z_ZB?(j?x014) zuf)a7(A|Vl*aV?Fg^qTN`L!hB5pqjel-kk-REuRn(?}ZC!26!(cWmupSAgODg6G?J z?o1)Q=pMz+x?smexE3&bo#)}k6!msa5ju)#pr{`kNNHV8L|wPAvi!v67cg*X$M_hg z7#{=``f}LQkohs98Ca!Lg-Tl(lMe~aX@hEVX&NkjbbIFeHua!2oHM-$IDnYDfcy#Y zT5*Ana|%1)Cn-wwPj|PtIYV%~%*it6A`u2T>zEX$8kky0c)HKNy;Bzl5x;3v8Y+{U=E2OcOMXV?KY%}I< z3MQz7l^~2%Gpj0Q*C4|Ker*Djq=rXPe>tt9p;t{%F8bp11Rj1D$`U021)bixr+QEQ zp2ql%kwFH;9BX%D%a*>I@Wz&LXT)PX`jnm;HDlcniC!yR$Q)1Qb5d%4(uyU$8Ke3T zQ5bK|rc-e#u+pw&^QPC8XxRtXq-8_#wW`$VLy5HNiZpF3$(a)lW=%MfpUH=y$NbYY zMts#Sn{)6GZ=-3Jk*PzI)_f@5>r{&OerHPk0dE0wgUwAKandX$Uy@Z*)Kh6m zz|69VKI2ID+Z6n^-i2ZSYDPAJlpzQ@!H~#lU?`4g0p=8-Y|sN{fJqFaCXLV-P!W@c z3IJ_3VmPxhtQT|g_9zm|t6 z;BHDVN?T@845PtWXTdbKnqXR;_6f0+)_f$C(q_Dv9ZHi+Bu`7-j&MeBrekzvgrC5q z!7l6eO0k;VT>MsTzIEUXZdMg(MINb`(ykp@k4XVJq(bk`MC!IxqIB#W)_qn|r|*s| zWoNvThC0~_vNUx4!A^j8qI}zck97jPgEh?y$u1#hmh5J$;HMP^^xrjb$A@l926=9~eVx&x*MKzvw$ zi39<7Q4X%hGT873a{o5gV{2eQRy*d-G3}FHl=?!1pNdLe)#f?LV$OzDm*={T?&JB7Fv`#cBF?@}>f@6h z4TE<)g%vlPo)CGHanqmfK?@?QsGA@}b)YB`}trZ&S6<Glj#*E ztrg1Y70R{>i4F9qe8$>9Vxv5&0Pk#*#tb-=()XTwn%DPinuqyb6mldrz6rzk!ih#O zG3iYRuRo|56F3bg?cKJqC6SRtq$VD>#KfY<1V@oIa%`r)39Em(NewoT@7p*|`jlCT-k9KiAs8}yLv%($E zTBaGL2oV>sR=_-~yOo?SDwMMmy$joT?)FdNBC`6p=2w}-=7|z9;-V?sxJMSY3kSAd zFpG$8YK*1?$=&S%R8|xGYDlgK%)EgT49^&$R^pSm7gw4_#{@$u`o#&qC=-kVF0y@y zB%}fYEsWwyki2x%M8}H?2^5FRqM=E3noy-*)lLXWbmS?rFyQ5ak0Qz(K9tT-0QRc# z>Pz$umGEj(Jn9Mpz8J&8xanD(y^@YM!37+=wc5K0Gysq*1P$dGF1`4SJMYglXC|U* za&dOMMytlgYC`=GI;0-j zD=c1-&p;&h;ykH@D31Z>ms6vW>KHSvk?Rc3-6k$+q*P>WsM+>B5}vo8sWld4=3eqp zio?I%G{s#$1Zb;|DCrXhuZ>LgK9XK!p*rbh@m3_eit~jyL6Bj!(~E5z>I{%Lk(dri zPJjF0cXzY4jMo-5VB7jl^$dmQ75u^_4hfx5TnbI4H@eMZG*x%cBZ!b1fw+sHHbLx0`I&V7Q z%?Z-_<3#=fOJZPg-WnK0QZ~v2!1q@R`r4btdfSYtBbK{7@7|=Wd7`S^IX3ohVx83Z zTVvdIn=_+i&KW)7pgcBa+x7>spU7(xR!gd>H=lApZZrca+D?d}sA6(4MJhzK#_cXb zlNPr1Kl)*bBTBU4jE+S(jVG7hBnS()rx*j6Hm%|p8-~^w%?gqh-Lxu-k%_B>{j_wp zHz~C7p~EpE@dZseHra(&vRYE7s|&XHQtEM|n0yhB2U{)X%CIWMpom4Vrg^$4&%uyN z>PbJdB5y!eY<7xuStFWCIf`&qI;SWpq5QBvi1!qfmxGISi{yvVEwv0pWFattDEj4^ zVUv=c;vN+4a{=ee`|L$cx@r)!zhQKgp8QSAd0;`0-Wpa5Co5rlobv!N37Age;0R}j zVILd9BiB6iu;hVZX>28n^yZw&T-#01K?pNTByOw$fNCQY8TwRqK<;Pcoe>T`+dP$q zA8oK0-U?FwL`KSV9beR6&4f*XX;<(S#y=3ou0^)!5>O1(9(RwE+e3k!dkAh;DWTv&4(T@%AR+#HZj^%zH^0osvwjN8YR{5pg(YWX-EX zFJmngoRI)cezm2>`xJpwq$B!BM?g1|Xauhe<>28C`J&gm@n-m>v4(+FhZ7>+&-U}- zvUugn=R>!>x?$VVOJu zU4at`it}6HR%LZ8>5j+?`=tZ#s~}NF9w&?R7?8Q#;#zIIEaN>qI<$KvHvagbbpIIG zXLYW`Z4&$#CIf-Z+f<;@F@JnD4alYvC+rzfsUVb7yB(ts8gk{B;32{l=3&uQxB|;$ z1xJm?PQBSJl?3cIpatXv;J63NzTWe>D;$?O(GEnJ;mhjn|Z@U}tD2YIppjkwniH+V_W*Ky_WJPptk#}N zVN$ZUndQ_bwnLi?d2sLU?ZbP9c1+wkux~VN8i+enu9UeacmvTUOh?JFmCD+&AxU8~ zgPY8bidTxEPJ&l+8n_E_v1(|BV-U;@YX>xUH;&;9W%2Hb^~4=321PKl_@Y05QW`o=&TbrBzZxxfM9^caJS!Dv#+1p zHp&L!w^#9Y4fN_$98##=gxQ#;Bbo3xX;8@=C94@yG4)|QU1c_ORc%L@;gB(8s;3G@ zN^+{`nh14~h_o1#`)QqmT@5{6Ps+Y}uxl&|PU~&DZw)hP>irS-e57aUH1k0Jby7rL z{_@!o#-3I-l~#o)HLE<%W8`Ax#y5yyX5m)I#&cvvIa&EZO8V5CTc47&SD`dQR;v-g zGBGmSw}l8;LSh5N^qryDJhWwRh5C7cazr#yQ0qyT=90h5yuw@0{;prFtzSbM^`B& zQ(hIl)gW;>No?$*G3_%@D$(7Nd_PaL1)|51M|h{)DB#@MsWWi&+iX+ci0$^pD3P3*8Fq#dotQR}f*0xl<7Wqx& z{kI4h(UqC7`CeU}G0ce7IgE0xdG%s|2i2Wstq^16o}2r63cVZQ*PXzE7|n)v5kre} z?gDS0mjaI%llM_pxqZEh@o9n_tPAzSem#K}$t5?T&5Pv4{lR#lt(b~3vlVXZ%=*0l zrC%*y3~Ig?COg>MTj=eBU%P!wtB>i!i|DNsv`ApKlfoB#c`s$%E5j&Y5C@EH)|Sbg z9F0-2EIGFHyGf~5*4|oflyl7jh>@A*)b1uG$=c!0`X%R1ya$^mI*=vwqRZT5&o=dL zE%f#};)XWd`3ONpn)FKYT06c_m+!`#UnldNX;1Z2gl7 z@dn$>xP6G{gu;blHno9+y%NeHYZ(#zF$W@ao;|T@D`9oW+98DIOFL zWM~+Q7?rB7hroH3V7A`gErs45M_m|O&&DoPmRFd$l{t(B;sL=qRM4B9#OQiC^dQe& zx`r^;+Q!~qV1SzuV-`$Q0h8=+E^MTb&jzN}nGshADwUvbLvL4fmqMnm(38=*HPe@J zqlhc6nqWy#;(aI~nBvoJV{gyK-ojSGt?HM3v0~7YL$?;Tk>cOLq6^Vg*I}bs^Gh(` z@*;tB^rpEBMGz<;t4co1P+Y8Xrs5`!Lf{P=oP%awUb83`#i;;~sM&5vb@<|Gf5r== z)!m0$^*U|{h$a3TPD735Zrr@~5@XqwzRKLrhhns)iSB`N&I3EBaX{1;YiB3lGlwMAXMHx^SbiMcq428=Qzvbl=0Al zs8T}8WB@a6H4+~1E`^EYr-MsN?AO`GZYdGbY;9T^6Ze(yT_p^9+*$*N6(wPG^?4LP zL;jBjr5KR+p=G9n8QWg!qRGOZO@*7V&OQ(K@nL146xgmah)xTf2!j*@ z8aji6-P^wdLs-NO_q@79NjNWP=7fSgSp~pxJG~RuMRA&`nw; z`cZ8qRU1^(15#sE3Fd0zpwrBPGg%3yFbId@Jfk~C?Mvv|3 z?%gm4D~YSjjL!|u-57PH79UiXj_zDk)b zQ{a=To?EZ@Xw6WReX}O#At%JcMG|3)=#;r=_LD{god6N0-G960fs`Z2@G-Uvw4sob z?%~j2%nJ5R+;=5d7EgZm-soXGNycu@;ODOBVm3>UMfi0|-Mc|cGzetUKQOK*Y~L-J zfYVHO8F3+=0HTBF6h5df5GQeMPB4ibd{`vXDngM*;%JhmotxIK3Q;*g)s-Rte|z5o zA7ynVPAHoKT5GLZf2?IkL^8q2Kmwv>1qpdTFa$~>qAX2^wA{rNm1{hZmv&kSY_$C0{=_8R3{3$j6U^1~(V`UETmVF2|1@ zGx5eTP&g&9Z2jf{S_pGoL07g5@dcN?I1vi%^c5srhIZgMP4@V)W3NZ`P{}f%&%?EM z<2Zt_Pzl0Q=UfGZa2k|30;C^{6c5_ni2&8Vfa=r6j~$mWdA5CW(upZ)X=!Tb)u9XR zp$kXVD<{>OE1}cv>a+Vu?uc^SsEs27Gkrb;zWd>obXx&D?7iN$&{Yn;qO2;^3BRpa zag`H5>c4mt$edj)7@Q(;hQ4r{ox{Ak?3 zFjQL_g$m`aP1*3qBXz6TG$KN6)#{0k!LA*{2U_0kZ5ZroRNG%rYYz-|bt91_IGFF0 zXNK+@*1tLf5T97;EL1jDpig$LQx1)0hfa*{!{@tCLu=unk9AWTZL1Jh{VI-t)r@JF zW1-qs@+avm>QVT)?i8bo9$MG9BW;K)wqc$K^;sN}%L7zsBB9X^$6-*C;^0}OIqFF@ z#yM08VPJLTFoabArZY_r$bP|mx$jn8jHOQa(a)XVUl!a&NEYdi+DxJHY!hdxxV?#byXN?8uawY(C zb=Jv2GmDg9Rw-=J?69%px<^jC{Yts7iVhZ3acHT^EPE&>IznR2B>3#`p6XEN7EQ8= zxEr;+jlGX3mDe1|J_ZsCgQ2T4pOq9yRpwytQMKlzR7aB7H%_qU5q4>cMTS12fZY|~ zR`M4^J?%(i40W>Bdk==rcMV>xA*`{GH0U1mJm~jrwx`MjNxUbe4;IHJ4UsuhLGzr-Rd0tW%J$I@c8$I_TRR)oxLBz;Rf_M!dKI#Pk3>U5pNi)5(vJmHmk z^)g|XFwgUIm{~@kkgm7l;9aNTo*eY+jJ4VRHaU>pQO zZ96^K)f3wJjJmZs)P|_rA>|iz9RFoUv^k8e3u|G%cdZXW2ou-{ zYt*7v0Ebhgo(4`Lig+m~tSr}qWpOxz!&aq-GMJ>sl;xocbTW*!B)DGMmh7uMnd>WB4Layu#;! z>~d6E$zOc=64$02H?bt~9z`f~do9Zfe7*{XH9r78 z=MAw0ZN}Am(aPc0S8U_l`i0wGekW_~+#fei-8=2xjMg}8oVb;rqWSTQNnp}s z-)U2u8`PGa!@K*@T0$H|)Sf|QI6c>9e3SzBozc9~uV&IH3~;@U%mKB)Uy0^uHkJ+e z3=idihd%&MWVkoDogR#49bj>m`pRc)0C7N$znXFH=H-uNtuuqKLvWRAFc8KHNY|y` zfB!u*3MyR%nEC=lyq<|l|3CnED>cBqEQqif+%=N;IDe$ecmnisG zZXZNG$d)+NGDo0n55d4RVvQREDGh87fqKz;9+`hbJDv_debq!cunNZ@(kM_6B*Cik z2{tDe+vp>EA_|N&I2kby9!&D7kUVy%xh8zhWqzef{IY_^H*Q~~(3aZqdOhYxNW z8bD^`^O5?I4bNX0B2Nw7#ENVM=_?oZo0dlKswXZWlR}O?pE%)NL9Gdl%-Bi%(b!M? zk#Y!sWD-`lTWvfqZ_gr>R{N}XB~=gvIwcsKFe{wwE7=+hKaaM&TabW|-V=F8{~g-? ze0a|V3sz%6TR~Y-sB8qhb}#ymF7G%ul&{Pv@O*k`gSnWNMlETM0d8-pr;_1zOmR~W z6&&1h+5qy;DP_(neCw#AnAy^2Z6i>@<-+DRP=rg!fH!bSy>NK2y9vI7dXC7YKWP?$ zAYChu)braYcba#B52yA#G(kQMUaeQ_8ttGNGRb1*fWk}wMH?e-S|hOGXOB71M8yC@ z$6g@l(7uTPq?+;-=F@n|d~6UxcNgF=8{C`&cN9OPz;U1crOjNtTJQyI_Ojn;Df?5a zNWcxH#sZ+j$(-NZA9(*1fq!Jb9)7NyuuR6pYhqKe4;GZoAOwt85xFFE*1#xJfAjEZ z@`yMQ?&ujlaDsNa>#Wu%v;3fbtF=cFa18xkj_p`H4|TyX%!fjj8QnZB#ZGBSyM=XH z!(kymav5Tkgbh01oRl6jO=djiJ-JuDj9HCKnlLWJj1Wyyna+b%7Fh@*Ga?ujGua0d z&$Tr2s0o|{LYlmQUe4q8Mi}0>8}emlm6a8^&BPmD_=H>dKguX3S@NYM zCN_o|wyWn3Qp=*H30W5U^wbOxG(inENK2E0+}dYK*-6qchUTLuyKZ7Pg#H*CN%h>JaaS zNl`@Ft)XgAi|7mUKIGa2bW~KxXy}hf%EQcKeG5d!%6h4afwOqU`U_xejNBW!=8d?g zi7)`X3YJVsYsJA1qvS(HF~u@kBUQU>FE!fCM7npR%oLRHpDZ_HVkEDWpNgQAr9{Xz zwKg_nPf6T({m5+BHmu<@XXt4=9y&Bo)Y!+nRfsbg*rOggOx?>n`*5_4Y&=K{G7FC^ zVVKQ%@Rpinsf^FNB-tpNG>F{w6S?z5-maF1QA(Zbt-xJ zk$EE7X{?TDH9g4*kd!0Nl!&_9M84jjbPGm%gO|4Gy}@hRpG0S{$3)sAkbUAldv>UE zZ!FUg?aN`eU3-AYV8lZO%nZ}?A~Uce=;tOOp;P0Pmgm;YCi1>5txZoqw1l|Et+?I@ zt01~~Xmc7^1O>-_*7+bq0lZh5E*8oYOLNnnwjvuti%voB|BSlC05UTPvdm0g?Fr6W zkT$isQEk~N$lRz2oXG8T(NNyChii*toml2Abw{i5bk$3E0(CH6&(liwJXjbEuyT-j(mT5y1iRI#>GAy87fW_)LBEUt{@BP z27}tQhNluoJE(oT!O@1vB?OW6!)m5-kq?@q%R_cThQpZ{CBQhC^vOYwI6z{{@I%`b zJR_u5i~}8IG&#P}ruecn{dpN$L`;@cC6Ox`0@(1(s4`ts=P5 zBlUr_MRb7I0!sWt+ zx~WFHk|na_D3N5J4H`1f(r)UNOtGpY_*DQfMegD6eB>T`D3Ef1IXt<*3caGk_C!eu z&Jie}Lu==g?45K?f=vhtv7gn50KO6gADj3j4bMKBS##fn{Nu|~zdEhsj-T}35l49T zqJ)NLFCOLa?89&y%BI$wRxebm+xw6a31^yU%W$<0UzE~@XIMo{2-%8W^OLUs%Em1BDGMn&;vlbom?#h;MO9KX2< z$$6-$L#@4x(_B2SHt!$a-aLG;IkfNc@V<-aPqm>HCTe4I_;h{vLXU7i)Ij3MZi!}j zZ8s=60OV%!zuS9oux}u|=d^lmE4Z{T^g!7< zC0OhWx;({hRAs2?irT*~RNX_m3LD$jtD%?n0wBp}Wy9(lQa5FSnR9+C(Ob3>H!=b? zp(f})sqOSy_a;&WHcxdOL+uR+i>)MpIvmWjslC-|M?I;`DGfu9GHFs7_v4BkcgkU- zok73wl%qdMV-B4_2PMiu8)a9y@E>rGi~IunE{jPi0dG2x#l8B^Yb?@cQ4q$&PFf@H zMWA2UgAsTEC&?|fM;^!>C`yOcIu|dZ6Ux(ss|8t~p$j|@%#Z|VCXW&`ZxJ_S9WC-{TwtyOD;fu%A z-n}A#&r?Q@B}n4U(7q1r%;G_iO)h}6o;QI6A!U1z+GgY*miomuG;kpFY&-2s=T)_P z4=g!N&#C7wtLF|6_SbVt-@pwgmJs}BZWS12CG=(Y66*5R$am;uqA4dnyFoCK333#4O5G&a&TGsO;*wpiorzv!FJNC8KhH6{Yn#-^P z5>o<>@#>J!4R&?QIjWDXh9=V3Vi+>Q(Au7>p}iO3st2o!)^WA{1*BF`vm%}qr7V0R-LVbmD<9c>tJW0u29e#KwSLrX&^xz_2(a$`uwj+|d; z14sN+Q&!=0EvreqJV`S~I04qs;rih{2ZlO3;r5bgs15E@SY7E;z4~`d6)oiWqq}Yq zmI)vQ%})cjT3#SSgBU|PK}V0#Opv*@4G;3d>o`YE7VGhEWe!9~>Ik zp5jai)o(*K6)qfcPCU&v!!ES2_bx_{-iFPBo~vW9WV;D_JG>c9e$xc{9HE{{s}r) z5a(ARl&jpUS4(AJ!UPUNcdsp_)zpER>0E zzAma`L?hY$X(L8QO=CZr$!M-3V;vJq?vsQMT?{py9J*AGbpa=g`s1e7eWSN?*upZG zy>Y)D88N<%uwZJ#2V#MEWf~K%5QL7q#vA*{L|aQ(b%#xB%wglSy7Adqj+45=m_YXV zM4~l*GG>}Yod~vx-6WTeUd1Tolugk^%EUUEF!8LzXHL+RC_*te$jf2$mKpn^OhbYr z-to4Y4l-=Qj9^2kY3tCwqnfscj4wS+x}rLIl_UV9yVjP5(AkqQ&5#L}3lmv#&8reG zWrR?=Isv7jt{S+b$VnAGoNS`V4nCt^IX8T08v-_G^gx_3W$(e}5~h9C2J$|xE!wO` z{N1qHJaspiwlA@bU+nXB13yo_TCz!DaK(}4IX7J0g4QaUzz18UQYNv1BnuYE#;K=6 zhug5WBvTb8E?)75t9Pk=yLc(6lB}VT`pO$Ztcz6+jbo`sO@kClbhSP5(KCk~C1&iZ z}5q5#r{+p`rE$A`9eNKCtsVu3+h5`V;77?&?b?iWd@FJ>w`cu1Hd=I!hB119Pq!0E3= z{|isXh!4A1vPB0tU^Z5YCtrLEya$F*MrcxNpM?d#p;bt22+4}_wZ~;bU0tEtW>|dp zbfR5RevU)k)evfHRClz8U+9EDp_6@TOB1M#=1w@HMpC%vDuQ>An$)PMYb0KBZqoA< zI&nTn+BDUmLOCUBE+dauc0(Pf)aIR}W8p(xWWPoC@aMON_na2G2k)@39NeVJ!Do=J zvm#78-LsR|Sm`F+aIyy{zIqOK_5gwa8}YO+`sp2RT*4A~ZEYPp91~CIqMx|MhSaPK zMDfL%p!+9T<2TG-_>J3Y-|70%+aI|l9!(&dmE)2pCQJG5Ad1}jDEe9T48Z3IR z*mL%q-VJXhPj=om^^R}X-TZD|W$C{=etV>L#+7F#p|%q1T+Ty6t&l!IQqzR!w9AvQ z>$ZJc=BQ9MBx_6QkgrT)uYdm5w!#l{P-1GW`QvSFnWAw+4i$?BSw-9 zks_6_s+b{5NBp|S5eXs#I66~gX=s0c_(V5hEQ{Y@#YO9V8#OFQr?6Nu1BT{ZXnBB? z-fh)Gr?$|e$I>ALvln~t5^K?fhKIBj z-g6{W+k)_CR|bNMuEWFw5qpQ}`>=Z=MHuOQp)8l_spV=dK45~N~HBs5mB#-VeX>0w%0 zu=Vlkr^dhXVD|jx!Us3E{`$_3F0!;fjH~t}%Oy0i%Ql(W+K47(+1|4rFWcA**K`nD z8u|5`E`u614*Dexo_`zV#oN$vZfj!0NuJ%0E4FpSil}n=19~;`D%o74062^2Y{V#H zQ*s35qTHkkiWe=< zEn2j+Ag3f<#v)GVO^2s;W`dFkfTl&ewRyJkKqQPA5iw?1V#J-K=k0h{h6WCYnofpy zTn<%l(Hdk3bGJ6#U5mlhW0W*3t)JQ&xu)8Xy`QkIinq!(vEY4}tRE@d(rI(r=F zk7&VrS^Bn2rPoVjlb(}eNQf@&st%oL*Ayk%q=ufwiG8Sw2jL9Wz7+1=t)AV_u$6)q z;itu5*F`w!#&LQKsLZ`~Em6k|30$`W4=K%rUtC^MjAmyk{#S%#&C!4ioLE&{bO;Wd zXLr#WZiq~a5FE8=K|y-JEBvsV6&n2NRb-~FPT^x?(Y{g^qo!@{@35&SS|Pzq(@C}Y zxE6=N92eSr=ifvSHH=gCl7yKm!;2Ex@WveNH>(T~WO>T+;@EJ-tM~(ULx=?NcQo%* zw|6sLYe`xW9|ISGHVVgx(*;hyl0a^k*lCe?7D7V2_?WVdF4S3r0+i+rKpooB7CL(@ zhOX#QYY}?_VCIe(FNfV>3wLaR^K%+QNrm-j`|$G(bkOm+7Vox^3>m%nX;k&>3aErY zBPg|7PIL@*H>D$8pJIiX*OLgp0Z-J{B3C!G%2}3DttuekFmt9{%;Z>OOCi_{^3SFw zalom&8p1t0(Yi?9%=UBRWj&n$t9vbdZKS9K1IcgK${w7^!_RM#zu=ZIMSyAG!1WWgqy(whk(SE2Abdjm&!2aXhsOb8ftqU4lwpyR%_4mi+lKN zo!Vc6(4$ozEU&iHnl%d@>qbpIKfM2P=-eea<%VVm>QL)hw6GJhFxEj9Du$a zwRKE@JU z8vDrLlhFnV#H+g*1+N8kg2B2j)8@XeyEL1pgqYrjgJYxsu_?HU7O%EAr;f1LnkjV9 zt_*hds5?&635++04tVlMN(lU*4Jkez$aDLZk|MjDee&w^yN%+aK@1d=jUn1CaOPVf zocUt@n8H3PwB%|PnfZajN{`1bjkPDH@mw2(#pBn3;Fl$CkH<|m8^##?QdXhLSqh+m zpo`tdWm zpTx3TG}m%KKsRp>$yJw?%Hmf`b1g%s1SdMy8ZZsfXTiDPq)r1J^hy0Z)}+Us6o(NB z=X|i{B^WJaxGW5uxOgg7bx2x?kGH1PIU0kVG4Ru*JkaWEE!3f=I_$8K$uiZUx*E}@ zO(eBF$xo~jdrC$Q3KM%u z_HUonPswD5WAr$kI~*fl5^*?Y=>(f8pTs+n8+qaLb7BIl2HsK&*hJF~C#Xf0biTI0}O z%K;nbt&|YT&t9>_X~JMWY-1(T!?q9o=-df>eAYQ!U8jw!Y&x48)#meOkZBIvD_%p!c7RkG>xqwcG=weBnB8^r zv_pa--WA7AcbG}Zt4i}R0rpYCF^_OWWAtLkA`&>f#zs>|a{6M>m-doCPQb4qqZ1(8PS^Lbhd^rUsbW)}iVewh#!V(NAO|oPL?Q zHQEO>%)W{3fW~YfnB+QJen=y)NxK)H&-ssd^kU>zY)3EgaV?VK9}(-~I(dmnc!_$G z9puWSw{%1&FI=rO6QU32#6_Z!M)lNXv;=>&&R8_7G2GOt9@`q%Oo(!{!sCs9N<=iV zVw@9^&Qub5ltOsxuu*duyQq0M8?%M%F>u1lezOSs72DLNva!Vo;|pL;fVZbQga|5v zlBE~(Jn5kS*R!?&t+FMQbTxB%rPny~*s&xoVv`C8rMLX)7wiGm_d})t ze^O*_QRab+F_<4WYjI6L=G-#4u|)du(;nK`#bOQ^spWClXp&l45 zT*Q=eR@Mz`o{7*Y`luv6N?&s;sOPt7*H6U`hW7NMeFmY<$zLzU35%dQM30s@Y~_0N zC{-f-wbN9|J8Vi7zK&Y5a8>zgr~E=Tbsz(z!)7okHCEmgu<_}Ycue4G>%2lNYNAlc zzHqRo$)NJc!?2;VCrBCw#I15ZW)yd_1d?n8^?m|bsiwF2sGUvn6)BsLWCrY%e>`az zmn?i1euRfXEGvukB0P1XjWfAR%ndJl2Z$R;p^K8XO<}=;oUTIESIdRfN?=8|7^*Li zJvVntHcw^8Zc?p7Ma!T@;oyVH6=!+bLUsKhU$y6r;7GcLw(JSN)T8zu9U5p0pRQ*U z*y^$zM>H7?n*D>^^=7YQ8>lxaKq_Q}Pb4>p69J9nq#;nH1?Uq*#$yIqTZohqw1sL# zXv@SI!V~Dfx~qXGdXr(GzZ()^Nzg4H@J*7xp!^YJn!yVecJc`c9Qg&2$}J%&4x{05 zZD><;yJh5v=*s}S;gf2mkLA{#Q%Fc4&g!THmB+}UxR99{6LWQIb{IvAWXmEhb0kgB zE_tkilO?$c!86uPIBV>*z{K)Q9!a?cJ!T67o(yU04tJpSti_-Q%oY_|3fDXR_;Ub0 z`vUlN0(+{3DM(%-B+7{NTbojbwq(|l1q-bDE_;DMk3=vV#-b$+HO+=G2Vyv8=A7i5 z8W*bwK{YAb$%-*RK{t#Lr7fL&)+3}1jq}Nn2uak7Zf})ugJN7~NPLCa7NapV_>EX- zzYHgd!OvWTI-Aw54iYQF0|zx={1ycTCc9YnA`1`i^=*uBQiJf&_iD()QZyn*uMQ6h zJ8Y$ue%O{GT!^PLaOf1yu8PUn=(A~F{s8Nl81I37H#n#xRTLZvV!aUa1w*89k3_={ zW&--p-L^8pTZ~_Kgc|xsA_{cBQUN}!>VpiD>8 zdBiC$!%U*GYd~Qcn@XKIOFb=xc(?T44LxG+<8 zCNH>cM6b;fm)Erp+%|@2)0n+BvBjFk?X+1L@I34eT6%9J#ZlcjVvy?p88?nL%BJ`( znHz_BO-*hbngMd8ZXDX8%#9Oc^cZ}!ic5>ZjU&=OayJeiX2@`k(2YZ?%lse9{0gM| zMB@C%^Wnt1H#Ce57!{OP(!HS(+R|nZ7wQ9|2&;7!rhM8oGsESe>7){^fJp|oh^Sf zXA9j`#N})mfv<%&^P%`!*wz~RTElL-4{7ASg72&WxH5MsLHWJ$tQxBf7{C zkO2jmXpR;sp0!LP(!nMV8}m99uVkRi_gz-24-gFpZ)5Zv4vw9G^aousU{7E(L@vML(vXlRu1TH_ zN0Iw+MF54T^m>Er$`y^UeY<03F!~;-*((d zhu#|pp~s=M1;4pGo&~Pb4Sco(?ZGYlLInE$q_zVie49JhW*i$QHzeXdj2rqwA09B? zJI7voxAUXuu!(>1+8CdoaSjN{6*+;Xl= zjSbbKQdE!fs2-KM6&dwx;A0>@&%Lf#*%Vyh+vF_X6wD?So$v`?$svDpO_}mdM#8wl z9dN_jk;0jjlwvH^F_60;=*{-{0*Vua9Vmo~7I>{IFZE(!kR*47A7f4q{s(iH3b_7a zvGxf+Mw!A8q(peBSgT?uj`K=y1^fY1#F$Og)G<>BGjq@m-S69Mq*$oMcAMfr!27@U z6rwQhOt)o{>4-n4Snp2--HuI@`hWMlyK_NdcGBw8``@qM`i`Y(Vq6<1Nf)X_F7c0z z#uERvOK+U|$oyAsDf#F3j@P`tE5pKAc`Ttz{6CELf<6wfoi%7JswR1N@WVrp|H*;A z4sSh8lR>qeCIOZ}($K&GID&*nX6uKaJ?04SIX&3j#E^6j4xA$oOR^j#!bKMiiw)V` zZm$xE=ZXtm2Xq`WVbzNM8nm7UNA|I4tx5b9_x&w8Hqkst>Q$ zL4Nq-8hwm_A9%&N&S|rI6{XCUlUtBmoQt#=268URT3NEJAnVcG<#0cJHh~}NJUeu{ zn$X7p3y_If=~|~4EW|}c*fd;Jl!DW3h0j$F_U(pu;##*eh++a!Od+mrF+k)N0zhsd zDIco8pp`6M1|^G^rI3_WCvgEUpqMl&n-4#t_D|0J-P7(9|8)3sb!WnH$mVAgDx04h zW!ZcSD2**nA5=P66ap3x&o6(t`KQ?j=l)>&-}e7L zxN}(?;_%)+4+4fXY@H77;Y6R5fttwUchHOYl`5{cTzC8dF? zOn5z=yl+e>Qd=5v8TghmDYoJ54M?3L5KpCxL{lKBaL0K_RoXeU{duaAZN%@S?rK1Y z;o0Pt28_yG7Ra=b&O&(No^uXcXisOTVT*d=Ao+mRn;xOh4l8A1`e)Dy@x;}znhTE% z-m*Knx>h?b3pAzIL}{i7-KU%%zM_YQ6AdV2ny7KUh9 zLVL1yGdmuj8H=yEh57mB^l~9~J*!{bR1&g-gGyPX628 zC;zqf*A_ilpIHCjRA$F;&vTEi{=N7q95#zhD9A8E!_^Lkj$RElo})q2+iD2F(7FC_ z-?^cIJ?f#unkJ#<7xg~zTLT+U{ir1GUFlXfZI<{FiAoon3$Ay=Qq0BX6e=6-DLhb$ zgLBZQGBh3+jy<4CitH*_8c`NWLy>4XP4&;DrojYtB9l`KQN~PE`*y2!jf8ic&yJ@K zDS53SdkIiwh(0wnvkF74HU};8XmRKwX*hgzix$Ah2Q6aEgmIAl2{$c-fJDY0I&=~3 z7x^9{fkKVWok#Muc(6lQKudX!zlpI>SPt`ZsL)}YL@KGwGBKpC(Si2RmQKita_Z^O z;WkoAAP2j;!_UDRLS*402veq~+)b=|B;@M3t9)R=e8kZ;ir-e^F4M+knX7bzbCV}P zB38q_t!ncXtKoxi4rNo&j_R93V<-pR0k7NR^DE^Q!Oa*DVr4{bh6j3vI(O#hX!L8t z6h7Ok*6xC3d{+Zcpk;PVD$+dcD%9v|E{|s9krisfahoPSbQ~zHF;VHT>6{Uq%t7M1 zw4!zu7IMw|EaN0#Fh;q?BDu!?$@)mA4(=%t8cn9itItH9NcV`a^X@>}IV5;Cr_;KR zoJLt~2+OAi5+E`<_4wXU)9Gjb-kO)S;3L1@^s%HQHMhvv@mx=^}L4C?RMyDIMA3MblC9y|P@H1St8^#9j(c zOQTPV3z@aufgA-J($rN?zM_%Y=<=84xc%CZ#4KkX`KV#PY`! zzmFB8rP=*BqT2-*l4i26XoG@wy6hWClYXcx)Yh$M7cW=*E{6^AoZT4;)zw2_DeSUO z40i8&IG@3;t8_bTpZ9GJAe0*r3w@QP>(QVqiWhyZEU#El84UWo6w9(~4MV7*4sSUK zmb|6QAIVytQ}R$QoX_Bu`5|REDI~$TEb8EEgK7i=`%~D z%-w#8KpqcG$z0-c(?x*24!9iQfpmCEMFsadAiz;ndS#w^(l1nhk>c_M*Jp#}sqndu z@kga}L#hEDCZz_)a-(s9Eek=)@zS6RHL6w&e{lq6`zpOb{4rGqzRcw<3c5Dy;FzCF z(D=&1-N=HLRCvtiV`1R>w1Q6fHhK-6SX`;44n(~`BD}_jRSJB__f}LwE?M+dsL9=J zu{febD>|u+%%^33B@h4oWTcl#;kbkN2e^}L7L<-#0XNwi7Qe=qGXe!XD0A2sLOkOd|cTO9S= z#NiHjYcte(Rc+ZxGGz{Lxuo_#AKLkhx)p9PkRm?RK9Glo1==vgx7i6TRA1|)IE#Fx zZU~G(?4$(cxJmQ^WF4HD3Qt5>)m`deELc11<{mR;qp{!eKap9@+rtIpQ-qU1oS!`dN@-@#4SH^ENp?*QKT7h za7&dO2U~-!$>3KtISy@^wjcx^G$j&U#4=5iL0ONshowQ9Q56lh={Bu_pALa94xxt* z^AhY}|C7bR(`A<*XK`#n<0DIryCb4of4p?_5=&`?zSACS_MwQwxtZ7qcw(4rMmr)p z9nqbdneF!l0(QL~B}T9lnTm8S(!LTX&TiCTR?u(S$Z)8hf(sXjbgdr#AdU!Uz-n|) z=aJmab85PVOBQe;nLvgn1XOn8?7CYJhg4e{Pm)~_|GP!$klu`-T8?EiFsuzA4)&5V zZ3y63eiTP8Ar~jWs6RYx$_aLr_zfOGUY|mhK zy9Mz`7Bt$~j+1+~2d)uO(w8fN3fD$2Txt@G;!ISa1WibcZ{|RNrMj~ZEnnbCx>PTw z%4g=b-RCJIe>!YlWh42Ovwzqp+XH5`K*`~HWMo8VGdv5@^ zW2mXa#2s!2p}l($tBF%8H*w7RoSW55;iL)#V@?fqoKi195D4t28@A)19qL;HOS6zT zHn9@WbNIh-Ws7_WR4CfS zLjxu>X14SNg&}=jobWP}Z<)2m>k3mCB$G`a%&aUt4VfS>(}HE0x_h{S>x6StYBUm< z>Y2$`+ng#>UdH#Tnj6p%hI^k2?djJH*P$!VhEMgF_zb%@%;$6xXqut%+rZ=~)~v`> zqg^}K^d${9W1C^SM`E;43tHH#Q0L^)yIQ~XXm->3VAbs7lQw-~V?54Dsjo1h-bn{( z5pDA5F;GGrl;4`JJ1B`;8T#h#MyMQbL~mopZ4e7>@hOiqIaF-Gi;3II|VF=!v~u+b9eYy+fdz$aE9Kz zf2g{F{35Y_VW8|Koc&uOF@W`QwEfZn3>=dwmkh&xj%suT={0ZADEnyfr++VTZ6cra z@uF40A?Cc-s%0nDkO;G;k@fAE5zVX^(C8{zwyl%Zpo@v2<2t0|qR>p|%zMz-I`2nY zQbyt3Hu#!q9%VR1ZlUu6&K-Nv_M+Z;rf6z_%oSoerW%OiM$G&zjhdUrxkE718MK7A z22CZ-EYC*QW@9>Meg5cER^J7(5sSaELIn~8L~o0`jx_SdkRo&&?^wwi6D9qrxfY@> zlP?jGd4T3w`1uSwPl%~$J+CQObyousC~MiF%2^Z|nd-F?GMV|VuP@YsFMI#7?oVg^ z>R+#ZZCAtVzkBV`cr17;dpeQ9fuA3Z;J_Qd^zn)Rom+Kg!_U_DO?dbHzqJSs{Cq-t z;u(#e{KLfupDD_I@3EiXaNx+V?w-Eaq9>ljZmgykA+4z_Q3C68%iKt*CS+gr;~Pnu zHhk5ktvhs}6YY)G!)4vB>cQ?q>c9)3#w+38Ry2#$9Y=+o+i-Q=VAolaHjgeCBuQ4?RrTCK5}%DeLWc+t4Z*9qtoH6jT^5oPm%x2P zY&4NzC>u#yH+1ZU(4m1)Lw3h}DcJ=H&5d+Z6wm1w+-h!2+=FpW+wf`Bh zg5T#0+I)EYX?nAv&Xb|tje~t{(3zuGNn4I^Z+EzD3%=IeO*##STKFYkqzz3^9~hXI zNlYU6VAp!-5Xp5AV#EVdLZ89EjlZF#1EY2#`%uA+23DmTBeEi3(ejgvl&-dgUTjAL zNcspjtZQ zmjkeRtDHCu2`fwiT4_>GiI1(y3FY#QE@3~wY~SxplYFQ0zpA1mEx zw@uR!lCl!^OoB|^r1F%c(&g=m2^aTP%@4fx!Nj$P#yx)Xk1UrrqavMTsnrs>CU{3< zP1ttze_R_E-un9uLj$LNIlCv{;yQvi!Kp8DH@V6yJWBdXPaq-d!OMRS3aS{qUTYy4 z8v1t~?3Lj_#kOX%%~j<}+mzvPDw`AsQD!+lZ%WWsilxMc?8b5=^OYXYW@nVeV42^C z6`*5?DX8O~X=45jWs z38X!w`wv55nX*>#Vj|N`XyK+lsv0bD;VgGgq&sXG4%@6JWngPPK9>&Y%$P-B(JxYP zvL-V4lt9^9$X}5$3#YLNq)6+m@%cQg2JQ(6r4X>j`PyeHKPb{6Ne z$N*5(i?rENa0N{`pd=Um%~96*6~&&8>OjY5&yrRt^?9)Uk`4bN;QJjms4)v1A2N8j zUpAME1EXtY#;jCO^M)EZN+2CyyrqI!0v}4!OQhn2$})_=85*z-%QJP!k|l9UGO7_# zjx&sc%8Bu;S#z8jBa`FNlVS(VrrERav4S=T@nGLk^<*CiF#OhbTHXD8T!I{v2+u^~ z6_fm?5z&$hyG(j%P)!V?t4H8OklQEVKZu4kbJ4V(ZDNF#yh?<|N?HL_E~{l_WpTy2uj145u8_Ag`g?ojAGdf#K~9 z>fRl?;0`~19R5&u9*Zu&@v7jA*fsD>=Nv4;Y4&WZqSG;9M{4!QrtXc5G!Q2!i6bIQ=be&WsvUFlJG93}T2r^G0( zFg#O2ICglPN^;X-t9eN$uwaP8Dakz1JmMXnZ^E4=UB8Ip^R%re$A5cYnFsxRy-2- zE>ZR^)~l-3enn%IWRs$?O1dx6`4sO?MB`foIh!rx+iVHnjOLKFp&Y?Tj)iX-@>yvq zUy+Ppop;gAUX5Eu7TqIb(LE9tVa0Wi6_YGkB-m^*aY(S$c*&9&XuNPqZ8A=CMYO^U zvrr~Xb7Y*FBjuDopv$acfPOJLbb!{F0o&VWSkHoyn_>jyihmg%CQ8w1m>;J-SEHP)$CQpFNc5WB| zecl;T3yBl*Aw0iQ3^4pW#P`u)Gm^ciXo@(!Ntg{6w`fKzg2?ddv5sl!4i?EMwt#O= zL~enB$XdWVH2eKC9Wzb%m$){O`r0KFa{~q#Sqo^nbIueo7nS<_%5r?eN`g}>m10Bd zy;MgS$CxULRW+ZU@i*B=j{mC8eR}^lGRMTDD6A%KV#9Lyv^0rQ7C)Q(7p^RfsikyX zVPL;5q0&PzQGoMvWKLYu4vl8SMFwiP?Fb~_?5_=Ned(@%+Ol={=Qj5kKF>~nrmPBxp z_@<+?((Lc1)D8CRP)|G;I&g5XYX@RsqQ*QUMoKfRDMfr7>}gVWKaaM@p=VDfhMO_X zYLhpX@v^Hv+ydEbR>qCG0ku*IuV6K0|!D!uUtEMqDf;|il{|%_0Ek4 zUdVm#iGc4PdiI_=eP=utjfHWMNQ0(gluehG@qgi_OA)@SCfF?alVGd_l|Zm$X1XZU z#rVY_!HZ1foI>+*nI9mcB-;ns zwb5?ECR{WzObXUlIvei(_^m%Yxa4H|sV|<~{n_0aYvPy<6$yOS&{^N7s@r*rU5f$oBXitKp(UXiL`#$q8i@vwCbXH3LZ_cgUhI{hG{wY;+7R(uQ z{Grzmy3_3ACZV8$>G+WZ$YzW2$SdZx{PYN>_tL5(r(lK>G& zno2xn?47+Lk8cz-D}dY=Fk|N1Zb+K?FW>zA%pWfqSM%+n8wY-NSARFw6?@jdK0Pb% z{lzz(+u=bF zH1VFK?@B#j+=E-4vR zpM3Mw^w0liSaW;vTd3a5QUZ_DXXp7mWs0BewamPDF)5*D!o^WB z6NdNHY04daCu7&a7=q-hb^gTMpgrMBC3^ zBj(p`q z;mEE}?fgdL(#~_+GnVuPzwyR5tT^%&;K;3(92rYFGG@#-UoF54xVFx}JW8Fn2Nt+c z>qYBb75sK`?AHjnixwbq=fS^p^C@3zuRlRn)>Gsky4J$7%huXgU^9AaF4~NeRbvU- z!us6;zsG((Y4WQ{bWP6)Ec3g|-H=v_B+e44e*nRJi@qR0O;@@#d+& zynpQP{yytFpL)3c?XB-9-}qYc|;vR>Q2o7lDeHO7P(Iyy(_C=R#gk^LZPZ1NjPHzof#>87!7 zB_#vNKTUc&X%MyWpJ@HR>0|SHXDxl?r|+wa&waV@;8`$^1Rg-jDvXpd!^pKsKy4zK z5&F=WvEtU*-`G%a;~kZ6FYI{v!r*@(g!2Vvusjh_7!pbvN=j}`8awf4NjHtT*(5&6 zlW+acq{;u4G->h;6vF7<)*)`E5WCOMe$KHldD7GG{Y~o|{;&LR^5m%$Vlsu8clXw+ zFJ?FGeB!o-gU`0w3X&&Jrw~c@tjeG-D-dw6^MZqwaFJHK?#PoV|GH(JeN>WX7{;+Q z&9sjrC5q|PnwFZbLT9CvA7L8e5zPkJyF#ap6u)R86ONkVrcTksPqh46rr6Q6)Fx;R zu`=DtpifwtF*8#lKtNyj?!VQZ`&`fU$MgKoxzD-&ea`)ST%>_4dZGfyq^XId-qWv- zp7gzw;y9^CPCQ#F;{a7Y$!F36-yp?;iAOb&5i_U!flK2(fS+cxCdWqDH!Wl`PCZpF zZy%j(rrE(?1TOo+YQdrSVM@`DCfbQzhyB5Ej2P^n_kCo_?D{x!=?qnz>IipZP`a%-LpRdNnqit8%9dtUz8`Nr~LU7W+p?F;EWfJOsBdeF@h_X7Rq~Z!q zy0w7h#+KNkwIj7)Daw!?W}>Mndoq#bljh-$D_rgGsojeh-jnt0v8f_X%F;=2vPXtj zA|F{%zUgxRm_k*x@c$7Kt{=)Vl&$wW`l$h+GQJJqNm9i){d@t5vWc%Q-0)qDWV)E8 zO1B>OL(k|ZmUgA_MLoyFJgpA71@OI4uWgBy6B&&73-#fivdgaSfqfX|y1~I^HPYMq zb=1@+*=S*F8e55-uQbJQ6%qH{C#|g~3VqYkq>e-K*sL ztQxsD3F{B^?LGeSM3>^7&mdCvAUe<}@0=Px1<<`1%=DMJwM15y0%INQynkYTXH0<_ zwn4s@A4@RI$+34b|IXh`t+Vf&j#OPw>>K4gbTX+HQs6NWLnxJj%F+$o@?jYKQ z+0>mPC?U01LGMh;yXO6_ z{WY~B0c+)xC5E}2^;sD)5d}Cj*f!{JTX$*0bHq(?=PyufQ<$m+;NfA}N9{op9 zJ9|T5mDKIokx}Uw=(92Eu8BQTo+Ke=76sVpHcaP^x9Fm!9_$H#oO`o&QiTQfAiGrY>z~d$VWJ|wf0K>Ae4z4b_Chvl^(cq)KSu% zx*L5Aa(n>-$exVKdHoV|1t8yh-1%f@_qI7>d{MQt&6n+Q9OLS3&d&Try1C<>j1b2I zaHkOxFaUB|wN8E8e0vi8Jo5^a$2z^!$E;J=)+4SqAe3@-1-^(WvtzWcNVod zS=rt$zP7C!_m{bb6p5Rk?&a3uHU)iUZ*v#}pHhC45!BseL1_PphPIcY`OsIzZpzE} z(n5=%H{@2Y7Z!)#&|18fA!9dt0jIonPuS(@%yT*YOxLk{h}P?!@7WH;PfiB3Gb=BZ zNW}+dg(GiE;)vm?=gUC!P&R!>M3|{rKe;hyXaEN5f)o*Ev 0 then - temp = container[i].CurrentMemberNum / (container[i].CurrentMaxMemberNum) - if (temp < min and temp ~= 1) then - teamTojoin = {} - min = temp - table.insert(teamTojoin, container[i]) - elseif temp == min and temp ~= 1 then - table.insert(teamTojoin, container[i]) - end - end - end - local a = 1 - if #teamTojoin > 0 then - a = math.random(1, #teamTojoin) - return teamTojoin[a] - else - return nil - end -end diff --git a/code/['World']['Global']['Define']['ConfigModule'].ModuleScript.lua b/code/['World']['Global']['Define']['ConfigModule'].ModuleScript.lua deleted file mode 100644 index e9ad873..0000000 --- a/code/['World']['Global']['Define']['ConfigModule'].ModuleScript.lua +++ /dev/null @@ -1,18 +0,0 @@ ---- CSV表格的定义,用于CSV表格载入 --- @module Csv Defines --- @copyright Lilith Games, Avatar Team -local Config = {} - --- 服务器预加载CSV --- csv: 对应的CSV表名 --- name: Config里面的lua table名称, 可自定义, 默认和csv相同 --- ids: 表格主键, 支持多主键 -Config.ServerPreload = {} - --- 客户端预加载CSV --- csv: 对应的CSV表名 --- name: Config里面的lua table名称, 可自定义, 默认和csv相同 --- ids: 表格主键, 支持多主键 -Config.ClientPreload = {} - -return Config diff --git a/code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua b/code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua deleted file mode 100644 index 2071385..0000000 --- a/code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua +++ /dev/null @@ -1,17 +0,0 @@ ---- 全局常量的定义,全部定义在Const这张表下面,用于定义全局常量参数或者枚举类型 --- @module Constant Defines --- @copyright Lilith Games, Avatar Team -local Const = {} - --- e.g. (need DELETE) -Const.MAX_PLAYERS = 4 - ---语言枚举 -Const.LanguageEnum = { - CHS = 'CHS', -- 简体中文 - CHT = 'CHT', -- 繁体中文 - EN = 'EN', -- 英文 - JP = 'JP' -- 日文 -} - -return Const diff --git a/code/['World']['Global']['Define']['EventsModule'].ModuleScript.lua b/code/['World']['Global']['Define']['EventsModule'].ModuleScript.lua deleted file mode 100644 index 2b207d8..0000000 --- a/code/['World']['Global']['Define']['EventsModule'].ModuleScript.lua +++ /dev/null @@ -1,14 +0,0 @@ ---- CustomEvent的定义,用于事件动态生成 --- @module Event Defines --- @copyright Lilith Games, Avatar Team -local Events = {} - --- 服务器事件列表 -Events.ServerEvents = {} - --- 客户端事件列表 -Events.ClientEvents = { - --通知事件 - 'NoticeEvent' -} -return Events diff --git a/code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua b/code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua deleted file mode 100644 index 2e15412..0000000 --- a/code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua +++ /dev/null @@ -1,9 +0,0 @@ ---- 全局变量的定义,全部定义在GlobalData这张表下面,用于全局可修改的参数 ---- @module GlobalData Defines ---- @copyright Lilith Games, Avatar Team -local GlobalData = {} - --- Test only -GlobalData.PlayerData = {} - -return GlobalData diff --git a/code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua deleted file mode 100644 index 1deb376..0000000 --- a/code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua +++ /dev/null @@ -1,18 +0,0 @@ ---- 客户端模块基础类, Client Module Base Class --- @module ClientBase, Client-side --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang -local ClientBase = class('ClientBase') - -function ClientBase:GetSelf() - return self -end - ---- 加载的时候运行的代码 -function ClientBase:InitDefault(_module) - -- print(string.format('[ClientBase][%s] InitDefault()', self.name)) - -- 初始化默认监听事件 - EventUtil.LinkConnects(localPlayer.C_Event, _module, self) -end - -return ClientBase diff --git a/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua deleted file mode 100644 index 07f4be4..0000000 --- a/code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua +++ /dev/null @@ -1,169 +0,0 @@ ---- 游戏心跳 ---- @module Client Heartbeat, Client-side ---- @copyright Lilith Games, Avatar Team ---- @author Yuancheng Zhang -local ClientHeartbeat = {} - --- Localize global vars -local Setting = FrameworkConfig.Client - --- 心跳包间隔时间,单位:秒 -local HEARTBEAT_DELTA = Setting.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 HeartbeatEnum = { - CONNECT = 1, -- 在线 - DISCONNECT = 2 -- 离线 -} - --- 正在运行 -local running = false - --- 上一次服务器发来的心跳时间戳缓存 -local cache = { - sTimestamp = nil, - cTimestamp = nil -} - --- 临时变量 -local diff -- 时间戳插值 -local sTmpTs, cTmpTs -- 时间戳缓存 - ---- 打印心跳日志 -local PrintHb = Setting.ShowHeartbeatLog and function(...) - print('[Heartbeat][Client]', ...) - end or function() - end - ---! 外部接口 - ---- 初始化心跳包 -function ClientHeartbeat.Init() - print('[Heartbeat][Client] Init()') - CheckSetting() - InitEventsAndListeners() -end - ---- 开始发出心跳 -function ClientHeartbeat.Start() - print('[Heartbeat][Client] Start()') - local cTimestamp - running = true - while (running) do - Update() - wait(HEARTBEAT_DELTA) - end -end - --- 停止心跳 -function ClientHeartbeat.Stop() - print('[Heartbeat][Client] Stop()') - running = false -end - ---! 私有函数 - --- 校验心跳参数 -function CheckSetting() - assert(HEARTBEAT_DELTA >= 1, '[Heartbeat][Client] HEARTBEAT_DELTA 必须大于1秒') - assert(HEARTBEAT_THRESHOLD_1 >= HEARTBEAT_DELTA, '[Heartbeat][Client] HEARTBEAT_THRESHOLD_1 >= HEARTBEAT_DELTA') - assert( - HEARTBEAT_THRESHOLD_2 >= HEARTBEAT_THRESHOLD_1, - '[Heartbeat][Client] HEARTBEAT_THRESHOLD_2 >= HEARTBEAT_THRESHOLD_1' - ) -end - ---- 初始化事件和绑定Handler -function InitEventsAndListeners() - if localPlayer.C_Event == nil then - world:CreateObject('FolderObject', 'C_Event', localPlayer) - end - world:CreateObject('CustomEvent', 'HeartbeatS2CEvent', localPlayer.C_Event) - localPlayer.C_Event.HeartbeatS2CEvent:Connect(HeartbeatS2CEventHandler) - - -- OnPlayerJoinEvent(玩家第一次加入,类似现在的OnPlayerAdded) - -- OnPlayerRejoinEvent(玩家离线后重新进入同一个房间) - -- OnPlayerDisconnectEvent(未接收到服务器心跳,在客户端第二个阶段,玩家离线可重连,弱网,转菊花) - -- OnPlayerReconnectEvent(玩家断线后重连) - -- OnPlayerLeaveEvent(玩家彻底离开,退出房间) - world:CreateObject('CustomEvent', 'OnPlayerJoinEvent', localPlayer.C_Event) - -- world:CreateObject('CustomEvent', 'OnPlayerRejoinEvent', localPlayer.C_Event) - world:CreateObject('CustomEvent', 'OnPlayerDisconnectEvent', localPlayer.C_Event) - world:CreateObject('CustomEvent', 'OnPlayerReconnectEvent', localPlayer.C_Event) - world:CreateObject('CustomEvent', 'OnPlayerLeaveEvent', localPlayer.C_Event) - - -- 掉线直接退出(默认,可选) - localPlayer.C_Event.OnPlayerLeaveEvent:Connect(QuitGame) -end - --- Update心跳 -function Update() - cTmpTs = Timer.GetTimeMillisecond() - sTmpTs = cache.sTimestamp - PrintHb(string.format('=> C = %s, S = %s, %s', cTmpTs, sTmpTs, localPlayer)) - CheckPlayerState(p, cTmpTs) - NetUtil.Fire_S('HeartbeatC2SEvent', localPlayer, cTmpTs, sTmpTs) -end - ---- 心跳事件Handler -function HeartbeatS2CEventHandler(_stimestamp, _cTimestamp) - if not running then - return - end - PrintHb(string.format('<= C = %s, S = %s, %s', _cTimestamp, _stimestamp, localPlayer)) - CheckPlayerJoin(_player, _sTimestamp) - cache.sTimestamp = _stimestamp - cache.cTimestamp = _cTimestamp -end - ---- 收包时,检查玩家是否连接服务器,或者重新连接服务器 -function CheckPlayerJoin(_player, _sTimestamp) - if not cache.sTimestamp then - --* 玩家新加入 OnPlayerJoinEvent - print('[Heartbeat][Client] OnPlayerJoinEvent, 新玩家加入,', localPlayer) - NetUtil.Fire_C('OnPlayerJoinEvent', localPlayer) - cache.state = HeartbeatEnum.CONNECT - elseif cache.state == HeartbeatEnum.DISCONNECT then - --* 玩家断线重连 OnPlayerReconnectEvent - print('[Heartbeat][Client] OnPlayerReconnectEvent, 玩家断线重连,', localPlayer) - NetUtil.Fire_C('OnPlayerReconnectEvent', localPlayer) - cache.state = HeartbeatEnum.CONNECT - end -end - ---- 发包时,检查玩家是否连接服务器 -function CheckPlayerState(_player, _cTimestamp) - if not cache.cTimestamp then - return - end - diff = _cTimestamp - cache.cTimestamp - PrintHb(string.format('==========================================> diff = %s, %s', diff * .001, localPlayer)) - if diff < HEARTBEAT_THRESHOLD_1 then - --* 玩家在线 - cache.state = HeartbeatEnum.CONNECT - elseif cache.state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then - --* 玩家断线,弱网环境 - 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 - --* 玩家断线, 退出游戏 - -- QuitGame() - NetUtil.Fire_C('OnPlayerLeaveEvent', localPlayer) - end -end - ---- 退出游戏 -function QuitGame() - print('[Heartbeat][Client] Game.Quit(), 玩家退出游戏') - Game.Quit() -end - -return ClientHeartbeat diff --git a/code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua deleted file mode 100644 index fc59abd..0000000 --- a/code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua +++ /dev/null @@ -1,151 +0,0 @@ ---- 游戏客户端主逻辑 --- @module Game Manager, Client-side --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang -local Client = {} - --- Localize global vars -local CsvUtil, XslUitl, ModuleUtil = CsvUtil, XslUitl, ModuleUtil -local Config = FrameworkConfig.Client - --- 已经初始化,正在运行 -local initialized, running = false, false - --- 含有InitDefault(),Init(),Update()的模块列表 -local initDefaultList, initList, updateList = {}, {}, {} - ---- 运行客户端 -function Client:Run() - print('[Client] Run()') - InitClient() - StartUpdate() -end - ---- 停止Update -function Client:Stop() - print('[Client] Stop()') - running = false - ClientHeartbeat.Stop() -end - ---- 初始化 -function InitClient() - if initialized then - return - end - print('[Client] InitClient()') - InitRandomSeed() - InitHeartbeat() - InitClientCustomEvents() - PreloadCsv() - GenInitAndUpdateList() - RunInitDefault() - InitOtherModules() - initialized = true -end - ---- 初始化心跳包 -function InitHeartbeat() - assert(ClientHeartbeat, '[Client][Heartbeat] 找不到ClientHeartbeat,请联系张远程') - ClientHeartbeat.Init() -end - ---- 初始化客户端的CustomEvent -function InitClientCustomEvents() - if localPlayer.C_Event == nil then - world:CreateObject('FolderObject', 'C_Event', localPlayer) - end - - -- 将插件中的CustomEvent放入Events.ClientEvents中 - for _, m in pairs(Config.PluginEvents) do - local evts = _G[m].ClientEvents - assert(evts, string.format('[Client] %s 中不存在ClientEvents,请检查模块,或从FrameworkConfig删除此配置', m)) - for __, evt in pairs(evts) do - if not table.exists(Events.ClientEvents, evt) then - table.insert(Events.ClientEvents, evt) - end - end - end - - -- 生成CustomEvent节点 - for _, evt in pairs(Events.ClientEvents) do - if localPlayer.C_Event[evt] == nil then - world:CreateObject('CustomEvent', evt, localPlayer.C_Event) - end - end -end - ---- 生成需要Init和Update的模块列表 -function GenInitAndUpdateList() - ModuleUtil.GetModuleListWithFunc(Module.C_Module, 'InitDefault', initDefaultList) - ModuleUtil.GetModuleListWithFunc(Module.C_Module, 'Init', initList) - ModuleUtil.GetModuleListWithFunc(Module.C_Module, 'Update', updateList) - for _, m in pairs(Config.PluginModules) do - ModuleUtil.GetModuleListWithFunc(m, 'InitDefault', initDefaultList) - ModuleUtil.GetModuleListWithFunc(m, 'Init', initList) - ModuleUtil.GetModuleListWithFunc(m, 'Update', updateList) - end -end - ---- 执行默认的Init方法 -function RunInitDefault() - for _, m in ipairs(initDefaultList) do - m:InitDefault(m) - end -end - ---- 初始化客户端随机种子 -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 - m:Init() - end -end - ---- 开始Update -function StartUpdate() - print('[Client] StartUpdate()') - assert(not running, '[Client] StartUpdate() 正在运行') - - running = true - - -- 开启心跳 - if FrameworkConfig.HeartbeatStart then - invoke(ClientHeartbeat.Start) - end - - local dt = 0 -- delta time 每帧时间 - local tt = 0 -- total time 游戏总时间 - local now = Timer.GetTimeMillisecond --时间函数缓存 - local prev, curr = now() / 1000, nil -- two timestamps - - while (running and wait()) do - curr = now() / 1000 - dt = curr - prev - tt = tt + dt - prev = curr - UpdateClient(dt, tt) - end -end - ---- Update函数 --- @param dt delta time 每帧时间 -function UpdateClient(_dt, _tt) - for _, m in ipairs(updateList) do - m:Update(_dt, _tt) - end -end - -return Client diff --git a/code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua deleted file mode 100644 index f0a515c..0000000 --- a/code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua +++ /dev/null @@ -1,42 +0,0 @@ ---- 框架配置 ---- @module Framework Global FrameworkConfig ---- @copyright Lilith Games, Avatar Team ---- @author Yuancheng Zhang -local FrameworkConfig = { - -- 启动心跳 - HeartbeatStart = true, - Server = { - -- 心跳包间隔时间,单位:秒 - HeartbeatDelta = 1, - -- 心跳阈值,单位:秒,范围定义如下: - -- 0s -> threshold_1 : connected - -- threshold_1 -> threshold_2 : disconnected, but player can reconnect - -- threshold_2 -> longer : disconnected, remove player - HeartbeatThreshold1 = 5, - HeartbeatThreshold2 = 10, - -- 显示心跳日志 - ShowHeartbeatLog = false, - -- 插件中需要使用声明周期的服务器模块目录 - PluginModules = {}, - -- 插件中服务器需要生成的CustomEvent, 模块中必须得有ServerEvents - PluginEvents = {} - }, - Client = { - -- 心跳包间隔时间,单位:秒 - HeartbeatDelta = 1, - -- 心跳阈值,单位:秒,范围定义如下: - -- 0s -> threshold_1 : connected - -- threshold_1 -> threshold_2 : disconnected, weak network, can reconnect - -- threshold_2 -> longer : disconnected, quit server - HeartbeatThreshold1 = 5, - HeartbeatThreshold2 = 10, - -- 显示心跳日志 - ShowHeartbeatLog = false, - -- 插件中需要使用声明周期的客户端模块目录 - PluginModules = {}, - -- 插件中客户端需要生成的CustomEvent,模块中必须得有ClientEvents - PluginEvents = {} - } -} - -return FrameworkConfig diff --git a/code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua deleted file mode 100644 index 213f46e..0000000 --- a/code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua +++ /dev/null @@ -1,18 +0,0 @@ ---- 服务器模块基础类, Server Module Base Class --- @module ServerBase, Server-side --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang -local ServerBase = class('ServerBase') - -function ServerBase:GetSelf() - return self -end - ---- 加载的时候运行的代码 -function ServerBase:InitDefault(_module) - -- print(string.format('[ServerBase][%s] InitDefault()', self.name)) - -- 初始化默认监听事件 - EventUtil.LinkConnects(world.S_Event, _module, self) -end - -return ServerBase diff --git a/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua deleted file mode 100644 index d79c0bf..0000000 --- a/code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua +++ /dev/null @@ -1,180 +0,0 @@ ---- 游戏服务器心跳 ---- @module Server Heartbeat, Server-side ---- @copyright Lilith Games, Avatar Team ---- @author Yuancheng Zhang -local ServerHeartbeat = {} - --- Localize global vars -local Setting = FrameworkConfig.Server - --- 心跳包间隔时间,单位:秒 -local HEARTBEAT_DELTA = Setting.HeartbeatDelta - --- 心跳阈值,单位:秒,范围定义如下: --- 0s -> threshold_1 : connected --- threshold_1 -> threshold_2 : disconnected, but player can rejoin --- threshold_2 -> longer : disconnected, remove player -local HEARTBEAT_THRESHOLD_1 = Setting.HeartbeatThreshold1 * 1000 -- second => ms -local HEARTBEAT_THRESHOLD_2 = Setting.HeartbeatThreshold2 * 1000 -- second => ms - --- 玩家心跳连接状态 -local HeartbeatEnum = { - CONNECT = 1, -- 在线 - DISCONNECT = 2 -- 离线 -} - --- 正在运行 -local running = false - --- 上一次客户端发来的心跳时间戳缓存 -local cache = {} - --- 临时变量 -local diff -- 时间戳插值 -local sTmpTs, cTmpTs -- 时间戳缓存 - ---- 打印心跳日志 -local PrintHb = Setting.ShowHeartbeatLog and function(...) - print('[Heartbeat][Server]', ...) - end or function() - end - ---! 外部接口 - ---- 初始化心跳包 -function ServerHeartbeat.Init() - print('[Heartbeat][Server] Init()') - CheckSetting() - InitEventsAndListeners() -end - ---- 开始发出心跳 -function ServerHeartbeat.Start() - print('[Heartbeat][Server] Start()') - running = true - while (running) do - Update() - wait(HEARTBEAT_DELTA) - end -end - ---- 停止心跳 -function ServerHeartbeat.Stop() - print('[Heartbeat][Server] Stop()') - running = false -end - ---! 私有函数 - ---- 校验心跳参数 -function CheckSetting() - assert(HEARTBEAT_DELTA >= 1, '[Heartbeat][Server] HEARTBEAT_DELTA 必须大于1秒') - assert(HEARTBEAT_THRESHOLD_1 >= HEARTBEAT_DELTA, '[Heartbeat][Server] HEARTBEAT_THRESHOLD_1 >= HEARTBEAT_DELTA') - assert( - HEARTBEAT_THRESHOLD_2 >= HEARTBEAT_THRESHOLD_1, - '[Heartbeat][Server] HEARTBEAT_THRESHOLD_2 >= HEARTBEAT_THRESHOLD_1' - ) -end - ---- 初始化事件和绑定Handler -function InitEventsAndListeners() - if world.S_Event == nil then - world:CreateObject('FolderObject', 'S_Event', world) - end - world:CreateObject('CustomEvent', 'HeartbeatC2SEvent', world.S_Event) - world.S_Event.HeartbeatC2SEvent:Connect(HeartbeatC2SEventHandler) - - -- OnAwakeEvent(玩家加入前初始化) - -- OnPlayerJoinEvent(玩家第一次加入,类似现在的OnPlayerAdded) - -- OnPlayerRejoinEvent(玩家离开房间后重新进入同一个房间) - -- OnPlayerDisconnectEvent(未接收到玩家心跳等待重连,在服务器第二个阶段) - -- OnPlayerReconnectEvent(玩家断线后重连) - -- OnPlayerLeaveEvent(玩家彻底离开,退出房间) - world:CreateObject('CustomEvent', 'OnAwakeEvent', world.S_Event) - world:CreateObject('CustomEvent', 'OnPlayerJoinEvent', world.S_Event) - -- world:CreateObject('CustomEvent', 'OnPlayerRejoinEvent', world.S_Event) - world:CreateObject('CustomEvent', 'OnPlayerDisconnectEvent', world.S_Event) - world:CreateObject('CustomEvent', 'OnPlayerReconnectEvent', world.S_Event) - world:CreateObject('CustomEvent', 'OnPlayerLeaveEvent', world.S_Event) - - -- 玩家退出,发出OnPlayerLeaveEvent - world.OnPlayerRemoved:Connect( - function(_player) - if cache[_player] then - print('[Heartbeat][Server] OnPlayerLeaveEvent, 玩家主动离开游戏,', _player) - NetUtil.Fire_S('OnPlayerLeaveEvent', _player) - end - end - ) -end - ---- Update心跳 -function Update() - for p, v in pairs(cache) do - if p and not p:IsNull() then - sTmpTs = Timer.GetTimeMillisecond() - cTmpTs = v.cTimestamp - PrintHb(string.format('=> S = %s, C = %s, %s', sTmpTs, cTmpTs, p)) - CheckPlayerStates(p, sTmpTs) - NetUtil.Fire_C('HeartbeatS2CEvent', p, sTmpTs, cTmpTs) - else - --* remove nil key from cache - cache[p] = nil - end - end -end - ---- 心跳事件Handler -function HeartbeatC2SEventHandler(_player, _cTimestamp, _sTimestamp) - if not running then - return - end - PrintHb(string.format('<= S = %s, C = %s, %s', _sTimestamp, _cTimestamp, _player)) - CheckPlayerJoin(_player) - cache[_player].cTimestamp = _cTimestamp - cache[_player].sTimestamp = _sTimestamp -end - ---- 收包时,检查玩家是否加入或重连 -function CheckPlayerJoin(_player) - if not cache[_player] then - --* 玩家新加入 OnPlayerJoinEvent - print('[Heartbeat][Server] OnPlayerJoinEvent, 新玩家加入,', _player) - NetUtil.Fire_S('OnPlayerJoinEvent', _player) - cache[_player] = { - state = HeartbeatEnum.CONNECT - } - elseif cache[_player].state == HeartbeatEnum.DISCONNECT then - --* 玩家断线重连 OnPlayerReconnectEvent - print('[Heartbeat][Server] OnPlayerReconnectEvent, 玩家断线重连,', _player) - NetUtil.Fire_S('OnPlayerReconnectEvent', _player) - cache[_player].state = HeartbeatEnum.CONNECT - end -end - ---- 发包时,检查玩家是否掉线 -function CheckPlayerStates(_player, _sTimestam) - if not cache[_player].sTimestamp then - return - end - diff = _sTimestam - cache[_player].sTimestamp - PrintHb(string.format('==========================================> diff = %s, %s', diff * .001, _player)) - if diff < HEARTBEAT_THRESHOLD_1 then - --* 玩家在线 - cache[_player].state = HeartbeatEnum.CONNECT - elseif cache[_player].state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then - --* 玩家断线 OnPlayerDisconnectEvent - print('[Heartbeat][Server] OnPlayerDisconnectEvent, 玩家离线, 等待断线重连,', _player) - NetUtil.Fire_S('OnPlayerDisconnectEvent', _player) - cache[_player].state = HeartbeatEnum.DISCONNECT - elseif cache[_player].state == HeartbeatEnum.DISCONNECT and diff >= HEARTBEAT_THRESHOLD_2 then - --* 玩家彻底断线,剔除玩家 OnPlayerLeaveEvent - print('[Heartbeat][Server] OnPlayerLeaveEvent, 剔除离线玩家,', _player) - NetUtil.Fire_S('OnPlayerLeaveEvent', _player) - print('[Heartbeat][Server] OnPlayerLeave, 发送客户端离线事件,', _player) - NetUtil.Fire_C('OnPlayerLeaveEvent', _player) - cache[_player] = nil - end -end - -return ServerHeartbeat diff --git a/code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua b/code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua deleted file mode 100644 index 199de55..0000000 --- a/code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua +++ /dev/null @@ -1,154 +0,0 @@ ---- 游戏服务器主逻辑 ---- @module Game Server, Server-side ---- @copyright Lilith Games, Avatar Team ---- @author Yuancheng Zhang -local Server = {} - --- Localize global vars -local CsvUtil, ModuleUtil = CsvUtil, ModuleUtil -local Config = FrameworkConfig.Server - --- 已经初始化,正在运行 -local initialized, running = false, false - --- 含有InitDefault(),Init(),Update()的模块列表 -local initDefaultList, initList, updateList = {}, {}, {} - ---- 运行服务器 -function Server:Run() - print('[Server] Run()') - InitServer() - StartUpdate() -end - ---- 停止Update -function Server:Stop() - print('[Server] Stop()') - running = false - ServerHeartbeat.Stop() -end - ---- 初始化 -function InitServer() - if initialized then - return - end - print('[Server] InitServer()') - InitRandomSeed() - InitHeartbeat() - InitServerCustomEvents() - InitCsvAndXls() - GenInitAndUpdateList() - RunInitDefault() - InitOtherModules() - initialized = true -end - ---- 初始化服务器的CustomEvent -function InitServerCustomEvents() - print('[Server] InitServerCustomEvents()') - if world.S_Event == nil then - world:CreateObject('FolderObject', 'S_Event', world) - end - - -- 将插件中的CustomEvent放入Events.ClientEvents中 - for _, m in pairs(Config.PluginEvents) do - local evts = _G[m].ServerEvents - assert(evts, string.format('[Server] %s 中不存在ServerEvents,请检查模块,或从FrameworkConfig删除此配置', m)) - for __, evt in pairs(evts) do - if not table.exists(Events.ServerEvents, evt) then - table.insert(Events.ServerEvents, evt) - end - end - end - - -- 生成CustomEvent节点 - for _, evt in pairs(Events.ServerEvents) do - if world.S_Event[evt] == nil then - world:CreateObject('CustomEvent', evt, world.S_Event) - end - end -end - ---- 初始化心跳包 -function InitHeartbeat() - assert(ServerHeartbeat, '[Server][Heartbeat] 找不到ServerHeartbeat,请联系张远程') - ServerHeartbeat.Init() -end - ---- 生成框架需要的节点 -function InitCsvAndXls() - if not world.Global.Csv then - world:CreateObject('FolderObject', 'Csv', world.Global) - end - if not world.Global.Xls then - world:CreateObject('FolderObject', 'Xls', world.Global) - end -end - ---- 生成需要Init和Update的模块列表 -function GenInitAndUpdateList() - ModuleUtil.GetModuleListWithFunc(Module.S_Module, 'InitDefault', initDefaultList) - ModuleUtil.GetModuleListWithFunc(Module.S_Module, 'Init', initList) - ModuleUtil.GetModuleListWithFunc(Module.S_Module, 'Update', updateList) - for _, m in pairs(FrameworkConfig.Server.PluginModules) do - ModuleUtil.GetModuleListWithFunc(m, 'InitDefault', initDefaultList) - ModuleUtil.GetModuleListWithFunc(m, 'Init', initList) - ModuleUtil.GetModuleListWithFunc(m, 'Update', updateList) - end -end - ---- 执行默认的Init方法 -function RunInitDefault() - for _, m in ipairs(initDefaultList) do - m:InitDefault(m) - end -end - ---- 初始化服务器随机种子 -function InitRandomSeed() - math.randomseed(os.time()) -end - ---- 初始化包含Init()方法的模块 -function InitOtherModules() - for _, m in ipairs(initList) do - m:Init() - end -end - ---- 开始Update -function StartUpdate() - print('[Server] StartUpdate()') - assert(not running, '[Server] StartUpdate() 正在运行') - - running = true - - -- 开启心跳 - if FrameworkConfig.HeartbeatStart then - invoke(ServerHeartbeat.Start) - end - - local dt = 0 -- delta time 每帧时间 - local tt = 0 -- total time 游戏总时间 - local now = Timer.GetTimeMillisecond --时间函数缓存 - local prev, curr = now() / 1000, nil -- two timestamps - - while (running and wait()) do - curr = now() / 1000 - dt = curr - prev - tt = tt + dt - prev = curr - UpdateServer(dt, tt) - end -end - ---- Update函数 ---- @param dt delta time 每帧时间 -function UpdateServer(_dt, _tt) - for _, m in ipairs(updateList) do - m:Update(_dt, _tt) - end -end - -return Server diff --git a/code/['World']['Global']['LuaFunctionScript'].Script.lua b/code/['World']['Global']['LuaFunctionScript'].Script.lua deleted file mode 100644 index 02fe3c5..0000000 --- a/code/['World']['Global']['LuaFunctionScript'].Script.lua +++ /dev/null @@ -1,968 +0,0 @@ ---- 提供一组常用函数,以及对 Lua 标准库的扩展 --- @script Lua function extension libraries --- @author Lilith Games, Avatar Team --- @see https://wiki.lilithgames.com/x/tSkMAg - ---- 检查并尝试转换为数值,如果无法转换则返回 0 --- @param mixed value 要检查的值 --- @param [integer base] 进制,默认为十进制 --- @return number -function checknumber(value, base) - return tonumber(value, base) or 0 -end - ---- 检查是否是有效的number类型 --- @param number -function isValidNumber(num) - return num ~= nil and num > 0 -end - ---- 检查并尝试转换为整数,如果无法转换则返回 0 --- @param mixed value 要检查的值 --- @return integer -function checkint(value) - return math.round(checknumber(value)) -end - ---- 检查并尝试转换为布尔值,除了 nil 和 false,其他任何值都会返回 true --- @param mixed value 要检查的值 --- @return boolean -function checkbool(value) - return (value ~= nil and value ~= false) -end - ---- 检查值是否是一个表格,如果不是则返回一个空表格 --- @param mixed value 要检查的值 --- @return table -function checktable(value) - if type(value) ~= 'table' then - value = {} - end - return value -end - ---- 处理对象 --- @param mixed obj Lua 对象 --- @param function method 对象方法 --- @return function -function handler(obj, method) - return function(...) - return method(obj, ...) - end -end - ---- 计算表格包含的字段数量 --- Lua table 的 "#" 操作只对依次排序的数值下标数组有效,table.nums() 则计算 table 中所有不为 nil 的值的个数。 --- @param table -function table.nums(t) - if t == nil then - return 0 - end - local count = 0 - for _ in pairs(t) do - count = count + 1 - end - return count -end - ---- 返回指定表格中的所有键 --- @param k-v table --- @return keys' table --- @usage example --- local hashtable = {a = 1, b = 2, c = 3} --- local keys = table.keys(hashtable) --- >> keys = {"a", "b", "c"} -function table.keys(hashtable) - local keys = {} - for k, _ in pairs(hashtable) do - table.insert(keys, k) - end - return keys -end - ---- 返回指定表格中的所有值 --- @param k-v table --- @return values' table --- @usage example --- local hashtable = {a = 1, b = 2, c = 3} --- local values = table.values(hashtable) --- >> values = {1, 2, 3} -function table.values(hashtable) - local values = {} - local i = 1 - for k, v in pairs(hashtable) do - values[i] = v - i = i + 1 - end - return values -end - ---- 将来源表格中所有键及其值复制到目标表格对象中,如果存在同名键,则覆盖其值 --- @param target table --- @param source table --- @usage example --- local dest = {a = 1, b = 2} --- local src = {c = 3, d = 4} --- table.merge(dest, src) --- >> dest = {a = 1, b = 2, c = 3, d = 4} -function table.merge(dest, src) - for k, v in pairs(src) do - dest[k] = v - end -end - ---- 深度将来源表格中所有键及其值复制到目标表格对象中,如果存在同名键,则覆盖其值,如果存在子表,则遍历子表进行复制 -function table.deepMerge(dest, src) - for k, v in pairs(src) do - if type(v) == 'table' then - if dest[k] == nil then - dest[k] = {} - end - table.deepMerge(dest[k], v) - else - dest[k] = v - end - end -end - ---- 将来源表格中所有键及其值复制到目标表格对象中,如果存在同名键,则覆盖其值 --- @param ... 多个表,第一个是目标表格 --- @return 返回一个新表 ----@author Sharif Ma -function table.MergeTables(...) - local tabs = {...} - if not tabs or #tabs == 0 then - return {} - end - local origin = {} - for k, v in pairs(tabs[1]) do - origin[k] = v - end - for i = 2, #tabs do - if origin then - if tabs[i] then - for _, v in pairs(tabs[i]) do - table.insert(origin, v) - end - end - else - origin = tabs[i] - end - end - return origin -end - ---- 在目标表格的指定位置插入来源表格,如果没有指定位置则连接两个表格 --- @param target table --- @param source table --- @param start index --- @usage example #1 --- local dest = {1, 2, 3} --- local src = {4, 5, 6} --- table.insertto(dest, src) --- >> dest = {1, 2, 3, 4, 5, 6} --- @usage example #2 --- local dest = {1, 2, 3} --- local src = {4, 5, 6} --- table.insertto(dest, src, 5) --- >> dest = {1, 2, 3, nil, 4, 5, 6} -function table.insertto(dest, src, begin) - if begin == nil then - begin = #dest + 1 - else - begin = checkint(begin) - if begin <= 0 then - begin = #dest + 1 - end - end - - local len = #src - for i = 0, len - 1 do - dest[i + begin] = src[i + 1] - end -end - ---- 从表格中查找指定值,返回其索引,如果没找到返回 false --- @param array table --- @param target value --- @param start index --- @return index or false --- @usage example --- local array = {"a", "b", "c"} --- print(table.indexof(array, "b")) --- >> 2 -function table.indexof(array, value, begin) - if array ~= nil then - for i = begin or 1, #array do - if array[i] == value then - return i - end - end - end - return 0 -end - ---- 检查表格中是否存在指定值 --- @param array table --- @param target value --- @return @boolean -function table.exists(array, value) - return table.indexof(array, value) > 0 -end - ---- 清空数组表格 --- @param array table -function table.cleararray(array) - if array ~= nil then - local count = #array - while count > 0 do - table.remove(array, count) - count = #array - end - end -end - ---- 清空k-v表格 --- @param k-v table -function table.clearhashtable(hashtable) - if hashtable ~= nil then - for k, v in pairs(hashtable) do - hashtable[k] = nil - end - end -end - ---- 清空表格 --- @param table --- @see table.clearhashtable -function table.cleartable(t) - table.clearhashtable(t) -end - ---- 截取Array其中一段,startIndex从1开始 return截取后的新数组 --- @param table array table --- @param @number start index --- @param @number length --- @return @table array table --- @usage example --- local array = {"a", "b", "c", "d"} --- print(table.subArray(array, 2, 2)) --- >> {"b", "c"} -function table.subArray(array, startIndex, length) - if array ~= nil then - local count = table.nums(array) - local tempArray = array - array = {} - if startIndex <= count then - local maxlength = count - startIndex + 1 - length = length > maxlength and maxlength or length - local endIndex = startIndex + length - 1 - for i = startIndex, endIndex do - table.insert(array, tempArray[i]) - end - end - end - return array -end - ---- 截取Array的后半段,startIndex从1开始 return截取后的新数组 --- @param table array table --- @param @number start index --- @return @table array table -function table.subArrayByStartIndex(array, startIndex) - if array ~= nil then - local count = table.nums(array) - local length = count - startIndex + 1 - return table.subArray(array, startIndex, length) - end - return array -end - ---- 从表格中查找指定值,返回其 key,如果没找到返回 nil --- @param table hash table --- @param any value --- @return key of value --- @usage --- local hashtable = {name = "dualface", comp = "chukong"} --- print(table.keyof(hashtable, "chukong")) --- >> comp -function table.keyof(hashtable, value) - for k, v in pairs(hashtable) do - if v == value then - return k - end - end - return nil -end - ---- 从表格中删除指定值,返回删除的值的个数 --- @usage --- local array = {"a", "b", "c", "c"} --- print(table.removebyvalue(array, "c", true)) --- >> 输出 2 -function table.removebyvalue(array, value, removeall) - local c, i, max = 0, 1, #array - while i <= max do - if array[i] == value then - table.remove(array, i) - c = c + 1 - i = i - 1 - max = max - 1 - if not removeall then - break - end - end - i = i + 1 - end - return c -end - ---- 数组混淆 -function table.shuffle(_tbl) - local j - for i = #_tbl, 2, -1 do - j = math.random(i) - _tbl[i], _tbl[j] = _tbl[j], _tbl[i] - end - return _tbl -end - ---- 对表格中每一个值执行一次指定的函数,并用函数返回值更新表格内容 --- @param table --- @param function fn 参数指定的函数具有两个参数,并且返回一个值。原型如下: --- function map_function(value, key) --- return value --- end --- @usage --- local t = {name = "dualface", comp = "chukong"} --- table.map(t, function(v, k) --- -- 在每一个值前后添加括号 --- return "[" .. v .. "]" --- end) --- 输出修改后的表格内容 --- for k, v in pairs(t) do --- print(k, v) --- end --- >> 输出 --- name [dualface] --- comp [chukong] -function table.map(t, fn) - for k, v in pairs(t) do - t[k] = fn(v, k) - end -end - ---- 对表格中每一个值执行一次指定的函数,但不改变表格内容 --- @param table --- @param function fn 参数指定的函数具有两个参数,没有返回值。原型如下: --- function map_function(value, key) --- -- no return here --- end --- @usage --- local t = {name = "dualface", comp = "chukong"} --- table.walk(t, function(v, k) --- -- 输出每一个值 --- print(v) --- end) -function table.walk(t, fn) - for k, v in pairs(t) do - fn(v, k) - end -end - ---- 对表格中每一个值执行一次指定的函数,如果该函数返回 false,则对应的值会从表格中删除 --- @param table --- @param function fn 参数指定的函数具有两个参数,并且返回一个 boolean 值。原型如下: --- !!!!该方法有局限性,执行后会修改原表格t中值 --- function map_function(value, key) --- return true or false --- end --- @usage --- local t = {name = "dualface", comp = "chukong"} --- table.filter(t, function(v, k) --- return v ~= "dualface" -- 当值等于 dualface 时过滤掉该值 --- end) --- 输出修改后的表格内容 --- for k, v in pairs(t) do --- print(k, v) --- end --- >> 输出 comp chukong -function table.filter(t, fn) - for k, v in pairs(t) do - if not fn(v, k) then - t[k] = nil - end - end -end - ---- 找到表格中每个符合matchFunc的条目 --- @param array table --- @param match function, return T/F --- @return all elements matched, default is {} -function table.findAll(array, matchFunc) - local ret, idx = {}, 1 - for i = 1, #array do - if matchFunc(array[i]) then - ret[idx] = array[i] - idx = idx + 1 - end - end - return ret -end - ---- 找到表格中每个符合matchFunc的条目,并执行walkFunc --- @param array table --- @param match function, return T/F --- @param walk function -function table.findAllAndWalk(array, matchFunc, walkFunc) - for i = 1, #array do - if matchFunc(array[i]) then - walkFunc(array[i]) - end - end -end - ---- 在表格中插入一个新值 --- @param array table --- @param new element -function table.insert_once(T, elem) - for _, v in ipairs(T) do - if v == elem then - return - end - end - table.insert(T, elem) -end - ---- 遍历表格,确保其中的值唯一 --- @function [parent=#table] unique --- @param table t 表格 --- @param boolean bArray t是否是数组,是数组,t中重复的项被移除后,后续的项会前移 --- @return table#table 包含所有唯一值的新表格 --- @usage --- 遍历表格,确保其中的值唯一 --- local t = {"a", "a", "b", "c"} -- 重复的 a 会被过滤掉 --- local n = table.unique(t) --- for k, v in pairs(n) do --- print(v) --- end --- >> 输出 a b c -function table.unique(t, bArray) - local check = {} - local n = {} - local idx = 1 - for k, v in pairs(t) do - if not check[v] then - if bArray then - n[idx] = v - idx = idx + 1 - else - n[k] = v - end - check[v] = true - end - end - return n -end - ---- table 深度复制 --- @param table --- @return a net table with same data -function table.deepcopy(object) - local lookup_table = {} - local function _copy(object) - if type(object) ~= 'table' then - return object - elseif lookup_table[object] then - return lookup_table[object] - end - local new_table = {} - lookup_table[object] = new_table - for key, value in pairs(object) do - new_table[_copy(key)] = _copy(value) - end - return setmetatable(new_table, getmetatable(object)) - end - return _copy(object) -end - ---- table 浅度复制(不处理metatable) -function table.shallowcopy(orig) - local orig_type = type(orig) - local copy - if orig_type == 'table' then - copy = {} - for orig_key, orig_value in next, orig, nil do - copy[table.shallowcopy(orig_key)] = table.shallowcopy(orig_value) - end - else - copy = orig - end - return copy -end - ---- 获取or创建一个子表 -function table.need(tb, key) - if type(tb) == 'table' then - local subTb = tb[key] - if subTb == nil then - subTb = {} - tb[key] = subTb - end - return subTb - end - return -end - ---- 打印table中的所有内容 --- @param data table --- @param @boolean showMetatable 是否显示元表 -function table.dump(data, showMetatable) - local result, tab = {}, ' ' - local function _dump(data, showMetatable, lastCount) - if type(data) ~= 'table' then - if type(data) == 'string' then - table.insert(result, '"') - table.insert(result, data) - table.insert(result, '"') - else - table.insert(result, tostring(data)) - end - else - --Format - local count = lastCount or 0 - count = count + 1 - table.insert(result, '{\n') - --Metatable - if showMetatable then - for i = 1, count do - table.insert(result, tab) - end - local mt = getmetatable(data) - table.insert(result, '"__metatable" = ') - _dump(mt, showMetatable, count) - table.insert(result, ',\n') - end - --Key - for key, value in pairs(data) do - for i = 1, count do - table.insert(result, tab) - end - if type(key) == 'string' then - table.insert(result, '"') - table.insert(result, key) - table.insert(result, '" = ') - elseif type(key) == 'number' then - table.insert(result, '[') - table.insert(result, key) - table.insert(result, '] = ') - else - table.insert(result, tostring(key)) - end - _dump(value, showMetatable, count) - table.insert(result, ',\n') - end - --Format - for i = 1, lastCount or 0 do - table.insert(result, tab) - end - table.insert(result, '}') - end - --Format - if not lastCount then - table.insert(result, '\n') - end - end - _dump(data, showMetatable, 0) - - -- print('dump: \n' .. table.concat(result)) - return 'dump: \n' .. table.concat(result) -end - ---- 用指定字符或字符串分割输入字符串,返回包含分割结果的数组 --- @param @string input 输入的字符串 --- @param @string delimiter 分隔符 --- @return array --- @usage example #1 --- local input = "Hello,World" --- local res = string.split(input, ",") --- >> res = {"Hello", "World"} --- @usage example #2 --- local input = "Hello-+-World-+-Quick" --- local res = string.split(input, "-+-") --- >> res = {"Hello", "World", "Quick"} -function string.split(input, delimiter) - input = tostring(input) - delimiter = tostring(delimiter) - if (delimiter == '') then - return false - end - local pos, arr = 0, {} - -- for each divider found - for st, sp in function() - return string.find(input, delimiter, pos, true) - end do - table.insert(arr, string.sub(input, pos, st - 1)) - pos = sp + 1 - end - table.insert(arr, string.sub(input, pos)) - return arr -end - ---- 判断字符串是否为空或者长度为零 --- @param @string 输入的字符串 -function string.isnilorempty(inputStr) - return inputStr == nil or inputStr == '' -end - ---- 去除输入字符串头部的空白字符,返回结果 --- @param @string input --- @return @string --- @usage example --- local input = " ABC" --- print(string.ltrim(input)) --- >> 输出 ABC,输入字符串前面的两个空格被去掉了 --- 空白字符包括: --- - 空格 --- - 制表符 \t --- - 换行符 \n --- - 回到行首符 \r -function string.ltrim(input) - return string.gsub(input, '^[ \t\n\r]+', '') -end - ---- 去除输入字符串尾部的空白字符,返回结果 --- @param @string input --- @return @string --- @usage example --- local input = "ABC " --- print(string.rtrim(input)) --- >> 输出 ABC,输入字符串最后的两个空格被去掉了 -function string.rtrim(input) - return string.gsub(input, '[ \t\n\r]+$', '') -end - ---- 去掉字符串首尾的空白字符,返回结果 --- @param @string input --- @return @string -function string.trim(input) - input = string.gsub(input, '^[ \t\n\r]+', '') - return string.gsub(input, '[ \t\n\r]+$', '') -end - ---- 将字符串的第一个字符转为大写,返回结果 --- @param @string input --- @return @string --- @usage example --- local input = "hello" --- print(string.ucfirst(input)) --- >> 输出 Hello -function string.ucfirst(input) - return string.upper(string.sub(input, 1, 1)) .. string.sub(input, 2) -end - -function string.firstToUpper(str) - return (str:gsub('^%l', string.upper)) -end - ---- 计算 UTF8 字符串的长度,每一个中文算一个字符 --- @param @string input --- @return @number cnt --- @usage example --- local input = "你好World" --- print(string.utf8len(input)) --- >> 输出 7 -function string.utf8len(input) - local len = string.len(input) - local left = len - local cnt = 0 - local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc} - while left ~= 0 do - local tmp = string.byte(input, -left) - local i = #arr - while arr[i] do - if tmp >= arr[i] then - left = left - i - break - end - i = i - 1 - end - cnt = cnt + 1 - end - return cnt -end - ---- 替换字符串内容 --- @param @string input --- @param @number start index --- @param new context --- @return a new string -function string.replace(str, index, char) - return table.concat {str:sub(1, index - 1), char, str:sub(index + 1)} -end - ---- 检查字符串是否为指定字符串开头 --- @param @string target --- @param @string start --- @return @boolean -function string.startswith(str, start) - return str:sub(1, #start) == start -end - ---- 检查字符串是否以指定字符串结尾 --- @param @string target --- @param @string start --- @return @boolean -function string.endswith(str, ending) - return ending == '' or str:sub(-(#ending)) == ending -end - ---- 四舍五入 --- @param a number --- @return a round number -function math.round(value) - return math.floor(value + 0.5) -end - ---- [0, 1]区间限定函数 --- @param a number --- @return a clamped number -function math.clamp01(value) - return math.min(1, math.max(0, value)) -end - ----最小数值和最大数值指定返回值的范围 --- @param a number --- @param min threshold --- @param max threshold --- @return a clamped number -function math.Clamp(value, min, max) - if value < min then - return min - end - if value > max then - return max - end - return value -end - ---- 高斯岁间变量 -function math.GaussRandom() - local u = math.random() - local v = math.random() - local z = math.sqrt(-2 * math.log(u)) * math.cos(2 * math.pi * v) - z = (z + 3) / 6 - z = 2 * z - 1 - if (math.abs(z) > 1) then - return math.GaussRandom() - end - return z -end - ---- 数据结构 队列 --- @usage queue example --- local myQueue = Queue:New() --- myQueue:Enqueue('a') --- myQueue:Enqueue('b') --- myQueue:Enqueue('c') --- myQueue:PrintElement() --- print(myQueue:Dequeue()) --- myQueue:PrintElement() --- myQueue:Clear() --- myQueue:PrintElement() -Queue = {} -function Queue:New() - local inst = { - _first = -1, - _last = -1, - _size = 0, - _queue = {} - } - setmetatable(inst, {__index = self}) - return inst -end - -function Queue:IsEmpty() - if self._size == 0 then - return true - end - return false -end - -function Queue:Enqueue(inElement) - if self._size == 0 then - self._first = 0 - self._last = 1 - self._size = 1 - self._queue[self._last] = inElement - else - self._last = self._last + 1 - self._queue[self._last] = inElement - self._size = self._size + 1 - end -end - -function Queue:Dequeue() - if self:IsEmpty() then - print('Error: the queue is empty') - return - end - self._size = self._size - 1 - self._first = self._first + 1 - local value = self._queue[self._first] - return value -end - -function Queue:Clear() - self._queue = nil - self._queue = {} - self._size = 0 - self._first = -1 - self._last = -1 -end - -function Queue:Size() - return self._size or 0 -end - -function Queue:PrintElement() - if self._size == 0 then - print('{}') - else - local f = self._first + 1 - local l = self._last - local str - local flag = true - while f ~= l do - if flag == true then - str = '{' .. tostring(self._queue[f]) - f = f + 1 - flag = false - else - str = str .. ',' .. tostring(self._queue[f]) - f = f + 1 - end - end - str = str .. ',' .. tostring(self._queue[l]) .. '}' - print(str) - end -end - -function Queue:GetValue(index) - if self:IsEmpty() or index == nil or index == 0 then - print('Error: Get Value Failure!') - return - end - if index > 0 then - return self._queue[self._first + index] - else - return self._queue[self._last + index + 1] - end -end - -function Queue:GetValues() - if self:IsEmpty() then - return - end - local data = {} - for i = self._first + 1, self._last, 1 do - data[#data + 1] = self._queue[i] - end - return data -end - ---- 数据结构 栈 --- @usage example --- local myStack = Stack:New() --- myStack:Push("a") --- myStack:Push("b") --- myStack:Push("c") --- myStack:PrintElement() --- print(myStack:Pop()) --- myStack:PrintElement() --- myStack:Clear() --- myStack:PrintElement() -Stack = {} -function Stack:New() - local inst = { - _last = 0, - _stack = {} - } - setmetatable(inst, {__index = self}) - - return inst -end - -function Stack:IsEmpty() - if self._last == 0 then - return true - end - return false -end - -function Stack:Push(inElement) - self._last = self._last + 1 - self._stack[self._last] = inElement -end - -function Stack:Pop() - if self:IsEmpty() then - --print("Error: the stack is empty") - return - end - local value = self._stack[self._last] - self._stack[self._last] = nil - self._last = self._last - 1 - return value -end - -function Stack:Exists(element, compairFunc) - if compairFunc == nil then - compairFunc = function(a, b) - return a == b - end - end - for i = self._last, 1, -1 do - if compairFunc(element, self._stack[i]) then - return i - end - end - return -1 -end - -function Stack:RemoveAt(index) - if index < 1 or index > self._last then - return - end - table.remove(self._stack, index) - self._last = self._last - 1 -end - -function Stack:Clear() - self._stack = nil - self._stack = {} - self._last = 0 -end - -function Stack:Size() - return self._last -end - -function Stack:PrintElement() - local str = '{' - for i = self._last, 1, -1 do - str = str .. tostring(self._stack[i]) .. ',' - end - str = str .. '}' - print(str) -end - - ---- uid递增计数器 -function UidCounter() - local num = 0 - return function() - num = num + 1 - return tostring(os.clock())..'-'..tostring(num) - end -end diff --git a/code/['World']['Global']['Module']['C_Module']['LanguageUtilModule'].ModuleScript.lua b/code/['World']['Global']['Module']['C_Module']['LanguageUtilModule'].ModuleScript.lua deleted file mode 100644 index cf83b84..0000000 --- a/code/['World']['Global']['Module']['C_Module']['LanguageUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,32 +0,0 @@ ---- 语言包模块:根据游戏内语言设置返回对应的语言文本 ---- @module LanguageUtil, Client-side ---- @copyright Lilith Games, Avatar Team ---- @author Xiexy, Yuancheng Zhang -local LanguageUtil, this = ModuleUtil.New('LanguageUtil', ClientBase) -local lang = Config.GlobalSetting.DefaultLanguage -local defaultLang = Const.LanguageEnum.CHS - ---- 设置当前语言 -function LanguageUtil.SetLanguage(_lang) - assert(Const.LanguageEnum[_lang], string.format('[LanguageUtil] %s 语言码不存在,请检查ConstModule', _lang)) - print(string.format('[LanguageUtil] 更改当前语言:%s => %s', lang, _lang)) - lang = _lang -end - ---- 根据ID返回当前游戏语言对应的文本信息,如果对应语言为空,默认返回'*'+中文内容 --- @param @number _id LanguagePack.xls中的编号 -function LanguageUtil.GetText(_id) - assert(not string.isnilorempty(_id), '[LanguageUtil] 翻译ID为空,请检查策划表和LanguagePack') - assert( - Config.LanguagePack[_id], - string.format('[LanguageUtil] LanguagePack[%s] 不存在对应翻译ID,请检查策划表和LanguagePack', _id) - ) - local text = Config.LanguagePack[_id][lang] - if string.isnilorempty(text) then - print(string.format('[LanguageUtil] LanguagePack[%s][%s] 不存在对应语言翻译内容,默认使用中文', _id, lang)) - text = '*' .. Config.LanguagePack[_id][defaultLang] - end - return text -end - -return LanguageUtil diff --git a/code/['World']['Global']['Module']['C_Module']['PlayerControlModule'].ModuleScript.lua b/code/['World']['Global']['Module']['C_Module']['PlayerControlModule'].ModuleScript.lua deleted file mode 100644 index d3bccdf..0000000 --- a/code/['World']['Global']['Module']['C_Module']['PlayerControlModule'].ModuleScript.lua +++ /dev/null @@ -1,182 +0,0 @@ ---- 玩家控制模块 ---- @module Player Controll, client-side ---- @copyright Lilith Games, Avatar Team -local PlayerControl, this = ModuleUtil.New('PlayerControl', ClientBase) -local player ---声明变量 -local isDead = false -local forwardDir = Vector3.Forward -local rightDir = Vector3.Right -local finalDir = Vector3.Zero -local horizontal = 0 -local vertical = 0 - --- 相机 -local camera, mode - --- 手机端交互UI -local gui, joystick, touchScreen, jumpButton - --- PC端交互按键 -local FORWARD_KEY = Enum.KeyCode.W -local BACK_KEY = Enum.KeyCode.S -local LEFT_KEY = Enum.KeyCode.A -local RIGHT_KEY = Enum.KeyCode.D -local JUMP_KEY = Enum.KeyCode.Space - --- 键盘的输入值 -local moveForwardAxis = 0 -local moveBackAxis = 0 -local moveLeftAxis = 0 -local moveRightAxis = 0 - -function PlayerControl:Init() - -- 获取本地玩家 - player = localPlayer - self:InitGui() - self:InitCamera() - self:InitListener() -end - -function PlayerControl:InitListener() - -- Main - world.OnRenderStepped:Connect(MainControl) - -- Player - player.OnHealthChange:Connect(HealthCheck) - player.OnDead:Connect(PlayerDie) - -- GUI - touchScreen.OnTouched:Connect(CountTouch) - touchScreen.OnPanStay:Connect(CameraMove) - touchScreen.OnPinchStay:Connect(CameraZoom) - jumpButton.OnDown:Connect(PlayerJump) - -- Keyboard - Input.OnKeyDown:Connect( - function() - if Input.GetPressKeyData(JUMP_KEY) == 1 then - PlayerJump() - end - end - ) -end - -function PlayerControl:InitGui() - gui = localPlayer.Local.ControlGui - joystick = gui.Joystick - touchScreen = gui.TouchFig - jumpButton = gui.JumpBtn -end - -function PlayerControl:InitCamera() - if not world.CurrentCamera and localPlayer.Local.Independent.GameCam then - world.CurrentCamera = localPlayer.Local.Independent.GameCam - end - camera = world.CurrentCamera - mode = Camera.CameraMode - camera.LookAt = player -end - --- 移动方向是否遵循摄像机方向 -function IsFreeMode() - return (mode == Enum.CameraMode.Social and camera.Distance >= 0) or mode == Enum.CameraMode.Orbital or - mode == Enum.CameraMode.Custom -end - ---获取按键盘时的移动方向最终取值 -function GetKeyValue() - moveForwardAxis = Input.GetPressKeyData(FORWARD_KEY) > 0 and 1 or 0 - moveBackAxis = Input.GetPressKeyData(BACK_KEY) > 0 and -1 or 0 - moveLeftAxis = Input.GetPressKeyData(LEFT_KEY) > 0 and 1 or 0 - moveRightAxis = Input.GetPressKeyData(RIGHT_KEY) > 0 and -1 or 0 - if player.State == Enum.CharacterState.Died then - moveForwardAxis, moveBackAxis, moveLeftAxis, moveRightAxis = 0, 0, 0, 0 - end -end - --- 获取移动方向 -function GetMoveDir() - forwardDir = IsFreeMode() and camera.Forward or player.Forward - forwardDir.y = 0 - rightDir = Vector3(0, 1, 0):Cross(forwardDir) - horizontal = joystick.Horizontal - vertical = joystick.Vertical - if horizontal ~= 0 or vertical ~= 0 then - finalDir = rightDir * horizontal + forwardDir * vertical - else - GetKeyValue() - finalDir = forwardDir * (moveForwardAxis + moveBackAxis) - rightDir * (moveLeftAxis + moveRightAxis) - end -end - --- 移动逻辑 -function PlayerMove(_dir) - _dir.y = 0 - if player.State == Enum.CharacterState.Died then - _dir = Vector3.Zero - end - if _dir.Magnitude > 0 then - if IsFreeMode then - player:FaceToDir(_dir, 4 * math.pi) - end - player:MoveTowards(Vector2(_dir.x, _dir.z).Normalized) - else - player:MoveTowards(Vector2.Zero) - end -end - --- 跳跃逻辑 -function PlayerJump() - if (player.IsOnGround or player.State == Enum.CharacterState.Seated) and not isDead then - player:Jump() - return - end -end - --- 死亡逻辑 -function PlayerDie() - isDead = true - wait(player.RespawnTime) - player:Reset() - isDead = false -end - --- 生命值检测 -function HealthCheck(oldHealth, newHealth) - if newHealth <= 0 then - player:Die() - end -end - --- 每个渲染帧处理操控逻辑 -function MainControl() - camera = world.CurrentCamera - mode = camera.CameraMode - GetMoveDir() - PlayerMove(finalDir) -end - --- 检测触屏的手指数 -local touchNumber = 0 -function CountTouch(container) - touchNumber = #container -end - --- 滑屏转向 -function CameraMove(_pos, _dis, _deltapos, _speed) - if touchNumber == 1 then - if IsFreeMode() then - camera:CameraMove(_deltapos) - else - player:RotateAround(player.Position, Vector3.Up, _deltapos.x) - camera:CameraMove(Vector2(0, _deltapos.y)) - end - end -end - --- 双指缩放摄像机距离 -function CameraZoom(_pos1, _pos2, _dis, _speed) - if mode == Enum.CameraMode.Social then - camera.Distance = camera.Distance - _dis / 50 - end -end - -return PlayerControl diff --git a/code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua b/code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua deleted file mode 100644 index cb06367..0000000 --- a/code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua +++ /dev/null @@ -1,92 +0,0 @@ ---- 玩家默认UI ---- @module Player Default GUI ---- @copyright Lilith Games, Avatar Team -local PlayerGuiDefault, this = ModuleUtil.New('PlayerGuiDefault', ClientBase) - --- 获取本地玩家 -local player - --- 姓名板 -local nameGUI - --- 血条 -local healthGUI, background, healthBar -local RED_BAR = ResourceManager.GetTexture('Internal/Blood_Red') -local GREEN_BAR = ResourceManager.GetTexture('Internal/Blood_Green') -local ORANGE_BAR = ResourceManager.GetTexture('Internal/Blood_Orange') -local HIT_LAST_TIME = 2 -local healthBarShowTime = 0 - -function PlayerGuiDefault:Init() - -- 获取本地玩家 - player = localPlayer - self:InitNameGui() - self:InitHealthBarGui() - self:InitListener() -end - --- 姓名板 -function PlayerGuiDefault:InitNameGui() - nameGUI = player.NameGui - nameGUI.NameBarTxt.Text = player.Name -end - --- 血条 -function PlayerGuiDefault:InitHealthBarGui() - healthGUI = player.HealthGui - background = healthGUI.BackgroundImg - healthBar = background.HealthBarImg -end - --- 初始化事件 -function PlayerGuiDefault:InitListener() - player.OnHealthChange:Connect(HealthChange) - world.OnRenderStepped:Connect(MainGUI) -end - --- 姓名板的显示逻辑 -function NameBarLogic() - nameGUI.Visible = player.DisplayName - if player.DisplayName then - local addedHeight = (healthGUI and healthGUI.ActiveSelf) and 1.1 or 1 - nameGUI.LocalPosition = Vector3(0, addedHeight + player.Avatar.Height, 0) - end -end - --- 血条随生命值颜色改变而改变 -function HealthChange(_oldHealth, _newHealth) - if _oldHealth > _newHealth then - healthBarShowTime = 2 - end - local percent = player.Health / player.MaxHealth - if percent >= 0.7 then - healthBar.Texture = GREEN_BAR - elseif percent >= 0.3 then - healthBar.Texture = ORANGE_BAR - else - healthBar.Texture = RED_BAR - end - healthBar.AnchorsX = Vector2(0.05, 0.9 * percent + 0.05) -end - --- 血条在各显示模式下的显示逻辑 -function HealthBarLogic(_delta) - healthBarShowTime = healthBarShowTime - _delta - if player.HealthDisplayMode == Enum.HealthDisplayMode.Always then - healthGUI.Visible = true - elseif player.HealthDisplayMode == Enum.HealthDisplayMode.Never then - healthGUI.Visible = false - elseif player.HealthDisplayMode == Enum.HealthDisplayMode.OnHit then - healthGUI.Visible = player.Health ~= player.MaxHealth - else - healthGUI.Visible = healthBarShowTime > 0 - end -end - --- 每个渲染帧更新姓名板和血条的显示逻辑 -function MainGUI(_delta) - NameBarLogic() - HealthBarLogic(_delta) -end - -return PlayerGuiDefault diff --git a/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua b/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua deleted file mode 100644 index b26b366..0000000 --- a/code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua +++ /dev/null @@ -1,29 +0,0 @@ ---- 用于场景mesh的一些快捷编辑功能 ---- @module SceneMeshEditor ---- @copyright Lilith Games, Avatar Team ---- @author Sid Zhang -local SceneMeshEditor = {} - ---- 将当前选中节点下的所有特定名称的mesh节点更改其引用 ---- @param _NodeName string 需要被替换资源的节点名字 ---- @param _MeshResource string FBX资源路径 ---- @param _root object 执行该操作的根节点,缺省则为选中的第一个节点 -function SceneMeshEditor:ChangeMesh(_NodeName, _MeshResource, _root) - if not _root then - _root = Editor.Selections[1] - end - if not _root then - print('[SceneMeshEditor] 没有选中或输入任何节点') - return - end - for _, v in pairs(_root:GetChildren()) do - if v.Name == _NodeName and v.ClassName == 'MeshObject' then - v.Mesh = ResourceManager.GetMesh(_MeshResource) - end - self:ChangeMesh(_NodeName, _MeshResource, v) - end -end - -return SceneMeshEditor - --- require(Module.Editor_Module.SceneMeshEditorModule):ChangeMesh() diff --git a/code/['World']['Global']['ModuleRequireScript'].Script.lua b/code/['World']['Global']['ModuleRequireScript'].Script.lua deleted file mode 100644 index 6b39fcf..0000000 --- a/code/['World']['Global']['ModuleRequireScript'].Script.lua +++ /dev/null @@ -1,40 +0,0 @@ ---- 将Global.Module目录下每一个用到模块提前require,定义为全局变量 --- @script Module Defines --- @copyright Lilith Games, Avatar Team - --- Utilities -ModuleUtil = require(Utility.ModuleUtilModule) -LuaJsonUtil = require(Utility.LuaJsonUtilModule) -NetUtil = require(Utility.NetUtilModule) -CsvUtil = require(Utility.CsvUtilModule) -XlsUtil = require(Utility.XlsUtilModule) -EventUtil = require(Utility.EventUtilModule) -UUID = require(Utility.UuidModule) -TweenController = require(Utility.TweenControllerModule) -GlobalFunc = require(Utility.GlobalFuncModule) -LinkedList = Utility.LinkedListModule -ValueChangeUtil = require(Utility.ValueChangeUtilModule) -TimeUtil = require(Utility.TimeUtilModule) -CloudLogUtil = require(Utility.CloudLogUtilModule) - --- Game Defines -GAME_ID = 'X0000' - --- Utility Initilization -TimeUtil.Init() -CloudLogUtil.Init(GAME_ID) - --- Framework -ModuleUtil.LoadModules(Framework) - --- Globle Defines -ModuleUtil.LoadModules(Define) -ModuleUtil.LoadXlsModules(Xls, Config) - --- Server and Clinet Modules -ModuleUtil.LoadModules(Module.S_Module) -ModuleUtil.LoadModules(Module.Cls_Module) -ModuleUtil.LoadModules(Module.C_Module) - --- Plugin Modules -GuideSystem = require(world.Global.Plugin.FUNC_Guide.GuideSystemModule) diff --git a/code/['World']['Global']['Plugin']['FUNC_Guide']['GuideSystemModule'].ModuleScript.lua b/code/['World']['Global']['Plugin']['FUNC_Guide']['GuideSystemModule'].ModuleScript.lua deleted file mode 100644 index 6a39364..0000000 --- a/code/['World']['Global']['Plugin']['FUNC_Guide']['GuideSystemModule'].ModuleScript.lua +++ /dev/null @@ -1,47 +0,0 @@ ----引导系统 ----@module GuideSystem ----@copyright Lilith Games, Avatar Team ----@author Sid Zhang, Yuancheng Zhang - -local GuideSystem = {} - ---- 引导的枚举类型 -GuideSystem.Enum = { - ClickGuide = 'ClickGuide' -} - ---- 显示强引导Ui ----@param _type Int 1:点击 ----@param _position Vector2 生成引导UI在屏幕的位置,Anchors值 ----@param _area Vector2 响应范围,Size ----@param _content String 文本介绍,nil则不显示文本 -function GuideSystem:ShowGuide(_type, _position, _area, _content, _callBack, ...) - local args = {...} - if _type == GuideSystem.Enum.ClickGuide then - local GuideNode = world:CreateInstance('ClickGuide', 'ClickGuide', localPlayer.Local) - if _position then - GuideNode.ImgDot.AnchorsX = Vector2(_position.X, _position.X) - GuideNode.ImgDot.AnchorsY = Vector2(_position.Y, _position.Y) - end - if _content then - GuideNode.ImgDot.FigTextBox.TxtContent.Text = _content - else - GuideNode.ImgDot.FigTextBox.Visible = false - end - if _area then - GuideNode.ImgDot.BtnClose.Size = _area - end - GuideNode.ImgDot.BtnClose.OnClick:Connect( - function() - if _callBack and type(_callBack) == 'function' then - _callBack(table.unpack(args)) - end - GuideNode:Destroy() - end - ) - else - error('param #1 :_type error') - end -end - -return GuideSystem diff --git a/code/['World']['Global']['Utility']['CamUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['CamUtilModule'].ModuleScript.lua deleted file mode 100644 index 700f852..0000000 --- a/code/['World']['Global']['Utility']['CamUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,41 +0,0 @@ ----摄像机工具类 ----@module Cam Utility ----@copyright Lilith Games, Avatar Team ----@author Sharif Ma ----@class CamUtil -local CamUtil = {} - ----将摄像机在水平面上转动到和角色朝向一致的角度 ----@param _player PlayerInstance 摄像机看向的物体 ----@param _cam Camera 转动的摄像机 ----@param _time number 转动过程的事件,不填则瞬间转动 -function CamUtil.ToRoleForward(_player, _cam, _time) - _time = _time or 0 - local dir = _player.Position - _cam.Position - local forward = _player.Forward - local alpha = Vector2.Angle(Vector2(dir.x, dir.z), Vector2(forward.x, forward.z)) - local left = _player.Left - if Vector3.Angle(left, dir) > 90 then - alpha = 360 - alpha - end - if _time == 0 then - _cam:CameraMoveInDegree(Vector2(alpha, 0)) - return - end - invoke( - function() - local curTime = 0 - while true do - local dt = wait() - local dtDe = alpha * dt / _time - _cam:CameraMoveInDegree(Vector2(dtDe, 0)) - curTime = curTime + dt - if curTime >= _time then - return - end - end - end - ) -end - -return CamUtil diff --git a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua deleted file mode 100644 index 65f6636..0000000 --- a/code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,24 +0,0 @@ ---- 埋点数据工具 ---- @module CloudLogUtil ---- @copyright Lilith Games, Avatar Team ---- @author Sharif Ma, Xinwu Zhang -local CloudLogUtil = {} - ----埋点工具初始化 ----@param _gameId string 游戏的唯一ID,和服务端定好后不可以更改的,游戏开始前执行 -function CloudLogUtil.Init(_gameId) - CloudLogUtil.gameId = _gameId -end - ----触发埋点相应的事件调用 ----@param _key string 埋点的键 -function CloudLogUtil.UploadLog(_key, _table) - local arg = LuaJsonUtil:encode(_table) - if localPlayer then - TrackService.CloudLogFromClient({_key, CloudLogUtil.gameId, arg}) - else - TrackService.CloudLogFromServer({_key, CloudLogUtil.gameId, arg}) - end -end - -return CloudLogUtil diff --git a/code/['World']['Global']['Utility']['CsvUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['CsvUtilModule'].ModuleScript.lua deleted file mode 100644 index 9c168a9..0000000 --- a/code/['World']['Global']['Utility']['CsvUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,244 +0,0 @@ ---- 读表工具: 将CSV导入成Lua Table,支持单一主键和多主键 --- @module CSV Utility --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang --- @see https://wiki.lilithgames.com/x/RGEMAg -local CsvUtil = {} - ---! 打印事件日志, true:开启打印 -local showLog, PrintGlobalKV, PrintLog = true - ---- 将表中的字符串改为数字 --- @param _t input table -local function StrToNum(_t) - for k, v in pairs(_t) do - _t[k] = tonumber(v) - end - return _t -end - ---- 类型解析配置表 -local parser = { - int = function(_raw) - return tonumber(_raw) - end, - float = function(_raw) - return tonumber(_raw) - end, - string = function(_raw) - return _raw - end, - boolean = function(_raw) - return string.lower(_raw) == 'true' - end, - vector2 = function(_raw) - return Vector2(table.unpack(StrToNum(string.split(_raw, ',')))) - end, - vector3 = function(_raw) - return Vector3(table.unpack(StrToNum(string.split(_raw, ',')))) - end, - euler = function(_raw) - return EulerDegree(table.unpack(StrToNum(string.split(_raw, ',')))) - end, - color = function(_raw) - return Color(table.unpack(StrToNum(string.split(_raw, ',')))) - end -} - ---- 读取配置表,会根据id生成lua表 --- @param _type String 数据类型 --- @parm _stringValue String 数据 --- @return value 解析出来的数值 -local function GetValue(_type, _stringValue) - _type = string.lower(_type) - assert(parser[_type], string.format('[CsvUtil][GlobalSetting] "%s" Type字段的值不是目前所支持的数据类型', _type)) - return parser[_type](_stringValue) -end - ---- 读取配置表,会根据id生成lua表 --- @param _csv 表格 --- @parma ... 表格的主键ids,可以为单一主键或多主键(多主键的id顺序决定lua table的结构) --- @usage exmaple #1 如果, 单一键值为主键 --- Level.csv 表格内容为: --- ---------------------------------- --- | String | String | Int | --- | level_id | level_name | reward | --- | easy_01 | Level 01 | 100 | --- | easy_02 | Level 02 | 140 | --- | hard_01 | Level 03 | 280 | --- | hard_02 | Level 04 | 320 | --- ---------------------------------- --- 调用函数 local levelCsv = CsvUtil.GetCsvInfo(Level, 'level_id') 导入的lua表格结果为: --- levelCsv = { --- easy_01 = { --- level_id = 'easy_01', --- level_name = 'Level 01', --- reward = 100 --- }, --- easy_02 = { --- level_id = 'easy_02', --- level_name = 'Level 02', --- reward = 140 --- }, --- hard_01 = { --- level_id = 'hard_01', --- level_name = 'Level 03', --- reward = 280 --- }, --- hard_02 = { --- level_id = 'hard_02', --- level_name = 'Level 04', --- reward = 320 --- } --- } --- @usage exmaple #2 如果, 多键值为主键 --- Enemy.csv 表格内容为: --- ---------------------------------- --- | String | String | Int | --- | enemy_id | difficulty | hp | --- | foe_01 | easy | 100 | --- | foe_01 | hard | 150 | --- | foe_02 | easy | 300 | --- | foe_02 | hard | 400 | --- ---------------------------------- --- 调用函数 local enemyCsv = CsvUtil.GetCsvInfo(Enemy, 'enemy_id', 'difficulty') 导入的lua表格结果为: --- enemyCsv = { --- foe_01 = { --- easy = { --- enemy_id = 'foe_01', --- difficulty = 'easy', --- hp = 100 --- }, --- hard = { --- enemy_id = 'foe_02', --- difficulty = 'hard', --- hp = 150 --- } --- }, --- foe_02 = { --- esay = { --- enemy_id = 'foe_02', --- difficulty = 'easy', --- hp = 300 --- }, --- hard = { --- enemy_id = 'foe_02', --- difficulty = 'hard', --- hp = 400 --- } --- } --- } --- 使用lua table中的数据方法: --- health = enemyCsv.foe_01.hard.hp 或 health = enemyCsv['foe_01']['hard']['hp'] --- health的值为150 -function CsvUtil.GetCsvInfo(_csv, ...) - local rawTable = _csv:GetRows() - local ids = {...} - if #ids < 1 or (#ids == 1 and ids[1] == 'Type') then - -- 默认用Type索引,直接返回 - return rawTable - end - local result = {} - local tmp, key, id, idstr -- 临时变量 - for _, v in pairs(rawTable) do - tmp = result - idstr = {} - for i = 1, #ids do - id = ids[i] - key = v[id] - idstr[i] = tostring(id) .. ',' - assert(not string.isnilorempty(key), string.format('[CsvUtil] CSV表格没有找到此id, CSV:%s, id: %s', _csv.Name, id)) - if i == #ids then - -- 最后的键,确定唯一性 - assert( - not tmp[key], - string.format('[CsvUtil] CSV数据重复, ids不是唯一的, CSV: %s, ids: %s', _csv.Name, table.concat(idstr)) - ) - tmp[key] = v - else - -- 多键,之后还有 - if tmp[key] == nil then - tmp[key] = {} - end - tmp = tmp[key] - end - end - end - return result -end - ---- 读取Config全局配置表 --- GlobleSetting.csv 表格内容为: --- --------------------------------------------------------- --- | String | String | String | String | --- | Key | Type | Value | Des | --- --------------------------------------------------------- --- | CubeMax | Int | 200 | 最大Cube数 | --- | BattleTime | Float | 5.45 | 战斗时间 | --- | GameTitle | String | Boom Party | 游戏标题 | --- | IsFree | Boolean | true | 是否免费 | --- | UiMapOrigin | Vector2 | 3,4 | UI地图原点位置 | --- | TreePos | Vector3 | 12,3,-3 | 树的位置 | --- | TreeRot | Euler | 45,90,0 | 树的旋转 | --- | TreeColor | Color | 255,255,255,0 | 树的颜色 | -function CsvUtil.GetGlobalCsvInfo(_csv) - local rawTable = _csv:GetRows() - if table.nums(rawTable) == 0 then - return - end - assert(rawTable['1'].Key, '[CsvUtil] 全局配置表的没有"Key"') - assert(rawTable['1'].Type, '[CsvUtil] 全局配置表的没有"Type"') - assert(rawTable['1'].Value, '[CsvUtil] 全局配置表的没有"Value"') - local result = {} - for _, v in pairs(rawTable) do - result[v.Key] = GetValue(v['Type'], v['Value']) - PrintGlobalKV(v.Key, v.Type, result[v.Key]) -- * 输出KV键值对 - end - return result -end - ---- 表格预加载,预加载配置模块:World.Global.Define.ConfigModule -function CsvUtil.PreloadCsv(_preloadList, _csvRoot, _config) - assert(_preloadList and #_preloadList > 0, '[CsvUtil] ConfigModule中没有预加载表格') - for _, pl in pairs(_preloadList) do - if not string.isnilorempty(pl.csv) then - pl.name = string.isnilorempty(pl.name) and pl.csv or pl.name - PrintLog(string.format('[CsvUtil] Load: %s.csv', pl.csv)) - if pl.csv == 'GlobalSetting' and _csvRoot[pl.csv] then - _config[pl.name] = CsvUtil.GetGlobalCsvInfo(_csvRoot[pl.csv]) - elseif not string.isnilorempty(pl.csv) and _csvRoot[pl.csv] then - pl.ids = pl.ids or {} - _config[pl.name] = CsvUtil.GetCsvInfo(_csvRoot[pl.csv], table.unpack(pl.ids)) - end - end - end -end - ---! 辅助功能 - ---- 输出全局变量键值对 -PrintGlobalKV = - showLog and - function(_key, _type, _value) - _type = string.lower(_type) - local showTypes = { - vector2 = 'Vector2', - vector3 = 'Vector3', - euler = 'EulerDegree', - color = 'Color' - } - if showTypes[_type] then - print(string.format('[CsvUtil][GlobalSetting] %s = %s%s ', _key, showTypes[_type], _value)) - else - print(string.format('[CsvUtil][GlobalSetting] %s = %s ', _key, _value)) - end - end or - function() - end - -PrintLog = showLog and function(...) - print(...) - end or function() - end - -return CsvUtil diff --git a/code/['World']['Global']['Utility']['EventUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['EventUtilModule'].ModuleScript.lua deleted file mode 100644 index 7fd554a..0000000 --- a/code/['World']['Global']['Utility']['EventUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,53 +0,0 @@ ---- 事件绑定工具 --- @module Event Connects Handler --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang, Yen Yuan -local EventUtil = {} - ---- 检查是否为Json化的字符串 --- @param _str @string 输入的字符串 --- @return @boolean true: json table string -local function IsJsonTable(_str) - return type(_str) == 'string' and string.endswith(_str, 'JSON') and string.startswith(_str, 'JSON') -end - ---- 处理Handler的传入参数 ---@param variable args ---@return variable args -local function ArgsAux(...) - local _s = {...} - for k, v in pairs(_s) do - if IsJsonTable(v) then - local json = string.sub(v, 5, -5) - _s[k] = LuaJsonUtil:decode(json) - end - end - return table.unpack(_s) -end - ---- 遍历所有的events,找到module中对应名称的handler,建立Connect --- @param _eventFolder 事件所在的节点folder --- @param _module 模块 --- @param _this module的self指针,用于闭包 -function EventUtil.LinkConnects(_eventFolder, _module, _this) - assert( - _eventFolder and _module and _this, - string.format('[EventUtil] 参数有空值: %s, %s, %s', _eventFolder, _module, _this) - ) - local events = _eventFolder:GetChildren() - for _, evt in pairs(events) do - if string.endswith(evt.Name, 'Event') then - local handler = _module[evt.Name .. 'Handler'] - if handler ~= nil then - -- print('[EventUtil]', _eventFolder, _module, evt) - evt:Connect( - function(...) - handler(_this, ArgsAux(...)) - end - ) - end - end - end -end - -return EventUtil diff --git a/code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua deleted file mode 100644 index f5c4474..0000000 --- a/code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua +++ /dev/null @@ -1,26 +0,0 @@ ---- 全局函数的定义 ---- @module GlobalFunc Defines ---- @copyright Lilith Games, Avatar Team ---- @author Sid Zhang -local GlobalFunc = {} - ---- 埋点上传日志 ---- @param _tableName string 表名 -function GlobalFunc.UploadLogs(_tableName, ...) - local args = {...} - if localPlayer then - pcall( - function() - TrackService.CloudLogFromClient({_tableName, table.unpack(args)}) - end - ) - else - pcall( - function() - TrackService.CloudLogFromServer({_tableName, table.unpack(args)}) - end - ) - end -end - -return GlobalFunc diff --git a/code/['World']['Global']['Utility']['LinkedListModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['LinkedListModule'].ModuleScript.lua deleted file mode 100644 index dc7fca4..0000000 --- a/code/['World']['Global']['Utility']['LinkedListModule'].ModuleScript.lua +++ /dev/null @@ -1,444 +0,0 @@ ---- C# 双向链表 --- @module C# doubly linked list implemented with lua --- @copyright Lilith Games, Avatar Team --- @author Bruce Chen --- @see https://wiki.lilithgames.com/x/7yRZAg --- @see https://github.com/BruceCheng1995/LuaLinkedList - -local LinkedList = {} -local LinkedNode = {} -LinkedNode.__index = LinkedNode - -local NativePrint = print -local EmptuFunc = function() -end ---是否开放内部日志 -function LinkedList:EnableLog(_enable) - if _enable then - print = NativePrint - else - print = EmptuFunc - end -end -LinkedList:EnableLog(false) ---新建节点 -function LinkedNode:new(value, list) - local o = {} - setmetatable(o, self) - o.List = list - o.Next = nil - o.Prev = nil - o.Value = value - return o -end ---克隆这个节点 -function LinkedNode:Clone() - return LinkedNode:new(self.Value, nil) -end ---节点失效 -function LinkedNode:Invalidate() - self.Next = nil - self.Prev = nil - self.List = nil -end ---打印 -function LinkedNode:tostring() - return tostring(self.Value) -end -LinkedNode.__tostring = LinkedNode.tostring - ---验证新节点是否是自由节点 -function LinkedList:ValidateNewNode(node) - if not node then - return false - end - --assert(LinkedNode:include(node),"instance of LinkedNode needed.") - if node.List ~= nil then - return false - end - return true -end - ---验证该节点是否是属于该表 -function LinkedList:ValidateNode(node) - if not node then - return false - end - --assert(LinkedNode:include(node),"instance of LinkedNode needed.") - if node.List ~= self then - return false - end - return true -end - ---将节点插入到node节点之前(list:链表,node:插在这个节点前面,newnode:被插入的节点) -local function InternalInsertNodeBefore(list, node, newnode) - newnode.Next = node - newnode.Prev = node.Prev - node.Prev.Next = newnode - node.Prev = newnode - list.Count = list.Count + 1 -end - ---将节点插入到一个空链表之前(list:链表,newnode:被插入的节点) -local function InternalInsertNodeToEmptyList(list, newnode) - newnode.Next = newnode - newnode.Prev = newnode - list.First = newnode - list.Count = list.Count + 1 -end - ---移除链表中的节点(list:链表,node:被删除的节点) -local function InternalRemoveNode(list, node) - if node.Next == node then - list.First = nil - else - node.Next.Prev = node.Prev - node.Prev.Next = node.Next - if list.First == node then - list.First = node.Next - end - end - node:Invalidate() - list.Count = list.Count - 1 -end - ---新建双向链表 -function LinkedList:new(tab) - local o = {} - setmetatable(o, self) - o.Count = 0 - o.First = nil - if type(tab) == 'table' then - for _, v in pairs(tab) do - o:AddLast(v) - end - end - return o -end - ---Add Value ---在尾部添加值(若传入值是表,则遍历表,并将所有值添加到尾部) -function LinkedList:Add(value) - if type(value) == 'table' then - for _, v in pairs(value) do - self:AddLast(v) - end - else - self:AddLast(value) - end -end - ---在尾部添加值 -function LinkedList:AddLast(value) - local newnode = LinkedNode:new(value, self) - if not self.First then - InternalInsertNodeToEmptyList(self, newnode) - else - InternalInsertNodeBefore(self, self.First, newnode) - end - return newnode -end - ---在头部添加值 -function LinkedList:AddFirst(value) - local newnode = LinkedNode:new(value, self) - if not self.First then - InternalInsertNodeToEmptyList(self, newnode) - else - InternalInsertNodeBefore(self, self.First, newnode) - self.First = newnode - end - return newnode -end - ---在指定节点后面添加值(node:插入在这个节点后,value:被插入的值) -function LinkedList:AddAfter(node, value) - if not self:ValidateNewNode(node) then - return - end - local newnode = LinkedNode:new(value, self) - InternalInsertNodeBefore(self, node.Next, newnode) - return newnode -end - ---在指定节点前面添加值(node:插入在这个节点前,value:被插入的值) -function LinkedList:AddBefore(node, value) - if not self:ValidateNode(node) then - return - end - local newnode = LinkedNode:new(value, self) - InternalInsertNodeBefore(self, node, newnode) - if node == self.First then - self.First = newnode - end - return newnode -end - ---Add Node ---在头部添加节点 -function LinkedList:AddNodeFirst(node) - if not self:ValidateNewNode(node) then - return - end - if not self.First then - InternalInsertNodeToEmptyList(self, node) - else - InternalInsertNodeBefore(self, self.First, node) - self.First = node - end - node.List = self -end - ---在尾部添加节点 -function LinkedList:AddNodeLast(node) - if not self:ValidateNewNode(node) then - return - end - if not self.First then - InternalInsertNodeToEmptyList(self, node) - else - InternalInsertNodeBefore(self, self.First, node) - end - node.List = self -end - ---在指定节点后面添加值(node:插入在这个节点后,newnode:被插入的节点) -function LinkedList:AddNodeAfter(node, newnode) - if not self:ValidateNode(node) and not self:ValidateNewNode(newnode) then - return - end - InternalInsertNodeBefore(self, node.Next, newnode) - newnode.List = self -end - ---在指定节点后面添加值(node:插入在这个节点前,newnode:被插入的节点) -function LinkedList:AddNodeBefore(node, newnode) - if not self:ValidateNode(node) and not self:ValidateNewNode(newnode) then - return - end - InternalInsertNodeBefore(self, node, newnode) - newnode.List = self - if node ~= self.First then - return - end - self.First = newnode -end - ---Remove ---找到表中的第一个指定值,并删除,返回是否命中 -function LinkedList:Remove(value) - local node = self:Find(value) - if not node then - return false - end - InternalRemoveNode(self, node) - return true -end - ---找到表中的第一个指定节点,并删除,返回是否命中 -function LinkedList:RemoveNode(node) - if not self:ValidateNode(node) then - return - end - InternalRemoveNode(self, node) -end - ---移除头部节点 -function LinkedList:RemoveFirst() - if self.First == nil then - print('[LinkedList] list is empty.') - else - InternalRemoveNode(self, self.First) - end -end - ---移除尾部节点 -function LinkedList:RemoveLast() - if self.First == nil then - print('[LinkedList] list is empty.') - else - InternalRemoveNode(self, self.First.Prev) - end -end - ---Find ---尝试找到表中的第一个指定值,若有则返回这个节点 -function LinkedList:Find(value) - local ptrnode = self.First - if value ~= nil then - while ptrnode.Value ~= value do - ptrnode = ptrnode.Next - if ptrnode == self.First then - goto close1 - end - end - return ptrnode - else - while ptrnode.Value ~= nil do - ptrnode = ptrnode.Next - if ptrnode == self.First then - goto close1 - end - end - return ptrnode - end - ::close1:: - return -end - ---尝试反向找到表中第一个指定值,若有则返回这个节点 -function LinkedList:FindLast(value) - if self.First == nil then - return - end - local prev = self.First.Prev - local ptrnode = prev - if value ~= nil then - while ptrnode.Value ~= value do - ptrnode = ptrnode.Prev - if ptrnode == Prev then - goto close2 - end - end - return ptrnode - else - while ptrnode.Value ~= nil do - ptrnode = ptrnode.Prev - if ptrnode == prev then - goto close2 - end - end - return ptrnode - end - ::close2:: - return -end - ---Other ---清空链表 -function LinkedList:Clear() - local ptrnode = self.First - while ptrnode ~= nil do - local lastnode = ptrnode - ptrnode = ptrnode.Next - lastnode:Invalidate() - end - self.First = nil - self.Count = 0 -end - ---向给定table的指定位置插入数值(tab:被插入表,index:序号) -function LinkedList:CopyTo(tab, index) - assert(type(tab) == 'table', '[LinkedList] bad argument "table"') - assert(index >= 1, '[LinkedList] Index out of range') - local ptrnode = self.First - if ptrnode == nil then - return - end - repeat - table.insert(tab, index, ptrnode.Value) - ptrnode = ptrnode.Next - index = index + 1 - until (ptrnode == self.First) -end - ---将链表中的数据拷贝到新表中,并将这个表输出 -function LinkedList:ToTable() - local tab = {} - self:CopyTo(tab, 1) - return tab -end - ---克隆当前链表,并返回 -function LinkedList:Clone() - local newlist = LinkedList:new() - local ptrnode = self.First - repeat - local clnode = ptrnode:Clone() - newlist:AddNodeLast(clnode) - ptrnode = ptrnode.Next - until (ptrnode == self.First) - return newlist -end - ---检查链表中是否包含指定值 -function LinkedList:Contains(value) - return self:Find(value) and true or false -end - ---将链表反向 -function LinkedList:Reverse() - local tmp - if not self.First then - print('[LinkedList] list is empty') - return - end - self.First = self.First.Prev - for item in self:ipairer() do - tmp = item.Next - item.Next = item.Prev - item.Prev = tmp - end -end - ---返回头部节点 -function LinkedList:GetFirst() - return self.First -end - ---返回尾部节点 -function LinkedList:GetLast() - return self.First ~= nil and self.First.Prev or nil -end - ---返回第index个节点 -function LinkedList:GetNode(index) - if index < 1 or index > self.Count then - print('[LinkedList] Index out of range') - return - end - local ptrnode = self.First.Prev - while index > 0 do - ptrnode = ptrnode.Next - index = index - 1 - end - return ptrnode -end - ---返回链表长度 -function LinkedList:Len() - return self.Count -end - ---返回迭代器 -function LinkedList:ipairer() - local ptrnode = self:GetLast() - local passFirst = false - return function() - if ptrnode then - if ptrnode ~= self:GetLast() or not passFirst then - passFirst = true - ptrnode = ptrnode.Next - return ptrnode - end - end - end -end - ---以文本方式表示此表 -function LinkedList:tostring() - local t = {} - for item in self:ipairer() do - table.insert(t, tostring(item)) - end - return 'LinkedList:{' .. table.concat(t, ',') .. '}' -end - -LinkedList.__index = LinkedList -LinkedList.__tostring = LinkedList.tostring - -return { - list = setmetatable(LinkedList, {__call = LinkedList.new}), - node = setmetatable(LinkedNode, {__call = LinkedNode.new}) -} diff --git a/code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua deleted file mode 100644 index c4de8af..0000000 --- a/code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,45 +0,0 @@ ---- Debug工具 --- @module Debug utilities --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang -local LogUtil = {} - ---- 日志级别枚举 -LogUtil.LevelEnum = { - -- 指出细粒度信息事件对调试应用程序是非常有帮助的 主要用于开发过程中打印一些运行信息 - DEBUG = 1, - -- 消息在粗粒度级别上突出强调应用程序的运行过程 - -- 打印一些你感兴趣的或者重要的信息 这个可以用于生产环境中输出程序运行的一些重要信息 - -- 但是不能滥用 避免打印过多的日志 - INFO = 2, - -- 表明会出现潜在错误的情形 有些信息不是错误信息 但是也要给程序员的一些提示 - -- 指出虽然发生错误事件 但仍然不影响系统的继续运行 - -- 打印错误和异常信息 如果不想输出太多的日志 可以使用这个级别 - ERROR = 3 -} - ---- 日志级别 -LogUtil.level = LogUtil.LevelEnum.DEBUG - ---- 开关 -LogUtil.debugMode = true - -function LogUtil.Test(...) - if LogUtil.debugMode and LogUtil.level <= LogUtil.LevelEnum.DEBUG then - print('[TEST]', ...) - end -end - -function LogUtil.Debug(...) - if LogUtil.debugMode and LogUtil.level <= LogUtil.LevelEnum.DEBUG then - print('[DEBUG]', ...) - end -end - -function LogUtil.Info(...) - if LogUtil.debugMode and LogUtil.level <= LogUtil.LevelEnum.INFO then - print('[INFO]', ...) - end -end - -return LogUtil diff --git a/code/['World']['Global']['Utility']['LuaJsonUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['LuaJsonUtilModule'].ModuleScript.lua deleted file mode 100644 index 9c97e13..0000000 --- a/code/['World']['Global']['Utility']['LuaJsonUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,1042 +0,0 @@ ---- -*- coding: utf-8 -*- ---- ---- Simple JSON encoding and decoding in pure Lua. ---- ---- Copyright 2010-2014 Jeffrey Friedl ---- http://regex.info/blog/ ---- ---- Latest version: http://regex.info/blog/lua/json ---- ---- This code is released under a Creative Commons CC-BY "Attribution" License: ---- http://creativecommons.org/licenses/by/3.0/deed.en_US ---- ---- It can be used for any purpose so long as the copyright notice above, ---- the web-page links above, and the 'AUTHOR_NOTE' string below are ---- maintained. Enjoy. ---- -local VERSION = 20141223.14 --- version history at end of file -local AUTHOR_NOTE = '-[ JSON.lua package by Jeffrey Friedl (http://regex.info/blog/lua/json) version 20141223.14 ]-' - ---- ---- The 'AUTHOR_NOTE' variable exists so that information about the source ---- of the package is maintained even in compiled versions. It's also ---- included in OBJDEF below mostly to quiet warnings about unused variables. ---- ----@module LuaJson -local OBJDEF = { - VERSION = VERSION, - AUTHOR_NOTE = AUTHOR_NOTE -} - ---- ---- Simple JSON encoding and decoding in pure Lua. ---- http://www.json.org/ ---- --- --- JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines --- --- local lua_value = JSON:decode(raw_json_text) --- --- local raw_json_text = JSON:encode(lua_table_or_value) --- local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability --- --- --- --- DECODING (from a JSON string to a Lua table) --- --- --- JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines --- --- local lua_value = JSON:decode(raw_json_text) --- --- If the JSON text is for an object or an array, e.g. --- { "what": "books", "count": 3 } --- or --- [ "Larry", "Curly", "Moe" ] --- --- the result is a Lua table, e.g. --- { what = "books", count = 3 } --- or --- { "Larry", "Curly", "Moe" } --- --- --- The encode and decode routines accept an optional second argument, --- "etc", which is not used during encoding or decoding, but upon error --- is passed along to error handlers. It can be of any type (including nil). --- --- --- --- ERROR HANDLING --- --- With most errors during decoding, this code calls --- --- JSON:onDecodeError(message, text, location, etc) --- --- with a message about the error, and if known, the JSON text being --- parsed and the byte count where the problem was discovered. You can --- replace the default JSON:onDecodeError() with your own function. --- --- The default onDecodeError() merely augments the message with data --- about the text and the location if known (and if a second 'etc' --- argument had been provided to decode(), its value is tacked onto the --- message as well), and then calls JSON.assert(), which itself defaults --- to Lua's built-in assert(), and can also be overridden. --- --- For example, in an Adobe Lightroom plugin, you might use something like --- --- function JSON:onDecodeError(message, text, location, etc) --- LrErrors.throwUserError("Internal Error: invalid JSON data") --- end --- --- or even just --- --- function JSON.assert(message) --- LrErrors.throwUserError("Internal Error: " .. message) --- end --- --- If JSON:decode() is passed a nil, this is called instead: --- --- JSON:onDecodeOfNilError(message, nil, nil, etc) --- --- and if JSON:decode() is passed HTML instead of JSON, this is called: --- --- JSON:onDecodeOfHTMLError(message, text, nil, etc) --- --- The use of the fourth 'etc' argument allows stronger coordination --- between decoding and error reporting, especially when you provide your --- own error-handling routines. Continuing with the the Adobe Lightroom --- plugin example: --- --- function JSON:onDecodeError(message, text, location, etc) --- local note = "Internal Error: invalid JSON data" --- if type(etc) = 'table' and etc.photo then --- note = note .. " while processing for " .. etc.photo:getFormattedMetadata('fileName') --- end --- LrErrors.throwUserError(note) --- end --- --- : --- : --- --- for i, photo in ipairs(photosToProcess) do --- : --- : --- local data = JSON:decode(someJsonText, { photo = photo }) --- : --- : --- end --- --- --- --- --- --- DECODING AND STRICT TYPES --- --- Because both JSON objects and JSON arrays are converted to Lua tables, --- it's not normally possible to tell which original JSON type a --- particular Lua table was derived from, or guarantee decode-encode --- round-trip equivalency. --- --- However, if you enable strictTypes, e.g. --- --- JSON = assert(loadfile "JSON.lua")() --load the routines --- JSON.strictTypes = true --- --- then the Lua table resulting from the decoding of a JSON object or --- JSON array is marked via Lua metatable, so that when re-encoded with --- JSON:encode() it ends up as the appropriate JSON type. --- --- (This is not the default because other routines may not work well with --- tables that have a metatable set, for example, Lightroom API calls.) --- --- --- ENCODING (from a lua table to a JSON string) --- --- JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines --- --- local raw_json_text = JSON:encode(lua_table_or_value) --- local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability --- local custom_pretty = JSON:encode(lua_table_or_value, etc, { pretty = true, indent = "| ", align_keys = false }) --- --- On error during encoding, this code calls: --- --- JSON:onEncodeError(message, etc) --- --- which you can override in your local JSON object. --- --- The 'etc' in the error call is the second argument to encode() --- and encode_pretty(), or nil if it wasn't provided. --- --- --- PRETTY-PRINTING --- --- An optional third argument, a table of options, allows a bit of --- configuration about how the encoding takes place: --- --- pretty = JSON:encode(val, etc, { --- pretty = true, -- if false, no other options matter --- indent = " ", -- this provides for a three-space indent per nesting level --- align_keys = false, -- see below --- }) --- --- encode() and encode_pretty() are identical except that encode_pretty() --- provides a default options table if none given in the call: --- --- { pretty = true, align_keys = false, indent = " " } --- --- For example, if --- --- JSON:encode(data) --- --- produces: --- --- {"city":"Kyoto","climate":{"avg_temp":16,"humidity":"high","snowfall":"minimal"},"country":"Japan","wards":11} --- --- then --- --- JSON:encode_pretty(data) --- --- produces: --- --- { --- "city": "Kyoto", --- "climate": { --- "avg_temp": 16, --- "humidity": "high", --- "snowfall": "minimal" --- }, --- "country": "Japan", --- "wards": 11 --- } --- --- The following three lines return identical results: --- JSON:encode_pretty(data) --- JSON:encode_pretty(data, nil, { pretty = true, align_keys = false, indent = " " }) --- JSON:encode (data, nil, { pretty = true, align_keys = false, indent = " " }) --- --- An example of setting your own indent string: --- --- JSON:encode_pretty(data, nil, { pretty = true, indent = "| " }) --- --- produces: --- --- { --- | "city": "Kyoto", --- | "climate": { --- | | "avg_temp": 16, --- | | "humidity": "high", --- | | "snowfall": "minimal" --- | }, --- | "country": "Japan", --- | "wards": 11 --- } --- --- An example of setting align_keys to true: --- --- JSON:encode_pretty(data, nil, { pretty = true, indent = " ", align_keys = true }) --- --- produces: --- --- { --- "city": "Kyoto", --- "climate": { --- "avg_temp": 16, --- "humidity": "high", --- "snowfall": "minimal" --- }, --- "country": "Japan", --- "wards": 11 --- } --- --- which I must admit is kinda ugly, sorry. This was the default for --- encode_pretty() prior to version 20141223.14. --- --- --- AMBIGUOUS SITUATIONS DURING THE ENCODING --- --- During the encode, if a Lua table being encoded contains both string --- and numeric keys, it fits neither JSON's idea of an object, nor its --- idea of an array. To get around this, when any string key exists (or --- when non-positive numeric keys exist), numeric keys are converted to --- strings. --- --- For example, --- JSON:encode({ "one", "two", "three", SOMESTRING = "some string" })) --- produces the JSON object --- {"1":"one","2":"two","3":"three","SOMESTRING":"some string"} --- --- To prohibit this conversion and instead make it an error condition, set --- JSON.noKeyConversion = true --- - --- --- SUMMARY OF METHODS YOU CAN OVERRIDE IN YOUR LOCAL LUA JSON OBJECT --- --- assert --- onDecodeError --- onDecodeOfNilError --- onDecodeOfHTMLError --- onEncodeError --- --- If you want to create a separate Lua JSON object with its own error handlers, --- you can reload JSON.lua or use the :new() method. --- ---------------------------------------------------------------------------- - -local default_pretty_indent = ' ' -local default_pretty_options = {pretty = true, align_keys = false, indent = default_pretty_indent} - -local isArray = { - __tostring = function() - return 'JSON array' - end -} -isArray.__index = isArray -local isObject = { - __tostring = function() - return 'JSON object' - end -} -isObject.__index = isObject - -function OBJDEF:newArray(tbl) - return setmetatable(tbl or {}, isArray) -end - -function OBJDEF:newObject(tbl) - return setmetatable(tbl or {}, isObject) -end - -local function unicode_codepoint_as_utf8(codepoint) - -- - -- codepoint is a number - -- - if codepoint <= 127 then - return string.char(codepoint) - elseif codepoint <= 2047 then - -- - -- 110yyyxx 10xxxxxx <-- useful notation from http://en.wikipedia.org/wiki/Utf8 - -- - local highpart = math.floor(codepoint / 0x40) - local lowpart = codepoint - (0x40 * highpart) - return string.char(0xC0 + highpart, 0x80 + lowpart) - elseif codepoint <= 65535 then - -- - -- 1110yyyy 10yyyyxx 10xxxxxx - -- - local highpart = math.floor(codepoint / 0x1000) - local remainder = codepoint - 0x1000 * highpart - local midpart = math.floor(remainder / 0x40) - local lowpart = remainder - 0x40 * midpart - - highpart = 0xE0 + highpart - midpart = 0x80 + midpart - lowpart = 0x80 + lowpart - - -- - -- Check for an invalid character (thanks Andy R. at Adobe). - -- See table 3.7, page 93, in http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#G28070 - -- - if - (highpart == 0xE0 and midpart < 0xA0) or (highpart == 0xED and midpart > 0x9F) or - (highpart == 0xF0 and midpart < 0x90) or - (highpart == 0xF4 and midpart > 0x8F) - then - return '?' - else - return string.char(highpart, midpart, lowpart) - end - else - -- - -- 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx - -- - local highpart = math.floor(codepoint / 0x40000) - local remainder = codepoint - 0x40000 * highpart - local midA = math.floor(remainder / 0x1000) - remainder = remainder - 0x1000 * midA - local midB = math.floor(remainder / 0x40) - local lowpart = remainder - 0x40 * midB - - return string.char(0xF0 + highpart, 0x80 + midA, 0x80 + midB, 0x80 + lowpart) - end -end - -function OBJDEF:onDecodeError(message, text, location, etc) - if text then - if location then - message = string.format('%s at char %d of: %s', message, location, text) - else - message = string.format('%s: %s', message, text) - end - end - - if etc ~= nil then - message = message .. ' (' .. OBJDEF:encode(etc) .. ')' - end - - if self.assert then - self.assert(false, message) - else - assert(false, message) - end -end - -OBJDEF.onDecodeOfNilError = OBJDEF.onDecodeError -OBJDEF.onDecodeOfHTMLError = OBJDEF.onDecodeError - -function OBJDEF:onEncodeError(message, etc) - if etc ~= nil then - message = message .. ' (' .. OBJDEF:encode(etc) .. ')' - end - - if self.assert then - self.assert(false, message) - else - assert(false, message) - end -end - -local function grok_number(self, text, start, etc) - -- - -- Grab the integer part - -- - local integer_part = text:match('^-?[1-9]%d*', start) or text:match('^-?0', start) - - if not integer_part then - self:onDecodeError('expected number', text, start, etc) - end - - local i = start + integer_part:len() - - -- - -- Grab an optional decimal part - -- - local decimal_part = text:match('^%.%d+', i) or '' - - i = i + decimal_part:len() - - -- - -- Grab an optional exponential part - -- - local exponent_part = text:match('^[eE][-+]?%d+', i) or '' - - i = i + exponent_part:len() - - local full_number_text = integer_part .. decimal_part .. exponent_part - local as_number = tonumber(full_number_text) - - if not as_number then - self:onDecodeError('bad number', text, start, etc) - end - - return as_number, i -end - -local function grok_string(self, text, start, etc) - if text:sub(start, start) ~= '"' then - self:onDecodeError("expected string's opening quote", text, start, etc) - end - - local i = start + 1 -- +1 to bypass the initial quote - local text_len = text:len() - local VALUE = '' - while i <= text_len do - local c = text:sub(i, i) - if c == '"' then - return VALUE, i + 1 - end - if c ~= '\\' then - VALUE = VALUE .. c - i = i + 1 - elseif text:match('^\\b', i) then - VALUE = VALUE .. '\b' - i = i + 2 - elseif text:match('^\\f', i) then - VALUE = VALUE .. '\f' - i = i + 2 - elseif text:match('^\\n', i) then - VALUE = VALUE .. '\n' - i = i + 2 - elseif text:match('^\\r', i) then - VALUE = VALUE .. '\r' - i = i + 2 - elseif text:match('^\\t', i) then - VALUE = VALUE .. '\t' - i = i + 2 - else - local hex = - text:match( - '^\\u([0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', - i - ) - if hex then - i = i + 6 -- bypass what we just read - - -- We have a Unicode codepoint. It could be standalone, or if in the proper range and - -- followed by another in a specific range, it'll be a two-code surrogate pair. - local codepoint = tonumber(hex, 16) - if codepoint >= 0xD800 and codepoint <= 0xDBFF then - -- it's a hi surrogate... see whether we have a following low - local lo_surrogate = - text:match('^\\u([dD][cdefCDEF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i) - if lo_surrogate then - i = i + 6 -- bypass the low surrogate we just read - codepoint = 0x2400 + (codepoint - 0xD800) * 0x400 + tonumber(lo_surrogate, 16) - else - -- not a proper low, so we'll just leave the first codepoint as is and spit it out. - end - end - VALUE = VALUE .. unicode_codepoint_as_utf8(codepoint) - else - -- just pass through what's escaped - VALUE = VALUE .. text:match('^\\(.)', i) - i = i + 2 - end - end - end - - self:onDecodeError('unclosed string', text, start, etc) -end - -local function skip_whitespace(text, start) - local _, match_end = text:find('^[ \n\r\t]+', start) -- [http://www.ietf.org/rfc/rfc4627.txt] Section 2 - if match_end then - return match_end + 1 - else - return start - end -end - -local grok_one -- assigned later - -local function grok_object(self, text, start, etc) - if text:sub(start, start) ~= '{' then - self:onDecodeError("expected '{'", text, start, etc) - end - - local i = skip_whitespace(text, start + 1) -- +1 to skip the '{' - - local VALUE = self.strictTypes and self:newObject {} or {} - - if text:sub(i, i) == '}' then - return VALUE, i + 1 - end - local text_len = text:len() - while i <= text_len do - local key, new_i = grok_string(self, text, i, etc) - - i = skip_whitespace(text, new_i) - - if text:sub(i, i) ~= ':' then - self:onDecodeError('expected colon', text, i, etc) - end - - i = skip_whitespace(text, i + 1) - - local new_val, new_i = grok_one(self, text, i) - - VALUE[key] = new_val - - -- - -- Expect now either '}' to end things, or a ',' to allow us to continue. - -- - i = skip_whitespace(text, new_i) - - local c = text:sub(i, i) - - if c == '}' then - return VALUE, i + 1 - end - - if text:sub(i, i) ~= ',' then - self:onDecodeError("expected comma or '}'", text, i, etc) - end - - i = skip_whitespace(text, i + 1) - end - - self:onDecodeError("unclosed '{'", text, start, etc) -end - -local function grok_array(self, text, start, etc) - if text:sub(start, start) ~= '[' then - self:onDecodeError("expected '['", text, start, etc) - end - - local i = skip_whitespace(text, start + 1) -- +1 to skip the '[' - local VALUE = self.strictTypes and self:newArray {} or {} - if text:sub(i, i) == ']' then - return VALUE, i + 1 - end - - local VALUE_INDEX = 1 - - local text_len = text:len() - while i <= text_len do - local val, new_i = grok_one(self, text, i) - - -- can't table.insert(VALUE, val) here because it's a no-op if val is nil - VALUE[VALUE_INDEX] = val - VALUE_INDEX = VALUE_INDEX + 1 - - i = skip_whitespace(text, new_i) - - -- - -- Expect now either ']' to end things, or a ',' to allow us to continue. - -- - local c = text:sub(i, i) - if c == ']' then - return VALUE, i + 1 - end - if text:sub(i, i) ~= ',' then - self:onDecodeError("expected comma or '['", text, i, etc) - end - i = skip_whitespace(text, i + 1) - end - self:onDecodeError("unclosed '['", text, start, etc) -end - -grok_one = function(self, text, start, etc) - -- Skip any whitespace - start = skip_whitespace(text, start) - - if start > text:len() then - self:onDecodeError('unexpected end of string', text, nil, etc) - end - - if text:find('^"', start) then - return grok_string(self, text, start, etc) - elseif text:find('^[-0123456789 ]', start) then - return grok_number(self, text, start, etc) - elseif text:find('^%{', start) then - return grok_object(self, text, start, etc) - elseif text:find('^%[', start) then - return grok_array(self, text, start, etc) - elseif text:find('^true', start) then - return true, start + 4 - elseif text:find('^false', start) then - return false, start + 5 - elseif text:find('^null', start) then - return nil, start + 4 - else - self:onDecodeError("can't parse JSON", text, start, etc) - end -end - ----@param text string -function OBJDEF:decode(text, etc) - if type(self) ~= 'table' or self.__index ~= OBJDEF then - OBJDEF:onDecodeError('JSON:decode must be called in method format', nil, nil, etc) - end - - if text == nil then - self:onDecodeOfNilError(string.format('nil passed to JSON:decode()'), nil, nil, etc) - elseif type(text) ~= 'string' then - self:onDecodeError( - string.format('expected string argument to JSON:decode(), got %s', type(text)), - nil, - nil, - etc - ) - end - - if text:match('^%s*$') then - return nil - end - - if text:match('^%s*<') then - -- Can't be JSON... we'll assume it's HTML - self:onDecodeOfHTMLError(string.format('html passed to JSON:decode()'), text, nil, etc) - end - - -- - -- Ensure that it's not UTF-32 or UTF-16. - -- Those are perfectly valid encodings for JSON (as per RFC 4627 section 3), - -- but this package can't handle them. - -- - if text:sub(1, 1):byte() == 0 or (text:len() >= 2 and text:sub(2, 2):byte() == 0) then - self:onDecodeError('JSON package groks only UTF-8, sorry', text, nil, etc) - end - - local success, value = pcall(grok_one, self, text, 1, etc) - - if success then - return value - else - -- if JSON:onDecodeError() didn't abort out of the pcall, we'll have received the error message here as "value", so pass it along as an assert. - if self.assert then - self.assert(false, value) - else - assert(false, value) - end - -- and if we're still here, return a nil and throw the error message on as a second arg - return nil, value - end -end - -local function backslash_replacement_function(c) - if c == '\n' then - return '\\n' - elseif c == '\r' then - return '\\r' - elseif c == '\t' then - return '\\t' - elseif c == '\b' then - return '\\b' - elseif c == '\f' then - return '\\f' - elseif c == '"' then - return '\\"' - elseif c == '\\' then - return '\\\\' - else - return string.format('\\u%04x', c:byte()) - end -end - -local chars_to_be_escaped_in_JSON_string = - '[' .. - '"' .. -- class sub-pattern to match a double quote - '%\\' .. -- class sub-pattern to match a backslash - '%z' .. -- class sub-pattern to match a null - '\001' .. - '-' .. - '\031' .. -- class sub-pattern to match control characters - ']' - -local function json_string_literal(value) - local newval = value:gsub(chars_to_be_escaped_in_JSON_string, backslash_replacement_function) - return '"' .. newval .. '"' -end - -local function object_or_array(self, T, etc) - -- - -- We need to inspect all the keys... if there are any strings, we'll convert to a JSON - -- object. If there are only numbers, it's a JSON array. - -- - -- If we'll be converting to a JSON object, we'll want to sort the keys so that the - -- end result is deterministic. - -- - local string_keys = {} - local number_keys = {} - local number_keys_must_be_strings = false - local maximum_number_key - - for key in pairs(T) do - if type(key) == 'string' then - table.insert(string_keys, key) - elseif type(key) == 'number' then - table.insert(number_keys, key) - if key <= 0 or key >= math.huge then - number_keys_must_be_strings = true - elseif not maximum_number_key or key > maximum_number_key then - maximum_number_key = key - end - else - self:onEncodeError("can't encode table with a key of type " .. type(key), etc) - end - end - - if #string_keys == 0 and not number_keys_must_be_strings then - -- - -- An empty table, or a numeric-only array - -- - if #number_keys > 0 then - return nil, maximum_number_key -- an array - elseif tostring(T) == 'JSON array' then - return nil - elseif tostring(T) == 'JSON object' then - return {} - else - -- have to guess, so we'll pick array, since empty arrays are likely more common than empty objects - return nil - end - end - - table.sort(string_keys) - - local map - if #number_keys > 0 then - -- - -- If we're here then we have either mixed string/number keys, or numbers inappropriate for a JSON array - -- It's not ideal, but we'll turn the numbers into strings so that we can at least create a JSON object. - -- - - if self.noKeyConversion then - self:onEncodeError('a table with both numeric and string keys could be an object or array; aborting', etc) - end - - -- - -- Have to make a shallow copy of the source table so we can remap the numeric keys to be strings - -- - map = {} - for key, val in pairs(T) do - map[key] = val - end - - table.sort(number_keys) - - -- - -- Throw numeric keys in there as strings - -- - for _, number_key in ipairs(number_keys) do - local string_key = tostring(number_key) - if map[string_key] == nil then - table.insert(string_keys, string_key) - map[string_key] = T[number_key] - else - self:onEncodeError( - 'conflict converting table with mixed-type keys into a JSON object: key ' .. - number_key .. ' exists both as a string and a number.', - etc - ) - end - end - end - - return string_keys, nil, map -end - --- --- Encode --- --- 'options' is nil, or a table with possible keys: --- pretty -- if true, return a pretty-printed version --- indent -- a string (usually of spaces) used to indent each nested level --- align_keys -- if true, align all the keys when formatting a table --- -local encode_value -- must predeclare because it calls itself -function encode_value(self, value, parents, etc, options, indent) - if value == nil then - return 'null' - elseif type(value) == 'string' then - return json_string_literal(value) - elseif type(value) == 'number' then - if value ~= value then - -- - -- NaN (Not a Number). - -- JSON has no NaN, so we have to fudge the best we can. This should really be a package option. - -- - return 'null' - elseif value >= math.huge then - -- - -- Positive infinity. JSON has no INF, so we have to fudge the best we can. This should - -- really be a package option. Note: at least with some implementations, positive infinity - -- is both ">= math.huge" and "<= -math.huge", which makes no sense but that's how it is. - -- Negative infinity is properly "<= -math.huge". So, we must be sure to check the ">=" - -- case first. - -- - return '1e+9999' - elseif value <= -math.huge then - -- - -- Negative infinity. - -- JSON has no INF, so we have to fudge the best we can. This should really be a package option. - -- - return '-1e+9999' - else - return tostring(value) - end - elseif type(value) == 'boolean' then - return tostring(value) - elseif type(value) ~= 'table' then - self:onEncodeError("can't convert " .. type(value) .. ' to JSON', etc) - else - -- - -- A table to be converted to either a JSON object or array. - -- - local T = value - - if type(options) ~= 'table' then - options = {} - end - if type(indent) ~= 'string' then - indent = '' - end - - if parents[T] then - self:onEncodeError('table ' .. tostring(T) .. ' is a child of itself', etc) - else - parents[T] = true - end - - local result_value - - local object_keys, maximum_number_key, map = object_or_array(self, T, etc) - if maximum_number_key then - -- - -- An array... - -- - local ITEMS = {} - for i = 1, maximum_number_key do - table.insert(ITEMS, encode_value(self, T[i], parents, etc, options, indent)) - end - - if options.pretty then - result_value = '[ ' .. table.concat(ITEMS, ', ') .. ' ]' - else - result_value = '[' .. table.concat(ITEMS, ',') .. ']' - end - elseif object_keys then - -- - -- An object - -- - local TT = map or T - - if options.pretty then - local KEYS = {} - local max_key_length = 0 - for _, key in ipairs(object_keys) do - local encoded = encode_value(self, tostring(key), parents, etc, options, indent) - if options.align_keys then - max_key_length = math.max(max_key_length, #encoded) - end - table.insert(KEYS, encoded) - end - local key_indent = indent .. tostring(options.indent or '') - local subtable_indent = - key_indent .. string.rep(' ', max_key_length) .. (options.align_keys and ' ' or '') - local FORMAT = '%s%' .. string.format('%d', max_key_length) .. 's: %s' - - local COMBINED_PARTS = {} - for i, key in ipairs(object_keys) do - local encoded_val = encode_value(self, TT[key], parents, etc, options, subtable_indent) - table.insert(COMBINED_PARTS, string.format(FORMAT, key_indent, KEYS[i], encoded_val)) - end - result_value = '{\n' .. table.concat(COMBINED_PARTS, ',\n') .. '\n' .. indent .. '}' - else - local PARTS = {} - for _, key in ipairs(object_keys) do - local encoded_val = encode_value(self, TT[key], parents, etc, options, indent) - local encoded_key = encode_value(self, tostring(key), parents, etc, options, indent) - table.insert(PARTS, string.format('%s:%s', encoded_key, encoded_val)) - end - result_value = '{' .. table.concat(PARTS, ',') .. '}' - end - else - -- - -- An empty array/object... we'll treat it as an array, though it should really be an option - -- - result_value = '[]' - end - - parents[T] = false - return result_value - end -end - -function OBJDEF:encode(value, etc, options) - if type(self) ~= 'table' or self.__index ~= OBJDEF then - OBJDEF:onEncodeError('JSON:encode must be called in method format', etc) - end - return encode_value(self, value, {}, etc, options or nil) -end - -function OBJDEF:encode_pretty(value, etc, options) - if type(self) ~= 'table' or self.__index ~= OBJDEF then - OBJDEF:onEncodeError('JSON:encode_pretty must be called in method format', etc) - end - return encode_value(self, value, {}, etc, options or default_pretty_options) -end - -function OBJDEF.__tostring() - return 'JSON encode/decode package' -end - -OBJDEF.__index = OBJDEF - -function OBJDEF:new(args) - local new = {} - - if args then - for key, val in pairs(args) do - new[key] = val - end - end - - return setmetatable(new, OBJDEF) -end - -return OBJDEF:new() - --- --- Version history: --- --- 20141223.14 The encode_pretty() routine produced fine results for small datasets, but isn't really --- appropriate for anything large, so with help from Alex Aulbach I've made the encode routines --- more flexible, and changed the default encode_pretty() to be more generally useful. --- --- Added a third 'options' argument to the encode() and encode_pretty() routines, to control --- how the encoding takes place. --- --- Updated docs to add assert() call to the loadfile() line, just as good practice so that --- if there is a problem loading JSON.lua, the appropriate error message will percolate up. --- --- 20140920.13 Put back (in a way that doesn't cause warnings about unused variables) the author string, --- so that the source of the package, and its version number, are visible in compiled copies. --- --- 20140911.12 Minor lua cleanup. --- Fixed internal reference to 'JSON.noKeyConversion' to reference 'self' instead of 'JSON'. --- (Thanks to SmugMug's David Parry for these.) --- --- 20140418.11 JSON nulls embedded within an array were being ignored, such that --- ["1",null,null,null,null,null,"seven"], --- would return --- {1,"seven"} --- It's now fixed to properly return --- {1, nil, nil, nil, nil, nil, "seven"} --- Thanks to "haddock" for catching the error. --- --- 20140116.10 The user's JSON.assert() wasn't always being used. Thanks to "blue" for the heads up. --- --- 20131118.9 Update for Lua 5.3... it seems that tostring(2/1) produces "2.0" instead of "2", --- and this caused some problems. --- --- 20131031.8 Unified the code for encode() and encode_pretty(); they had been stupidly separate, --- and had of course diverged (encode_pretty didn't get the fixes that encode got, so --- sometimes produced incorrect results; thanks to Mattie for the heads up). --- --- Handle encoding tables with non-positive numeric keys (unlikely, but possible). --- --- If a table has both numeric and string keys, or its numeric keys are inappropriate --- (such as being non-positive or infinite), the numeric keys are turned into --- string keys appropriate for a JSON object. So, as before, --- JSON:encode({ "one", "two", "three" }) --- produces the array --- ["one","two","three"] --- but now something with mixed key types like --- JSON:encode({ "one", "two", "three", SOMESTRING = "some string" })) --- instead of throwing an error produces an object: --- {"1":"one","2":"two","3":"three","SOMESTRING":"some string"} --- --- To maintain the prior throw-an-error semantics, set --- JSON.noKeyConversion = true --- --- 20131004.7 Release under a Creative Commons CC-BY license, which I should have done from day one, sorry. --- --- 20130120.6 Comment update: added a link to the specific page on my blog where this code can --- be found, so that folks who come across the code outside of my blog can find updates --- more easily. --- --- 20111207.5 Added support for the 'etc' arguments, for better error reporting. --- --- 20110731.4 More feedback from David Kolf on how to make the tests for Nan/Infinity system independent. --- --- 20110730.3 Incorporated feedback from David Kolf at http://lua-users.org/wiki/JsonModules: --- --- * When encoding lua for JSON, Sparse numeric arrays are now handled by --- spitting out full arrays, such that --- JSON:encode({"one", "two", [10] = "ten"}) --- returns --- ["one","two",null,null,null,null,null,null,null,"ten"] --- --- In 20100810.2 and earlier, only up to the first non-null value would have been retained. --- --- * When encoding lua for JSON, numeric value NaN gets spit out as null, and infinity as "1+e9999". --- Version 20100810.2 and earlier created invalid JSON in both cases. --- --- * Unicode surrogate pairs are now detected when decoding JSON. --- --- 20100810.2 added some checking to ensure that an invalid Unicode character couldn't leak in to the UTF-8 encoding --- --- 20100731.1 initial public release --- diff --git a/code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua deleted file mode 100644 index fc900a4..0000000 --- a/code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,68 +0,0 @@ ---- 模块工具 --- @module Module utilities --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang - -local ModuleUtil = {} - ---- 加载模块目录 --- @param _root 模块目录的节点 --- @param _scope 载入后脚本的作用域 -function ModuleUtil.LoadModules(_root, _scope) - _scope = _scope or _G - assert(_root, '[ModuleUtil] Node does NOT exist!') - local tmp = _root:GetChildren() - for _, v in pairs(tmp) do - name = (v.Name):gsub('Module', '') - -- print('[ModuleUtil] Load: ' .. name) - _scope[name] = require(v) - end -end - ---- 加载XLS表格目录 --- @param _root 模块目录的节点 -function ModuleUtil.LoadXlsModules(_root, _config) - assert(_root, '[ModuleUtil] Node does NOT exist!') - assert(_config, '[ModuleUtil] Config does NOT exist!') - local tmp = _root:GetChildren() - for _, v in pairs(tmp) do - name = (v.Name):gsub('XlsModule', '') - print('[ModuleUtil] Load: ' .. name) - _config[name] = require(v) - end -end - ---- 加载多个模块目录 -function ModuleUtil.LoadAllModules(...) - local args = table.pack(...) - for i = 1, args.n do - if args[i] then - ModuleUtil.LoadModules(args[i]) - end - end -end - ---- 将有包含特定方法的模块筛选出来,并放在一个table中 --- @param _root 模块目录的节点 --- @param @string _fn 方法名 function_name --- @param @table _list 存放的table -function ModuleUtil.GetModuleListWithFunc(_root, _fn, _list) - assert(_root, '[ModuleUtil] Node does NOT exist!') - assert(not string.isnilorempty(_fn), '[ModuleUtil] Function name is nil or empty!') - assert(_list, '[ModuleUtil] List is NOT initialized!') - local tmp, name = _root:GetChildren() - for _, v in pairs(tmp) do - name = (v.Name):gsub('Module', '') - if _G[name] and _G[name][_fn] and type(_G[name][_fn]) == 'function' then - table.insert(_list, _G[name]) - end - end -end - ---- 新建一个模块实例(ServerBase or ClientBase) -function ModuleUtil.New(_name, _baseClass) - local t = class(_name, _baseClass) - return t, t:GetSelf() -end - -return ModuleUtil diff --git a/code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua deleted file mode 100644 index ec3ddaa..0000000 --- a/code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,123 +0,0 @@ ---- 网路工具/事件工具 --- @module Network utilities --- @copyright Lilith Games, Avatar Team --- @author Sharif Ma, Yuancheng Zhang, Yen Yuan -local NetUtil = {} - --- 格式化事件参数, Table=>JSON -local FormatArgs - ---! 事件参数校验, true:开启校验 -local valid, ValidateArgs = true - ---! 打印事件日志, true:开启打印 -local showLog, PrintEventLog = false - -local FireEnum = { - SERVER = 1, - CLIENT = 2, - BROADCAST = 3 -} - ---! 外部接口 - ---- 向服务器发送消息 --- @param @string _eventName 事件的名字(严格对应) --- @param ... 事件参数 -function NetUtil.Fire_S(_eventName, ...) - ValidateArgs(FireEnum.SERVER, _eventName) - local args = {...} - world.S_Event[_eventName]:Fire(table.unpack(args)) - PrintEventLog(FireEnum.SERVER, _eventName, nil, args) -end - ---- 向指定的玩家发送消息 --- @param @string _eventName 事件的名字 --- @param _player 玩家对象 --- @param ... 事件参数 -function NetUtil.Fire_C(_eventName, _player, ...) - if(_player == nil) then - return - end - ValidateArgs(FireEnum.CLIENT, _eventName, _player) - local args = {...} - _player.C_Event[_eventName]:Fire(table.unpack(args)) - PrintEventLog(FireEnum.CLIENT, _eventName, _player, args) -end - ---- 客户端广播 --- @param @string _eventName 事件的名字(严格对应) --- @param ... 事件参数 -function NetUtil.Broadcast(_eventName, ...) - ValidateArgs(FireEnum.BROADCAST, _eventName, ...) - local args = {...} - world.Players:BroadcastEvent(_eventName, table.unpack(args)) - PrintEventLog(FireEnum.BROADCAST, _eventName, nil, args) -end - ---! 私有函数 - ---- 格式化事件参数 -FormatArgs = function(...) - local args = {...} - for k, v in pairs(args) do - if type(v) == 'table' then - args[k] = string.format('JSON%sJSON', LuaJsonUtil:encode(v)) - end - end - return args -end - ---! 辅助功能 - ---- 事件参数校验 -ValidateArgs = - valid and - function(_fireEnum, _eventName, _player) - if _fireEnum == FireEnum.SERVER then - --! Fire_S 检查参数 - assert(not string.isnilorempty(_eventName), '[NetUtil][Fire_S] 事件名为空') - assert(world.S_Event[_eventName], string.format('[NetUtil][Fire_S] 服务器不存在事件: %s', _eventName)) - elseif _fireEnum == FireEnum.CLIENT then - --! Fire_C 检查参数 - assert(not string.isnilorempty(_eventName), '[NetUtil] 事件名为空') - assert( - _player and _player.ClassName == 'PlayerInstance', - string.format('[NetUtil][Fire_C]第2个参数需要是玩家对象, 错误事件: %s', _eventName) - ) - assert( - _player.C_Event[_eventName], - string.format('[NetUtil][Fire_C] 客户端玩家不存在事件: %s, 玩家: %s', _player.Name, _eventName) - ) - elseif _fireEnum == FireEnum.BROADCAST then - --! Broadcase 检查参数 - assert(not string.isnilorempty(_eventName), '[NetUtil][Broadcast] 事件名为空') - end - end or - function() - end - ---- 打印事件日志 -PrintEventLog = showLog and function(_fireEnum, _eventName, _player, _args) - if _fireEnum == FireEnum.SERVER then - --* Fire_S 参数打印 - print(string.format('[NetUtil][服务器] %s, 参数 = %s, %s', _eventName, #_args, table.dump(_args))) - elseif _fireEnum == FireEnum.CLIENT then - --* Fire_C 参数打印 - print( - string.format( - '[NetUtil][客户端] %s, 玩家=%s, 参数 = %s, %s', - _eventName, - _player.Name, - #_args, - table.dump(_args) - ) - ) - elseif _fireEnum == FireEnum.BROADCAST then - --* Broadcase 参数打印 - print(string.format('[NetUtil][客户端][广播] %s, 参数 = %s, %s', _eventName, #_args, table.dump(_args))) - end - end or function() - end - -return NetUtil diff --git a/code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua deleted file mode 100644 index b276648..0000000 --- a/code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,65 +0,0 @@ ----对象池工具模块 ----@module ObjPoolUtil --- @copyright Lilith Games, Avatar Team --- @author Yen Yuan ----@class ObjPoolUtil -local ObjPoolUtil = class('ObjPoolUtil') - ----创建某一个对象的对象池 ----@param _folderName Object 管理的目录 ----@param _objName string 对象的Archetype名 ----@param _maxCount number 对象池最大上限,不填则为100 ----@return ObjPoolUtil -function ObjPoolUtil.static.Newpool(_folderName, _objName, _maxCount) - if _folderName == nil or _objName == nil then - error('[ObjPoolUtil] 管理目录或管理对象为空') - end - if _maxCount == nil then - _maxCount = 100 - end - local realPool = class(_objName .. 'Pool', ObjPoolUtil) - realPool.static.obj = _objName - realPool.static.folder = _folderName - realPool.static.maxCount = _maxCount - realPool.pool = {} - print(string.format('[ObjPoolUtil] 创建了一个%s的对象池,目录为%s', _objName, _folderName)) - return realPool -end - ----从池中创建对象到世界下 ----@param _position Vector3 ----@param _rotation EulerDegree -function ObjPoolUtil:Spawn(_position, _rotation) - local realObj = nil - if #self.pool == 0 then - realObj = world:CreateInstance(self.obj, self.obj, self.folder, _position, _rotation) - if realObj == nil then - error(string.format('[ObjPoolUtil] Archetype下没有名为%s的对象', self.obj)) - return - end - return realObj - else - realObj = self.pool[1] - self.pool[1].Position = _position - self.pool[1].Rotation = _rotation - self.pool[1]:SetActive(true) - table.remove(self.pool, 1) - return realObj - end -end - ----从世界中销毁对象到池中 ----@param _obj Object -function ObjPoolUtil:Despawn(_obj) - if _obj == nil then - error('[ObjPoolUtil] 传入对象为空') - elseif #self.pool > self.maxCount then - error(string.format('[ObjPoolUtil] %s对象池已满,该对象会永久销毁', self.obj)) - _obj:Destroy() - else - table.insert(self.pool, _obj) - _obj:SetActive(false) - end -end - -return ObjPoolUtil diff --git a/code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua deleted file mode 100644 index 81b6e87..0000000 --- a/code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,65 +0,0 @@ ---- 音效播放模块 ----@module SoundUtil ----@copyright Lilith Games, Avatar Team ----@author Sharif Ma ----@class SoundUtil -local SoundUtil = {} - -function SoundUtil:Init() - print('[SoundUtil] Init()') - self.SoundPlaying = {} - self.Table_Sound = Config.Sound -end - ----创建一个新音效并播放 ----@param _ID number 音效的ID ----@param _SoundSourceObj Object 音效的挂载物体,不填则为2D音效,挂载在主摄像机上 -function SoundUtil:PlaySound(_ID, _SoundSourceObj) - local Info, _Duration - _SoundSourceObj = _SoundSourceObj or world.CurrentCamera - Info = self.Table_Sound[_ID] - assert(Info, '[SoundUtil] 表中不存在该ID的音效') - _Duration = Info.Duration - local sameSoundPlayingNum = 0 - for k, v in pairs(self.SoundPlaying) do - if v == _ID then - sameSoundPlayingNum = sameSoundPlayingNum + 1 - end - end - if sameSoundPlayingNum > 0 and not Info.CoverPlay then - print(string.format('[SoundUtil] %s音效CoverPlay字段为false,不能覆盖播放', _ID)) - return - end - - local Audio = world:CreateObject('AudioSource', 'Audio_' .. Info.FileName, _SoundSourceObj) - Audio.LocalPosition = Vector3.Zero - Audio.SoundClip = ResourceManager.GetSoundClip('Audio/' .. Info.FileName) - print('[SoundUtil] Audio.SoundClip', Audio.SoundClip) - Audio.Volume = Info.Volume - Audio.MaxDistance = 10 - Audio.MinDistance = 10 - Audio.Loop = Info.IsLoop - Audio:Play() - table.insert(self.SoundPlaying, _ID) - _Duration = _Duration or 1 - invoke( - function() - if Audio then - Audio:Destroy() - end - end, - _Duration - ) - invoke( - function() - for k, v in pairs(self.SoundPlaying) do - if v == _ID then - table.remove(self.SoundPlaying, k) - end - end - end, - _Duration - ) -end - -return SoundUtil diff --git a/code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua deleted file mode 100644 index 65d83de..0000000 --- a/code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,149 +0,0 @@ ---- 时间管理器模块 --- @module Module Time Manager --- @copyright Lilith Games, Avatar Team --- @author Bingyun Chen, Yuancheng Zhang --- @see the functions defined by JavaScript syntax - -local TimeUtil = {} - --- All registered events -local eventList = {} - --- Current active event list -local activeEvents = {} - -local running = false - --- Set update delta time -local DELTA_TIME = .05 - ---- Find all registered events to trigger -local function CheckEvents() - -- now = os.time() - local now = Timer.GetTimeMillisecond() - local i, event = 1 - while i <= #eventList do - event = eventList[i] - if event.triggerTime <= now then - table.insert(activeEvents, event) - if event.loop then - event.triggerTime = event.triggerTime + event.delay - i = i + 1 - else - table.remove(eventList, i) - end - else - i = i + 1 - end - end -end - ---- Trigger events -local function TriggerEvents() - local i = 1 - while i <= #activeEvents do - event = activeEvents[i] - invoke(event.func) - table.remove(activeEvents, i) - end -end - ---- Update -local function StartUpdate() - while running do - -- print(os.time()) - CheckEvents() - TriggerEvents() - wait(DELTA_TIME) - end -end - ---- Initialization -function TimeUtil.Init() - TimeUtil.Start() -end - ---- Run Update() -function TimeUtil.Start() - running = true - invoke(StartUpdate) -end - ---- Stop Update() -function TimeUtil.Stop() - running = false -end - ---- Call a function after a specified number of milliseconds, --- use ClearTimeout() method to prevent the function from running --- @param _func execution function to call --- @param _delayTime --- @return timer id --- @see https://www.w3schools.com/jsref/met_win_settimeout.asp -function TimeUtil.SetTimeout(_func, _seconds) - assert(_func, '[TimeUtil] TimeUtil.SetTimeout() _func 不能为空') - assert(_seconds >= 0, '[TimeUtil] TimeUtil.SetTimeout() 延迟时间需大于等于0') - if _seconds == 0 then - print('[TimeUtil] TimeUtil.SetTimeout() 事件立即执行') - invoke(_func) - return - end - local id = #eventList + 1 - -- convert to milliseconds - local ms = math.floor(_seconds * 1000) - local timestamp = ms + Timer.GetTimeMillisecond() - table.insert( - eventList, - { - id = id, - func = _func, - delay = ms, - triggerTime = timestamp - } - ) - return id -end - ---- Call a function or evaluates an expression at specified intervals (in milliseconds), --- the method will continue calling the function until ClearInterval() is called, or the game is over. --- @param _func execution function to call --- @param _delayTime --- @return timer id --- @see https://www.w3schools.com/jsref/met_win_setinterval.asp -function TimeUtil.SetInterval(_func, _seconds) - assert(_func, '[TimeUtil] TimeUtil.SetInterval() _func 不能为空') - assert(_seconds > 0, '[TimeUtil] TimeUtil.SetInterval() 延迟时间需大于0') - local id = #eventList + 1 - -- convert to milliseconds - local ms = math.floor(_seconds * 1000) - local timestamp = ms + Timer.GetTimeMillisecond() - table.insert( - eventList, - { - id = id, - func = _func, - delay = ms, - triggerTime = timestamp, - loop = true - } - ) - return id -end - ---- Clear a timer set with the SetTimeout() method --- @param _id timmer id --- @see https://www.w3schools.com/jsref/met_win_cleartimeout.asp -function TimeUtil.ClearTimeout(_id) - for k, e in pairs(eventList) do - if e.id == _id then - table.remove(eventList, k) - break - end - end -end - ---- Clear a timer set with the SetInterval() method, used as ClearTimeout() --- @see https://www.w3schools.com/jsref/met_win_clearinterval.asp -TimeUtil.ClearInterval = TimeUtil.ClearTimeout - -return TimeUtil diff --git a/code/['World']['Global']['Utility']['TweenControllerModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['TweenControllerModule'].ModuleScript.lua deleted file mode 100644 index ead6bd1..0000000 --- a/code/['World']['Global']['Utility']['TweenControllerModule'].ModuleScript.lua +++ /dev/null @@ -1,38 +0,0 @@ ----控制某个变量随时间变化的协程类 ----@module TweenController ----@copyright Lilith Games, Avatar Team ----@author An Dai -local TweenController = class('TweenController') - ----_name:类名,_sender:使用它的类,_getTotalTime:获得总时间的方法,_update _callback:回调函数 _isFix:是否在fixupdate中执行, _start: 开始函数 -function TweenController:initialize(_name, _sender, _getTotalTime, _update, _callback, _isFix, _start) - _start = _start or function() - return - end - - local updateStr = (_isFix and 'Fix' or '') .. 'Update' - - self.Start = function(self) - _start() - self.totalTime = _getTotalTime() - self.time = 0 - _sender[updateStr .. 'Table'][_name] = self - end - - self[updateStr] = function(self, _dt) - self.time = self.time + _dt - if (self.time > self.totalTime) then - self:Stop() - goto UpdateReturn - end - _update(self.time, self.totalTime, _dt) - ::UpdateReturn:: - end - - self.Stop = function(self) - _sender[updateStr .. 'Table'][_name] = nil - _callback() - end -end - -return TweenController diff --git a/code/['World']['Global']['Utility']['UuidModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['UuidModule'].ModuleScript.lua deleted file mode 100644 index b58ffa8..0000000 --- a/code/['World']['Global']['Utility']['UuidModule'].ModuleScript.lua +++ /dev/null @@ -1,229 +0,0 @@ ---------------------------------------------------------------------------------------- --- Copyright 2012 Rackspace (original), 2013 Thijs Schreijer (modifications) --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS-IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- see http://www.ietf.org/rfc/rfc4122.txt --- --- Note that this is not a true version 4 (random) UUID. Since `os.time()` precision is only 1 second, it would be hard --- to guarantee spacial uniqueness when two hosts generate a uuid after being seeded during the same second. This --- is solved by using the node field from a version 1 UUID. It represents the mac address. --- --- 28-apr-2013 modified by Thijs Schreijer from the original [Rackspace code](https://github.com/kans/zirgo/blob/807250b1af6725bad4776c931c89a784c1e34db2/util/uuid.lua) as a generic Lua module. --- Regarding the above mention on `os.time()`; the modifications use the `socket.gettime()` function from LuaSocket --- if available and hence reduce that problem (provided LuaSocket has been loaded before uuid). --- --- **6-nov-2015 Please take note of this issue**; [https://github.com/Mashape/kong/issues/478](https://github.com/Mashape/kong/issues/478) --- It demonstrates the problem of using time as a random seed. Specifically when used from multiple processes. --- So make sure to seed only once, application wide. And to not have multiple processes do that --- simultaneously (like nginx does for example). - -local M = {} - -local bitsize = 32 -- bitsize assumed for Lua VM. See randomseed function below. -local lua_version = tonumber(_VERSION:match('%d%.*%d*')) -- grab Lua version used - -local MATRIX_AND = {{0, 0}, {0, 1}} -local MATRIX_OR = {{0, 1}, {1, 1}} -local HEXES = '0123456789abcdef' - -local math_floor = math.floor -local math_random = math.random -local math_abs = math.abs -local string_sub = string.sub -local to_number = tonumber -local assert = assert -local type = type - --- performs the bitwise operation specified by truth matrix on two numbers. -local function BITWISE(x, y, matrix) - local z = 0 - local pow = 1 - while x > 0 or y > 0 do - z = z + (matrix[x % 2 + 1][y % 2 + 1] * pow) - pow = pow * 2 - x = math_floor(x / 2) - y = math_floor(y / 2) - end - return z -end - -local function INT2HEX(x) - local s, base = '', 16 - local d - while x > 0 do - d = x % base + 1 - x = math_floor(x / base) - s = string_sub(HEXES, d, d) .. s - end - while #s < 2 do - s = '0' .. s - end - return s -end - ----------------------------------------------------------------------------- --- Creates a new uuid. Either provide a unique hex string, or make sure the --- random seed is properly set. The module table itself is a shortcut to this --- function, so `my_uuid = uuid.new()` equals `my_uuid = uuid()`. --- --- For proper use there are 3 options; --- --- 1. first require `luasocket`, then call `uuid.seed()`, and request a uuid using no --- parameter, eg. `my_uuid = uuid()` --- 2. use `uuid` without `luasocket`, set a random seed using `uuid.randomseed(some_good_seed)`, --- and request a uuid using no parameter, eg. `my_uuid = uuid()` --- 3. use `uuid` without `luasocket`, and request a uuid using an unique hex string, --- eg. `my_uuid = uuid(my_networkcard_macaddress)` --- --- @return a properly formatted uuid string --- @param hwaddr (optional) string containing a unique hex value (e.g.: `00:0c:29:69:41:c6`), to be used to compensate for the lesser `math_random()` function. Use a mac address for solid results. If omitted, a fully randomized uuid will be generated, but then you must ensure that the random seed is set properly! --- @usage --- local uuid = require("uuid") --- print("here's a new uuid: ",uuid()) -function M.new(hwaddr) - -- bytes are treated as 8bit unsigned bytes. - local bytes = { - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255) - } - - if hwaddr then - assert(type(hwaddr) == 'string', 'Expected hex string, got ' .. type(hwaddr)) - -- Cleanup provided string, assume mac address, so start from back and cleanup until we've got 12 characters - local i, str = #hwaddr, hwaddr - hwaddr = '' - while i > 0 and #hwaddr < 12 do - local c = str:sub(i, i):lower() - if HEXES:find(c, 1, true) then - -- valid HEX character, so append it - hwaddr = c .. hwaddr - end - i = i - 1 - end - assert( - #hwaddr == 12, - "Provided string did not contain at least 12 hex characters, retrieved '" .. - hwaddr .. "' from '" .. str .. "'" - ) - - -- no split() in lua. :( - bytes[11] = to_number(hwaddr:sub(1, 2), 16) - bytes[12] = to_number(hwaddr:sub(3, 4), 16) - bytes[13] = to_number(hwaddr:sub(5, 6), 16) - bytes[14] = to_number(hwaddr:sub(7, 8), 16) - bytes[15] = to_number(hwaddr:sub(9, 10), 16) - bytes[16] = to_number(hwaddr:sub(11, 12), 16) - end - - -- set the version - bytes[7] = BITWISE(bytes[7], 0x0f, MATRIX_AND) - bytes[7] = BITWISE(bytes[7], 0x40, MATRIX_OR) - -- set the variant - bytes[9] = BITWISE(bytes[7], 0x3f, MATRIX_AND) - bytes[9] = BITWISE(bytes[7], 0x80, MATRIX_OR) - return INT2HEX(bytes[1]) .. - INT2HEX(bytes[2]) .. - INT2HEX(bytes[3]) .. - INT2HEX(bytes[4]) .. - '-' .. - INT2HEX(bytes[5]) .. - INT2HEX(bytes[6]) .. - '-' .. - INT2HEX(bytes[7]) .. - INT2HEX(bytes[8]) .. - '-' .. - INT2HEX(bytes[9]) .. - INT2HEX(bytes[10]) .. - '-' .. - INT2HEX(bytes[11]) .. - INT2HEX(bytes[12]) .. - INT2HEX(bytes[13]) .. - INT2HEX(bytes[14]) .. - INT2HEX(bytes[15]) .. INT2HEX(bytes[16]) -end - ----------------------------------------------------------------------------- --- Improved randomseed function. --- Lua 5.1 and 5.2 both truncate the seed given if it exceeds the integer --- range. If this happens, the seed will be 0 or 1 and all randomness will --- be gone (each application run will generate the same sequence of random --- numbers in that case). This improved version drops the most significant --- bits in those cases to get the seed within the proper range again. --- @param seed the random seed to set (integer from 0 - 2^32, negative values will be made positive) --- @return the (potentially modified) seed used --- @usage --- local socket = require("socket") -- gettime() has higher precision than os.time() --- local uuid = require("uuid") --- -- see also example at uuid.seed() --- uuid.randomseed(socket.gettime()*10000) --- print("here's a new uuid: ",uuid()) -function M.randomseed(seed) - seed = math_floor(math_abs(seed)) - if seed >= (2 ^ bitsize) then - -- integer overflow, so reduce to prevent a bad seed - seed = seed - math_floor(seed / 2 ^ bitsize) * (2 ^ bitsize) - end - if lua_version < 5.2 then - -- 5.1 uses (incorrect) signed int - math.randomseed(seed - 2 ^ (bitsize - 1)) - else - -- 5.2 uses (correct) unsigned int - math.randomseed(seed) - end - return seed -end - ----------------------------------------------------------------------------- --- Seeds the random generator. --- It does so in 2 possible ways; --- --- 1. use `os.time()`: this only offers resolution to one second (used when --- LuaSocket hasn't been loaded yet --- 2. use luasocket `gettime()` function, but it only does so when LuaSocket --- has been required already. --- @usage --- local socket = require("socket") -- gettime() has higher precision than os.time() --- -- LuaSocket loaded, so below line does the same as the example from randomseed() --- uuid.seed() --- print("here's a new uuid: ",uuid()) -function M.seed() - -- if package.loaded['socket'] and package.loaded['socket'].gettime then - -- return M.randomseed(package.loaded['socket'].gettime() * 10000) - -- else - return M.randomseed(os.time()) - -- end -end - -return setmetatable( - M, - { - __call = function(self, hwaddr) - return self.new(hwaddr) - end - } -) diff --git a/code/['World']['Global']['Utility']['ValueChangeUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['ValueChangeUtilModule'].ModuleScript.lua deleted file mode 100644 index 05cb6a8..0000000 --- a/code/['World']['Global']['Utility']['ValueChangeUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,137 +0,0 @@ ---- 值改变及值改变事件 ---- @module ValueChangeUtil Module ---- @copyright Lilith Games, Avatar Team ---- @author Xin Tan -local ValueChangeUtil = {} - ---- 数据变化事件 ---- @param _table table 事件表 ---- @param _index string 索引 ---- @param _oldValue mixed 旧值 ---- @param _newValue mixed 新值 ---- @param _targetPlayer PlayerInstance 这条数据对应的玩家实例 -function ValueChangeUtil.DataChangeEvent(_table, _index, _oldValue, _newValue) - if not _table[_index] or type(_table[_index]) ~= "function" then - return - end - _table[_index](_oldValue, _newValue) -end - ---- 将目标表(或其中某个值)改为新值 ---- @param _table table 目标表 ---- @param _index string 目标索引(改整个目标表时填nil) ---- @param _value mixed 新值 ---- @param _eventTable table 数值改变事件表(不响应时不传) -function ValueChangeUtil.ChangeValue(_table, _index, _value, _eventTable) - if type(_table) ~= "table" then - print("[error]传入的目标表类型错误") - return - end - - local tmp = _table - local eventtmp = _eventTable or false - - -- 参数含索引时 - if _index then - local idx = {} - if type(_index) == "string" then - -- 将索引通过'.'拆开 - idx = string.split(_index, '.') - elseif type(_index) == "table" then - idx = _index - end - -- 一层层向下索引 - for i = 1, #idx - 1 do - -- 若目标表没有对应的索引则建立空表 - if type(tmp[idx[i]]) ~= "table" then - tmp[idx[i]] = {} - end - tmp = tmp[idx[i]] - if eventtmp then - if type(eventtmp[idx[i]]) ~= "table" then - eventtmp[idx[i]] = {} - end - eventtmp = eventtmp[idx[i]] - end - end - - -- 若目标值不是table,则直接赋值 - if type(_value) ~= "table" then - local oldValue = table.shallowcopy(tmp[idx[#idx]]) - tmp[idx[#idx]] = _value - if eventtmp then - ValueChangeUtil.DataChangeEvent(eventtmp, idx[#idx], oldValue, _value) - end - return - else - -- 目标值是table - -- 若目标索引不是table,则创建table - if type(tmp[idx[#idx]]) ~= "table" then - tmp[idx[#idx]] = {} - if eventtmp and type( eventtmp[idx[#idx]]) ~= "table" then - eventtmp[idx[#idx]] = {} - end - end - tmp = tmp[idx[#idx]] - if eventtmp then - eventtmp = eventtmp[idx[#idx]] - end - end - else - -- 参数无索引时,从目标表根目录开始同步 - if type(_value) ~= "table" then - print("[error]传入的新值类型错误") - return - end - end - - -- 清除目标索引表与新值的差集 - for k, v in pairs(tmp) do - if not _value[k] then - local oldValue = tmp[k] - tmp[k] = nil - if eventtmp then - ValueChangeUtil.DataChangeEvent(eventtmp, k, oldValue, nil) - end - end - end - - -- 逐层覆盖数据 - for k, v in pairs(_value) do - -- 如果值为table则向下递归 - if type(v) == "table" then - ValueChangeUtil.ChangeValue(tmp, k, v, eventtmp) - else - -- 若值不是table,则直接赋值 - local oldValue = tmp[k] - tmp[k] = v - if eventtmp then - ValueChangeUtil.DataChangeEvent(eventtmp, k, oldValue, v) - end - end - end - if eventtmp then - ValueChangeUtil.DataChangeEvent(eventtmp, "parentTableEvent") - end -end - ---- 进行数据验证,将对照表中存在而目标表中不存在键补充至目标表中 ---- @param _table table 目标表 ---- @param _contrast table 对照表 -function ValueChangeUtil.VerifyTable(_table, _contrast) - for k, v in pairs(_contrast) do - -- 如果值为table则向下递归 - if type(v) == "table" then - if not _table[k] then - _table[k] = table.shallowcopy(v) - else - ValueChangeUtil.VerifyTable(_table[k], v) - end - else - -- 若值不是table,则直接校对 - if not _table[k] then _table[k] = v end - end - end -end - -return ValueChangeUtil diff --git a/code/['World']['Global']['Utility']['XlsUtilModule'].ModuleScript.lua b/code/['World']['Global']['Utility']['XlsUtilModule'].ModuleScript.lua deleted file mode 100644 index 2fb193e..0000000 --- a/code/['World']['Global']['Utility']['XlsUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,162 +0,0 @@ ---- 读表工具: 将导入成Lua Table,支持单一主键和多主键 --- @module XLS Utility --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang --- @see https://wiki.lilithgames.com/x/RGEMAg -local XlsUtil = {} - ---! 打印事件日志, true:开启打印 -local showLog, PrintGlobalKV, PrintLog = true - ---- 将表中的字符串改为数字 --- @param _t input table -local function StrToNum(_t) - for k, v in pairs(_t) do - _t[k] = tonumber(v) - end - return _t -end - ---- 类型解析配置表 -local parser = { - int = function(_raw) - return math.floor(tonumber(_raw)) - end, - float = function(_raw) - return tonumber(_raw) - end, - string = function(_raw) - return _raw - end, - boolean = function(_raw) - return string.lower(_raw) == 'true' - end, - vector2 = function(_raw) - return Vector2(table.unpack(StrToNum(string.split(_raw, ',')))) - end, - vector3 = function(_raw) - return Vector3(table.unpack(StrToNum(string.split(_raw, ',')))) - end, - euler = function(_raw) - return EulerDegree(table.unpack(StrToNum(string.split(_raw, ',')))) - end, - color = function(_raw) - return Color(table.unpack(StrToNum(string.split(_raw, ',')))) - end -} - ---- 读取配置表,会根据id生成lua表 --- @param _type String 数据类型 --- @parm _stringValue String 数据 --- @return value 解析出来的数值 -local function GetValue(_type, _stringValue) - _type = string.lower(_type) - assert(parser[_type], string.format('[XlsUtil][GlobalSetting] "%s" Type字段的值不是目前所支持的数据类型', _type)) - return parser[_type](_stringValue) -end - ---- 根据id转换lua table -function XlsUtil.GetXlsInfo(_xls, ...) - local ids = {...} - if #ids < 1 or (#ids == 1 and ids[1] == 'Type') then - -- 默认用Type索引,直接返回 - return _xls - end - local rawTable = _xls - local result = {} - local tmp, key, id, idstr -- 临时变量 - for _, v in pairs(rawTable) do - tmp = result - idstr = {} - for i = 1, #ids do - id = ids[i] - key = v[id] - idstr[i] = tostring(id) .. ',' - assert( - not string.isnilorempty(key), - string.format('[XlsUtil] Excel表格没有找到此id, Excel:%s, id: %s', _xls.Name, id) - ) - if i == #ids then - -- 最后的键,确定唯一性 - assert( - not tmp[key], - string.format('[XlsUtil] Excel数据重复, ids不是唯一的, Excel: %s, ids: %s', _xls.Name, table.concat(idstr)) - ) - tmp[key] = v - else - -- 多键,之后还有 - if tmp[key] == nil then - tmp[key] = {} - end - tmp = tmp[key] - end - end - end - return result -end - ---- 读取Config全局配置表 -function XlsUtil.GetGlobalXlsInfo(_xls) - local rawTable = _xls - if table.nums(rawTable) == 0 then - return - end - assert(rawTable[1].Key, '[XlsUtil] 全局配置表的没有"Key"') - assert(rawTable[1].Type, '[XlsUtil] 全局配置表的没有"Type"') - assert(rawTable[1].Value, '[XlsUtil] 全局配置表的没有"Value"') - local result = {} - for _, v in pairs(rawTable) do - result[v.Key] = GetValue(v['Type'], v['Value']) - PrintGlobalKV(v.Key, v.Type, result[v.Key]) -- * 输出KV键值对 - end - return result -end - ---- 表格预加载,预加载配置模块:World.Global.Define.ConfigModule -function XlsUtil.PreloadXls(_preloadList, _xlsRoot, _config) - -- todo: load xls lua talbe - assert(_preloadList and #_preloadList > 0, 'ConfigModule中没有预加载表格') - - for _, pl in pairs(_preloadList) do - if not string.isnilorempty(pl.xls) then - pl.name = string.isnilorempty(pl.name) and pl.xls or pl.name - pl.module = string.isnilorempty(pl.module) and pl.xls .. 'Xls' or pl.module - PrintLog(string.format('[XlsUtil] Load: %s', pl.module)) - if pl.xls == 'GlobalSetting' and _xlsRoot[pl.module .. 'Module'] then - _config[pl.name] = XlsUtil.GetGlobalXlsInfo(_G[pl.module]) - elseif not string.isnilorempty(pl.xls) and _G[pl.module] then - pl.ids = pl.ids or {} - _config[pl.name] = XlsUtil.GetXlsInfo(_G[pl.module], table.unpack(pl.ids)) - end - end - end -end - ---! 辅助功能 - ---- 输出全局变量键值对 -PrintGlobalKV = - showLog and - function(_key, _type, _value) - _type = string.lower(_type) - local showTypes = { - vector2 = 'Vector2', - vector3 = 'Vector3', - euler = 'EulerDegree', - color = 'Color' - } - if showTypes[_type] then - print(string.format('[XlsUtil][GlobalSetting] %s = %s%s ', _key, showTypes[_type], _value)) - else - print(string.format('[XlsUtil][GlobalSetting] %s = %s ', _key, _value)) - end - end or - function() - end - -PrintLog = showLog and function(...) - print(...) - end or function() - end - -return XlsUtil diff --git a/code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua b/code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua deleted file mode 100644 index 0fe52fb..0000000 --- a/code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua +++ /dev/null @@ -1,110 +0,0 @@ ---- This file is generated by ava-x2l.exe, ---- Don't change it manaully. ---- @copyright Lilith Games, Project Da Vinci(Avatar Team) ---- @see https://www.projectdavinci.com/ ---- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/ExampleTable1.xlsx - -local Example1Xls = { - [1] = { - house = { - id = 1, - name = 'house', - use_money = 1000, - use_food = 2.33, - is_init = true, - defense = 100, - args_int_arr = {1, 2, 3}, - args_float_arr = {1.23, 2, 3.23}, - args_string_arr = {'sdf', '23e', 's'}, - args_bool_arr = {true, false, true}, - args_vect2 = Vector2(-1, 0.5), - args_vect3 = Vector3(2, 0.3, -4), - args_euler = EulerDegree(12, 23, 43), - args_color = Color(129, 12, 3, 0), - args_lua = function() print(23) end, - Des1 = 'Example1_Des1_1_house', - Des2 = 'Example1_Des2_1_house' - }, - MMM = { - id = 1, - name = 'MMM', - use_money = 123, - use_food = 336.2, - is_init = true, - defense = 0, - args_int_arr = {1, 2, 3}, - args_float_arr = {1, 2.3445, 3}, - args_string_arr = {'你好', '你在哪'}, - args_bool_arr = {true, false}, - args_vect2 = Vector2(0, 4), - args_vect3 = Vector3(-2, 3, 5), - args_euler = EulerDegree(0, 0, 0), - args_color = Color(0, 0, 0, 0), - args_lua = {a = 2, b='234'}, - Des1 = 'Example1_Des1_1_MMM', - Des2 = 'Example1_Des2_1_MMM' - }, - ddd = { - id = 1, - name = 'ddd', - use_money = 456, - use_food = 222.33665, - is_init = false, - defense = 130, - args_int_arr = {3, 2, 5}, - args_float_arr = {3, 2, 2.5}, - args_string_arr = {'我在这里啊', '你在那', '呢'}, - args_bool_arr = {false, true}, - args_vect2 = Vector2(2, 0.5), - args_vect3 = Vector3(0.6, 3, -8.4), - args_euler = EulerDegree(0, 0, 0), - args_color = Color(0, 0, 0, 0), - args_lua = nil, - Des1 = 'Example1_Des1_1_ddd', - Des2 = 'Example1_Des2_1_ddd' - } - }, - [2] = { - farm = { - id = 2, - name = 'farm', - use_money = 100, - use_food = 220.0, - is_init = false, - defense = 200, - args_int_arr = {2, 3}, - args_float_arr = {200.3, 3, 234.23}, - args_string_arr = {'df', 'ssd', 'dd', 'dd'}, - args_bool_arr = {}, - args_vect2 = Vector2.Zero, - args_vect3 = Vector3.Zero, - args_euler = EulerDegree(0, 0, 0), - args_color = Color(0, 0, 0, 0), - args_lua = nil, - Des1 = 'Example1_Des1_2_farm', - Des2 = 'Example1_Des2_2_farm' - }, - MMM = { - id = 2, - name = 'MMM', - use_money = 0, - use_food = 22.1, - is_init = false, - defense = 234, - args_int_arr = {3, 6, 6, 7}, - args_float_arr = {3, 6.3, 6, 7}, - args_string_arr = {'ss', 'd', 'd', 'd'}, - args_bool_arr = {true, true}, - args_vect2 = Vector2.Zero, - args_vect3 = Vector3.Zero, - args_euler = EulerDegree(0, 0, 0), - args_color = Color(0, 0, 0, 0), - args_lua = "还没有添加检查", - Des1 = 'Example1_Des1_2_MMM', - Des2 = 'Example1_Des2_2_MMM' - } - } -} - -return Example1Xls diff --git a/code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua b/code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua deleted file mode 100644 index 7ac1d42..0000000 --- a/code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua +++ /dev/null @@ -1,83 +0,0 @@ ---- This file is generated by ava-x2l.exe, ---- Don't change it manaully. ---- @copyright Lilith Games, Project Da Vinci(Avatar Team) ---- @see https://www.projectdavinci.com/ ---- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/ExampleTable1.xlsx - -local Example2Xls = { - [1] = { - id = 1, - name = 'house', - use_money = 1000, - use_food = 2.33, - is_init = true, - defense = 100, - args1 = {1, 2, 3}, - args2 = {1.23, 2, 3.23}, - args3 = {'sdf', '23e', 's'}, - args4 = {true, false, true} - }, - [2] = { - id = 2, - name = '你好吗?', - use_money = 123, - use_food = 336.2, - is_init = true, - defense = 0, - args1 = {1, 2, 3}, - args2 = {1, 2.3445, 3}, - args3 = {'你好', '你在哪'}, - args4 = {true, false} - }, - [3] = { - id = 3, - name = '', - use_money = 456, - use_food = 222.33665, - is_init = false, - defense = 130, - args1 = {3, 2, 5}, - args2 = {3, 2, 2.5}, - args3 = {'我在这里啊', '你在那', '呢'}, - args4 = {false, true} - }, - [4] = { - id = 4, - name = 'farm', - use_money = 100, - use_food = 220.0, - is_init = false, - defense = 200, - args1 = {2, 3}, - args2 = {200.3, 3, 234.23}, - args3 = {'df', 'ssd', 'dd', 'dd'}, - args4 = {} - }, - [5] = { - id = 5, - name = 'house5', - use_money = 0, - use_food = 22.1, - is_init = false, - defense = 234, - args1 = {3, 6, 6, 7}, - args2 = {3, 6.3, 6, 7}, - args3 = {'ss', 'd', 'd', 'd'}, - args4 = {true, true} - }, - [6] = { - id = 6, - name = 'horse3', - use_money = 200, - use_food = 0, - is_init = false, - defense = 333, - args1 = {}, - args2 = {}, - args3 = {'2e', 'w', 'e', 'we'}, - args4 = {false, false, false, false} - } -} - -return Example2Xls diff --git a/code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua b/code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua deleted file mode 100644 index 5cb4d8d..0000000 --- a/code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua +++ /dev/null @@ -1,31 +0,0 @@ ---- This file is generated by ava-x2l.exe, ---- Don't change it manaully. ---- @copyright Lilith Games, Project Da Vinci(Avatar Team) ---- @see https://www.projectdavinci.com/ ---- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/GlobalSetting.xls - -local GlobalSettingXls = { - DefaultLanguage = { - Key = 'DefaultLanguage', - Value = "CHS" - }, - PlayerPosition = { - Key = 'PlayerPosition', - Value = Vector3(0,-1,0) - }, - PlayerRotation = { - Key = 'PlayerRotation', - Value = Euler(90,0,0) - }, - MaxPlayerNumber = { - Key = 'MaxPlayerNumber', - Value = 100.0 - }, - ScoreRate = { - Key = 'ScoreRate', - Value = 12.5 - } -} - -return GlobalSettingXls diff --git a/code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua b/code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua deleted file mode 100644 index 4bd1d8d..0000000 --- a/code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua +++ /dev/null @@ -1,81 +0,0 @@ ---- This file is generated by ava-x2l.exe, ---- Don't change it manaully. ---- @copyright Lilith Games, Project Da Vinci(Avatar Team) ---- @see https://www.projectdavinci.com/ ---- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/LanguagePack.xls - -local LanguagePackXls = { - Example1_Des1_1_house = { - ID = 'Example1_Des1_1_house', - CHS = '我真的很想%s吃饭', - CHT = '', - EN = '', - JP = '' - }, - Example1_Des2_1_house = { - ID = 'Example1_Des2_1_house', - CHS = '做什么', - CHT = '', - EN = '', - JP = '' - }, - Example1_Des1_1_MMM = { - ID = 'Example1_Des1_1_MMM', - CHS = '我饿了', - CHT = '', - EN = '', - JP = '' - }, - Example1_Des2_1_MMM = { - ID = 'Example1_Des2_1_MMM', - CHS = '工作是什么', - CHT = '', - EN = '', - JP = '' - }, - Example1_Des1_1_ddd = { - ID = 'Example1_Des1_1_ddd', - CHS = '到底什么时候能吃饭', - CHT = '', - EN = '', - JP = '' - }, - Example1_Des2_1_ddd = { - ID = 'Example1_Des2_1_ddd', - CHS = '我是谁', - CHT = '', - EN = '', - JP = '' - }, - Example1_Des1_2_farm = { - ID = 'Example1_Des1_2_farm', - CHS = '今天晚上吃什么', - CHT = '', - EN = '', - JP = '' - }, - Example1_Des2_2_farm = { - ID = 'Example1_Des2_2_farm', - CHS = '我从哪里来', - CHT = '', - EN = '', - JP = '' - }, - Example1_Des1_2_MMM = { - ID = 'Example1_Des1_2_MMM', - CHS = '下班就去吃饭吧', - CHT = '', - EN = '', - JP = '' - }, - Example1_Des2_2_MMM = { - ID = 'Example1_Des2_2_MMM', - CHS = '就这样吧', - CHT = '', - EN = '', - JP = '' - } -} - -return LanguagePackXls diff --git a/code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua b/code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua deleted file mode 100644 index 8718a45..0000000 --- a/code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua +++ /dev/null @@ -1,21 +0,0 @@ ---- This file is generated by ava-x2l.exe, ---- Don't change it manaully. ---- @copyright Lilith Games, Project Da Vinci(Avatar Team) ---- @see https://www.projectdavinci.com/ ---- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/Sound.xls - -local SoundXls = { - test_01 = { - Type = 1, - ID = 'test_01', - IsLoop = false, - Volume = 0, - FileName = '', - Detail = '', - Duration = 0, - CoverPlay = false - } -} - -return SoundXls diff --git a/code/['World']['S_Code']['ServerMainScript'].Script.lua b/code/['World']['S_Code']['ServerMainScript'].Script.lua deleted file mode 100644 index 5a5bcff..0000000 --- a/code/['World']['S_Code']['ServerMainScript'].Script.lua +++ /dev/null @@ -1,5 +0,0 @@ ---- 服务器代码入口 --- @script Server Main Function --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang -Server:Run() diff --git a/xls/ExampleTable1.xls b/xls/ExampleTable1.xls deleted file mode 100644 index 8c6a4d7..0000000 --- a/xls/ExampleTable1.xls +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fae81df311873a30204372e4ec7be21c89c78e283ecf26b7d7d1bed3e3148662 -size 38912 diff --git a/xls/ExampleTable1.xlsx b/xls/ExampleTable1.xlsx deleted file mode 100644 index da90a5e..0000000 --- a/xls/ExampleTable1.xlsx +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a2b1df1b741ae1e77fd025994f4081103fabc3b7d26e99221fb83ca2f7730e55 -size 14896 diff --git a/xls/GlobalSetting.xls b/xls/GlobalSetting.xls deleted file mode 100644 index f33224c..0000000 --- a/xls/GlobalSetting.xls +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e215602bf7c91ed4d5e26ce068f3352f39887550eaa1b1218fdb92b01bafbade -size 24064 diff --git a/xls/LanguagePack.xls b/xls/LanguagePack.xls deleted file mode 100644 index 2c020e3..0000000 --- a/xls/LanguagePack.xls +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f6463250613591736ae1da46ac0ecac332617da498bcb7a7e4417df7f57080a4 -size 5632 diff --git a/xls/Sound.xls b/xls/Sound.xls deleted file mode 100644 index d247fda..0000000 --- a/xls/Sound.xls +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8a37659cba95b2aa8c4f1c62907a7cbc6075ebf165e2b1323823092770fb1414 -size 27136 From f38a2a70cc1cad8aca2b9c1a3d0ce47516229033 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 18:35:25 +0800 Subject: [PATCH 18/39] upload all folders --- ...ickGuide']['GuideEffectScript'].Script.lua | 20 + ...]['C_Code']['ClientMainScript'].Script.lua | 4 + ...lobal']['AutoAssignTeamScript'].Script.lua | 31 + ...'Define']['ConfigModule'].ModuleScript.lua | 18 + ...['Define']['ConstModule'].ModuleScript.lua | 17 + ...'Define']['EventsModule'].ModuleScript.lua | 14 + ...ine']['GlobalDataModule'].ModuleScript.lua | 9 + ...ork']['ClientBaseModule'].ModuleScript.lua | 18 + ...['ClientHeartbeatModule'].ModuleScript.lua | 169 +++ ...amework']['ClientModule'].ModuleScript.lua | 151 +++ ...['FrameworkConfigModule'].ModuleScript.lua | 42 + ...ork']['ServerBaseModule'].ModuleScript.lua | 18 + ...['ServerHeartbeatModule'].ModuleScript.lua | 180 +++ ...amework']['ServerModule'].ModuleScript.lua | 154 +++ ...['Global']['LuaFunctionScript'].Script.lua | 968 +++++++++++++++ ...e']['LanguageUtilModule'].ModuleScript.lua | 32 + ...']['PlayerControlModule'].ModuleScript.lua | 182 +++ ...'PlayerGuiDefaultModule'].ModuleScript.lua | 92 ++ ...['SceneMeshEditorModule'].ModuleScript.lua | 29 + ...Global']['ModuleRequireScript'].Script.lua | 40 + ...de']['GuideSystemModule'].ModuleScript.lua | 47 + ...tility']['CamUtilModule'].ModuleScript.lua | 41 + ...y']['CloudLogUtilModule'].ModuleScript.lua | 24 + ...tility']['CsvUtilModule'].ModuleScript.lua | 244 ++++ ...lity']['EventUtilModule'].ModuleScript.lua | 53 + ...ity']['GlobalFuncModule'].ModuleScript.lua | 26 + ...ity']['LinkedListModule'].ModuleScript.lua | 444 +++++++ ...tility']['LogUtilModule'].ModuleScript.lua | 45 + ...ty']['LuaJsonUtilModule'].ModuleScript.lua | 1042 +++++++++++++++++ ...ity']['ModuleUtilModule'].ModuleScript.lua | 68 ++ ...tility']['NetUtilModule'].ModuleScript.lua | 123 ++ ...ty']['ObjPoolUtilModule'].ModuleScript.lua | 65 + ...lity']['SoundUtilModule'].ModuleScript.lua | 65 + ...ility']['TimeUtilModule'].ModuleScript.lua | 149 +++ ...['TweenControllerModule'].ModuleScript.lua | 38 + ...['Utility']['UuidModule'].ModuleScript.lua | 229 ++++ ...['ValueChangeUtilModule'].ModuleScript.lua | 137 +++ ...tility']['XlsUtilModule'].ModuleScript.lua | 162 +++ ...ls']['Example1XlsModule'].ModuleScript.lua | 110 ++ ...ls']['Example2XlsModule'].ModuleScript.lua | 83 ++ ...'GlobalSettingXlsModule'].ModuleScript.lua | 31 + ...['LanguagePackXlsModule'].ModuleScript.lua | 81 ++ ...['Xls']['SoundXlsModule'].ModuleScript.lua | 21 + ...]['S_Code']['ServerMainScript'].Script.lua | 5 + Smap/avatar-ava.smap | Bin 0 -> 67356 bytes Xls/ExampleTable1.xls | 3 + Xls/ExampleTable1.xlsx | 3 + Xls/GlobalSetting.xls | 3 + Xls/LanguagePack.xls | 3 + Xls/Sound.xls | 3 + 50 files changed, 5536 insertions(+) create mode 100644 Code/['Archetypes']['GuideArchetype']['ClickGuide']['GuideEffectScript'].Script.lua create mode 100644 Code/['Archetypes']['Player']['Local']['C_Code']['ClientMainScript'].Script.lua create mode 100644 Code/['World']['Global']['AutoAssignTeamScript'].Script.lua create mode 100644 Code/['World']['Global']['Define']['ConfigModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Define']['EventsModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['LuaFunctionScript'].Script.lua create mode 100644 Code/['World']['Global']['Module']['C_Module']['LanguageUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Module']['C_Module']['PlayerControlModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['ModuleRequireScript'].Script.lua create mode 100644 Code/['World']['Global']['Plugin']['FUNC_Guide']['GuideSystemModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['CamUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['CsvUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['EventUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['LinkedListModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['LuaJsonUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['TweenControllerModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['UuidModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['ValueChangeUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Utility']['XlsUtilModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua create mode 100644 Code/['World']['S_Code']['ServerMainScript'].Script.lua create mode 100644 Smap/avatar-ava.smap create mode 100644 Xls/ExampleTable1.xls create mode 100644 Xls/ExampleTable1.xlsx create mode 100644 Xls/GlobalSetting.xls create mode 100644 Xls/LanguagePack.xls create mode 100644 Xls/Sound.xls diff --git a/Code/['Archetypes']['GuideArchetype']['ClickGuide']['GuideEffectScript'].Script.lua b/Code/['Archetypes']['GuideArchetype']['ClickGuide']['GuideEffectScript'].Script.lua new file mode 100644 index 0000000..5f81e92 --- /dev/null +++ b/Code/['Archetypes']['GuideArchetype']['ClickGuide']['GuideEffectScript'].Script.lua @@ -0,0 +1,20 @@ +---引导系统-客户端表现 +---@script Guide effect +---@copyright Lilith Games, Avatar Team +---@author Sid Zhang + +local root = script.Parent +local tweenerHand = Tween:TweenProperty(root.ImgDot.ImgHand, {Pivot = Vector2(0.35, 1)}, 0.5, Enum.EaseCurve.Linear) +local tweenerCircle = + Tween:TweenProperty(root.ImgDot.ImgCircle, {Size = Vector2(276, 276), Alpha = 0}, 0.5, Enum.EaseCurve.Linear) + +::Repeat:: +--重置UI位置与状态 +root.ImgDot.ImgHand.Pivot = Vector2(0.35, 1.5) +root.ImgDot.ImgCircle.Size = Vector2(48, 48) +root.ImgDot.ImgCircle.Alpha = 1 +tweenerHand:Play() +tweenerHand:WaitForComplete() +tweenerCircle:Play() +tweenerCircle:WaitForComplete() +goto Repeat diff --git a/Code/['Archetypes']['Player']['Local']['C_Code']['ClientMainScript'].Script.lua b/Code/['Archetypes']['Player']['Local']['C_Code']['ClientMainScript'].Script.lua new file mode 100644 index 0000000..2bfd865 --- /dev/null +++ b/Code/['Archetypes']['Player']['Local']['C_Code']['ClientMainScript'].Script.lua @@ -0,0 +1,4 @@ +--- 客户端代码入口 +-- @script Client Main Function +-- @copyright Lilith Games, Avatar Team +Client:Run() diff --git a/Code/['World']['Global']['AutoAssignTeamScript'].Script.lua b/Code/['World']['Global']['AutoAssignTeamScript'].Script.lua new file mode 100644 index 0000000..49b8ef4 --- /dev/null +++ b/Code/['World']['Global']['AutoAssignTeamScript'].Script.lua @@ -0,0 +1,31 @@ +--- 玩家加入 +-- @script Auto assign +-- @copyright Lilith Games, Avatar Team + +--- 编辑器默认方法 +-- run once when script init +function autoAssign() + local container = world:FindTeams() + local min = 1 + local teamTojoin = {} + local playerfolder = world.Players + for i = 1, #container, 1 do + if container[i].CurrentMaxMemberNum > 0 then + temp = container[i].CurrentMemberNum / (container[i].CurrentMaxMemberNum) + if (temp < min and temp ~= 1) then + teamTojoin = {} + min = temp + table.insert(teamTojoin, container[i]) + elseif temp == min and temp ~= 1 then + table.insert(teamTojoin, container[i]) + end + end + end + local a = 1 + if #teamTojoin > 0 then + a = math.random(1, #teamTojoin) + return teamTojoin[a] + else + return nil + end +end diff --git a/Code/['World']['Global']['Define']['ConfigModule'].ModuleScript.lua b/Code/['World']['Global']['Define']['ConfigModule'].ModuleScript.lua new file mode 100644 index 0000000..e9ad873 --- /dev/null +++ b/Code/['World']['Global']['Define']['ConfigModule'].ModuleScript.lua @@ -0,0 +1,18 @@ +--- CSV表格的定义,用于CSV表格载入 +-- @module Csv Defines +-- @copyright Lilith Games, Avatar Team +local Config = {} + +-- 服务器预加载CSV +-- csv: 对应的CSV表名 +-- name: Config里面的lua table名称, 可自定义, 默认和csv相同 +-- ids: 表格主键, 支持多主键 +Config.ServerPreload = {} + +-- 客户端预加载CSV +-- csv: 对应的CSV表名 +-- name: Config里面的lua table名称, 可自定义, 默认和csv相同 +-- ids: 表格主键, 支持多主键 +Config.ClientPreload = {} + +return Config diff --git a/Code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua b/Code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua new file mode 100644 index 0000000..2071385 --- /dev/null +++ b/Code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua @@ -0,0 +1,17 @@ +--- 全局常量的定义,全部定义在Const这张表下面,用于定义全局常量参数或者枚举类型 +-- @module Constant Defines +-- @copyright Lilith Games, Avatar Team +local Const = {} + +-- e.g. (need DELETE) +Const.MAX_PLAYERS = 4 + +--语言枚举 +Const.LanguageEnum = { + CHS = 'CHS', -- 简体中文 + CHT = 'CHT', -- 繁体中文 + EN = 'EN', -- 英文 + JP = 'JP' -- 日文 +} + +return Const diff --git a/Code/['World']['Global']['Define']['EventsModule'].ModuleScript.lua b/Code/['World']['Global']['Define']['EventsModule'].ModuleScript.lua new file mode 100644 index 0000000..2b207d8 --- /dev/null +++ b/Code/['World']['Global']['Define']['EventsModule'].ModuleScript.lua @@ -0,0 +1,14 @@ +--- CustomEvent的定义,用于事件动态生成 +-- @module Event Defines +-- @copyright Lilith Games, Avatar Team +local Events = {} + +-- 服务器事件列表 +Events.ServerEvents = {} + +-- 客户端事件列表 +Events.ClientEvents = { + --通知事件 + 'NoticeEvent' +} +return Events diff --git a/Code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua b/Code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua new file mode 100644 index 0000000..2e15412 --- /dev/null +++ b/Code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua @@ -0,0 +1,9 @@ +--- 全局变量的定义,全部定义在GlobalData这张表下面,用于全局可修改的参数 +--- @module GlobalData Defines +--- @copyright Lilith Games, Avatar Team +local GlobalData = {} + +-- Test only +GlobalData.PlayerData = {} + +return GlobalData diff --git a/Code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua new file mode 100644 index 0000000..1deb376 --- /dev/null +++ b/Code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua @@ -0,0 +1,18 @@ +--- 客户端模块基础类, Client Module Base Class +-- @module ClientBase, Client-side +-- @copyright Lilith Games, Avatar Team +-- @author Yuancheng Zhang +local ClientBase = class('ClientBase') + +function ClientBase:GetSelf() + return self +end + +--- 加载的时候运行的代码 +function ClientBase:InitDefault(_module) + -- print(string.format('[ClientBase][%s] InitDefault()', self.name)) + -- 初始化默认监听事件 + EventUtil.LinkConnects(localPlayer.C_Event, _module, self) +end + +return ClientBase diff --git a/Code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua new file mode 100644 index 0000000..07f4be4 --- /dev/null +++ b/Code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua @@ -0,0 +1,169 @@ +--- 游戏心跳 +--- @module Client Heartbeat, Client-side +--- @copyright Lilith Games, Avatar Team +--- @author Yuancheng Zhang +local ClientHeartbeat = {} + +-- Localize global vars +local Setting = FrameworkConfig.Client + +-- 心跳包间隔时间,单位:秒 +local HEARTBEAT_DELTA = Setting.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 HeartbeatEnum = { + CONNECT = 1, -- 在线 + DISCONNECT = 2 -- 离线 +} + +-- 正在运行 +local running = false + +-- 上一次服务器发来的心跳时间戳缓存 +local cache = { + sTimestamp = nil, + cTimestamp = nil +} + +-- 临时变量 +local diff -- 时间戳插值 +local sTmpTs, cTmpTs -- 时间戳缓存 + +--- 打印心跳日志 +local PrintHb = Setting.ShowHeartbeatLog and function(...) + print('[Heartbeat][Client]', ...) + end or function() + end + +--! 外部接口 + +--- 初始化心跳包 +function ClientHeartbeat.Init() + print('[Heartbeat][Client] Init()') + CheckSetting() + InitEventsAndListeners() +end + +--- 开始发出心跳 +function ClientHeartbeat.Start() + print('[Heartbeat][Client] Start()') + local cTimestamp + running = true + while (running) do + Update() + wait(HEARTBEAT_DELTA) + end +end + +-- 停止心跳 +function ClientHeartbeat.Stop() + print('[Heartbeat][Client] Stop()') + running = false +end + +--! 私有函数 + +-- 校验心跳参数 +function CheckSetting() + assert(HEARTBEAT_DELTA >= 1, '[Heartbeat][Client] HEARTBEAT_DELTA 必须大于1秒') + assert(HEARTBEAT_THRESHOLD_1 >= HEARTBEAT_DELTA, '[Heartbeat][Client] HEARTBEAT_THRESHOLD_1 >= HEARTBEAT_DELTA') + assert( + HEARTBEAT_THRESHOLD_2 >= HEARTBEAT_THRESHOLD_1, + '[Heartbeat][Client] HEARTBEAT_THRESHOLD_2 >= HEARTBEAT_THRESHOLD_1' + ) +end + +--- 初始化事件和绑定Handler +function InitEventsAndListeners() + if localPlayer.C_Event == nil then + world:CreateObject('FolderObject', 'C_Event', localPlayer) + end + world:CreateObject('CustomEvent', 'HeartbeatS2CEvent', localPlayer.C_Event) + localPlayer.C_Event.HeartbeatS2CEvent:Connect(HeartbeatS2CEventHandler) + + -- OnPlayerJoinEvent(玩家第一次加入,类似现在的OnPlayerAdded) + -- OnPlayerRejoinEvent(玩家离线后重新进入同一个房间) + -- OnPlayerDisconnectEvent(未接收到服务器心跳,在客户端第二个阶段,玩家离线可重连,弱网,转菊花) + -- OnPlayerReconnectEvent(玩家断线后重连) + -- OnPlayerLeaveEvent(玩家彻底离开,退出房间) + world:CreateObject('CustomEvent', 'OnPlayerJoinEvent', localPlayer.C_Event) + -- world:CreateObject('CustomEvent', 'OnPlayerRejoinEvent', localPlayer.C_Event) + world:CreateObject('CustomEvent', 'OnPlayerDisconnectEvent', localPlayer.C_Event) + world:CreateObject('CustomEvent', 'OnPlayerReconnectEvent', localPlayer.C_Event) + world:CreateObject('CustomEvent', 'OnPlayerLeaveEvent', localPlayer.C_Event) + + -- 掉线直接退出(默认,可选) + localPlayer.C_Event.OnPlayerLeaveEvent:Connect(QuitGame) +end + +-- Update心跳 +function Update() + cTmpTs = Timer.GetTimeMillisecond() + sTmpTs = cache.sTimestamp + PrintHb(string.format('=> C = %s, S = %s, %s', cTmpTs, sTmpTs, localPlayer)) + CheckPlayerState(p, cTmpTs) + NetUtil.Fire_S('HeartbeatC2SEvent', localPlayer, cTmpTs, sTmpTs) +end + +--- 心跳事件Handler +function HeartbeatS2CEventHandler(_stimestamp, _cTimestamp) + if not running then + return + end + PrintHb(string.format('<= C = %s, S = %s, %s', _cTimestamp, _stimestamp, localPlayer)) + CheckPlayerJoin(_player, _sTimestamp) + cache.sTimestamp = _stimestamp + cache.cTimestamp = _cTimestamp +end + +--- 收包时,检查玩家是否连接服务器,或者重新连接服务器 +function CheckPlayerJoin(_player, _sTimestamp) + if not cache.sTimestamp then + --* 玩家新加入 OnPlayerJoinEvent + print('[Heartbeat][Client] OnPlayerJoinEvent, 新玩家加入,', localPlayer) + NetUtil.Fire_C('OnPlayerJoinEvent', localPlayer) + cache.state = HeartbeatEnum.CONNECT + elseif cache.state == HeartbeatEnum.DISCONNECT then + --* 玩家断线重连 OnPlayerReconnectEvent + print('[Heartbeat][Client] OnPlayerReconnectEvent, 玩家断线重连,', localPlayer) + NetUtil.Fire_C('OnPlayerReconnectEvent', localPlayer) + cache.state = HeartbeatEnum.CONNECT + end +end + +--- 发包时,检查玩家是否连接服务器 +function CheckPlayerState(_player, _cTimestamp) + if not cache.cTimestamp then + return + end + diff = _cTimestamp - cache.cTimestamp + PrintHb(string.format('==========================================> diff = %s, %s', diff * .001, localPlayer)) + if diff < HEARTBEAT_THRESHOLD_1 then + --* 玩家在线 + cache.state = HeartbeatEnum.CONNECT + elseif cache.state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then + --* 玩家断线,弱网环境 + 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 + --* 玩家断线, 退出游戏 + -- QuitGame() + NetUtil.Fire_C('OnPlayerLeaveEvent', localPlayer) + end +end + +--- 退出游戏 +function QuitGame() + print('[Heartbeat][Client] Game.Quit(), 玩家退出游戏') + Game.Quit() +end + +return ClientHeartbeat diff --git a/Code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua new file mode 100644 index 0000000..fc59abd --- /dev/null +++ b/Code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua @@ -0,0 +1,151 @@ +--- 游戏客户端主逻辑 +-- @module Game Manager, Client-side +-- @copyright Lilith Games, Avatar Team +-- @author Yuancheng Zhang +local Client = {} + +-- Localize global vars +local CsvUtil, XslUitl, ModuleUtil = CsvUtil, XslUitl, ModuleUtil +local Config = FrameworkConfig.Client + +-- 已经初始化,正在运行 +local initialized, running = false, false + +-- 含有InitDefault(),Init(),Update()的模块列表 +local initDefaultList, initList, updateList = {}, {}, {} + +--- 运行客户端 +function Client:Run() + print('[Client] Run()') + InitClient() + StartUpdate() +end + +--- 停止Update +function Client:Stop() + print('[Client] Stop()') + running = false + ClientHeartbeat.Stop() +end + +--- 初始化 +function InitClient() + if initialized then + return + end + print('[Client] InitClient()') + InitRandomSeed() + InitHeartbeat() + InitClientCustomEvents() + PreloadCsv() + GenInitAndUpdateList() + RunInitDefault() + InitOtherModules() + initialized = true +end + +--- 初始化心跳包 +function InitHeartbeat() + assert(ClientHeartbeat, '[Client][Heartbeat] 找不到ClientHeartbeat,请联系张远程') + ClientHeartbeat.Init() +end + +--- 初始化客户端的CustomEvent +function InitClientCustomEvents() + if localPlayer.C_Event == nil then + world:CreateObject('FolderObject', 'C_Event', localPlayer) + end + + -- 将插件中的CustomEvent放入Events.ClientEvents中 + for _, m in pairs(Config.PluginEvents) do + local evts = _G[m].ClientEvents + assert(evts, string.format('[Client] %s 中不存在ClientEvents,请检查模块,或从FrameworkConfig删除此配置', m)) + for __, evt in pairs(evts) do + if not table.exists(Events.ClientEvents, evt) then + table.insert(Events.ClientEvents, evt) + end + end + end + + -- 生成CustomEvent节点 + for _, evt in pairs(Events.ClientEvents) do + if localPlayer.C_Event[evt] == nil then + world:CreateObject('CustomEvent', evt, localPlayer.C_Event) + end + end +end + +--- 生成需要Init和Update的模块列表 +function GenInitAndUpdateList() + ModuleUtil.GetModuleListWithFunc(Module.C_Module, 'InitDefault', initDefaultList) + ModuleUtil.GetModuleListWithFunc(Module.C_Module, 'Init', initList) + ModuleUtil.GetModuleListWithFunc(Module.C_Module, 'Update', updateList) + for _, m in pairs(Config.PluginModules) do + ModuleUtil.GetModuleListWithFunc(m, 'InitDefault', initDefaultList) + ModuleUtil.GetModuleListWithFunc(m, 'Init', initList) + ModuleUtil.GetModuleListWithFunc(m, 'Update', updateList) + end +end + +--- 执行默认的Init方法 +function RunInitDefault() + for _, m in ipairs(initDefaultList) do + m:InitDefault(m) + end +end + +--- 初始化客户端随机种子 +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 + m:Init() + end +end + +--- 开始Update +function StartUpdate() + print('[Client] StartUpdate()') + assert(not running, '[Client] StartUpdate() 正在运行') + + running = true + + -- 开启心跳 + if FrameworkConfig.HeartbeatStart then + invoke(ClientHeartbeat.Start) + end + + local dt = 0 -- delta time 每帧时间 + local tt = 0 -- total time 游戏总时间 + local now = Timer.GetTimeMillisecond --时间函数缓存 + local prev, curr = now() / 1000, nil -- two timestamps + + while (running and wait()) do + curr = now() / 1000 + dt = curr - prev + tt = tt + dt + prev = curr + UpdateClient(dt, tt) + end +end + +--- Update函数 +-- @param dt delta time 每帧时间 +function UpdateClient(_dt, _tt) + for _, m in ipairs(updateList) do + m:Update(_dt, _tt) + end +end + +return Client diff --git a/Code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua new file mode 100644 index 0000000..f0a515c --- /dev/null +++ b/Code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua @@ -0,0 +1,42 @@ +--- 框架配置 +--- @module Framework Global FrameworkConfig +--- @copyright Lilith Games, Avatar Team +--- @author Yuancheng Zhang +local FrameworkConfig = { + -- 启动心跳 + HeartbeatStart = true, + Server = { + -- 心跳包间隔时间,单位:秒 + HeartbeatDelta = 1, + -- 心跳阈值,单位:秒,范围定义如下: + -- 0s -> threshold_1 : connected + -- threshold_1 -> threshold_2 : disconnected, but player can reconnect + -- threshold_2 -> longer : disconnected, remove player + HeartbeatThreshold1 = 5, + HeartbeatThreshold2 = 10, + -- 显示心跳日志 + ShowHeartbeatLog = false, + -- 插件中需要使用声明周期的服务器模块目录 + PluginModules = {}, + -- 插件中服务器需要生成的CustomEvent, 模块中必须得有ServerEvents + PluginEvents = {} + }, + Client = { + -- 心跳包间隔时间,单位:秒 + HeartbeatDelta = 1, + -- 心跳阈值,单位:秒,范围定义如下: + -- 0s -> threshold_1 : connected + -- threshold_1 -> threshold_2 : disconnected, weak network, can reconnect + -- threshold_2 -> longer : disconnected, quit server + HeartbeatThreshold1 = 5, + HeartbeatThreshold2 = 10, + -- 显示心跳日志 + ShowHeartbeatLog = false, + -- 插件中需要使用声明周期的客户端模块目录 + PluginModules = {}, + -- 插件中客户端需要生成的CustomEvent,模块中必须得有ClientEvents + PluginEvents = {} + } +} + +return FrameworkConfig diff --git a/Code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua new file mode 100644 index 0000000..213f46e --- /dev/null +++ b/Code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua @@ -0,0 +1,18 @@ +--- 服务器模块基础类, Server Module Base Class +-- @module ServerBase, Server-side +-- @copyright Lilith Games, Avatar Team +-- @author Yuancheng Zhang +local ServerBase = class('ServerBase') + +function ServerBase:GetSelf() + return self +end + +--- 加载的时候运行的代码 +function ServerBase:InitDefault(_module) + -- print(string.format('[ServerBase][%s] InitDefault()', self.name)) + -- 初始化默认监听事件 + EventUtil.LinkConnects(world.S_Event, _module, self) +end + +return ServerBase diff --git a/Code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua new file mode 100644 index 0000000..d79c0bf --- /dev/null +++ b/Code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua @@ -0,0 +1,180 @@ +--- 游戏服务器心跳 +--- @module Server Heartbeat, Server-side +--- @copyright Lilith Games, Avatar Team +--- @author Yuancheng Zhang +local ServerHeartbeat = {} + +-- Localize global vars +local Setting = FrameworkConfig.Server + +-- 心跳包间隔时间,单位:秒 +local HEARTBEAT_DELTA = Setting.HeartbeatDelta + +-- 心跳阈值,单位:秒,范围定义如下: +-- 0s -> threshold_1 : connected +-- threshold_1 -> threshold_2 : disconnected, but player can rejoin +-- threshold_2 -> longer : disconnected, remove player +local HEARTBEAT_THRESHOLD_1 = Setting.HeartbeatThreshold1 * 1000 -- second => ms +local HEARTBEAT_THRESHOLD_2 = Setting.HeartbeatThreshold2 * 1000 -- second => ms + +-- 玩家心跳连接状态 +local HeartbeatEnum = { + CONNECT = 1, -- 在线 + DISCONNECT = 2 -- 离线 +} + +-- 正在运行 +local running = false + +-- 上一次客户端发来的心跳时间戳缓存 +local cache = {} + +-- 临时变量 +local diff -- 时间戳插值 +local sTmpTs, cTmpTs -- 时间戳缓存 + +--- 打印心跳日志 +local PrintHb = Setting.ShowHeartbeatLog and function(...) + print('[Heartbeat][Server]', ...) + end or function() + end + +--! 外部接口 + +--- 初始化心跳包 +function ServerHeartbeat.Init() + print('[Heartbeat][Server] Init()') + CheckSetting() + InitEventsAndListeners() +end + +--- 开始发出心跳 +function ServerHeartbeat.Start() + print('[Heartbeat][Server] Start()') + running = true + while (running) do + Update() + wait(HEARTBEAT_DELTA) + end +end + +--- 停止心跳 +function ServerHeartbeat.Stop() + print('[Heartbeat][Server] Stop()') + running = false +end + +--! 私有函数 + +--- 校验心跳参数 +function CheckSetting() + assert(HEARTBEAT_DELTA >= 1, '[Heartbeat][Server] HEARTBEAT_DELTA 必须大于1秒') + assert(HEARTBEAT_THRESHOLD_1 >= HEARTBEAT_DELTA, '[Heartbeat][Server] HEARTBEAT_THRESHOLD_1 >= HEARTBEAT_DELTA') + assert( + HEARTBEAT_THRESHOLD_2 >= HEARTBEAT_THRESHOLD_1, + '[Heartbeat][Server] HEARTBEAT_THRESHOLD_2 >= HEARTBEAT_THRESHOLD_1' + ) +end + +--- 初始化事件和绑定Handler +function InitEventsAndListeners() + if world.S_Event == nil then + world:CreateObject('FolderObject', 'S_Event', world) + end + world:CreateObject('CustomEvent', 'HeartbeatC2SEvent', world.S_Event) + world.S_Event.HeartbeatC2SEvent:Connect(HeartbeatC2SEventHandler) + + -- OnAwakeEvent(玩家加入前初始化) + -- OnPlayerJoinEvent(玩家第一次加入,类似现在的OnPlayerAdded) + -- OnPlayerRejoinEvent(玩家离开房间后重新进入同一个房间) + -- OnPlayerDisconnectEvent(未接收到玩家心跳等待重连,在服务器第二个阶段) + -- OnPlayerReconnectEvent(玩家断线后重连) + -- OnPlayerLeaveEvent(玩家彻底离开,退出房间) + world:CreateObject('CustomEvent', 'OnAwakeEvent', world.S_Event) + world:CreateObject('CustomEvent', 'OnPlayerJoinEvent', world.S_Event) + -- world:CreateObject('CustomEvent', 'OnPlayerRejoinEvent', world.S_Event) + world:CreateObject('CustomEvent', 'OnPlayerDisconnectEvent', world.S_Event) + world:CreateObject('CustomEvent', 'OnPlayerReconnectEvent', world.S_Event) + world:CreateObject('CustomEvent', 'OnPlayerLeaveEvent', world.S_Event) + + -- 玩家退出,发出OnPlayerLeaveEvent + world.OnPlayerRemoved:Connect( + function(_player) + if cache[_player] then + print('[Heartbeat][Server] OnPlayerLeaveEvent, 玩家主动离开游戏,', _player) + NetUtil.Fire_S('OnPlayerLeaveEvent', _player) + end + end + ) +end + +--- Update心跳 +function Update() + for p, v in pairs(cache) do + if p and not p:IsNull() then + sTmpTs = Timer.GetTimeMillisecond() + cTmpTs = v.cTimestamp + PrintHb(string.format('=> S = %s, C = %s, %s', sTmpTs, cTmpTs, p)) + CheckPlayerStates(p, sTmpTs) + NetUtil.Fire_C('HeartbeatS2CEvent', p, sTmpTs, cTmpTs) + else + --* remove nil key from cache + cache[p] = nil + end + end +end + +--- 心跳事件Handler +function HeartbeatC2SEventHandler(_player, _cTimestamp, _sTimestamp) + if not running then + return + end + PrintHb(string.format('<= S = %s, C = %s, %s', _sTimestamp, _cTimestamp, _player)) + CheckPlayerJoin(_player) + cache[_player].cTimestamp = _cTimestamp + cache[_player].sTimestamp = _sTimestamp +end + +--- 收包时,检查玩家是否加入或重连 +function CheckPlayerJoin(_player) + if not cache[_player] then + --* 玩家新加入 OnPlayerJoinEvent + print('[Heartbeat][Server] OnPlayerJoinEvent, 新玩家加入,', _player) + NetUtil.Fire_S('OnPlayerJoinEvent', _player) + cache[_player] = { + state = HeartbeatEnum.CONNECT + } + elseif cache[_player].state == HeartbeatEnum.DISCONNECT then + --* 玩家断线重连 OnPlayerReconnectEvent + print('[Heartbeat][Server] OnPlayerReconnectEvent, 玩家断线重连,', _player) + NetUtil.Fire_S('OnPlayerReconnectEvent', _player) + cache[_player].state = HeartbeatEnum.CONNECT + end +end + +--- 发包时,检查玩家是否掉线 +function CheckPlayerStates(_player, _sTimestam) + if not cache[_player].sTimestamp then + return + end + diff = _sTimestam - cache[_player].sTimestamp + PrintHb(string.format('==========================================> diff = %s, %s', diff * .001, _player)) + if diff < HEARTBEAT_THRESHOLD_1 then + --* 玩家在线 + cache[_player].state = HeartbeatEnum.CONNECT + elseif cache[_player].state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then + --* 玩家断线 OnPlayerDisconnectEvent + print('[Heartbeat][Server] OnPlayerDisconnectEvent, 玩家离线, 等待断线重连,', _player) + NetUtil.Fire_S('OnPlayerDisconnectEvent', _player) + cache[_player].state = HeartbeatEnum.DISCONNECT + elseif cache[_player].state == HeartbeatEnum.DISCONNECT and diff >= HEARTBEAT_THRESHOLD_2 then + --* 玩家彻底断线,剔除玩家 OnPlayerLeaveEvent + print('[Heartbeat][Server] OnPlayerLeaveEvent, 剔除离线玩家,', _player) + NetUtil.Fire_S('OnPlayerLeaveEvent', _player) + print('[Heartbeat][Server] OnPlayerLeave, 发送客户端离线事件,', _player) + NetUtil.Fire_C('OnPlayerLeaveEvent', _player) + cache[_player] = nil + end +end + +return ServerHeartbeat diff --git a/Code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua new file mode 100644 index 0000000..199de55 --- /dev/null +++ b/Code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua @@ -0,0 +1,154 @@ +--- 游戏服务器主逻辑 +--- @module Game Server, Server-side +--- @copyright Lilith Games, Avatar Team +--- @author Yuancheng Zhang +local Server = {} + +-- Localize global vars +local CsvUtil, ModuleUtil = CsvUtil, ModuleUtil +local Config = FrameworkConfig.Server + +-- 已经初始化,正在运行 +local initialized, running = false, false + +-- 含有InitDefault(),Init(),Update()的模块列表 +local initDefaultList, initList, updateList = {}, {}, {} + +--- 运行服务器 +function Server:Run() + print('[Server] Run()') + InitServer() + StartUpdate() +end + +--- 停止Update +function Server:Stop() + print('[Server] Stop()') + running = false + ServerHeartbeat.Stop() +end + +--- 初始化 +function InitServer() + if initialized then + return + end + print('[Server] InitServer()') + InitRandomSeed() + InitHeartbeat() + InitServerCustomEvents() + InitCsvAndXls() + GenInitAndUpdateList() + RunInitDefault() + InitOtherModules() + initialized = true +end + +--- 初始化服务器的CustomEvent +function InitServerCustomEvents() + print('[Server] InitServerCustomEvents()') + if world.S_Event == nil then + world:CreateObject('FolderObject', 'S_Event', world) + end + + -- 将插件中的CustomEvent放入Events.ClientEvents中 + for _, m in pairs(Config.PluginEvents) do + local evts = _G[m].ServerEvents + assert(evts, string.format('[Server] %s 中不存在ServerEvents,请检查模块,或从FrameworkConfig删除此配置', m)) + for __, evt in pairs(evts) do + if not table.exists(Events.ServerEvents, evt) then + table.insert(Events.ServerEvents, evt) + end + end + end + + -- 生成CustomEvent节点 + for _, evt in pairs(Events.ServerEvents) do + if world.S_Event[evt] == nil then + world:CreateObject('CustomEvent', evt, world.S_Event) + end + end +end + +--- 初始化心跳包 +function InitHeartbeat() + assert(ServerHeartbeat, '[Server][Heartbeat] 找不到ServerHeartbeat,请联系张远程') + ServerHeartbeat.Init() +end + +--- 生成框架需要的节点 +function InitCsvAndXls() + if not world.Global.Csv then + world:CreateObject('FolderObject', 'Csv', world.Global) + end + if not world.Global.Xls then + world:CreateObject('FolderObject', 'Xls', world.Global) + end +end + +--- 生成需要Init和Update的模块列表 +function GenInitAndUpdateList() + ModuleUtil.GetModuleListWithFunc(Module.S_Module, 'InitDefault', initDefaultList) + ModuleUtil.GetModuleListWithFunc(Module.S_Module, 'Init', initList) + ModuleUtil.GetModuleListWithFunc(Module.S_Module, 'Update', updateList) + for _, m in pairs(FrameworkConfig.Server.PluginModules) do + ModuleUtil.GetModuleListWithFunc(m, 'InitDefault', initDefaultList) + ModuleUtil.GetModuleListWithFunc(m, 'Init', initList) + ModuleUtil.GetModuleListWithFunc(m, 'Update', updateList) + end +end + +--- 执行默认的Init方法 +function RunInitDefault() + for _, m in ipairs(initDefaultList) do + m:InitDefault(m) + end +end + +--- 初始化服务器随机种子 +function InitRandomSeed() + math.randomseed(os.time()) +end + +--- 初始化包含Init()方法的模块 +function InitOtherModules() + for _, m in ipairs(initList) do + m:Init() + end +end + +--- 开始Update +function StartUpdate() + print('[Server] StartUpdate()') + assert(not running, '[Server] StartUpdate() 正在运行') + + running = true + + -- 开启心跳 + if FrameworkConfig.HeartbeatStart then + invoke(ServerHeartbeat.Start) + end + + local dt = 0 -- delta time 每帧时间 + local tt = 0 -- total time 游戏总时间 + local now = Timer.GetTimeMillisecond --时间函数缓存 + local prev, curr = now() / 1000, nil -- two timestamps + + while (running and wait()) do + curr = now() / 1000 + dt = curr - prev + tt = tt + dt + prev = curr + UpdateServer(dt, tt) + end +end + +--- Update函数 +--- @param dt delta time 每帧时间 +function UpdateServer(_dt, _tt) + for _, m in ipairs(updateList) do + m:Update(_dt, _tt) + end +end + +return Server diff --git a/Code/['World']['Global']['LuaFunctionScript'].Script.lua b/Code/['World']['Global']['LuaFunctionScript'].Script.lua new file mode 100644 index 0000000..02fe3c5 --- /dev/null +++ b/Code/['World']['Global']['LuaFunctionScript'].Script.lua @@ -0,0 +1,968 @@ +--- 提供一组常用函数,以及对 Lua 标准库的扩展 +-- @script Lua function extension libraries +-- @author Lilith Games, Avatar Team +-- @see https://wiki.lilithgames.com/x/tSkMAg + +--- 检查并尝试转换为数值,如果无法转换则返回 0 +-- @param mixed value 要检查的值 +-- @param [integer base] 进制,默认为十进制 +-- @return number +function checknumber(value, base) + return tonumber(value, base) or 0 +end + +--- 检查是否是有效的number类型 +-- @param number +function isValidNumber(num) + return num ~= nil and num > 0 +end + +--- 检查并尝试转换为整数,如果无法转换则返回 0 +-- @param mixed value 要检查的值 +-- @return integer +function checkint(value) + return math.round(checknumber(value)) +end + +--- 检查并尝试转换为布尔值,除了 nil 和 false,其他任何值都会返回 true +-- @param mixed value 要检查的值 +-- @return boolean +function checkbool(value) + return (value ~= nil and value ~= false) +end + +--- 检查值是否是一个表格,如果不是则返回一个空表格 +-- @param mixed value 要检查的值 +-- @return table +function checktable(value) + if type(value) ~= 'table' then + value = {} + end + return value +end + +--- 处理对象 +-- @param mixed obj Lua 对象 +-- @param function method 对象方法 +-- @return function +function handler(obj, method) + return function(...) + return method(obj, ...) + end +end + +--- 计算表格包含的字段数量 +-- Lua table 的 "#" 操作只对依次排序的数值下标数组有效,table.nums() 则计算 table 中所有不为 nil 的值的个数。 +-- @param table +function table.nums(t) + if t == nil then + return 0 + end + local count = 0 + for _ in pairs(t) do + count = count + 1 + end + return count +end + +--- 返回指定表格中的所有键 +-- @param k-v table +-- @return keys' table +-- @usage example +-- local hashtable = {a = 1, b = 2, c = 3} +-- local keys = table.keys(hashtable) +-- >> keys = {"a", "b", "c"} +function table.keys(hashtable) + local keys = {} + for k, _ in pairs(hashtable) do + table.insert(keys, k) + end + return keys +end + +--- 返回指定表格中的所有值 +-- @param k-v table +-- @return values' table +-- @usage example +-- local hashtable = {a = 1, b = 2, c = 3} +-- local values = table.values(hashtable) +-- >> values = {1, 2, 3} +function table.values(hashtable) + local values = {} + local i = 1 + for k, v in pairs(hashtable) do + values[i] = v + i = i + 1 + end + return values +end + +--- 将来源表格中所有键及其值复制到目标表格对象中,如果存在同名键,则覆盖其值 +-- @param target table +-- @param source table +-- @usage example +-- local dest = {a = 1, b = 2} +-- local src = {c = 3, d = 4} +-- table.merge(dest, src) +-- >> dest = {a = 1, b = 2, c = 3, d = 4} +function table.merge(dest, src) + for k, v in pairs(src) do + dest[k] = v + end +end + +--- 深度将来源表格中所有键及其值复制到目标表格对象中,如果存在同名键,则覆盖其值,如果存在子表,则遍历子表进行复制 +function table.deepMerge(dest, src) + for k, v in pairs(src) do + if type(v) == 'table' then + if dest[k] == nil then + dest[k] = {} + end + table.deepMerge(dest[k], v) + else + dest[k] = v + end + end +end + +--- 将来源表格中所有键及其值复制到目标表格对象中,如果存在同名键,则覆盖其值 +-- @param ... 多个表,第一个是目标表格 +-- @return 返回一个新表 +---@author Sharif Ma +function table.MergeTables(...) + local tabs = {...} + if not tabs or #tabs == 0 then + return {} + end + local origin = {} + for k, v in pairs(tabs[1]) do + origin[k] = v + end + for i = 2, #tabs do + if origin then + if tabs[i] then + for _, v in pairs(tabs[i]) do + table.insert(origin, v) + end + end + else + origin = tabs[i] + end + end + return origin +end + +--- 在目标表格的指定位置插入来源表格,如果没有指定位置则连接两个表格 +-- @param target table +-- @param source table +-- @param start index +-- @usage example #1 +-- local dest = {1, 2, 3} +-- local src = {4, 5, 6} +-- table.insertto(dest, src) +-- >> dest = {1, 2, 3, 4, 5, 6} +-- @usage example #2 +-- local dest = {1, 2, 3} +-- local src = {4, 5, 6} +-- table.insertto(dest, src, 5) +-- >> dest = {1, 2, 3, nil, 4, 5, 6} +function table.insertto(dest, src, begin) + if begin == nil then + begin = #dest + 1 + else + begin = checkint(begin) + if begin <= 0 then + begin = #dest + 1 + end + end + + local len = #src + for i = 0, len - 1 do + dest[i + begin] = src[i + 1] + end +end + +--- 从表格中查找指定值,返回其索引,如果没找到返回 false +-- @param array table +-- @param target value +-- @param start index +-- @return index or false +-- @usage example +-- local array = {"a", "b", "c"} +-- print(table.indexof(array, "b")) +-- >> 2 +function table.indexof(array, value, begin) + if array ~= nil then + for i = begin or 1, #array do + if array[i] == value then + return i + end + end + end + return 0 +end + +--- 检查表格中是否存在指定值 +-- @param array table +-- @param target value +-- @return @boolean +function table.exists(array, value) + return table.indexof(array, value) > 0 +end + +--- 清空数组表格 +-- @param array table +function table.cleararray(array) + if array ~= nil then + local count = #array + while count > 0 do + table.remove(array, count) + count = #array + end + end +end + +--- 清空k-v表格 +-- @param k-v table +function table.clearhashtable(hashtable) + if hashtable ~= nil then + for k, v in pairs(hashtable) do + hashtable[k] = nil + end + end +end + +--- 清空表格 +-- @param table +-- @see table.clearhashtable +function table.cleartable(t) + table.clearhashtable(t) +end + +--- 截取Array其中一段,startIndex从1开始 return截取后的新数组 +-- @param table array table +-- @param @number start index +-- @param @number length +-- @return @table array table +-- @usage example +-- local array = {"a", "b", "c", "d"} +-- print(table.subArray(array, 2, 2)) +-- >> {"b", "c"} +function table.subArray(array, startIndex, length) + if array ~= nil then + local count = table.nums(array) + local tempArray = array + array = {} + if startIndex <= count then + local maxlength = count - startIndex + 1 + length = length > maxlength and maxlength or length + local endIndex = startIndex + length - 1 + for i = startIndex, endIndex do + table.insert(array, tempArray[i]) + end + end + end + return array +end + +--- 截取Array的后半段,startIndex从1开始 return截取后的新数组 +-- @param table array table +-- @param @number start index +-- @return @table array table +function table.subArrayByStartIndex(array, startIndex) + if array ~= nil then + local count = table.nums(array) + local length = count - startIndex + 1 + return table.subArray(array, startIndex, length) + end + return array +end + +--- 从表格中查找指定值,返回其 key,如果没找到返回 nil +-- @param table hash table +-- @param any value +-- @return key of value +-- @usage +-- local hashtable = {name = "dualface", comp = "chukong"} +-- print(table.keyof(hashtable, "chukong")) +-- >> comp +function table.keyof(hashtable, value) + for k, v in pairs(hashtable) do + if v == value then + return k + end + end + return nil +end + +--- 从表格中删除指定值,返回删除的值的个数 +-- @usage +-- local array = {"a", "b", "c", "c"} +-- print(table.removebyvalue(array, "c", true)) +-- >> 输出 2 +function table.removebyvalue(array, value, removeall) + local c, i, max = 0, 1, #array + while i <= max do + if array[i] == value then + table.remove(array, i) + c = c + 1 + i = i - 1 + max = max - 1 + if not removeall then + break + end + end + i = i + 1 + end + return c +end + +--- 数组混淆 +function table.shuffle(_tbl) + local j + for i = #_tbl, 2, -1 do + j = math.random(i) + _tbl[i], _tbl[j] = _tbl[j], _tbl[i] + end + return _tbl +end + +--- 对表格中每一个值执行一次指定的函数,并用函数返回值更新表格内容 +-- @param table +-- @param function fn 参数指定的函数具有两个参数,并且返回一个值。原型如下: +-- function map_function(value, key) +-- return value +-- end +-- @usage +-- local t = {name = "dualface", comp = "chukong"} +-- table.map(t, function(v, k) +-- -- 在每一个值前后添加括号 +-- return "[" .. v .. "]" +-- end) +-- 输出修改后的表格内容 +-- for k, v in pairs(t) do +-- print(k, v) +-- end +-- >> 输出 +-- name [dualface] +-- comp [chukong] +function table.map(t, fn) + for k, v in pairs(t) do + t[k] = fn(v, k) + end +end + +--- 对表格中每一个值执行一次指定的函数,但不改变表格内容 +-- @param table +-- @param function fn 参数指定的函数具有两个参数,没有返回值。原型如下: +-- function map_function(value, key) +-- -- no return here +-- end +-- @usage +-- local t = {name = "dualface", comp = "chukong"} +-- table.walk(t, function(v, k) +-- -- 输出每一个值 +-- print(v) +-- end) +function table.walk(t, fn) + for k, v in pairs(t) do + fn(v, k) + end +end + +--- 对表格中每一个值执行一次指定的函数,如果该函数返回 false,则对应的值会从表格中删除 +-- @param table +-- @param function fn 参数指定的函数具有两个参数,并且返回一个 boolean 值。原型如下: +-- !!!!该方法有局限性,执行后会修改原表格t中值 +-- function map_function(value, key) +-- return true or false +-- end +-- @usage +-- local t = {name = "dualface", comp = "chukong"} +-- table.filter(t, function(v, k) +-- return v ~= "dualface" -- 当值等于 dualface 时过滤掉该值 +-- end) +-- 输出修改后的表格内容 +-- for k, v in pairs(t) do +-- print(k, v) +-- end +-- >> 输出 comp chukong +function table.filter(t, fn) + for k, v in pairs(t) do + if not fn(v, k) then + t[k] = nil + end + end +end + +--- 找到表格中每个符合matchFunc的条目 +-- @param array table +-- @param match function, return T/F +-- @return all elements matched, default is {} +function table.findAll(array, matchFunc) + local ret, idx = {}, 1 + for i = 1, #array do + if matchFunc(array[i]) then + ret[idx] = array[i] + idx = idx + 1 + end + end + return ret +end + +--- 找到表格中每个符合matchFunc的条目,并执行walkFunc +-- @param array table +-- @param match function, return T/F +-- @param walk function +function table.findAllAndWalk(array, matchFunc, walkFunc) + for i = 1, #array do + if matchFunc(array[i]) then + walkFunc(array[i]) + end + end +end + +--- 在表格中插入一个新值 +-- @param array table +-- @param new element +function table.insert_once(T, elem) + for _, v in ipairs(T) do + if v == elem then + return + end + end + table.insert(T, elem) +end + +--- 遍历表格,确保其中的值唯一 +-- @function [parent=#table] unique +-- @param table t 表格 +-- @param boolean bArray t是否是数组,是数组,t中重复的项被移除后,后续的项会前移 +-- @return table#table 包含所有唯一值的新表格 +-- @usage +-- 遍历表格,确保其中的值唯一 +-- local t = {"a", "a", "b", "c"} -- 重复的 a 会被过滤掉 +-- local n = table.unique(t) +-- for k, v in pairs(n) do +-- print(v) +-- end +-- >> 输出 a b c +function table.unique(t, bArray) + local check = {} + local n = {} + local idx = 1 + for k, v in pairs(t) do + if not check[v] then + if bArray then + n[idx] = v + idx = idx + 1 + else + n[k] = v + end + check[v] = true + end + end + return n +end + +--- table 深度复制 +-- @param table +-- @return a net table with same data +function table.deepcopy(object) + local lookup_table = {} + local function _copy(object) + if type(object) ~= 'table' then + return object + elseif lookup_table[object] then + return lookup_table[object] + end + local new_table = {} + lookup_table[object] = new_table + for key, value in pairs(object) do + new_table[_copy(key)] = _copy(value) + end + return setmetatable(new_table, getmetatable(object)) + end + return _copy(object) +end + +--- table 浅度复制(不处理metatable) +function table.shallowcopy(orig) + local orig_type = type(orig) + local copy + if orig_type == 'table' then + copy = {} + for orig_key, orig_value in next, orig, nil do + copy[table.shallowcopy(orig_key)] = table.shallowcopy(orig_value) + end + else + copy = orig + end + return copy +end + +--- 获取or创建一个子表 +function table.need(tb, key) + if type(tb) == 'table' then + local subTb = tb[key] + if subTb == nil then + subTb = {} + tb[key] = subTb + end + return subTb + end + return +end + +--- 打印table中的所有内容 +-- @param data table +-- @param @boolean showMetatable 是否显示元表 +function table.dump(data, showMetatable) + local result, tab = {}, ' ' + local function _dump(data, showMetatable, lastCount) + if type(data) ~= 'table' then + if type(data) == 'string' then + table.insert(result, '"') + table.insert(result, data) + table.insert(result, '"') + else + table.insert(result, tostring(data)) + end + else + --Format + local count = lastCount or 0 + count = count + 1 + table.insert(result, '{\n') + --Metatable + if showMetatable then + for i = 1, count do + table.insert(result, tab) + end + local mt = getmetatable(data) + table.insert(result, '"__metatable" = ') + _dump(mt, showMetatable, count) + table.insert(result, ',\n') + end + --Key + for key, value in pairs(data) do + for i = 1, count do + table.insert(result, tab) + end + if type(key) == 'string' then + table.insert(result, '"') + table.insert(result, key) + table.insert(result, '" = ') + elseif type(key) == 'number' then + table.insert(result, '[') + table.insert(result, key) + table.insert(result, '] = ') + else + table.insert(result, tostring(key)) + end + _dump(value, showMetatable, count) + table.insert(result, ',\n') + end + --Format + for i = 1, lastCount or 0 do + table.insert(result, tab) + end + table.insert(result, '}') + end + --Format + if not lastCount then + table.insert(result, '\n') + end + end + _dump(data, showMetatable, 0) + + -- print('dump: \n' .. table.concat(result)) + return 'dump: \n' .. table.concat(result) +end + +--- 用指定字符或字符串分割输入字符串,返回包含分割结果的数组 +-- @param @string input 输入的字符串 +-- @param @string delimiter 分隔符 +-- @return array +-- @usage example #1 +-- local input = "Hello,World" +-- local res = string.split(input, ",") +-- >> res = {"Hello", "World"} +-- @usage example #2 +-- local input = "Hello-+-World-+-Quick" +-- local res = string.split(input, "-+-") +-- >> res = {"Hello", "World", "Quick"} +function string.split(input, delimiter) + input = tostring(input) + delimiter = tostring(delimiter) + if (delimiter == '') then + return false + end + local pos, arr = 0, {} + -- for each divider found + for st, sp in function() + return string.find(input, delimiter, pos, true) + end do + table.insert(arr, string.sub(input, pos, st - 1)) + pos = sp + 1 + end + table.insert(arr, string.sub(input, pos)) + return arr +end + +--- 判断字符串是否为空或者长度为零 +-- @param @string 输入的字符串 +function string.isnilorempty(inputStr) + return inputStr == nil or inputStr == '' +end + +--- 去除输入字符串头部的空白字符,返回结果 +-- @param @string input +-- @return @string +-- @usage example +-- local input = " ABC" +-- print(string.ltrim(input)) +-- >> 输出 ABC,输入字符串前面的两个空格被去掉了 +-- 空白字符包括: +-- - 空格 +-- - 制表符 \t +-- - 换行符 \n +-- - 回到行首符 \r +function string.ltrim(input) + return string.gsub(input, '^[ \t\n\r]+', '') +end + +--- 去除输入字符串尾部的空白字符,返回结果 +-- @param @string input +-- @return @string +-- @usage example +-- local input = "ABC " +-- print(string.rtrim(input)) +-- >> 输出 ABC,输入字符串最后的两个空格被去掉了 +function string.rtrim(input) + return string.gsub(input, '[ \t\n\r]+$', '') +end + +--- 去掉字符串首尾的空白字符,返回结果 +-- @param @string input +-- @return @string +function string.trim(input) + input = string.gsub(input, '^[ \t\n\r]+', '') + return string.gsub(input, '[ \t\n\r]+$', '') +end + +--- 将字符串的第一个字符转为大写,返回结果 +-- @param @string input +-- @return @string +-- @usage example +-- local input = "hello" +-- print(string.ucfirst(input)) +-- >> 输出 Hello +function string.ucfirst(input) + return string.upper(string.sub(input, 1, 1)) .. string.sub(input, 2) +end + +function string.firstToUpper(str) + return (str:gsub('^%l', string.upper)) +end + +--- 计算 UTF8 字符串的长度,每一个中文算一个字符 +-- @param @string input +-- @return @number cnt +-- @usage example +-- local input = "你好World" +-- print(string.utf8len(input)) +-- >> 输出 7 +function string.utf8len(input) + local len = string.len(input) + local left = len + local cnt = 0 + local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc} + while left ~= 0 do + local tmp = string.byte(input, -left) + local i = #arr + while arr[i] do + if tmp >= arr[i] then + left = left - i + break + end + i = i - 1 + end + cnt = cnt + 1 + end + return cnt +end + +--- 替换字符串内容 +-- @param @string input +-- @param @number start index +-- @param new context +-- @return a new string +function string.replace(str, index, char) + return table.concat {str:sub(1, index - 1), char, str:sub(index + 1)} +end + +--- 检查字符串是否为指定字符串开头 +-- @param @string target +-- @param @string start +-- @return @boolean +function string.startswith(str, start) + return str:sub(1, #start) == start +end + +--- 检查字符串是否以指定字符串结尾 +-- @param @string target +-- @param @string start +-- @return @boolean +function string.endswith(str, ending) + return ending == '' or str:sub(-(#ending)) == ending +end + +--- 四舍五入 +-- @param a number +-- @return a round number +function math.round(value) + return math.floor(value + 0.5) +end + +--- [0, 1]区间限定函数 +-- @param a number +-- @return a clamped number +function math.clamp01(value) + return math.min(1, math.max(0, value)) +end + +---最小数值和最大数值指定返回值的范围 +-- @param a number +-- @param min threshold +-- @param max threshold +-- @return a clamped number +function math.Clamp(value, min, max) + if value < min then + return min + end + if value > max then + return max + end + return value +end + +--- 高斯岁间变量 +function math.GaussRandom() + local u = math.random() + local v = math.random() + local z = math.sqrt(-2 * math.log(u)) * math.cos(2 * math.pi * v) + z = (z + 3) / 6 + z = 2 * z - 1 + if (math.abs(z) > 1) then + return math.GaussRandom() + end + return z +end + +--- 数据结构 队列 +-- @usage queue example +-- local myQueue = Queue:New() +-- myQueue:Enqueue('a') +-- myQueue:Enqueue('b') +-- myQueue:Enqueue('c') +-- myQueue:PrintElement() +-- print(myQueue:Dequeue()) +-- myQueue:PrintElement() +-- myQueue:Clear() +-- myQueue:PrintElement() +Queue = {} +function Queue:New() + local inst = { + _first = -1, + _last = -1, + _size = 0, + _queue = {} + } + setmetatable(inst, {__index = self}) + return inst +end + +function Queue:IsEmpty() + if self._size == 0 then + return true + end + return false +end + +function Queue:Enqueue(inElement) + if self._size == 0 then + self._first = 0 + self._last = 1 + self._size = 1 + self._queue[self._last] = inElement + else + self._last = self._last + 1 + self._queue[self._last] = inElement + self._size = self._size + 1 + end +end + +function Queue:Dequeue() + if self:IsEmpty() then + print('Error: the queue is empty') + return + end + self._size = self._size - 1 + self._first = self._first + 1 + local value = self._queue[self._first] + return value +end + +function Queue:Clear() + self._queue = nil + self._queue = {} + self._size = 0 + self._first = -1 + self._last = -1 +end + +function Queue:Size() + return self._size or 0 +end + +function Queue:PrintElement() + if self._size == 0 then + print('{}') + else + local f = self._first + 1 + local l = self._last + local str + local flag = true + while f ~= l do + if flag == true then + str = '{' .. tostring(self._queue[f]) + f = f + 1 + flag = false + else + str = str .. ',' .. tostring(self._queue[f]) + f = f + 1 + end + end + str = str .. ',' .. tostring(self._queue[l]) .. '}' + print(str) + end +end + +function Queue:GetValue(index) + if self:IsEmpty() or index == nil or index == 0 then + print('Error: Get Value Failure!') + return + end + if index > 0 then + return self._queue[self._first + index] + else + return self._queue[self._last + index + 1] + end +end + +function Queue:GetValues() + if self:IsEmpty() then + return + end + local data = {} + for i = self._first + 1, self._last, 1 do + data[#data + 1] = self._queue[i] + end + return data +end + +--- 数据结构 栈 +-- @usage example +-- local myStack = Stack:New() +-- myStack:Push("a") +-- myStack:Push("b") +-- myStack:Push("c") +-- myStack:PrintElement() +-- print(myStack:Pop()) +-- myStack:PrintElement() +-- myStack:Clear() +-- myStack:PrintElement() +Stack = {} +function Stack:New() + local inst = { + _last = 0, + _stack = {} + } + setmetatable(inst, {__index = self}) + + return inst +end + +function Stack:IsEmpty() + if self._last == 0 then + return true + end + return false +end + +function Stack:Push(inElement) + self._last = self._last + 1 + self._stack[self._last] = inElement +end + +function Stack:Pop() + if self:IsEmpty() then + --print("Error: the stack is empty") + return + end + local value = self._stack[self._last] + self._stack[self._last] = nil + self._last = self._last - 1 + return value +end + +function Stack:Exists(element, compairFunc) + if compairFunc == nil then + compairFunc = function(a, b) + return a == b + end + end + for i = self._last, 1, -1 do + if compairFunc(element, self._stack[i]) then + return i + end + end + return -1 +end + +function Stack:RemoveAt(index) + if index < 1 or index > self._last then + return + end + table.remove(self._stack, index) + self._last = self._last - 1 +end + +function Stack:Clear() + self._stack = nil + self._stack = {} + self._last = 0 +end + +function Stack:Size() + return self._last +end + +function Stack:PrintElement() + local str = '{' + for i = self._last, 1, -1 do + str = str .. tostring(self._stack[i]) .. ',' + end + str = str .. '}' + print(str) +end + + +--- uid递增计数器 +function UidCounter() + local num = 0 + return function() + num = num + 1 + return tostring(os.clock())..'-'..tostring(num) + end +end diff --git a/Code/['World']['Global']['Module']['C_Module']['LanguageUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Module']['C_Module']['LanguageUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..cf83b84 --- /dev/null +++ b/Code/['World']['Global']['Module']['C_Module']['LanguageUtilModule'].ModuleScript.lua @@ -0,0 +1,32 @@ +--- 语言包模块:根据游戏内语言设置返回对应的语言文本 +--- @module LanguageUtil, Client-side +--- @copyright Lilith Games, Avatar Team +--- @author Xiexy, Yuancheng Zhang +local LanguageUtil, this = ModuleUtil.New('LanguageUtil', ClientBase) +local lang = Config.GlobalSetting.DefaultLanguage +local defaultLang = Const.LanguageEnum.CHS + +--- 设置当前语言 +function LanguageUtil.SetLanguage(_lang) + assert(Const.LanguageEnum[_lang], string.format('[LanguageUtil] %s 语言码不存在,请检查ConstModule', _lang)) + print(string.format('[LanguageUtil] 更改当前语言:%s => %s', lang, _lang)) + lang = _lang +end + +--- 根据ID返回当前游戏语言对应的文本信息,如果对应语言为空,默认返回'*'+中文内容 +-- @param @number _id LanguagePack.xls中的编号 +function LanguageUtil.GetText(_id) + assert(not string.isnilorempty(_id), '[LanguageUtil] 翻译ID为空,请检查策划表和LanguagePack') + assert( + Config.LanguagePack[_id], + string.format('[LanguageUtil] LanguagePack[%s] 不存在对应翻译ID,请检查策划表和LanguagePack', _id) + ) + local text = Config.LanguagePack[_id][lang] + if string.isnilorempty(text) then + print(string.format('[LanguageUtil] LanguagePack[%s][%s] 不存在对应语言翻译内容,默认使用中文', _id, lang)) + text = '*' .. Config.LanguagePack[_id][defaultLang] + end + return text +end + +return LanguageUtil diff --git a/Code/['World']['Global']['Module']['C_Module']['PlayerControlModule'].ModuleScript.lua b/Code/['World']['Global']['Module']['C_Module']['PlayerControlModule'].ModuleScript.lua new file mode 100644 index 0000000..d3bccdf --- /dev/null +++ b/Code/['World']['Global']['Module']['C_Module']['PlayerControlModule'].ModuleScript.lua @@ -0,0 +1,182 @@ +--- 玩家控制模块 +--- @module Player Controll, client-side +--- @copyright Lilith Games, Avatar Team +local PlayerControl, this = ModuleUtil.New('PlayerControl', ClientBase) +local player +--声明变量 +local isDead = false +local forwardDir = Vector3.Forward +local rightDir = Vector3.Right +local finalDir = Vector3.Zero +local horizontal = 0 +local vertical = 0 + +-- 相机 +local camera, mode + +-- 手机端交互UI +local gui, joystick, touchScreen, jumpButton + +-- PC端交互按键 +local FORWARD_KEY = Enum.KeyCode.W +local BACK_KEY = Enum.KeyCode.S +local LEFT_KEY = Enum.KeyCode.A +local RIGHT_KEY = Enum.KeyCode.D +local JUMP_KEY = Enum.KeyCode.Space + +-- 键盘的输入值 +local moveForwardAxis = 0 +local moveBackAxis = 0 +local moveLeftAxis = 0 +local moveRightAxis = 0 + +function PlayerControl:Init() + -- 获取本地玩家 + player = localPlayer + self:InitGui() + self:InitCamera() + self:InitListener() +end + +function PlayerControl:InitListener() + -- Main + world.OnRenderStepped:Connect(MainControl) + -- Player + player.OnHealthChange:Connect(HealthCheck) + player.OnDead:Connect(PlayerDie) + -- GUI + touchScreen.OnTouched:Connect(CountTouch) + touchScreen.OnPanStay:Connect(CameraMove) + touchScreen.OnPinchStay:Connect(CameraZoom) + jumpButton.OnDown:Connect(PlayerJump) + -- Keyboard + Input.OnKeyDown:Connect( + function() + if Input.GetPressKeyData(JUMP_KEY) == 1 then + PlayerJump() + end + end + ) +end + +function PlayerControl:InitGui() + gui = localPlayer.Local.ControlGui + joystick = gui.Joystick + touchScreen = gui.TouchFig + jumpButton = gui.JumpBtn +end + +function PlayerControl:InitCamera() + if not world.CurrentCamera and localPlayer.Local.Independent.GameCam then + world.CurrentCamera = localPlayer.Local.Independent.GameCam + end + camera = world.CurrentCamera + mode = Camera.CameraMode + camera.LookAt = player +end + +-- 移动方向是否遵循摄像机方向 +function IsFreeMode() + return (mode == Enum.CameraMode.Social and camera.Distance >= 0) or mode == Enum.CameraMode.Orbital or + mode == Enum.CameraMode.Custom +end + +--获取按键盘时的移动方向最终取值 +function GetKeyValue() + moveForwardAxis = Input.GetPressKeyData(FORWARD_KEY) > 0 and 1 or 0 + moveBackAxis = Input.GetPressKeyData(BACK_KEY) > 0 and -1 or 0 + moveLeftAxis = Input.GetPressKeyData(LEFT_KEY) > 0 and 1 or 0 + moveRightAxis = Input.GetPressKeyData(RIGHT_KEY) > 0 and -1 or 0 + if player.State == Enum.CharacterState.Died then + moveForwardAxis, moveBackAxis, moveLeftAxis, moveRightAxis = 0, 0, 0, 0 + end +end + +-- 获取移动方向 +function GetMoveDir() + forwardDir = IsFreeMode() and camera.Forward or player.Forward + forwardDir.y = 0 + rightDir = Vector3(0, 1, 0):Cross(forwardDir) + horizontal = joystick.Horizontal + vertical = joystick.Vertical + if horizontal ~= 0 or vertical ~= 0 then + finalDir = rightDir * horizontal + forwardDir * vertical + else + GetKeyValue() + finalDir = forwardDir * (moveForwardAxis + moveBackAxis) - rightDir * (moveLeftAxis + moveRightAxis) + end +end + +-- 移动逻辑 +function PlayerMove(_dir) + _dir.y = 0 + if player.State == Enum.CharacterState.Died then + _dir = Vector3.Zero + end + if _dir.Magnitude > 0 then + if IsFreeMode then + player:FaceToDir(_dir, 4 * math.pi) + end + player:MoveTowards(Vector2(_dir.x, _dir.z).Normalized) + else + player:MoveTowards(Vector2.Zero) + end +end + +-- 跳跃逻辑 +function PlayerJump() + if (player.IsOnGround or player.State == Enum.CharacterState.Seated) and not isDead then + player:Jump() + return + end +end + +-- 死亡逻辑 +function PlayerDie() + isDead = true + wait(player.RespawnTime) + player:Reset() + isDead = false +end + +-- 生命值检测 +function HealthCheck(oldHealth, newHealth) + if newHealth <= 0 then + player:Die() + end +end + +-- 每个渲染帧处理操控逻辑 +function MainControl() + camera = world.CurrentCamera + mode = camera.CameraMode + GetMoveDir() + PlayerMove(finalDir) +end + +-- 检测触屏的手指数 +local touchNumber = 0 +function CountTouch(container) + touchNumber = #container +end + +-- 滑屏转向 +function CameraMove(_pos, _dis, _deltapos, _speed) + if touchNumber == 1 then + if IsFreeMode() then + camera:CameraMove(_deltapos) + else + player:RotateAround(player.Position, Vector3.Up, _deltapos.x) + camera:CameraMove(Vector2(0, _deltapos.y)) + end + end +end + +-- 双指缩放摄像机距离 +function CameraZoom(_pos1, _pos2, _dis, _speed) + if mode == Enum.CameraMode.Social then + camera.Distance = camera.Distance - _dis / 50 + end +end + +return PlayerControl diff --git a/Code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua b/Code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua new file mode 100644 index 0000000..cb06367 --- /dev/null +++ b/Code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua @@ -0,0 +1,92 @@ +--- 玩家默认UI +--- @module Player Default GUI +--- @copyright Lilith Games, Avatar Team +local PlayerGuiDefault, this = ModuleUtil.New('PlayerGuiDefault', ClientBase) + +-- 获取本地玩家 +local player + +-- 姓名板 +local nameGUI + +-- 血条 +local healthGUI, background, healthBar +local RED_BAR = ResourceManager.GetTexture('Internal/Blood_Red') +local GREEN_BAR = ResourceManager.GetTexture('Internal/Blood_Green') +local ORANGE_BAR = ResourceManager.GetTexture('Internal/Blood_Orange') +local HIT_LAST_TIME = 2 +local healthBarShowTime = 0 + +function PlayerGuiDefault:Init() + -- 获取本地玩家 + player = localPlayer + self:InitNameGui() + self:InitHealthBarGui() + self:InitListener() +end + +-- 姓名板 +function PlayerGuiDefault:InitNameGui() + nameGUI = player.NameGui + nameGUI.NameBarTxt.Text = player.Name +end + +-- 血条 +function PlayerGuiDefault:InitHealthBarGui() + healthGUI = player.HealthGui + background = healthGUI.BackgroundImg + healthBar = background.HealthBarImg +end + +-- 初始化事件 +function PlayerGuiDefault:InitListener() + player.OnHealthChange:Connect(HealthChange) + world.OnRenderStepped:Connect(MainGUI) +end + +-- 姓名板的显示逻辑 +function NameBarLogic() + nameGUI.Visible = player.DisplayName + if player.DisplayName then + local addedHeight = (healthGUI and healthGUI.ActiveSelf) and 1.1 or 1 + nameGUI.LocalPosition = Vector3(0, addedHeight + player.Avatar.Height, 0) + end +end + +-- 血条随生命值颜色改变而改变 +function HealthChange(_oldHealth, _newHealth) + if _oldHealth > _newHealth then + healthBarShowTime = 2 + end + local percent = player.Health / player.MaxHealth + if percent >= 0.7 then + healthBar.Texture = GREEN_BAR + elseif percent >= 0.3 then + healthBar.Texture = ORANGE_BAR + else + healthBar.Texture = RED_BAR + end + healthBar.AnchorsX = Vector2(0.05, 0.9 * percent + 0.05) +end + +-- 血条在各显示模式下的显示逻辑 +function HealthBarLogic(_delta) + healthBarShowTime = healthBarShowTime - _delta + if player.HealthDisplayMode == Enum.HealthDisplayMode.Always then + healthGUI.Visible = true + elseif player.HealthDisplayMode == Enum.HealthDisplayMode.Never then + healthGUI.Visible = false + elseif player.HealthDisplayMode == Enum.HealthDisplayMode.OnHit then + healthGUI.Visible = player.Health ~= player.MaxHealth + else + healthGUI.Visible = healthBarShowTime > 0 + end +end + +-- 每个渲染帧更新姓名板和血条的显示逻辑 +function MainGUI(_delta) + NameBarLogic() + HealthBarLogic(_delta) +end + +return PlayerGuiDefault diff --git a/Code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua b/Code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua new file mode 100644 index 0000000..02d7657 --- /dev/null +++ b/Code/['World']['Global']['Module']['Editor_Module']['SceneMeshEditorModule'].ModuleScript.lua @@ -0,0 +1,29 @@ +--- 用于场景mesh的一些快捷编辑功能 +--- @module SceneMeshEditor +--- @copyright Lilith Games, Avatar Team +--- @author Sid Zhang +local SceneMeshEditor = {} + +--- 将当前选中节点下的所有特定名称的mesh节点更改其引用 +--- @param _NodeName string 需要被替换资源的节点名字 +--- @param _MeshResource string FBX资源路径 +--- @param _root object 执行该操作的根节点,缺省则为选中的第一个节点 +function SceneMeshEditor:ChangeMesh(_NodeName, _MeshResource, _root) + if not _root then + _root = Editor.Selections[1] + end + if not _root then + print('[SceneMeshEditor] 没有选中或输入任何节点') + return + end + for _, v in pairs(_root:GetChildren()) do + if v.Name == _NodeName and v.ClassName == 'MeshObject' then + v.Mesh = ResourceManager.GetMesh(_MeshResource) + end + self:ChangeMesh(_NodeName, _MeshResource, v) + end +end + +return SceneMeshEditor + +-- require(Module.Editor_Module.SceneMeshEditorModule):ChangeMesh() diff --git a/Code/['World']['Global']['ModuleRequireScript'].Script.lua b/Code/['World']['Global']['ModuleRequireScript'].Script.lua new file mode 100644 index 0000000..6b39fcf --- /dev/null +++ b/Code/['World']['Global']['ModuleRequireScript'].Script.lua @@ -0,0 +1,40 @@ +--- 将Global.Module目录下每一个用到模块提前require,定义为全局变量 +-- @script Module Defines +-- @copyright Lilith Games, Avatar Team + +-- Utilities +ModuleUtil = require(Utility.ModuleUtilModule) +LuaJsonUtil = require(Utility.LuaJsonUtilModule) +NetUtil = require(Utility.NetUtilModule) +CsvUtil = require(Utility.CsvUtilModule) +XlsUtil = require(Utility.XlsUtilModule) +EventUtil = require(Utility.EventUtilModule) +UUID = require(Utility.UuidModule) +TweenController = require(Utility.TweenControllerModule) +GlobalFunc = require(Utility.GlobalFuncModule) +LinkedList = Utility.LinkedListModule +ValueChangeUtil = require(Utility.ValueChangeUtilModule) +TimeUtil = require(Utility.TimeUtilModule) +CloudLogUtil = require(Utility.CloudLogUtilModule) + +-- Game Defines +GAME_ID = 'X0000' + +-- Utility Initilization +TimeUtil.Init() +CloudLogUtil.Init(GAME_ID) + +-- Framework +ModuleUtil.LoadModules(Framework) + +-- Globle Defines +ModuleUtil.LoadModules(Define) +ModuleUtil.LoadXlsModules(Xls, Config) + +-- Server and Clinet Modules +ModuleUtil.LoadModules(Module.S_Module) +ModuleUtil.LoadModules(Module.Cls_Module) +ModuleUtil.LoadModules(Module.C_Module) + +-- Plugin Modules +GuideSystem = require(world.Global.Plugin.FUNC_Guide.GuideSystemModule) diff --git a/Code/['World']['Global']['Plugin']['FUNC_Guide']['GuideSystemModule'].ModuleScript.lua b/Code/['World']['Global']['Plugin']['FUNC_Guide']['GuideSystemModule'].ModuleScript.lua new file mode 100644 index 0000000..6a39364 --- /dev/null +++ b/Code/['World']['Global']['Plugin']['FUNC_Guide']['GuideSystemModule'].ModuleScript.lua @@ -0,0 +1,47 @@ +---引导系统 +---@module GuideSystem +---@copyright Lilith Games, Avatar Team +---@author Sid Zhang, Yuancheng Zhang + +local GuideSystem = {} + +--- 引导的枚举类型 +GuideSystem.Enum = { + ClickGuide = 'ClickGuide' +} + +--- 显示强引导Ui +---@param _type Int 1:点击 +---@param _position Vector2 生成引导UI在屏幕的位置,Anchors值 +---@param _area Vector2 响应范围,Size +---@param _content String 文本介绍,nil则不显示文本 +function GuideSystem:ShowGuide(_type, _position, _area, _content, _callBack, ...) + local args = {...} + if _type == GuideSystem.Enum.ClickGuide then + local GuideNode = world:CreateInstance('ClickGuide', 'ClickGuide', localPlayer.Local) + if _position then + GuideNode.ImgDot.AnchorsX = Vector2(_position.X, _position.X) + GuideNode.ImgDot.AnchorsY = Vector2(_position.Y, _position.Y) + end + if _content then + GuideNode.ImgDot.FigTextBox.TxtContent.Text = _content + else + GuideNode.ImgDot.FigTextBox.Visible = false + end + if _area then + GuideNode.ImgDot.BtnClose.Size = _area + end + GuideNode.ImgDot.BtnClose.OnClick:Connect( + function() + if _callBack and type(_callBack) == 'function' then + _callBack(table.unpack(args)) + end + GuideNode:Destroy() + end + ) + else + error('param #1 :_type error') + end +end + +return GuideSystem diff --git a/Code/['World']['Global']['Utility']['CamUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['CamUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..700f852 --- /dev/null +++ b/Code/['World']['Global']['Utility']['CamUtilModule'].ModuleScript.lua @@ -0,0 +1,41 @@ +---摄像机工具类 +---@module Cam Utility +---@copyright Lilith Games, Avatar Team +---@author Sharif Ma +---@class CamUtil +local CamUtil = {} + +---将摄像机在水平面上转动到和角色朝向一致的角度 +---@param _player PlayerInstance 摄像机看向的物体 +---@param _cam Camera 转动的摄像机 +---@param _time number 转动过程的事件,不填则瞬间转动 +function CamUtil.ToRoleForward(_player, _cam, _time) + _time = _time or 0 + local dir = _player.Position - _cam.Position + local forward = _player.Forward + local alpha = Vector2.Angle(Vector2(dir.x, dir.z), Vector2(forward.x, forward.z)) + local left = _player.Left + if Vector3.Angle(left, dir) > 90 then + alpha = 360 - alpha + end + if _time == 0 then + _cam:CameraMoveInDegree(Vector2(alpha, 0)) + return + end + invoke( + function() + local curTime = 0 + while true do + local dt = wait() + local dtDe = alpha * dt / _time + _cam:CameraMoveInDegree(Vector2(dtDe, 0)) + curTime = curTime + dt + if curTime >= _time then + return + end + end + end + ) +end + +return CamUtil diff --git a/Code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..65f6636 --- /dev/null +++ b/Code/['World']['Global']['Utility']['CloudLogUtilModule'].ModuleScript.lua @@ -0,0 +1,24 @@ +--- 埋点数据工具 +--- @module CloudLogUtil +--- @copyright Lilith Games, Avatar Team +--- @author Sharif Ma, Xinwu Zhang +local CloudLogUtil = {} + +---埋点工具初始化 +---@param _gameId string 游戏的唯一ID,和服务端定好后不可以更改的,游戏开始前执行 +function CloudLogUtil.Init(_gameId) + CloudLogUtil.gameId = _gameId +end + +---触发埋点相应的事件调用 +---@param _key string 埋点的键 +function CloudLogUtil.UploadLog(_key, _table) + local arg = LuaJsonUtil:encode(_table) + if localPlayer then + TrackService.CloudLogFromClient({_key, CloudLogUtil.gameId, arg}) + else + TrackService.CloudLogFromServer({_key, CloudLogUtil.gameId, arg}) + end +end + +return CloudLogUtil diff --git a/Code/['World']['Global']['Utility']['CsvUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['CsvUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..9c168a9 --- /dev/null +++ b/Code/['World']['Global']['Utility']['CsvUtilModule'].ModuleScript.lua @@ -0,0 +1,244 @@ +--- 读表工具: 将CSV导入成Lua Table,支持单一主键和多主键 +-- @module CSV Utility +-- @copyright Lilith Games, Avatar Team +-- @author Yuancheng Zhang +-- @see https://wiki.lilithgames.com/x/RGEMAg +local CsvUtil = {} + +--! 打印事件日志, true:开启打印 +local showLog, PrintGlobalKV, PrintLog = true + +--- 将表中的字符串改为数字 +-- @param _t input table +local function StrToNum(_t) + for k, v in pairs(_t) do + _t[k] = tonumber(v) + end + return _t +end + +--- 类型解析配置表 +local parser = { + int = function(_raw) + return tonumber(_raw) + end, + float = function(_raw) + return tonumber(_raw) + end, + string = function(_raw) + return _raw + end, + boolean = function(_raw) + return string.lower(_raw) == 'true' + end, + vector2 = function(_raw) + return Vector2(table.unpack(StrToNum(string.split(_raw, ',')))) + end, + vector3 = function(_raw) + return Vector3(table.unpack(StrToNum(string.split(_raw, ',')))) + end, + euler = function(_raw) + return EulerDegree(table.unpack(StrToNum(string.split(_raw, ',')))) + end, + color = function(_raw) + return Color(table.unpack(StrToNum(string.split(_raw, ',')))) + end +} + +--- 读取配置表,会根据id生成lua表 +-- @param _type String 数据类型 +-- @parm _stringValue String 数据 +-- @return value 解析出来的数值 +local function GetValue(_type, _stringValue) + _type = string.lower(_type) + assert(parser[_type], string.format('[CsvUtil][GlobalSetting] "%s" Type字段的值不是目前所支持的数据类型', _type)) + return parser[_type](_stringValue) +end + +--- 读取配置表,会根据id生成lua表 +-- @param _csv 表格 +-- @parma ... 表格的主键ids,可以为单一主键或多主键(多主键的id顺序决定lua table的结构) +-- @usage exmaple #1 如果, 单一键值为主键 +-- Level.csv 表格内容为: +-- ---------------------------------- +-- | String | String | Int | +-- | level_id | level_name | reward | +-- | easy_01 | Level 01 | 100 | +-- | easy_02 | Level 02 | 140 | +-- | hard_01 | Level 03 | 280 | +-- | hard_02 | Level 04 | 320 | +-- ---------------------------------- +-- 调用函数 local levelCsv = CsvUtil.GetCsvInfo(Level, 'level_id') 导入的lua表格结果为: +-- levelCsv = { +-- easy_01 = { +-- level_id = 'easy_01', +-- level_name = 'Level 01', +-- reward = 100 +-- }, +-- easy_02 = { +-- level_id = 'easy_02', +-- level_name = 'Level 02', +-- reward = 140 +-- }, +-- hard_01 = { +-- level_id = 'hard_01', +-- level_name = 'Level 03', +-- reward = 280 +-- }, +-- hard_02 = { +-- level_id = 'hard_02', +-- level_name = 'Level 04', +-- reward = 320 +-- } +-- } +-- @usage exmaple #2 如果, 多键值为主键 +-- Enemy.csv 表格内容为: +-- ---------------------------------- +-- | String | String | Int | +-- | enemy_id | difficulty | hp | +-- | foe_01 | easy | 100 | +-- | foe_01 | hard | 150 | +-- | foe_02 | easy | 300 | +-- | foe_02 | hard | 400 | +-- ---------------------------------- +-- 调用函数 local enemyCsv = CsvUtil.GetCsvInfo(Enemy, 'enemy_id', 'difficulty') 导入的lua表格结果为: +-- enemyCsv = { +-- foe_01 = { +-- easy = { +-- enemy_id = 'foe_01', +-- difficulty = 'easy', +-- hp = 100 +-- }, +-- hard = { +-- enemy_id = 'foe_02', +-- difficulty = 'hard', +-- hp = 150 +-- } +-- }, +-- foe_02 = { +-- esay = { +-- enemy_id = 'foe_02', +-- difficulty = 'easy', +-- hp = 300 +-- }, +-- hard = { +-- enemy_id = 'foe_02', +-- difficulty = 'hard', +-- hp = 400 +-- } +-- } +-- } +-- 使用lua table中的数据方法: +-- health = enemyCsv.foe_01.hard.hp 或 health = enemyCsv['foe_01']['hard']['hp'] +-- health的值为150 +function CsvUtil.GetCsvInfo(_csv, ...) + local rawTable = _csv:GetRows() + local ids = {...} + if #ids < 1 or (#ids == 1 and ids[1] == 'Type') then + -- 默认用Type索引,直接返回 + return rawTable + end + local result = {} + local tmp, key, id, idstr -- 临时变量 + for _, v in pairs(rawTable) do + tmp = result + idstr = {} + for i = 1, #ids do + id = ids[i] + key = v[id] + idstr[i] = tostring(id) .. ',' + assert(not string.isnilorempty(key), string.format('[CsvUtil] CSV表格没有找到此id, CSV:%s, id: %s', _csv.Name, id)) + if i == #ids then + -- 最后的键,确定唯一性 + assert( + not tmp[key], + string.format('[CsvUtil] CSV数据重复, ids不是唯一的, CSV: %s, ids: %s', _csv.Name, table.concat(idstr)) + ) + tmp[key] = v + else + -- 多键,之后还有 + if tmp[key] == nil then + tmp[key] = {} + end + tmp = tmp[key] + end + end + end + return result +end + +--- 读取Config全局配置表 +-- GlobleSetting.csv 表格内容为: +-- --------------------------------------------------------- +-- | String | String | String | String | +-- | Key | Type | Value | Des | +-- --------------------------------------------------------- +-- | CubeMax | Int | 200 | 最大Cube数 | +-- | BattleTime | Float | 5.45 | 战斗时间 | +-- | GameTitle | String | Boom Party | 游戏标题 | +-- | IsFree | Boolean | true | 是否免费 | +-- | UiMapOrigin | Vector2 | 3,4 | UI地图原点位置 | +-- | TreePos | Vector3 | 12,3,-3 | 树的位置 | +-- | TreeRot | Euler | 45,90,0 | 树的旋转 | +-- | TreeColor | Color | 255,255,255,0 | 树的颜色 | +function CsvUtil.GetGlobalCsvInfo(_csv) + local rawTable = _csv:GetRows() + if table.nums(rawTable) == 0 then + return + end + assert(rawTable['1'].Key, '[CsvUtil] 全局配置表的没有"Key"') + assert(rawTable['1'].Type, '[CsvUtil] 全局配置表的没有"Type"') + assert(rawTable['1'].Value, '[CsvUtil] 全局配置表的没有"Value"') + local result = {} + for _, v in pairs(rawTable) do + result[v.Key] = GetValue(v['Type'], v['Value']) + PrintGlobalKV(v.Key, v.Type, result[v.Key]) -- * 输出KV键值对 + end + return result +end + +--- 表格预加载,预加载配置模块:World.Global.Define.ConfigModule +function CsvUtil.PreloadCsv(_preloadList, _csvRoot, _config) + assert(_preloadList and #_preloadList > 0, '[CsvUtil] ConfigModule中没有预加载表格') + for _, pl in pairs(_preloadList) do + if not string.isnilorempty(pl.csv) then + pl.name = string.isnilorempty(pl.name) and pl.csv or pl.name + PrintLog(string.format('[CsvUtil] Load: %s.csv', pl.csv)) + if pl.csv == 'GlobalSetting' and _csvRoot[pl.csv] then + _config[pl.name] = CsvUtil.GetGlobalCsvInfo(_csvRoot[pl.csv]) + elseif not string.isnilorempty(pl.csv) and _csvRoot[pl.csv] then + pl.ids = pl.ids or {} + _config[pl.name] = CsvUtil.GetCsvInfo(_csvRoot[pl.csv], table.unpack(pl.ids)) + end + end + end +end + +--! 辅助功能 + +--- 输出全局变量键值对 +PrintGlobalKV = + showLog and + function(_key, _type, _value) + _type = string.lower(_type) + local showTypes = { + vector2 = 'Vector2', + vector3 = 'Vector3', + euler = 'EulerDegree', + color = 'Color' + } + if showTypes[_type] then + print(string.format('[CsvUtil][GlobalSetting] %s = %s%s ', _key, showTypes[_type], _value)) + else + print(string.format('[CsvUtil][GlobalSetting] %s = %s ', _key, _value)) + end + end or + function() + end + +PrintLog = showLog and function(...) + print(...) + end or function() + end + +return CsvUtil diff --git a/Code/['World']['Global']['Utility']['EventUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['EventUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..7fd554a --- /dev/null +++ b/Code/['World']['Global']['Utility']['EventUtilModule'].ModuleScript.lua @@ -0,0 +1,53 @@ +--- 事件绑定工具 +-- @module Event Connects Handler +-- @copyright Lilith Games, Avatar Team +-- @author Yuancheng Zhang, Yen Yuan +local EventUtil = {} + +--- 检查是否为Json化的字符串 +-- @param _str @string 输入的字符串 +-- @return @boolean true: json table string +local function IsJsonTable(_str) + return type(_str) == 'string' and string.endswith(_str, 'JSON') and string.startswith(_str, 'JSON') +end + +--- 处理Handler的传入参数 +--@param variable args +--@return variable args +local function ArgsAux(...) + local _s = {...} + for k, v in pairs(_s) do + if IsJsonTable(v) then + local json = string.sub(v, 5, -5) + _s[k] = LuaJsonUtil:decode(json) + end + end + return table.unpack(_s) +end + +--- 遍历所有的events,找到module中对应名称的handler,建立Connect +-- @param _eventFolder 事件所在的节点folder +-- @param _module 模块 +-- @param _this module的self指针,用于闭包 +function EventUtil.LinkConnects(_eventFolder, _module, _this) + assert( + _eventFolder and _module and _this, + string.format('[EventUtil] 参数有空值: %s, %s, %s', _eventFolder, _module, _this) + ) + local events = _eventFolder:GetChildren() + for _, evt in pairs(events) do + if string.endswith(evt.Name, 'Event') then + local handler = _module[evt.Name .. 'Handler'] + if handler ~= nil then + -- print('[EventUtil]', _eventFolder, _module, evt) + evt:Connect( + function(...) + handler(_this, ArgsAux(...)) + end + ) + end + end + end +end + +return EventUtil diff --git a/Code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua new file mode 100644 index 0000000..f5c4474 --- /dev/null +++ b/Code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua @@ -0,0 +1,26 @@ +--- 全局函数的定义 +--- @module GlobalFunc Defines +--- @copyright Lilith Games, Avatar Team +--- @author Sid Zhang +local GlobalFunc = {} + +--- 埋点上传日志 +--- @param _tableName string 表名 +function GlobalFunc.UploadLogs(_tableName, ...) + local args = {...} + if localPlayer then + pcall( + function() + TrackService.CloudLogFromClient({_tableName, table.unpack(args)}) + end + ) + else + pcall( + function() + TrackService.CloudLogFromServer({_tableName, table.unpack(args)}) + end + ) + end +end + +return GlobalFunc diff --git a/Code/['World']['Global']['Utility']['LinkedListModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['LinkedListModule'].ModuleScript.lua new file mode 100644 index 0000000..dc7fca4 --- /dev/null +++ b/Code/['World']['Global']['Utility']['LinkedListModule'].ModuleScript.lua @@ -0,0 +1,444 @@ +--- C# 双向链表 +-- @module C# doubly linked list implemented with lua +-- @copyright Lilith Games, Avatar Team +-- @author Bruce Chen +-- @see https://wiki.lilithgames.com/x/7yRZAg +-- @see https://github.com/BruceCheng1995/LuaLinkedList + +local LinkedList = {} +local LinkedNode = {} +LinkedNode.__index = LinkedNode + +local NativePrint = print +local EmptuFunc = function() +end +--是否开放内部日志 +function LinkedList:EnableLog(_enable) + if _enable then + print = NativePrint + else + print = EmptuFunc + end +end +LinkedList:EnableLog(false) +--新建节点 +function LinkedNode:new(value, list) + local o = {} + setmetatable(o, self) + o.List = list + o.Next = nil + o.Prev = nil + o.Value = value + return o +end +--克隆这个节点 +function LinkedNode:Clone() + return LinkedNode:new(self.Value, nil) +end +--节点失效 +function LinkedNode:Invalidate() + self.Next = nil + self.Prev = nil + self.List = nil +end +--打印 +function LinkedNode:tostring() + return tostring(self.Value) +end +LinkedNode.__tostring = LinkedNode.tostring + +--验证新节点是否是自由节点 +function LinkedList:ValidateNewNode(node) + if not node then + return false + end + --assert(LinkedNode:include(node),"instance of LinkedNode needed.") + if node.List ~= nil then + return false + end + return true +end + +--验证该节点是否是属于该表 +function LinkedList:ValidateNode(node) + if not node then + return false + end + --assert(LinkedNode:include(node),"instance of LinkedNode needed.") + if node.List ~= self then + return false + end + return true +end + +--将节点插入到node节点之前(list:链表,node:插在这个节点前面,newnode:被插入的节点) +local function InternalInsertNodeBefore(list, node, newnode) + newnode.Next = node + newnode.Prev = node.Prev + node.Prev.Next = newnode + node.Prev = newnode + list.Count = list.Count + 1 +end + +--将节点插入到一个空链表之前(list:链表,newnode:被插入的节点) +local function InternalInsertNodeToEmptyList(list, newnode) + newnode.Next = newnode + newnode.Prev = newnode + list.First = newnode + list.Count = list.Count + 1 +end + +--移除链表中的节点(list:链表,node:被删除的节点) +local function InternalRemoveNode(list, node) + if node.Next == node then + list.First = nil + else + node.Next.Prev = node.Prev + node.Prev.Next = node.Next + if list.First == node then + list.First = node.Next + end + end + node:Invalidate() + list.Count = list.Count - 1 +end + +--新建双向链表 +function LinkedList:new(tab) + local o = {} + setmetatable(o, self) + o.Count = 0 + o.First = nil + if type(tab) == 'table' then + for _, v in pairs(tab) do + o:AddLast(v) + end + end + return o +end + +--Add Value +--在尾部添加值(若传入值是表,则遍历表,并将所有值添加到尾部) +function LinkedList:Add(value) + if type(value) == 'table' then + for _, v in pairs(value) do + self:AddLast(v) + end + else + self:AddLast(value) + end +end + +--在尾部添加值 +function LinkedList:AddLast(value) + local newnode = LinkedNode:new(value, self) + if not self.First then + InternalInsertNodeToEmptyList(self, newnode) + else + InternalInsertNodeBefore(self, self.First, newnode) + end + return newnode +end + +--在头部添加值 +function LinkedList:AddFirst(value) + local newnode = LinkedNode:new(value, self) + if not self.First then + InternalInsertNodeToEmptyList(self, newnode) + else + InternalInsertNodeBefore(self, self.First, newnode) + self.First = newnode + end + return newnode +end + +--在指定节点后面添加值(node:插入在这个节点后,value:被插入的值) +function LinkedList:AddAfter(node, value) + if not self:ValidateNewNode(node) then + return + end + local newnode = LinkedNode:new(value, self) + InternalInsertNodeBefore(self, node.Next, newnode) + return newnode +end + +--在指定节点前面添加值(node:插入在这个节点前,value:被插入的值) +function LinkedList:AddBefore(node, value) + if not self:ValidateNode(node) then + return + end + local newnode = LinkedNode:new(value, self) + InternalInsertNodeBefore(self, node, newnode) + if node == self.First then + self.First = newnode + end + return newnode +end + +--Add Node +--在头部添加节点 +function LinkedList:AddNodeFirst(node) + if not self:ValidateNewNode(node) then + return + end + if not self.First then + InternalInsertNodeToEmptyList(self, node) + else + InternalInsertNodeBefore(self, self.First, node) + self.First = node + end + node.List = self +end + +--在尾部添加节点 +function LinkedList:AddNodeLast(node) + if not self:ValidateNewNode(node) then + return + end + if not self.First then + InternalInsertNodeToEmptyList(self, node) + else + InternalInsertNodeBefore(self, self.First, node) + end + node.List = self +end + +--在指定节点后面添加值(node:插入在这个节点后,newnode:被插入的节点) +function LinkedList:AddNodeAfter(node, newnode) + if not self:ValidateNode(node) and not self:ValidateNewNode(newnode) then + return + end + InternalInsertNodeBefore(self, node.Next, newnode) + newnode.List = self +end + +--在指定节点后面添加值(node:插入在这个节点前,newnode:被插入的节点) +function LinkedList:AddNodeBefore(node, newnode) + if not self:ValidateNode(node) and not self:ValidateNewNode(newnode) then + return + end + InternalInsertNodeBefore(self, node, newnode) + newnode.List = self + if node ~= self.First then + return + end + self.First = newnode +end + +--Remove +--找到表中的第一个指定值,并删除,返回是否命中 +function LinkedList:Remove(value) + local node = self:Find(value) + if not node then + return false + end + InternalRemoveNode(self, node) + return true +end + +--找到表中的第一个指定节点,并删除,返回是否命中 +function LinkedList:RemoveNode(node) + if not self:ValidateNode(node) then + return + end + InternalRemoveNode(self, node) +end + +--移除头部节点 +function LinkedList:RemoveFirst() + if self.First == nil then + print('[LinkedList] list is empty.') + else + InternalRemoveNode(self, self.First) + end +end + +--移除尾部节点 +function LinkedList:RemoveLast() + if self.First == nil then + print('[LinkedList] list is empty.') + else + InternalRemoveNode(self, self.First.Prev) + end +end + +--Find +--尝试找到表中的第一个指定值,若有则返回这个节点 +function LinkedList:Find(value) + local ptrnode = self.First + if value ~= nil then + while ptrnode.Value ~= value do + ptrnode = ptrnode.Next + if ptrnode == self.First then + goto close1 + end + end + return ptrnode + else + while ptrnode.Value ~= nil do + ptrnode = ptrnode.Next + if ptrnode == self.First then + goto close1 + end + end + return ptrnode + end + ::close1:: + return +end + +--尝试反向找到表中第一个指定值,若有则返回这个节点 +function LinkedList:FindLast(value) + if self.First == nil then + return + end + local prev = self.First.Prev + local ptrnode = prev + if value ~= nil then + while ptrnode.Value ~= value do + ptrnode = ptrnode.Prev + if ptrnode == Prev then + goto close2 + end + end + return ptrnode + else + while ptrnode.Value ~= nil do + ptrnode = ptrnode.Prev + if ptrnode == prev then + goto close2 + end + end + return ptrnode + end + ::close2:: + return +end + +--Other +--清空链表 +function LinkedList:Clear() + local ptrnode = self.First + while ptrnode ~= nil do + local lastnode = ptrnode + ptrnode = ptrnode.Next + lastnode:Invalidate() + end + self.First = nil + self.Count = 0 +end + +--向给定table的指定位置插入数值(tab:被插入表,index:序号) +function LinkedList:CopyTo(tab, index) + assert(type(tab) == 'table', '[LinkedList] bad argument "table"') + assert(index >= 1, '[LinkedList] Index out of range') + local ptrnode = self.First + if ptrnode == nil then + return + end + repeat + table.insert(tab, index, ptrnode.Value) + ptrnode = ptrnode.Next + index = index + 1 + until (ptrnode == self.First) +end + +--将链表中的数据拷贝到新表中,并将这个表输出 +function LinkedList:ToTable() + local tab = {} + self:CopyTo(tab, 1) + return tab +end + +--克隆当前链表,并返回 +function LinkedList:Clone() + local newlist = LinkedList:new() + local ptrnode = self.First + repeat + local clnode = ptrnode:Clone() + newlist:AddNodeLast(clnode) + ptrnode = ptrnode.Next + until (ptrnode == self.First) + return newlist +end + +--检查链表中是否包含指定值 +function LinkedList:Contains(value) + return self:Find(value) and true or false +end + +--将链表反向 +function LinkedList:Reverse() + local tmp + if not self.First then + print('[LinkedList] list is empty') + return + end + self.First = self.First.Prev + for item in self:ipairer() do + tmp = item.Next + item.Next = item.Prev + item.Prev = tmp + end +end + +--返回头部节点 +function LinkedList:GetFirst() + return self.First +end + +--返回尾部节点 +function LinkedList:GetLast() + return self.First ~= nil and self.First.Prev or nil +end + +--返回第index个节点 +function LinkedList:GetNode(index) + if index < 1 or index > self.Count then + print('[LinkedList] Index out of range') + return + end + local ptrnode = self.First.Prev + while index > 0 do + ptrnode = ptrnode.Next + index = index - 1 + end + return ptrnode +end + +--返回链表长度 +function LinkedList:Len() + return self.Count +end + +--返回迭代器 +function LinkedList:ipairer() + local ptrnode = self:GetLast() + local passFirst = false + return function() + if ptrnode then + if ptrnode ~= self:GetLast() or not passFirst then + passFirst = true + ptrnode = ptrnode.Next + return ptrnode + end + end + end +end + +--以文本方式表示此表 +function LinkedList:tostring() + local t = {} + for item in self:ipairer() do + table.insert(t, tostring(item)) + end + return 'LinkedList:{' .. table.concat(t, ',') .. '}' +end + +LinkedList.__index = LinkedList +LinkedList.__tostring = LinkedList.tostring + +return { + list = setmetatable(LinkedList, {__call = LinkedList.new}), + node = setmetatable(LinkedNode, {__call = LinkedNode.new}) +} diff --git a/Code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..c4de8af --- /dev/null +++ b/Code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua @@ -0,0 +1,45 @@ +--- Debug工具 +-- @module Debug utilities +-- @copyright Lilith Games, Avatar Team +-- @author Yuancheng Zhang +local LogUtil = {} + +--- 日志级别枚举 +LogUtil.LevelEnum = { + -- 指出细粒度信息事件对调试应用程序是非常有帮助的 主要用于开发过程中打印一些运行信息 + DEBUG = 1, + -- 消息在粗粒度级别上突出强调应用程序的运行过程 + -- 打印一些你感兴趣的或者重要的信息 这个可以用于生产环境中输出程序运行的一些重要信息 + -- 但是不能滥用 避免打印过多的日志 + INFO = 2, + -- 表明会出现潜在错误的情形 有些信息不是错误信息 但是也要给程序员的一些提示 + -- 指出虽然发生错误事件 但仍然不影响系统的继续运行 + -- 打印错误和异常信息 如果不想输出太多的日志 可以使用这个级别 + ERROR = 3 +} + +--- 日志级别 +LogUtil.level = LogUtil.LevelEnum.DEBUG + +--- 开关 +LogUtil.debugMode = true + +function LogUtil.Test(...) + if LogUtil.debugMode and LogUtil.level <= LogUtil.LevelEnum.DEBUG then + print('[TEST]', ...) + end +end + +function LogUtil.Debug(...) + if LogUtil.debugMode and LogUtil.level <= LogUtil.LevelEnum.DEBUG then + print('[DEBUG]', ...) + end +end + +function LogUtil.Info(...) + if LogUtil.debugMode and LogUtil.level <= LogUtil.LevelEnum.INFO then + print('[INFO]', ...) + end +end + +return LogUtil diff --git a/Code/['World']['Global']['Utility']['LuaJsonUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['LuaJsonUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..9c97e13 --- /dev/null +++ b/Code/['World']['Global']['Utility']['LuaJsonUtilModule'].ModuleScript.lua @@ -0,0 +1,1042 @@ +--- -*- coding: utf-8 -*- +--- +--- Simple JSON encoding and decoding in pure Lua. +--- +--- Copyright 2010-2014 Jeffrey Friedl +--- http://regex.info/blog/ +--- +--- Latest version: http://regex.info/blog/lua/json +--- +--- This code is released under a Creative Commons CC-BY "Attribution" License: +--- http://creativecommons.org/licenses/by/3.0/deed.en_US +--- +--- It can be used for any purpose so long as the copyright notice above, +--- the web-page links above, and the 'AUTHOR_NOTE' string below are +--- maintained. Enjoy. +--- +local VERSION = 20141223.14 --- version history at end of file +local AUTHOR_NOTE = '-[ JSON.lua package by Jeffrey Friedl (http://regex.info/blog/lua/json) version 20141223.14 ]-' + +--- +--- The 'AUTHOR_NOTE' variable exists so that information about the source +--- of the package is maintained even in compiled versions. It's also +--- included in OBJDEF below mostly to quiet warnings about unused variables. +--- +---@module LuaJson +local OBJDEF = { + VERSION = VERSION, + AUTHOR_NOTE = AUTHOR_NOTE +} + +--- +--- Simple JSON encoding and decoding in pure Lua. +--- http://www.json.org/ +--- +-- +-- JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines +-- +-- local lua_value = JSON:decode(raw_json_text) +-- +-- local raw_json_text = JSON:encode(lua_table_or_value) +-- local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability +-- +-- +-- +-- DECODING (from a JSON string to a Lua table) +-- +-- +-- JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines +-- +-- local lua_value = JSON:decode(raw_json_text) +-- +-- If the JSON text is for an object or an array, e.g. +-- { "what": "books", "count": 3 } +-- or +-- [ "Larry", "Curly", "Moe" ] +-- +-- the result is a Lua table, e.g. +-- { what = "books", count = 3 } +-- or +-- { "Larry", "Curly", "Moe" } +-- +-- +-- The encode and decode routines accept an optional second argument, +-- "etc", which is not used during encoding or decoding, but upon error +-- is passed along to error handlers. It can be of any type (including nil). +-- +-- +-- +-- ERROR HANDLING +-- +-- With most errors during decoding, this code calls +-- +-- JSON:onDecodeError(message, text, location, etc) +-- +-- with a message about the error, and if known, the JSON text being +-- parsed and the byte count where the problem was discovered. You can +-- replace the default JSON:onDecodeError() with your own function. +-- +-- The default onDecodeError() merely augments the message with data +-- about the text and the location if known (and if a second 'etc' +-- argument had been provided to decode(), its value is tacked onto the +-- message as well), and then calls JSON.assert(), which itself defaults +-- to Lua's built-in assert(), and can also be overridden. +-- +-- For example, in an Adobe Lightroom plugin, you might use something like +-- +-- function JSON:onDecodeError(message, text, location, etc) +-- LrErrors.throwUserError("Internal Error: invalid JSON data") +-- end +-- +-- or even just +-- +-- function JSON.assert(message) +-- LrErrors.throwUserError("Internal Error: " .. message) +-- end +-- +-- If JSON:decode() is passed a nil, this is called instead: +-- +-- JSON:onDecodeOfNilError(message, nil, nil, etc) +-- +-- and if JSON:decode() is passed HTML instead of JSON, this is called: +-- +-- JSON:onDecodeOfHTMLError(message, text, nil, etc) +-- +-- The use of the fourth 'etc' argument allows stronger coordination +-- between decoding and error reporting, especially when you provide your +-- own error-handling routines. Continuing with the the Adobe Lightroom +-- plugin example: +-- +-- function JSON:onDecodeError(message, text, location, etc) +-- local note = "Internal Error: invalid JSON data" +-- if type(etc) = 'table' and etc.photo then +-- note = note .. " while processing for " .. etc.photo:getFormattedMetadata('fileName') +-- end +-- LrErrors.throwUserError(note) +-- end +-- +-- : +-- : +-- +-- for i, photo in ipairs(photosToProcess) do +-- : +-- : +-- local data = JSON:decode(someJsonText, { photo = photo }) +-- : +-- : +-- end +-- +-- +-- +-- +-- +-- DECODING AND STRICT TYPES +-- +-- Because both JSON objects and JSON arrays are converted to Lua tables, +-- it's not normally possible to tell which original JSON type a +-- particular Lua table was derived from, or guarantee decode-encode +-- round-trip equivalency. +-- +-- However, if you enable strictTypes, e.g. +-- +-- JSON = assert(loadfile "JSON.lua")() --load the routines +-- JSON.strictTypes = true +-- +-- then the Lua table resulting from the decoding of a JSON object or +-- JSON array is marked via Lua metatable, so that when re-encoded with +-- JSON:encode() it ends up as the appropriate JSON type. +-- +-- (This is not the default because other routines may not work well with +-- tables that have a metatable set, for example, Lightroom API calls.) +-- +-- +-- ENCODING (from a lua table to a JSON string) +-- +-- JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines +-- +-- local raw_json_text = JSON:encode(lua_table_or_value) +-- local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability +-- local custom_pretty = JSON:encode(lua_table_or_value, etc, { pretty = true, indent = "| ", align_keys = false }) +-- +-- On error during encoding, this code calls: +-- +-- JSON:onEncodeError(message, etc) +-- +-- which you can override in your local JSON object. +-- +-- The 'etc' in the error call is the second argument to encode() +-- and encode_pretty(), or nil if it wasn't provided. +-- +-- +-- PRETTY-PRINTING +-- +-- An optional third argument, a table of options, allows a bit of +-- configuration about how the encoding takes place: +-- +-- pretty = JSON:encode(val, etc, { +-- pretty = true, -- if false, no other options matter +-- indent = " ", -- this provides for a three-space indent per nesting level +-- align_keys = false, -- see below +-- }) +-- +-- encode() and encode_pretty() are identical except that encode_pretty() +-- provides a default options table if none given in the call: +-- +-- { pretty = true, align_keys = false, indent = " " } +-- +-- For example, if +-- +-- JSON:encode(data) +-- +-- produces: +-- +-- {"city":"Kyoto","climate":{"avg_temp":16,"humidity":"high","snowfall":"minimal"},"country":"Japan","wards":11} +-- +-- then +-- +-- JSON:encode_pretty(data) +-- +-- produces: +-- +-- { +-- "city": "Kyoto", +-- "climate": { +-- "avg_temp": 16, +-- "humidity": "high", +-- "snowfall": "minimal" +-- }, +-- "country": "Japan", +-- "wards": 11 +-- } +-- +-- The following three lines return identical results: +-- JSON:encode_pretty(data) +-- JSON:encode_pretty(data, nil, { pretty = true, align_keys = false, indent = " " }) +-- JSON:encode (data, nil, { pretty = true, align_keys = false, indent = " " }) +-- +-- An example of setting your own indent string: +-- +-- JSON:encode_pretty(data, nil, { pretty = true, indent = "| " }) +-- +-- produces: +-- +-- { +-- | "city": "Kyoto", +-- | "climate": { +-- | | "avg_temp": 16, +-- | | "humidity": "high", +-- | | "snowfall": "minimal" +-- | }, +-- | "country": "Japan", +-- | "wards": 11 +-- } +-- +-- An example of setting align_keys to true: +-- +-- JSON:encode_pretty(data, nil, { pretty = true, indent = " ", align_keys = true }) +-- +-- produces: +-- +-- { +-- "city": "Kyoto", +-- "climate": { +-- "avg_temp": 16, +-- "humidity": "high", +-- "snowfall": "minimal" +-- }, +-- "country": "Japan", +-- "wards": 11 +-- } +-- +-- which I must admit is kinda ugly, sorry. This was the default for +-- encode_pretty() prior to version 20141223.14. +-- +-- +-- AMBIGUOUS SITUATIONS DURING THE ENCODING +-- +-- During the encode, if a Lua table being encoded contains both string +-- and numeric keys, it fits neither JSON's idea of an object, nor its +-- idea of an array. To get around this, when any string key exists (or +-- when non-positive numeric keys exist), numeric keys are converted to +-- strings. +-- +-- For example, +-- JSON:encode({ "one", "two", "three", SOMESTRING = "some string" })) +-- produces the JSON object +-- {"1":"one","2":"two","3":"three","SOMESTRING":"some string"} +-- +-- To prohibit this conversion and instead make it an error condition, set +-- JSON.noKeyConversion = true +-- + +-- +-- SUMMARY OF METHODS YOU CAN OVERRIDE IN YOUR LOCAL LUA JSON OBJECT +-- +-- assert +-- onDecodeError +-- onDecodeOfNilError +-- onDecodeOfHTMLError +-- onEncodeError +-- +-- If you want to create a separate Lua JSON object with its own error handlers, +-- you can reload JSON.lua or use the :new() method. +-- +--------------------------------------------------------------------------- + +local default_pretty_indent = ' ' +local default_pretty_options = {pretty = true, align_keys = false, indent = default_pretty_indent} + +local isArray = { + __tostring = function() + return 'JSON array' + end +} +isArray.__index = isArray +local isObject = { + __tostring = function() + return 'JSON object' + end +} +isObject.__index = isObject + +function OBJDEF:newArray(tbl) + return setmetatable(tbl or {}, isArray) +end + +function OBJDEF:newObject(tbl) + return setmetatable(tbl or {}, isObject) +end + +local function unicode_codepoint_as_utf8(codepoint) + -- + -- codepoint is a number + -- + if codepoint <= 127 then + return string.char(codepoint) + elseif codepoint <= 2047 then + -- + -- 110yyyxx 10xxxxxx <-- useful notation from http://en.wikipedia.org/wiki/Utf8 + -- + local highpart = math.floor(codepoint / 0x40) + local lowpart = codepoint - (0x40 * highpart) + return string.char(0xC0 + highpart, 0x80 + lowpart) + elseif codepoint <= 65535 then + -- + -- 1110yyyy 10yyyyxx 10xxxxxx + -- + local highpart = math.floor(codepoint / 0x1000) + local remainder = codepoint - 0x1000 * highpart + local midpart = math.floor(remainder / 0x40) + local lowpart = remainder - 0x40 * midpart + + highpart = 0xE0 + highpart + midpart = 0x80 + midpart + lowpart = 0x80 + lowpart + + -- + -- Check for an invalid character (thanks Andy R. at Adobe). + -- See table 3.7, page 93, in http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#G28070 + -- + if + (highpart == 0xE0 and midpart < 0xA0) or (highpart == 0xED and midpart > 0x9F) or + (highpart == 0xF0 and midpart < 0x90) or + (highpart == 0xF4 and midpart > 0x8F) + then + return '?' + else + return string.char(highpart, midpart, lowpart) + end + else + -- + -- 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx + -- + local highpart = math.floor(codepoint / 0x40000) + local remainder = codepoint - 0x40000 * highpart + local midA = math.floor(remainder / 0x1000) + remainder = remainder - 0x1000 * midA + local midB = math.floor(remainder / 0x40) + local lowpart = remainder - 0x40 * midB + + return string.char(0xF0 + highpart, 0x80 + midA, 0x80 + midB, 0x80 + lowpart) + end +end + +function OBJDEF:onDecodeError(message, text, location, etc) + if text then + if location then + message = string.format('%s at char %d of: %s', message, location, text) + else + message = string.format('%s: %s', message, text) + end + end + + if etc ~= nil then + message = message .. ' (' .. OBJDEF:encode(etc) .. ')' + end + + if self.assert then + self.assert(false, message) + else + assert(false, message) + end +end + +OBJDEF.onDecodeOfNilError = OBJDEF.onDecodeError +OBJDEF.onDecodeOfHTMLError = OBJDEF.onDecodeError + +function OBJDEF:onEncodeError(message, etc) + if etc ~= nil then + message = message .. ' (' .. OBJDEF:encode(etc) .. ')' + end + + if self.assert then + self.assert(false, message) + else + assert(false, message) + end +end + +local function grok_number(self, text, start, etc) + -- + -- Grab the integer part + -- + local integer_part = text:match('^-?[1-9]%d*', start) or text:match('^-?0', start) + + if not integer_part then + self:onDecodeError('expected number', text, start, etc) + end + + local i = start + integer_part:len() + + -- + -- Grab an optional decimal part + -- + local decimal_part = text:match('^%.%d+', i) or '' + + i = i + decimal_part:len() + + -- + -- Grab an optional exponential part + -- + local exponent_part = text:match('^[eE][-+]?%d+', i) or '' + + i = i + exponent_part:len() + + local full_number_text = integer_part .. decimal_part .. exponent_part + local as_number = tonumber(full_number_text) + + if not as_number then + self:onDecodeError('bad number', text, start, etc) + end + + return as_number, i +end + +local function grok_string(self, text, start, etc) + if text:sub(start, start) ~= '"' then + self:onDecodeError("expected string's opening quote", text, start, etc) + end + + local i = start + 1 -- +1 to bypass the initial quote + local text_len = text:len() + local VALUE = '' + while i <= text_len do + local c = text:sub(i, i) + if c == '"' then + return VALUE, i + 1 + end + if c ~= '\\' then + VALUE = VALUE .. c + i = i + 1 + elseif text:match('^\\b', i) then + VALUE = VALUE .. '\b' + i = i + 2 + elseif text:match('^\\f', i) then + VALUE = VALUE .. '\f' + i = i + 2 + elseif text:match('^\\n', i) then + VALUE = VALUE .. '\n' + i = i + 2 + elseif text:match('^\\r', i) then + VALUE = VALUE .. '\r' + i = i + 2 + elseif text:match('^\\t', i) then + VALUE = VALUE .. '\t' + i = i + 2 + else + local hex = + text:match( + '^\\u([0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', + i + ) + if hex then + i = i + 6 -- bypass what we just read + + -- We have a Unicode codepoint. It could be standalone, or if in the proper range and + -- followed by another in a specific range, it'll be a two-code surrogate pair. + local codepoint = tonumber(hex, 16) + if codepoint >= 0xD800 and codepoint <= 0xDBFF then + -- it's a hi surrogate... see whether we have a following low + local lo_surrogate = + text:match('^\\u([dD][cdefCDEF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i) + if lo_surrogate then + i = i + 6 -- bypass the low surrogate we just read + codepoint = 0x2400 + (codepoint - 0xD800) * 0x400 + tonumber(lo_surrogate, 16) + else + -- not a proper low, so we'll just leave the first codepoint as is and spit it out. + end + end + VALUE = VALUE .. unicode_codepoint_as_utf8(codepoint) + else + -- just pass through what's escaped + VALUE = VALUE .. text:match('^\\(.)', i) + i = i + 2 + end + end + end + + self:onDecodeError('unclosed string', text, start, etc) +end + +local function skip_whitespace(text, start) + local _, match_end = text:find('^[ \n\r\t]+', start) -- [http://www.ietf.org/rfc/rfc4627.txt] Section 2 + if match_end then + return match_end + 1 + else + return start + end +end + +local grok_one -- assigned later + +local function grok_object(self, text, start, etc) + if text:sub(start, start) ~= '{' then + self:onDecodeError("expected '{'", text, start, etc) + end + + local i = skip_whitespace(text, start + 1) -- +1 to skip the '{' + + local VALUE = self.strictTypes and self:newObject {} or {} + + if text:sub(i, i) == '}' then + return VALUE, i + 1 + end + local text_len = text:len() + while i <= text_len do + local key, new_i = grok_string(self, text, i, etc) + + i = skip_whitespace(text, new_i) + + if text:sub(i, i) ~= ':' then + self:onDecodeError('expected colon', text, i, etc) + end + + i = skip_whitespace(text, i + 1) + + local new_val, new_i = grok_one(self, text, i) + + VALUE[key] = new_val + + -- + -- Expect now either '}' to end things, or a ',' to allow us to continue. + -- + i = skip_whitespace(text, new_i) + + local c = text:sub(i, i) + + if c == '}' then + return VALUE, i + 1 + end + + if text:sub(i, i) ~= ',' then + self:onDecodeError("expected comma or '}'", text, i, etc) + end + + i = skip_whitespace(text, i + 1) + end + + self:onDecodeError("unclosed '{'", text, start, etc) +end + +local function grok_array(self, text, start, etc) + if text:sub(start, start) ~= '[' then + self:onDecodeError("expected '['", text, start, etc) + end + + local i = skip_whitespace(text, start + 1) -- +1 to skip the '[' + local VALUE = self.strictTypes and self:newArray {} or {} + if text:sub(i, i) == ']' then + return VALUE, i + 1 + end + + local VALUE_INDEX = 1 + + local text_len = text:len() + while i <= text_len do + local val, new_i = grok_one(self, text, i) + + -- can't table.insert(VALUE, val) here because it's a no-op if val is nil + VALUE[VALUE_INDEX] = val + VALUE_INDEX = VALUE_INDEX + 1 + + i = skip_whitespace(text, new_i) + + -- + -- Expect now either ']' to end things, or a ',' to allow us to continue. + -- + local c = text:sub(i, i) + if c == ']' then + return VALUE, i + 1 + end + if text:sub(i, i) ~= ',' then + self:onDecodeError("expected comma or '['", text, i, etc) + end + i = skip_whitespace(text, i + 1) + end + self:onDecodeError("unclosed '['", text, start, etc) +end + +grok_one = function(self, text, start, etc) + -- Skip any whitespace + start = skip_whitespace(text, start) + + if start > text:len() then + self:onDecodeError('unexpected end of string', text, nil, etc) + end + + if text:find('^"', start) then + return grok_string(self, text, start, etc) + elseif text:find('^[-0123456789 ]', start) then + return grok_number(self, text, start, etc) + elseif text:find('^%{', start) then + return grok_object(self, text, start, etc) + elseif text:find('^%[', start) then + return grok_array(self, text, start, etc) + elseif text:find('^true', start) then + return true, start + 4 + elseif text:find('^false', start) then + return false, start + 5 + elseif text:find('^null', start) then + return nil, start + 4 + else + self:onDecodeError("can't parse JSON", text, start, etc) + end +end + +---@param text string +function OBJDEF:decode(text, etc) + if type(self) ~= 'table' or self.__index ~= OBJDEF then + OBJDEF:onDecodeError('JSON:decode must be called in method format', nil, nil, etc) + end + + if text == nil then + self:onDecodeOfNilError(string.format('nil passed to JSON:decode()'), nil, nil, etc) + elseif type(text) ~= 'string' then + self:onDecodeError( + string.format('expected string argument to JSON:decode(), got %s', type(text)), + nil, + nil, + etc + ) + end + + if text:match('^%s*$') then + return nil + end + + if text:match('^%s*<') then + -- Can't be JSON... we'll assume it's HTML + self:onDecodeOfHTMLError(string.format('html passed to JSON:decode()'), text, nil, etc) + end + + -- + -- Ensure that it's not UTF-32 or UTF-16. + -- Those are perfectly valid encodings for JSON (as per RFC 4627 section 3), + -- but this package can't handle them. + -- + if text:sub(1, 1):byte() == 0 or (text:len() >= 2 and text:sub(2, 2):byte() == 0) then + self:onDecodeError('JSON package groks only UTF-8, sorry', text, nil, etc) + end + + local success, value = pcall(grok_one, self, text, 1, etc) + + if success then + return value + else + -- if JSON:onDecodeError() didn't abort out of the pcall, we'll have received the error message here as "value", so pass it along as an assert. + if self.assert then + self.assert(false, value) + else + assert(false, value) + end + -- and if we're still here, return a nil and throw the error message on as a second arg + return nil, value + end +end + +local function backslash_replacement_function(c) + if c == '\n' then + return '\\n' + elseif c == '\r' then + return '\\r' + elseif c == '\t' then + return '\\t' + elseif c == '\b' then + return '\\b' + elseif c == '\f' then + return '\\f' + elseif c == '"' then + return '\\"' + elseif c == '\\' then + return '\\\\' + else + return string.format('\\u%04x', c:byte()) + end +end + +local chars_to_be_escaped_in_JSON_string = + '[' .. + '"' .. -- class sub-pattern to match a double quote + '%\\' .. -- class sub-pattern to match a backslash + '%z' .. -- class sub-pattern to match a null + '\001' .. + '-' .. + '\031' .. -- class sub-pattern to match control characters + ']' + +local function json_string_literal(value) + local newval = value:gsub(chars_to_be_escaped_in_JSON_string, backslash_replacement_function) + return '"' .. newval .. '"' +end + +local function object_or_array(self, T, etc) + -- + -- We need to inspect all the keys... if there are any strings, we'll convert to a JSON + -- object. If there are only numbers, it's a JSON array. + -- + -- If we'll be converting to a JSON object, we'll want to sort the keys so that the + -- end result is deterministic. + -- + local string_keys = {} + local number_keys = {} + local number_keys_must_be_strings = false + local maximum_number_key + + for key in pairs(T) do + if type(key) == 'string' then + table.insert(string_keys, key) + elseif type(key) == 'number' then + table.insert(number_keys, key) + if key <= 0 or key >= math.huge then + number_keys_must_be_strings = true + elseif not maximum_number_key or key > maximum_number_key then + maximum_number_key = key + end + else + self:onEncodeError("can't encode table with a key of type " .. type(key), etc) + end + end + + if #string_keys == 0 and not number_keys_must_be_strings then + -- + -- An empty table, or a numeric-only array + -- + if #number_keys > 0 then + return nil, maximum_number_key -- an array + elseif tostring(T) == 'JSON array' then + return nil + elseif tostring(T) == 'JSON object' then + return {} + else + -- have to guess, so we'll pick array, since empty arrays are likely more common than empty objects + return nil + end + end + + table.sort(string_keys) + + local map + if #number_keys > 0 then + -- + -- If we're here then we have either mixed string/number keys, or numbers inappropriate for a JSON array + -- It's not ideal, but we'll turn the numbers into strings so that we can at least create a JSON object. + -- + + if self.noKeyConversion then + self:onEncodeError('a table with both numeric and string keys could be an object or array; aborting', etc) + end + + -- + -- Have to make a shallow copy of the source table so we can remap the numeric keys to be strings + -- + map = {} + for key, val in pairs(T) do + map[key] = val + end + + table.sort(number_keys) + + -- + -- Throw numeric keys in there as strings + -- + for _, number_key in ipairs(number_keys) do + local string_key = tostring(number_key) + if map[string_key] == nil then + table.insert(string_keys, string_key) + map[string_key] = T[number_key] + else + self:onEncodeError( + 'conflict converting table with mixed-type keys into a JSON object: key ' .. + number_key .. ' exists both as a string and a number.', + etc + ) + end + end + end + + return string_keys, nil, map +end + +-- +-- Encode +-- +-- 'options' is nil, or a table with possible keys: +-- pretty -- if true, return a pretty-printed version +-- indent -- a string (usually of spaces) used to indent each nested level +-- align_keys -- if true, align all the keys when formatting a table +-- +local encode_value -- must predeclare because it calls itself +function encode_value(self, value, parents, etc, options, indent) + if value == nil then + return 'null' + elseif type(value) == 'string' then + return json_string_literal(value) + elseif type(value) == 'number' then + if value ~= value then + -- + -- NaN (Not a Number). + -- JSON has no NaN, so we have to fudge the best we can. This should really be a package option. + -- + return 'null' + elseif value >= math.huge then + -- + -- Positive infinity. JSON has no INF, so we have to fudge the best we can. This should + -- really be a package option. Note: at least with some implementations, positive infinity + -- is both ">= math.huge" and "<= -math.huge", which makes no sense but that's how it is. + -- Negative infinity is properly "<= -math.huge". So, we must be sure to check the ">=" + -- case first. + -- + return '1e+9999' + elseif value <= -math.huge then + -- + -- Negative infinity. + -- JSON has no INF, so we have to fudge the best we can. This should really be a package option. + -- + return '-1e+9999' + else + return tostring(value) + end + elseif type(value) == 'boolean' then + return tostring(value) + elseif type(value) ~= 'table' then + self:onEncodeError("can't convert " .. type(value) .. ' to JSON', etc) + else + -- + -- A table to be converted to either a JSON object or array. + -- + local T = value + + if type(options) ~= 'table' then + options = {} + end + if type(indent) ~= 'string' then + indent = '' + end + + if parents[T] then + self:onEncodeError('table ' .. tostring(T) .. ' is a child of itself', etc) + else + parents[T] = true + end + + local result_value + + local object_keys, maximum_number_key, map = object_or_array(self, T, etc) + if maximum_number_key then + -- + -- An array... + -- + local ITEMS = {} + for i = 1, maximum_number_key do + table.insert(ITEMS, encode_value(self, T[i], parents, etc, options, indent)) + end + + if options.pretty then + result_value = '[ ' .. table.concat(ITEMS, ', ') .. ' ]' + else + result_value = '[' .. table.concat(ITEMS, ',') .. ']' + end + elseif object_keys then + -- + -- An object + -- + local TT = map or T + + if options.pretty then + local KEYS = {} + local max_key_length = 0 + for _, key in ipairs(object_keys) do + local encoded = encode_value(self, tostring(key), parents, etc, options, indent) + if options.align_keys then + max_key_length = math.max(max_key_length, #encoded) + end + table.insert(KEYS, encoded) + end + local key_indent = indent .. tostring(options.indent or '') + local subtable_indent = + key_indent .. string.rep(' ', max_key_length) .. (options.align_keys and ' ' or '') + local FORMAT = '%s%' .. string.format('%d', max_key_length) .. 's: %s' + + local COMBINED_PARTS = {} + for i, key in ipairs(object_keys) do + local encoded_val = encode_value(self, TT[key], parents, etc, options, subtable_indent) + table.insert(COMBINED_PARTS, string.format(FORMAT, key_indent, KEYS[i], encoded_val)) + end + result_value = '{\n' .. table.concat(COMBINED_PARTS, ',\n') .. '\n' .. indent .. '}' + else + local PARTS = {} + for _, key in ipairs(object_keys) do + local encoded_val = encode_value(self, TT[key], parents, etc, options, indent) + local encoded_key = encode_value(self, tostring(key), parents, etc, options, indent) + table.insert(PARTS, string.format('%s:%s', encoded_key, encoded_val)) + end + result_value = '{' .. table.concat(PARTS, ',') .. '}' + end + else + -- + -- An empty array/object... we'll treat it as an array, though it should really be an option + -- + result_value = '[]' + end + + parents[T] = false + return result_value + end +end + +function OBJDEF:encode(value, etc, options) + if type(self) ~= 'table' or self.__index ~= OBJDEF then + OBJDEF:onEncodeError('JSON:encode must be called in method format', etc) + end + return encode_value(self, value, {}, etc, options or nil) +end + +function OBJDEF:encode_pretty(value, etc, options) + if type(self) ~= 'table' or self.__index ~= OBJDEF then + OBJDEF:onEncodeError('JSON:encode_pretty must be called in method format', etc) + end + return encode_value(self, value, {}, etc, options or default_pretty_options) +end + +function OBJDEF.__tostring() + return 'JSON encode/decode package' +end + +OBJDEF.__index = OBJDEF + +function OBJDEF:new(args) + local new = {} + + if args then + for key, val in pairs(args) do + new[key] = val + end + end + + return setmetatable(new, OBJDEF) +end + +return OBJDEF:new() + +-- +-- Version history: +-- +-- 20141223.14 The encode_pretty() routine produced fine results for small datasets, but isn't really +-- appropriate for anything large, so with help from Alex Aulbach I've made the encode routines +-- more flexible, and changed the default encode_pretty() to be more generally useful. +-- +-- Added a third 'options' argument to the encode() and encode_pretty() routines, to control +-- how the encoding takes place. +-- +-- Updated docs to add assert() call to the loadfile() line, just as good practice so that +-- if there is a problem loading JSON.lua, the appropriate error message will percolate up. +-- +-- 20140920.13 Put back (in a way that doesn't cause warnings about unused variables) the author string, +-- so that the source of the package, and its version number, are visible in compiled copies. +-- +-- 20140911.12 Minor lua cleanup. +-- Fixed internal reference to 'JSON.noKeyConversion' to reference 'self' instead of 'JSON'. +-- (Thanks to SmugMug's David Parry for these.) +-- +-- 20140418.11 JSON nulls embedded within an array were being ignored, such that +-- ["1",null,null,null,null,null,"seven"], +-- would return +-- {1,"seven"} +-- It's now fixed to properly return +-- {1, nil, nil, nil, nil, nil, "seven"} +-- Thanks to "haddock" for catching the error. +-- +-- 20140116.10 The user's JSON.assert() wasn't always being used. Thanks to "blue" for the heads up. +-- +-- 20131118.9 Update for Lua 5.3... it seems that tostring(2/1) produces "2.0" instead of "2", +-- and this caused some problems. +-- +-- 20131031.8 Unified the code for encode() and encode_pretty(); they had been stupidly separate, +-- and had of course diverged (encode_pretty didn't get the fixes that encode got, so +-- sometimes produced incorrect results; thanks to Mattie for the heads up). +-- +-- Handle encoding tables with non-positive numeric keys (unlikely, but possible). +-- +-- If a table has both numeric and string keys, or its numeric keys are inappropriate +-- (such as being non-positive or infinite), the numeric keys are turned into +-- string keys appropriate for a JSON object. So, as before, +-- JSON:encode({ "one", "two", "three" }) +-- produces the array +-- ["one","two","three"] +-- but now something with mixed key types like +-- JSON:encode({ "one", "two", "three", SOMESTRING = "some string" })) +-- instead of throwing an error produces an object: +-- {"1":"one","2":"two","3":"three","SOMESTRING":"some string"} +-- +-- To maintain the prior throw-an-error semantics, set +-- JSON.noKeyConversion = true +-- +-- 20131004.7 Release under a Creative Commons CC-BY license, which I should have done from day one, sorry. +-- +-- 20130120.6 Comment update: added a link to the specific page on my blog where this code can +-- be found, so that folks who come across the code outside of my blog can find updates +-- more easily. +-- +-- 20111207.5 Added support for the 'etc' arguments, for better error reporting. +-- +-- 20110731.4 More feedback from David Kolf on how to make the tests for Nan/Infinity system independent. +-- +-- 20110730.3 Incorporated feedback from David Kolf at http://lua-users.org/wiki/JsonModules: +-- +-- * When encoding lua for JSON, Sparse numeric arrays are now handled by +-- spitting out full arrays, such that +-- JSON:encode({"one", "two", [10] = "ten"}) +-- returns +-- ["one","two",null,null,null,null,null,null,null,"ten"] +-- +-- In 20100810.2 and earlier, only up to the first non-null value would have been retained. +-- +-- * When encoding lua for JSON, numeric value NaN gets spit out as null, and infinity as "1+e9999". +-- Version 20100810.2 and earlier created invalid JSON in both cases. +-- +-- * Unicode surrogate pairs are now detected when decoding JSON. +-- +-- 20100810.2 added some checking to ensure that an invalid Unicode character couldn't leak in to the UTF-8 encoding +-- +-- 20100731.1 initial public release +-- diff --git a/Code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..fc900a4 --- /dev/null +++ b/Code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua @@ -0,0 +1,68 @@ +--- 模块工具 +-- @module Module utilities +-- @copyright Lilith Games, Avatar Team +-- @author Yuancheng Zhang + +local ModuleUtil = {} + +--- 加载模块目录 +-- @param _root 模块目录的节点 +-- @param _scope 载入后脚本的作用域 +function ModuleUtil.LoadModules(_root, _scope) + _scope = _scope or _G + assert(_root, '[ModuleUtil] Node does NOT exist!') + local tmp = _root:GetChildren() + for _, v in pairs(tmp) do + name = (v.Name):gsub('Module', '') + -- print('[ModuleUtil] Load: ' .. name) + _scope[name] = require(v) + end +end + +--- 加载XLS表格目录 +-- @param _root 模块目录的节点 +function ModuleUtil.LoadXlsModules(_root, _config) + assert(_root, '[ModuleUtil] Node does NOT exist!') + assert(_config, '[ModuleUtil] Config does NOT exist!') + local tmp = _root:GetChildren() + for _, v in pairs(tmp) do + name = (v.Name):gsub('XlsModule', '') + print('[ModuleUtil] Load: ' .. name) + _config[name] = require(v) + end +end + +--- 加载多个模块目录 +function ModuleUtil.LoadAllModules(...) + local args = table.pack(...) + for i = 1, args.n do + if args[i] then + ModuleUtil.LoadModules(args[i]) + end + end +end + +--- 将有包含特定方法的模块筛选出来,并放在一个table中 +-- @param _root 模块目录的节点 +-- @param @string _fn 方法名 function_name +-- @param @table _list 存放的table +function ModuleUtil.GetModuleListWithFunc(_root, _fn, _list) + assert(_root, '[ModuleUtil] Node does NOT exist!') + assert(not string.isnilorempty(_fn), '[ModuleUtil] Function name is nil or empty!') + assert(_list, '[ModuleUtil] List is NOT initialized!') + local tmp, name = _root:GetChildren() + for _, v in pairs(tmp) do + name = (v.Name):gsub('Module', '') + if _G[name] and _G[name][_fn] and type(_G[name][_fn]) == 'function' then + table.insert(_list, _G[name]) + end + end +end + +--- 新建一个模块实例(ServerBase or ClientBase) +function ModuleUtil.New(_name, _baseClass) + local t = class(_name, _baseClass) + return t, t:GetSelf() +end + +return ModuleUtil diff --git a/Code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..ec3ddaa --- /dev/null +++ b/Code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua @@ -0,0 +1,123 @@ +--- 网路工具/事件工具 +-- @module Network utilities +-- @copyright Lilith Games, Avatar Team +-- @author Sharif Ma, Yuancheng Zhang, Yen Yuan +local NetUtil = {} + +-- 格式化事件参数, Table=>JSON +local FormatArgs + +--! 事件参数校验, true:开启校验 +local valid, ValidateArgs = true + +--! 打印事件日志, true:开启打印 +local showLog, PrintEventLog = false + +local FireEnum = { + SERVER = 1, + CLIENT = 2, + BROADCAST = 3 +} + +--! 外部接口 + +--- 向服务器发送消息 +-- @param @string _eventName 事件的名字(严格对应) +-- @param ... 事件参数 +function NetUtil.Fire_S(_eventName, ...) + ValidateArgs(FireEnum.SERVER, _eventName) + local args = {...} + world.S_Event[_eventName]:Fire(table.unpack(args)) + PrintEventLog(FireEnum.SERVER, _eventName, nil, args) +end + +--- 向指定的玩家发送消息 +-- @param @string _eventName 事件的名字 +-- @param _player 玩家对象 +-- @param ... 事件参数 +function NetUtil.Fire_C(_eventName, _player, ...) + if(_player == nil) then + return + end + ValidateArgs(FireEnum.CLIENT, _eventName, _player) + local args = {...} + _player.C_Event[_eventName]:Fire(table.unpack(args)) + PrintEventLog(FireEnum.CLIENT, _eventName, _player, args) +end + +--- 客户端广播 +-- @param @string _eventName 事件的名字(严格对应) +-- @param ... 事件参数 +function NetUtil.Broadcast(_eventName, ...) + ValidateArgs(FireEnum.BROADCAST, _eventName, ...) + local args = {...} + world.Players:BroadcastEvent(_eventName, table.unpack(args)) + PrintEventLog(FireEnum.BROADCAST, _eventName, nil, args) +end + +--! 私有函数 + +--- 格式化事件参数 +FormatArgs = function(...) + local args = {...} + for k, v in pairs(args) do + if type(v) == 'table' then + args[k] = string.format('JSON%sJSON', LuaJsonUtil:encode(v)) + end + end + return args +end + +--! 辅助功能 + +--- 事件参数校验 +ValidateArgs = + valid and + function(_fireEnum, _eventName, _player) + if _fireEnum == FireEnum.SERVER then + --! Fire_S 检查参数 + assert(not string.isnilorempty(_eventName), '[NetUtil][Fire_S] 事件名为空') + assert(world.S_Event[_eventName], string.format('[NetUtil][Fire_S] 服务器不存在事件: %s', _eventName)) + elseif _fireEnum == FireEnum.CLIENT then + --! Fire_C 检查参数 + assert(not string.isnilorempty(_eventName), '[NetUtil] 事件名为空') + assert( + _player and _player.ClassName == 'PlayerInstance', + string.format('[NetUtil][Fire_C]第2个参数需要是玩家对象, 错误事件: %s', _eventName) + ) + assert( + _player.C_Event[_eventName], + string.format('[NetUtil][Fire_C] 客户端玩家不存在事件: %s, 玩家: %s', _player.Name, _eventName) + ) + elseif _fireEnum == FireEnum.BROADCAST then + --! Broadcase 检查参数 + assert(not string.isnilorempty(_eventName), '[NetUtil][Broadcast] 事件名为空') + end + end or + function() + end + +--- 打印事件日志 +PrintEventLog = showLog and function(_fireEnum, _eventName, _player, _args) + if _fireEnum == FireEnum.SERVER then + --* Fire_S 参数打印 + print(string.format('[NetUtil][服务器] %s, 参数 = %s, %s', _eventName, #_args, table.dump(_args))) + elseif _fireEnum == FireEnum.CLIENT then + --* Fire_C 参数打印 + print( + string.format( + '[NetUtil][客户端] %s, 玩家=%s, 参数 = %s, %s', + _eventName, + _player.Name, + #_args, + table.dump(_args) + ) + ) + elseif _fireEnum == FireEnum.BROADCAST then + --* Broadcase 参数打印 + print(string.format('[NetUtil][客户端][广播] %s, 参数 = %s, %s', _eventName, #_args, table.dump(_args))) + end + end or function() + end + +return NetUtil diff --git a/Code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..b276648 --- /dev/null +++ b/Code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua @@ -0,0 +1,65 @@ +---对象池工具模块 +---@module ObjPoolUtil +-- @copyright Lilith Games, Avatar Team +-- @author Yen Yuan +---@class ObjPoolUtil +local ObjPoolUtil = class('ObjPoolUtil') + +---创建某一个对象的对象池 +---@param _folderName Object 管理的目录 +---@param _objName string 对象的Archetype名 +---@param _maxCount number 对象池最大上限,不填则为100 +---@return ObjPoolUtil +function ObjPoolUtil.static.Newpool(_folderName, _objName, _maxCount) + if _folderName == nil or _objName == nil then + error('[ObjPoolUtil] 管理目录或管理对象为空') + end + if _maxCount == nil then + _maxCount = 100 + end + local realPool = class(_objName .. 'Pool', ObjPoolUtil) + realPool.static.obj = _objName + realPool.static.folder = _folderName + realPool.static.maxCount = _maxCount + realPool.pool = {} + print(string.format('[ObjPoolUtil] 创建了一个%s的对象池,目录为%s', _objName, _folderName)) + return realPool +end + +---从池中创建对象到世界下 +---@param _position Vector3 +---@param _rotation EulerDegree +function ObjPoolUtil:Spawn(_position, _rotation) + local realObj = nil + if #self.pool == 0 then + realObj = world:CreateInstance(self.obj, self.obj, self.folder, _position, _rotation) + if realObj == nil then + error(string.format('[ObjPoolUtil] Archetype下没有名为%s的对象', self.obj)) + return + end + return realObj + else + realObj = self.pool[1] + self.pool[1].Position = _position + self.pool[1].Rotation = _rotation + self.pool[1]:SetActive(true) + table.remove(self.pool, 1) + return realObj + end +end + +---从世界中销毁对象到池中 +---@param _obj Object +function ObjPoolUtil:Despawn(_obj) + if _obj == nil then + error('[ObjPoolUtil] 传入对象为空') + elseif #self.pool > self.maxCount then + error(string.format('[ObjPoolUtil] %s对象池已满,该对象会永久销毁', self.obj)) + _obj:Destroy() + else + table.insert(self.pool, _obj) + _obj:SetActive(false) + end +end + +return ObjPoolUtil diff --git a/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..81b6e87 --- /dev/null +++ b/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua @@ -0,0 +1,65 @@ +--- 音效播放模块 +---@module SoundUtil +---@copyright Lilith Games, Avatar Team +---@author Sharif Ma +---@class SoundUtil +local SoundUtil = {} + +function SoundUtil:Init() + print('[SoundUtil] Init()') + self.SoundPlaying = {} + self.Table_Sound = Config.Sound +end + +---创建一个新音效并播放 +---@param _ID number 音效的ID +---@param _SoundSourceObj Object 音效的挂载物体,不填则为2D音效,挂载在主摄像机上 +function SoundUtil:PlaySound(_ID, _SoundSourceObj) + local Info, _Duration + _SoundSourceObj = _SoundSourceObj or world.CurrentCamera + Info = self.Table_Sound[_ID] + assert(Info, '[SoundUtil] 表中不存在该ID的音效') + _Duration = Info.Duration + local sameSoundPlayingNum = 0 + for k, v in pairs(self.SoundPlaying) do + if v == _ID then + sameSoundPlayingNum = sameSoundPlayingNum + 1 + end + end + if sameSoundPlayingNum > 0 and not Info.CoverPlay then + print(string.format('[SoundUtil] %s音效CoverPlay字段为false,不能覆盖播放', _ID)) + return + end + + local Audio = world:CreateObject('AudioSource', 'Audio_' .. Info.FileName, _SoundSourceObj) + Audio.LocalPosition = Vector3.Zero + Audio.SoundClip = ResourceManager.GetSoundClip('Audio/' .. Info.FileName) + print('[SoundUtil] Audio.SoundClip', Audio.SoundClip) + Audio.Volume = Info.Volume + Audio.MaxDistance = 10 + Audio.MinDistance = 10 + Audio.Loop = Info.IsLoop + Audio:Play() + table.insert(self.SoundPlaying, _ID) + _Duration = _Duration or 1 + invoke( + function() + if Audio then + Audio:Destroy() + end + end, + _Duration + ) + invoke( + function() + for k, v in pairs(self.SoundPlaying) do + if v == _ID then + table.remove(self.SoundPlaying, k) + end + end + end, + _Duration + ) +end + +return SoundUtil diff --git a/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..65d83de --- /dev/null +++ b/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua @@ -0,0 +1,149 @@ +--- 时间管理器模块 +-- @module Module Time Manager +-- @copyright Lilith Games, Avatar Team +-- @author Bingyun Chen, Yuancheng Zhang +-- @see the functions defined by JavaScript syntax + +local TimeUtil = {} + +-- All registered events +local eventList = {} + +-- Current active event list +local activeEvents = {} + +local running = false + +-- Set update delta time +local DELTA_TIME = .05 + +--- Find all registered events to trigger +local function CheckEvents() + -- now = os.time() + local now = Timer.GetTimeMillisecond() + local i, event = 1 + while i <= #eventList do + event = eventList[i] + if event.triggerTime <= now then + table.insert(activeEvents, event) + if event.loop then + event.triggerTime = event.triggerTime + event.delay + i = i + 1 + else + table.remove(eventList, i) + end + else + i = i + 1 + end + end +end + +--- Trigger events +local function TriggerEvents() + local i = 1 + while i <= #activeEvents do + event = activeEvents[i] + invoke(event.func) + table.remove(activeEvents, i) + end +end + +--- Update +local function StartUpdate() + while running do + -- print(os.time()) + CheckEvents() + TriggerEvents() + wait(DELTA_TIME) + end +end + +--- Initialization +function TimeUtil.Init() + TimeUtil.Start() +end + +--- Run Update() +function TimeUtil.Start() + running = true + invoke(StartUpdate) +end + +--- Stop Update() +function TimeUtil.Stop() + running = false +end + +--- Call a function after a specified number of milliseconds, +-- use ClearTimeout() method to prevent the function from running +-- @param _func execution function to call +-- @param _delayTime +-- @return timer id +-- @see https://www.w3schools.com/jsref/met_win_settimeout.asp +function TimeUtil.SetTimeout(_func, _seconds) + assert(_func, '[TimeUtil] TimeUtil.SetTimeout() _func 不能为空') + assert(_seconds >= 0, '[TimeUtil] TimeUtil.SetTimeout() 延迟时间需大于等于0') + if _seconds == 0 then + print('[TimeUtil] TimeUtil.SetTimeout() 事件立即执行') + invoke(_func) + return + end + local id = #eventList + 1 + -- convert to milliseconds + local ms = math.floor(_seconds * 1000) + local timestamp = ms + Timer.GetTimeMillisecond() + table.insert( + eventList, + { + id = id, + func = _func, + delay = ms, + triggerTime = timestamp + } + ) + return id +end + +--- Call a function or evaluates an expression at specified intervals (in milliseconds), +-- the method will continue calling the function until ClearInterval() is called, or the game is over. +-- @param _func execution function to call +-- @param _delayTime +-- @return timer id +-- @see https://www.w3schools.com/jsref/met_win_setinterval.asp +function TimeUtil.SetInterval(_func, _seconds) + assert(_func, '[TimeUtil] TimeUtil.SetInterval() _func 不能为空') + assert(_seconds > 0, '[TimeUtil] TimeUtil.SetInterval() 延迟时间需大于0') + local id = #eventList + 1 + -- convert to milliseconds + local ms = math.floor(_seconds * 1000) + local timestamp = ms + Timer.GetTimeMillisecond() + table.insert( + eventList, + { + id = id, + func = _func, + delay = ms, + triggerTime = timestamp, + loop = true + } + ) + return id +end + +--- Clear a timer set with the SetTimeout() method +-- @param _id timmer id +-- @see https://www.w3schools.com/jsref/met_win_cleartimeout.asp +function TimeUtil.ClearTimeout(_id) + for k, e in pairs(eventList) do + if e.id == _id then + table.remove(eventList, k) + break + end + end +end + +--- Clear a timer set with the SetInterval() method, used as ClearTimeout() +-- @see https://www.w3schools.com/jsref/met_win_clearinterval.asp +TimeUtil.ClearInterval = TimeUtil.ClearTimeout + +return TimeUtil diff --git a/Code/['World']['Global']['Utility']['TweenControllerModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['TweenControllerModule'].ModuleScript.lua new file mode 100644 index 0000000..ead6bd1 --- /dev/null +++ b/Code/['World']['Global']['Utility']['TweenControllerModule'].ModuleScript.lua @@ -0,0 +1,38 @@ +---控制某个变量随时间变化的协程类 +---@module TweenController +---@copyright Lilith Games, Avatar Team +---@author An Dai +local TweenController = class('TweenController') + +---_name:类名,_sender:使用它的类,_getTotalTime:获得总时间的方法,_update _callback:回调函数 _isFix:是否在fixupdate中执行, _start: 开始函数 +function TweenController:initialize(_name, _sender, _getTotalTime, _update, _callback, _isFix, _start) + _start = _start or function() + return + end + + local updateStr = (_isFix and 'Fix' or '') .. 'Update' + + self.Start = function(self) + _start() + self.totalTime = _getTotalTime() + self.time = 0 + _sender[updateStr .. 'Table'][_name] = self + end + + self[updateStr] = function(self, _dt) + self.time = self.time + _dt + if (self.time > self.totalTime) then + self:Stop() + goto UpdateReturn + end + _update(self.time, self.totalTime, _dt) + ::UpdateReturn:: + end + + self.Stop = function(self) + _sender[updateStr .. 'Table'][_name] = nil + _callback() + end +end + +return TweenController diff --git a/Code/['World']['Global']['Utility']['UuidModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['UuidModule'].ModuleScript.lua new file mode 100644 index 0000000..b58ffa8 --- /dev/null +++ b/Code/['World']['Global']['Utility']['UuidModule'].ModuleScript.lua @@ -0,0 +1,229 @@ +--------------------------------------------------------------------------------------- +-- Copyright 2012 Rackspace (original), 2013 Thijs Schreijer (modifications) +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS-IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- see http://www.ietf.org/rfc/rfc4122.txt +-- +-- Note that this is not a true version 4 (random) UUID. Since `os.time()` precision is only 1 second, it would be hard +-- to guarantee spacial uniqueness when two hosts generate a uuid after being seeded during the same second. This +-- is solved by using the node field from a version 1 UUID. It represents the mac address. +-- +-- 28-apr-2013 modified by Thijs Schreijer from the original [Rackspace code](https://github.com/kans/zirgo/blob/807250b1af6725bad4776c931c89a784c1e34db2/util/uuid.lua) as a generic Lua module. +-- Regarding the above mention on `os.time()`; the modifications use the `socket.gettime()` function from LuaSocket +-- if available and hence reduce that problem (provided LuaSocket has been loaded before uuid). +-- +-- **6-nov-2015 Please take note of this issue**; [https://github.com/Mashape/kong/issues/478](https://github.com/Mashape/kong/issues/478) +-- It demonstrates the problem of using time as a random seed. Specifically when used from multiple processes. +-- So make sure to seed only once, application wide. And to not have multiple processes do that +-- simultaneously (like nginx does for example). + +local M = {} + +local bitsize = 32 -- bitsize assumed for Lua VM. See randomseed function below. +local lua_version = tonumber(_VERSION:match('%d%.*%d*')) -- grab Lua version used + +local MATRIX_AND = {{0, 0}, {0, 1}} +local MATRIX_OR = {{0, 1}, {1, 1}} +local HEXES = '0123456789abcdef' + +local math_floor = math.floor +local math_random = math.random +local math_abs = math.abs +local string_sub = string.sub +local to_number = tonumber +local assert = assert +local type = type + +-- performs the bitwise operation specified by truth matrix on two numbers. +local function BITWISE(x, y, matrix) + local z = 0 + local pow = 1 + while x > 0 or y > 0 do + z = z + (matrix[x % 2 + 1][y % 2 + 1] * pow) + pow = pow * 2 + x = math_floor(x / 2) + y = math_floor(y / 2) + end + return z +end + +local function INT2HEX(x) + local s, base = '', 16 + local d + while x > 0 do + d = x % base + 1 + x = math_floor(x / base) + s = string_sub(HEXES, d, d) .. s + end + while #s < 2 do + s = '0' .. s + end + return s +end + +---------------------------------------------------------------------------- +-- Creates a new uuid. Either provide a unique hex string, or make sure the +-- random seed is properly set. The module table itself is a shortcut to this +-- function, so `my_uuid = uuid.new()` equals `my_uuid = uuid()`. +-- +-- For proper use there are 3 options; +-- +-- 1. first require `luasocket`, then call `uuid.seed()`, and request a uuid using no +-- parameter, eg. `my_uuid = uuid()` +-- 2. use `uuid` without `luasocket`, set a random seed using `uuid.randomseed(some_good_seed)`, +-- and request a uuid using no parameter, eg. `my_uuid = uuid()` +-- 3. use `uuid` without `luasocket`, and request a uuid using an unique hex string, +-- eg. `my_uuid = uuid(my_networkcard_macaddress)` +-- +-- @return a properly formatted uuid string +-- @param hwaddr (optional) string containing a unique hex value (e.g.: `00:0c:29:69:41:c6`), to be used to compensate for the lesser `math_random()` function. Use a mac address for solid results. If omitted, a fully randomized uuid will be generated, but then you must ensure that the random seed is set properly! +-- @usage +-- local uuid = require("uuid") +-- print("here's a new uuid: ",uuid()) +function M.new(hwaddr) + -- bytes are treated as 8bit unsigned bytes. + local bytes = { + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255), + math_random(0, 255) + } + + if hwaddr then + assert(type(hwaddr) == 'string', 'Expected hex string, got ' .. type(hwaddr)) + -- Cleanup provided string, assume mac address, so start from back and cleanup until we've got 12 characters + local i, str = #hwaddr, hwaddr + hwaddr = '' + while i > 0 and #hwaddr < 12 do + local c = str:sub(i, i):lower() + if HEXES:find(c, 1, true) then + -- valid HEX character, so append it + hwaddr = c .. hwaddr + end + i = i - 1 + end + assert( + #hwaddr == 12, + "Provided string did not contain at least 12 hex characters, retrieved '" .. + hwaddr .. "' from '" .. str .. "'" + ) + + -- no split() in lua. :( + bytes[11] = to_number(hwaddr:sub(1, 2), 16) + bytes[12] = to_number(hwaddr:sub(3, 4), 16) + bytes[13] = to_number(hwaddr:sub(5, 6), 16) + bytes[14] = to_number(hwaddr:sub(7, 8), 16) + bytes[15] = to_number(hwaddr:sub(9, 10), 16) + bytes[16] = to_number(hwaddr:sub(11, 12), 16) + end + + -- set the version + bytes[7] = BITWISE(bytes[7], 0x0f, MATRIX_AND) + bytes[7] = BITWISE(bytes[7], 0x40, MATRIX_OR) + -- set the variant + bytes[9] = BITWISE(bytes[7], 0x3f, MATRIX_AND) + bytes[9] = BITWISE(bytes[7], 0x80, MATRIX_OR) + return INT2HEX(bytes[1]) .. + INT2HEX(bytes[2]) .. + INT2HEX(bytes[3]) .. + INT2HEX(bytes[4]) .. + '-' .. + INT2HEX(bytes[5]) .. + INT2HEX(bytes[6]) .. + '-' .. + INT2HEX(bytes[7]) .. + INT2HEX(bytes[8]) .. + '-' .. + INT2HEX(bytes[9]) .. + INT2HEX(bytes[10]) .. + '-' .. + INT2HEX(bytes[11]) .. + INT2HEX(bytes[12]) .. + INT2HEX(bytes[13]) .. + INT2HEX(bytes[14]) .. + INT2HEX(bytes[15]) .. INT2HEX(bytes[16]) +end + +---------------------------------------------------------------------------- +-- Improved randomseed function. +-- Lua 5.1 and 5.2 both truncate the seed given if it exceeds the integer +-- range. If this happens, the seed will be 0 or 1 and all randomness will +-- be gone (each application run will generate the same sequence of random +-- numbers in that case). This improved version drops the most significant +-- bits in those cases to get the seed within the proper range again. +-- @param seed the random seed to set (integer from 0 - 2^32, negative values will be made positive) +-- @return the (potentially modified) seed used +-- @usage +-- local socket = require("socket") -- gettime() has higher precision than os.time() +-- local uuid = require("uuid") +-- -- see also example at uuid.seed() +-- uuid.randomseed(socket.gettime()*10000) +-- print("here's a new uuid: ",uuid()) +function M.randomseed(seed) + seed = math_floor(math_abs(seed)) + if seed >= (2 ^ bitsize) then + -- integer overflow, so reduce to prevent a bad seed + seed = seed - math_floor(seed / 2 ^ bitsize) * (2 ^ bitsize) + end + if lua_version < 5.2 then + -- 5.1 uses (incorrect) signed int + math.randomseed(seed - 2 ^ (bitsize - 1)) + else + -- 5.2 uses (correct) unsigned int + math.randomseed(seed) + end + return seed +end + +---------------------------------------------------------------------------- +-- Seeds the random generator. +-- It does so in 2 possible ways; +-- +-- 1. use `os.time()`: this only offers resolution to one second (used when +-- LuaSocket hasn't been loaded yet +-- 2. use luasocket `gettime()` function, but it only does so when LuaSocket +-- has been required already. +-- @usage +-- local socket = require("socket") -- gettime() has higher precision than os.time() +-- -- LuaSocket loaded, so below line does the same as the example from randomseed() +-- uuid.seed() +-- print("here's a new uuid: ",uuid()) +function M.seed() + -- if package.loaded['socket'] and package.loaded['socket'].gettime then + -- return M.randomseed(package.loaded['socket'].gettime() * 10000) + -- else + return M.randomseed(os.time()) + -- end +end + +return setmetatable( + M, + { + __call = function(self, hwaddr) + return self.new(hwaddr) + end + } +) diff --git a/Code/['World']['Global']['Utility']['ValueChangeUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['ValueChangeUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..05cb6a8 --- /dev/null +++ b/Code/['World']['Global']['Utility']['ValueChangeUtilModule'].ModuleScript.lua @@ -0,0 +1,137 @@ +--- 值改变及值改变事件 +--- @module ValueChangeUtil Module +--- @copyright Lilith Games, Avatar Team +--- @author Xin Tan +local ValueChangeUtil = {} + +--- 数据变化事件 +--- @param _table table 事件表 +--- @param _index string 索引 +--- @param _oldValue mixed 旧值 +--- @param _newValue mixed 新值 +--- @param _targetPlayer PlayerInstance 这条数据对应的玩家实例 +function ValueChangeUtil.DataChangeEvent(_table, _index, _oldValue, _newValue) + if not _table[_index] or type(_table[_index]) ~= "function" then + return + end + _table[_index](_oldValue, _newValue) +end + +--- 将目标表(或其中某个值)改为新值 +--- @param _table table 目标表 +--- @param _index string 目标索引(改整个目标表时填nil) +--- @param _value mixed 新值 +--- @param _eventTable table 数值改变事件表(不响应时不传) +function ValueChangeUtil.ChangeValue(_table, _index, _value, _eventTable) + if type(_table) ~= "table" then + print("[error]传入的目标表类型错误") + return + end + + local tmp = _table + local eventtmp = _eventTable or false + + -- 参数含索引时 + if _index then + local idx = {} + if type(_index) == "string" then + -- 将索引通过'.'拆开 + idx = string.split(_index, '.') + elseif type(_index) == "table" then + idx = _index + end + -- 一层层向下索引 + for i = 1, #idx - 1 do + -- 若目标表没有对应的索引则建立空表 + if type(tmp[idx[i]]) ~= "table" then + tmp[idx[i]] = {} + end + tmp = tmp[idx[i]] + if eventtmp then + if type(eventtmp[idx[i]]) ~= "table" then + eventtmp[idx[i]] = {} + end + eventtmp = eventtmp[idx[i]] + end + end + + -- 若目标值不是table,则直接赋值 + if type(_value) ~= "table" then + local oldValue = table.shallowcopy(tmp[idx[#idx]]) + tmp[idx[#idx]] = _value + if eventtmp then + ValueChangeUtil.DataChangeEvent(eventtmp, idx[#idx], oldValue, _value) + end + return + else + -- 目标值是table + -- 若目标索引不是table,则创建table + if type(tmp[idx[#idx]]) ~= "table" then + tmp[idx[#idx]] = {} + if eventtmp and type( eventtmp[idx[#idx]]) ~= "table" then + eventtmp[idx[#idx]] = {} + end + end + tmp = tmp[idx[#idx]] + if eventtmp then + eventtmp = eventtmp[idx[#idx]] + end + end + else + -- 参数无索引时,从目标表根目录开始同步 + if type(_value) ~= "table" then + print("[error]传入的新值类型错误") + return + end + end + + -- 清除目标索引表与新值的差集 + for k, v in pairs(tmp) do + if not _value[k] then + local oldValue = tmp[k] + tmp[k] = nil + if eventtmp then + ValueChangeUtil.DataChangeEvent(eventtmp, k, oldValue, nil) + end + end + end + + -- 逐层覆盖数据 + for k, v in pairs(_value) do + -- 如果值为table则向下递归 + if type(v) == "table" then + ValueChangeUtil.ChangeValue(tmp, k, v, eventtmp) + else + -- 若值不是table,则直接赋值 + local oldValue = tmp[k] + tmp[k] = v + if eventtmp then + ValueChangeUtil.DataChangeEvent(eventtmp, k, oldValue, v) + end + end + end + if eventtmp then + ValueChangeUtil.DataChangeEvent(eventtmp, "parentTableEvent") + end +end + +--- 进行数据验证,将对照表中存在而目标表中不存在键补充至目标表中 +--- @param _table table 目标表 +--- @param _contrast table 对照表 +function ValueChangeUtil.VerifyTable(_table, _contrast) + for k, v in pairs(_contrast) do + -- 如果值为table则向下递归 + if type(v) == "table" then + if not _table[k] then + _table[k] = table.shallowcopy(v) + else + ValueChangeUtil.VerifyTable(_table[k], v) + end + else + -- 若值不是table,则直接校对 + if not _table[k] then _table[k] = v end + end + end +end + +return ValueChangeUtil diff --git a/Code/['World']['Global']['Utility']['XlsUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['XlsUtilModule'].ModuleScript.lua new file mode 100644 index 0000000..2fb193e --- /dev/null +++ b/Code/['World']['Global']['Utility']['XlsUtilModule'].ModuleScript.lua @@ -0,0 +1,162 @@ +--- 读表工具: 将导入成Lua Table,支持单一主键和多主键 +-- @module XLS Utility +-- @copyright Lilith Games, Avatar Team +-- @author Yuancheng Zhang +-- @see https://wiki.lilithgames.com/x/RGEMAg +local XlsUtil = {} + +--! 打印事件日志, true:开启打印 +local showLog, PrintGlobalKV, PrintLog = true + +--- 将表中的字符串改为数字 +-- @param _t input table +local function StrToNum(_t) + for k, v in pairs(_t) do + _t[k] = tonumber(v) + end + return _t +end + +--- 类型解析配置表 +local parser = { + int = function(_raw) + return math.floor(tonumber(_raw)) + end, + float = function(_raw) + return tonumber(_raw) + end, + string = function(_raw) + return _raw + end, + boolean = function(_raw) + return string.lower(_raw) == 'true' + end, + vector2 = function(_raw) + return Vector2(table.unpack(StrToNum(string.split(_raw, ',')))) + end, + vector3 = function(_raw) + return Vector3(table.unpack(StrToNum(string.split(_raw, ',')))) + end, + euler = function(_raw) + return EulerDegree(table.unpack(StrToNum(string.split(_raw, ',')))) + end, + color = function(_raw) + return Color(table.unpack(StrToNum(string.split(_raw, ',')))) + end +} + +--- 读取配置表,会根据id生成lua表 +-- @param _type String 数据类型 +-- @parm _stringValue String 数据 +-- @return value 解析出来的数值 +local function GetValue(_type, _stringValue) + _type = string.lower(_type) + assert(parser[_type], string.format('[XlsUtil][GlobalSetting] "%s" Type字段的值不是目前所支持的数据类型', _type)) + return parser[_type](_stringValue) +end + +--- 根据id转换lua table +function XlsUtil.GetXlsInfo(_xls, ...) + local ids = {...} + if #ids < 1 or (#ids == 1 and ids[1] == 'Type') then + -- 默认用Type索引,直接返回 + return _xls + end + local rawTable = _xls + local result = {} + local tmp, key, id, idstr -- 临时变量 + for _, v in pairs(rawTable) do + tmp = result + idstr = {} + for i = 1, #ids do + id = ids[i] + key = v[id] + idstr[i] = tostring(id) .. ',' + assert( + not string.isnilorempty(key), + string.format('[XlsUtil] Excel表格没有找到此id, Excel:%s, id: %s', _xls.Name, id) + ) + if i == #ids then + -- 最后的键,确定唯一性 + assert( + not tmp[key], + string.format('[XlsUtil] Excel数据重复, ids不是唯一的, Excel: %s, ids: %s', _xls.Name, table.concat(idstr)) + ) + tmp[key] = v + else + -- 多键,之后还有 + if tmp[key] == nil then + tmp[key] = {} + end + tmp = tmp[key] + end + end + end + return result +end + +--- 读取Config全局配置表 +function XlsUtil.GetGlobalXlsInfo(_xls) + local rawTable = _xls + if table.nums(rawTable) == 0 then + return + end + assert(rawTable[1].Key, '[XlsUtil] 全局配置表的没有"Key"') + assert(rawTable[1].Type, '[XlsUtil] 全局配置表的没有"Type"') + assert(rawTable[1].Value, '[XlsUtil] 全局配置表的没有"Value"') + local result = {} + for _, v in pairs(rawTable) do + result[v.Key] = GetValue(v['Type'], v['Value']) + PrintGlobalKV(v.Key, v.Type, result[v.Key]) -- * 输出KV键值对 + end + return result +end + +--- 表格预加载,预加载配置模块:World.Global.Define.ConfigModule +function XlsUtil.PreloadXls(_preloadList, _xlsRoot, _config) + -- todo: load xls lua talbe + assert(_preloadList and #_preloadList > 0, 'ConfigModule中没有预加载表格') + + for _, pl in pairs(_preloadList) do + if not string.isnilorempty(pl.xls) then + pl.name = string.isnilorempty(pl.name) and pl.xls or pl.name + pl.module = string.isnilorempty(pl.module) and pl.xls .. 'Xls' or pl.module + PrintLog(string.format('[XlsUtil] Load: %s', pl.module)) + if pl.xls == 'GlobalSetting' and _xlsRoot[pl.module .. 'Module'] then + _config[pl.name] = XlsUtil.GetGlobalXlsInfo(_G[pl.module]) + elseif not string.isnilorempty(pl.xls) and _G[pl.module] then + pl.ids = pl.ids or {} + _config[pl.name] = XlsUtil.GetXlsInfo(_G[pl.module], table.unpack(pl.ids)) + end + end + end +end + +--! 辅助功能 + +--- 输出全局变量键值对 +PrintGlobalKV = + showLog and + function(_key, _type, _value) + _type = string.lower(_type) + local showTypes = { + vector2 = 'Vector2', + vector3 = 'Vector3', + euler = 'EulerDegree', + color = 'Color' + } + if showTypes[_type] then + print(string.format('[XlsUtil][GlobalSetting] %s = %s%s ', _key, showTypes[_type], _value)) + else + print(string.format('[XlsUtil][GlobalSetting] %s = %s ', _key, _value)) + end + end or + function() + end + +PrintLog = showLog and function(...) + print(...) + end or function() + end + +return XlsUtil diff --git a/Code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua new file mode 100644 index 0000000..0fe52fb --- /dev/null +++ b/Code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua @@ -0,0 +1,110 @@ +--- This file is generated by ava-x2l.exe, +--- Don't change it manaully. +--- @copyright Lilith Games, Project Da Vinci(Avatar Team) +--- @see https://www.projectdavinci.com/ +--- @see https://github.com/endaye/avatar-ava-xls2lua +--- source file: ./xls/ExampleTable1.xlsx + +local Example1Xls = { + [1] = { + house = { + id = 1, + name = 'house', + use_money = 1000, + use_food = 2.33, + is_init = true, + defense = 100, + args_int_arr = {1, 2, 3}, + args_float_arr = {1.23, 2, 3.23}, + args_string_arr = {'sdf', '23e', 's'}, + args_bool_arr = {true, false, true}, + args_vect2 = Vector2(-1, 0.5), + args_vect3 = Vector3(2, 0.3, -4), + args_euler = EulerDegree(12, 23, 43), + args_color = Color(129, 12, 3, 0), + args_lua = function() print(23) end, + Des1 = 'Example1_Des1_1_house', + Des2 = 'Example1_Des2_1_house' + }, + MMM = { + id = 1, + name = 'MMM', + use_money = 123, + use_food = 336.2, + is_init = true, + defense = 0, + args_int_arr = {1, 2, 3}, + args_float_arr = {1, 2.3445, 3}, + args_string_arr = {'你好', '你在哪'}, + args_bool_arr = {true, false}, + args_vect2 = Vector2(0, 4), + args_vect3 = Vector3(-2, 3, 5), + args_euler = EulerDegree(0, 0, 0), + args_color = Color(0, 0, 0, 0), + args_lua = {a = 2, b='234'}, + Des1 = 'Example1_Des1_1_MMM', + Des2 = 'Example1_Des2_1_MMM' + }, + ddd = { + id = 1, + name = 'ddd', + use_money = 456, + use_food = 222.33665, + is_init = false, + defense = 130, + args_int_arr = {3, 2, 5}, + args_float_arr = {3, 2, 2.5}, + args_string_arr = {'我在这里啊', '你在那', '呢'}, + args_bool_arr = {false, true}, + args_vect2 = Vector2(2, 0.5), + args_vect3 = Vector3(0.6, 3, -8.4), + args_euler = EulerDegree(0, 0, 0), + args_color = Color(0, 0, 0, 0), + args_lua = nil, + Des1 = 'Example1_Des1_1_ddd', + Des2 = 'Example1_Des2_1_ddd' + } + }, + [2] = { + farm = { + id = 2, + name = 'farm', + use_money = 100, + use_food = 220.0, + is_init = false, + defense = 200, + args_int_arr = {2, 3}, + args_float_arr = {200.3, 3, 234.23}, + args_string_arr = {'df', 'ssd', 'dd', 'dd'}, + args_bool_arr = {}, + args_vect2 = Vector2.Zero, + args_vect3 = Vector3.Zero, + args_euler = EulerDegree(0, 0, 0), + args_color = Color(0, 0, 0, 0), + args_lua = nil, + Des1 = 'Example1_Des1_2_farm', + Des2 = 'Example1_Des2_2_farm' + }, + MMM = { + id = 2, + name = 'MMM', + use_money = 0, + use_food = 22.1, + is_init = false, + defense = 234, + args_int_arr = {3, 6, 6, 7}, + args_float_arr = {3, 6.3, 6, 7}, + args_string_arr = {'ss', 'd', 'd', 'd'}, + args_bool_arr = {true, true}, + args_vect2 = Vector2.Zero, + args_vect3 = Vector3.Zero, + args_euler = EulerDegree(0, 0, 0), + args_color = Color(0, 0, 0, 0), + args_lua = "还没有添加检查", + Des1 = 'Example1_Des1_2_MMM', + Des2 = 'Example1_Des2_2_MMM' + } + } +} + +return Example1Xls diff --git a/Code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua new file mode 100644 index 0000000..7ac1d42 --- /dev/null +++ b/Code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua @@ -0,0 +1,83 @@ +--- This file is generated by ava-x2l.exe, +--- Don't change it manaully. +--- @copyright Lilith Games, Project Da Vinci(Avatar Team) +--- @see https://www.projectdavinci.com/ +--- @see https://github.com/endaye/avatar-ava-xls2lua +--- source file: ./xls/ExampleTable1.xlsx + +local Example2Xls = { + [1] = { + id = 1, + name = 'house', + use_money = 1000, + use_food = 2.33, + is_init = true, + defense = 100, + args1 = {1, 2, 3}, + args2 = {1.23, 2, 3.23}, + args3 = {'sdf', '23e', 's'}, + args4 = {true, false, true} + }, + [2] = { + id = 2, + name = '你好吗?', + use_money = 123, + use_food = 336.2, + is_init = true, + defense = 0, + args1 = {1, 2, 3}, + args2 = {1, 2.3445, 3}, + args3 = {'你好', '你在哪'}, + args4 = {true, false} + }, + [3] = { + id = 3, + name = '', + use_money = 456, + use_food = 222.33665, + is_init = false, + defense = 130, + args1 = {3, 2, 5}, + args2 = {3, 2, 2.5}, + args3 = {'我在这里啊', '你在那', '呢'}, + args4 = {false, true} + }, + [4] = { + id = 4, + name = 'farm', + use_money = 100, + use_food = 220.0, + is_init = false, + defense = 200, + args1 = {2, 3}, + args2 = {200.3, 3, 234.23}, + args3 = {'df', 'ssd', 'dd', 'dd'}, + args4 = {} + }, + [5] = { + id = 5, + name = 'house5', + use_money = 0, + use_food = 22.1, + is_init = false, + defense = 234, + args1 = {3, 6, 6, 7}, + args2 = {3, 6.3, 6, 7}, + args3 = {'ss', 'd', 'd', 'd'}, + args4 = {true, true} + }, + [6] = { + id = 6, + name = 'horse3', + use_money = 200, + use_food = 0, + is_init = false, + defense = 333, + args1 = {}, + args2 = {}, + args3 = {'2e', 'w', 'e', 'we'}, + args4 = {false, false, false, false} + } +} + +return Example2Xls diff --git a/Code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua new file mode 100644 index 0000000..5cb4d8d --- /dev/null +++ b/Code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua @@ -0,0 +1,31 @@ +--- This file is generated by ava-x2l.exe, +--- Don't change it manaully. +--- @copyright Lilith Games, Project Da Vinci(Avatar Team) +--- @see https://www.projectdavinci.com/ +--- @see https://github.com/endaye/avatar-ava-xls2lua +--- source file: ./xls/GlobalSetting.xls + +local GlobalSettingXls = { + DefaultLanguage = { + Key = 'DefaultLanguage', + Value = "CHS" + }, + PlayerPosition = { + Key = 'PlayerPosition', + Value = Vector3(0,-1,0) + }, + PlayerRotation = { + Key = 'PlayerRotation', + Value = Euler(90,0,0) + }, + MaxPlayerNumber = { + Key = 'MaxPlayerNumber', + Value = 100.0 + }, + ScoreRate = { + Key = 'ScoreRate', + Value = 12.5 + } +} + +return GlobalSettingXls diff --git a/Code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua new file mode 100644 index 0000000..4bd1d8d --- /dev/null +++ b/Code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua @@ -0,0 +1,81 @@ +--- This file is generated by ava-x2l.exe, +--- Don't change it manaully. +--- @copyright Lilith Games, Project Da Vinci(Avatar Team) +--- @see https://www.projectdavinci.com/ +--- @see https://github.com/endaye/avatar-ava-xls2lua +--- source file: ./xls/LanguagePack.xls + +local LanguagePackXls = { + Example1_Des1_1_house = { + ID = 'Example1_Des1_1_house', + CHS = '我真的很想%s吃饭', + CHT = '', + EN = '', + JP = '' + }, + Example1_Des2_1_house = { + ID = 'Example1_Des2_1_house', + CHS = '做什么', + CHT = '', + EN = '', + JP = '' + }, + Example1_Des1_1_MMM = { + ID = 'Example1_Des1_1_MMM', + CHS = '我饿了', + CHT = '', + EN = '', + JP = '' + }, + Example1_Des2_1_MMM = { + ID = 'Example1_Des2_1_MMM', + CHS = '工作是什么', + CHT = '', + EN = '', + JP = '' + }, + Example1_Des1_1_ddd = { + ID = 'Example1_Des1_1_ddd', + CHS = '到底什么时候能吃饭', + CHT = '', + EN = '', + JP = '' + }, + Example1_Des2_1_ddd = { + ID = 'Example1_Des2_1_ddd', + CHS = '我是谁', + CHT = '', + EN = '', + JP = '' + }, + Example1_Des1_2_farm = { + ID = 'Example1_Des1_2_farm', + CHS = '今天晚上吃什么', + CHT = '', + EN = '', + JP = '' + }, + Example1_Des2_2_farm = { + ID = 'Example1_Des2_2_farm', + CHS = '我从哪里来', + CHT = '', + EN = '', + JP = '' + }, + Example1_Des1_2_MMM = { + ID = 'Example1_Des1_2_MMM', + CHS = '下班就去吃饭吧', + CHT = '', + EN = '', + JP = '' + }, + Example1_Des2_2_MMM = { + ID = 'Example1_Des2_2_MMM', + CHS = '就这样吧', + CHT = '', + EN = '', + JP = '' + } +} + +return LanguagePackXls diff --git a/Code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua new file mode 100644 index 0000000..8718a45 --- /dev/null +++ b/Code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua @@ -0,0 +1,21 @@ +--- This file is generated by ava-x2l.exe, +--- Don't change it manaully. +--- @copyright Lilith Games, Project Da Vinci(Avatar Team) +--- @see https://www.projectdavinci.com/ +--- @see https://github.com/endaye/avatar-ava-xls2lua +--- source file: ./xls/Sound.xls + +local SoundXls = { + test_01 = { + Type = 1, + ID = 'test_01', + IsLoop = false, + Volume = 0, + FileName = '', + Detail = '', + Duration = 0, + CoverPlay = false + } +} + +return SoundXls diff --git a/Code/['World']['S_Code']['ServerMainScript'].Script.lua b/Code/['World']['S_Code']['ServerMainScript'].Script.lua new file mode 100644 index 0000000..5a5bcff --- /dev/null +++ b/Code/['World']['S_Code']['ServerMainScript'].Script.lua @@ -0,0 +1,5 @@ +--- 服务器代码入口 +-- @script Server Main Function +-- @copyright Lilith Games, Avatar Team +-- @author Yuancheng Zhang +Server:Run() diff --git a/Smap/avatar-ava.smap b/Smap/avatar-ava.smap new file mode 100644 index 0000000000000000000000000000000000000000..6de308a17405157aa2df3240bc7aade6137562a6 GIT binary patch literal 67356 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 Date: Tue, 18 May 2021 18:39:07 +0800 Subject: [PATCH 19/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0x2l=E7=9B=B8=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ava-x2l-config.json | 8 ++--- ...ls']['Example1XlsModule'].ModuleScript.lua | 34 +++++++++---------- ...ls']['Example2XlsModule'].ModuleScript.lua | 16 ++++----- ...'GlobalSettingXlsModule'].ModuleScript.lua | 27 ++++----------- ...['LanguagePackXlsModule'].ModuleScript.lua | 2 +- ...['Xls']['SoundXlsModule'].ModuleScript.lua | 10 +++--- Xls/LanguagePack.xls | 2 +- 7 files changed, 41 insertions(+), 58 deletions(-) diff --git a/.ava-x2l-config.json b/.ava-x2l-config.json index 78ee6f6..d0a1999 100644 --- a/.ava-x2l-config.json +++ b/.ava-x2l-config.json @@ -1,9 +1,7 @@ { - "input_folder": "./xls", - "output_folder": "./code", + "input_folder": "./Xls", + "output_folder": "./Code", "output_lua_template": "['World']['Global']['Xls']['{sheet_name}XlsModule'].ModuleScript.lua", - "kv_xls": [ - "GlobalSetting.xlsx" - ], + "kv_xls": "['GlobalSetting.xlsx']", "translate_xls": "LanguagePack.xls" } \ No newline at end of file diff --git a/Code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua index 0fe52fb..fcf1d6c 100644 --- a/Code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Xls']['Example1XlsModule'].ModuleScript.lua @@ -3,7 +3,7 @@ --- @copyright Lilith Games, Project Da Vinci(Avatar Team) --- @see https://www.projectdavinci.com/ --- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/ExampleTable1.xlsx +--- source file: ./Xls/ExampleTable1.xlsx local Example1Xls = { [1] = { @@ -32,15 +32,15 @@ local Example1Xls = { use_money = 123, use_food = 336.2, is_init = true, - defense = 0, + defense = nil, args_int_arr = {1, 2, 3}, args_float_arr = {1, 2.3445, 3}, args_string_arr = {'你好', '你在哪'}, args_bool_arr = {true, false}, args_vect2 = Vector2(0, 4), args_vect3 = Vector3(-2, 3, 5), - args_euler = EulerDegree(0, 0, 0), - args_color = Color(0, 0, 0, 0), + args_euler = nil, + args_color = nil, args_lua = {a = 2, b='234'}, Des1 = 'Example1_Des1_1_MMM', Des2 = 'Example1_Des2_1_MMM' @@ -58,8 +58,8 @@ local Example1Xls = { args_bool_arr = {false, true}, args_vect2 = Vector2(2, 0.5), args_vect3 = Vector3(0.6, 3, -8.4), - args_euler = EulerDegree(0, 0, 0), - args_color = Color(0, 0, 0, 0), + args_euler = nil, + args_color = nil, args_lua = nil, Des1 = 'Example1_Des1_1_ddd', Des2 = 'Example1_Des2_1_ddd' @@ -76,11 +76,11 @@ local Example1Xls = { args_int_arr = {2, 3}, args_float_arr = {200.3, 3, 234.23}, args_string_arr = {'df', 'ssd', 'dd', 'dd'}, - args_bool_arr = {}, - args_vect2 = Vector2.Zero, - args_vect3 = Vector3.Zero, - args_euler = EulerDegree(0, 0, 0), - args_color = Color(0, 0, 0, 0), + args_bool_arr = nil, + args_vect2 = nil, + args_vect3 = nil, + args_euler = nil, + args_color = nil, args_lua = nil, Des1 = 'Example1_Des1_2_farm', Des2 = 'Example1_Des2_2_farm' @@ -88,18 +88,18 @@ local Example1Xls = { MMM = { id = 2, name = 'MMM', - use_money = 0, + use_money = nil, use_food = 22.1, - is_init = false, + is_init = nil, defense = 234, args_int_arr = {3, 6, 6, 7}, args_float_arr = {3, 6.3, 6, 7}, args_string_arr = {'ss', 'd', 'd', 'd'}, args_bool_arr = {true, true}, - args_vect2 = Vector2.Zero, - args_vect3 = Vector3.Zero, - args_euler = EulerDegree(0, 0, 0), - args_color = Color(0, 0, 0, 0), + args_vect2 = nil, + args_vect3 = nil, + args_euler = nil, + args_color = nil, args_lua = "还没有添加检查", Des1 = 'Example1_Des1_2_MMM', Des2 = 'Example1_Des2_2_MMM' diff --git a/Code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua index 7ac1d42..22acd09 100644 --- a/Code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Xls']['Example2XlsModule'].ModuleScript.lua @@ -3,7 +3,7 @@ --- @copyright Lilith Games, Project Da Vinci(Avatar Team) --- @see https://www.projectdavinci.com/ --- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/ExampleTable1.xlsx +--- source file: ./Xls/ExampleTable1.xlsx local Example2Xls = { [1] = { @@ -24,7 +24,7 @@ local Example2Xls = { use_money = 123, use_food = 336.2, is_init = true, - defense = 0, + defense = nil, args1 = {1, 2, 3}, args2 = {1, 2.3445, 3}, args3 = {'你好', '你在哪'}, @@ -52,14 +52,14 @@ local Example2Xls = { args1 = {2, 3}, args2 = {200.3, 3, 234.23}, args3 = {'df', 'ssd', 'dd', 'dd'}, - args4 = {} + args4 = nil }, [5] = { id = 5, name = 'house5', - use_money = 0, + use_money = nil, use_food = 22.1, - is_init = false, + is_init = nil, defense = 234, args1 = {3, 6, 6, 7}, args2 = {3, 6.3, 6, 7}, @@ -70,11 +70,11 @@ local Example2Xls = { id = 6, name = 'horse3', use_money = 200, - use_food = 0, + use_food = nil, is_init = false, defense = 333, - args1 = {}, - args2 = {}, + args1 = nil, + args2 = nil, args3 = {'2e', 'w', 'e', 'we'}, args4 = {false, false, false, false} } diff --git a/Code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua index 5cb4d8d..a32bc49 100644 --- a/Code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Xls']['GlobalSettingXlsModule'].ModuleScript.lua @@ -3,29 +3,14 @@ --- @copyright Lilith Games, Project Da Vinci(Avatar Team) --- @see https://www.projectdavinci.com/ --- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/GlobalSetting.xls +--- source file: ./Xls/GlobalSetting.xls local GlobalSettingXls = { - DefaultLanguage = { - Key = 'DefaultLanguage', - Value = "CHS" - }, - PlayerPosition = { - Key = 'PlayerPosition', - Value = Vector3(0,-1,0) - }, - PlayerRotation = { - Key = 'PlayerRotation', - Value = Euler(90,0,0) - }, - MaxPlayerNumber = { - Key = 'MaxPlayerNumber', - Value = 100.0 - }, - ScoreRate = { - Key = 'ScoreRate', - Value = 12.5 - } + DefaultLanguage = "CHS", + PlayerPosition = Vector3(0,-1,0), + PlayerRotation = Euler(90,0,0), + MaxPlayerNumber = 100.0, + ScoreRate = 12.5 } return GlobalSettingXls diff --git a/Code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua index 4bd1d8d..bceb350 100644 --- a/Code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Xls']['LanguagePackXlsModule'].ModuleScript.lua @@ -3,7 +3,7 @@ --- @copyright Lilith Games, Project Da Vinci(Avatar Team) --- @see https://www.projectdavinci.com/ --- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/LanguagePack.xls +--- source file: ./Xls/LanguagePack.xls local LanguagePackXls = { Example1_Des1_1_house = { diff --git a/Code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua b/Code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua index 8718a45..424405e 100644 --- a/Code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Xls']['SoundXlsModule'].ModuleScript.lua @@ -3,18 +3,18 @@ --- @copyright Lilith Games, Project Da Vinci(Avatar Team) --- @see https://www.projectdavinci.com/ --- @see https://github.com/endaye/avatar-ava-xls2lua ---- source file: ./xls/Sound.xls +--- source file: ./Xls/Sound.xls local SoundXls = { test_01 = { Type = 1, ID = 'test_01', - IsLoop = false, - Volume = 0, + IsLoop = nil, + Volume = nil, FileName = '', Detail = '', - Duration = 0, - CoverPlay = false + Duration = nil, + CoverPlay = nil } } diff --git a/Xls/LanguagePack.xls b/Xls/LanguagePack.xls index 256d1d6..2c020e3 100644 --- a/Xls/LanguagePack.xls +++ b/Xls/LanguagePack.xls @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6899c342011b76a57a5cdfa599d99143ae4497428556334a4077ace5dd736d1a +oid sha256:f6463250613591736ae1da46ac0ecac332617da498bcb7a7e4417df7f57080a4 size 5632 From 04fd6c313bf295bcaa29d054a7f83c9b8041e14e Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 18:54:10 +0800 Subject: [PATCH 20/39] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...'PlayerGuiDefaultModule'].ModuleScript.lua | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua b/Code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua index cb06367..a2b09a0 100644 --- a/Code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Module']['C_Module']['PlayerGuiDefaultModule'].ModuleScript.lua @@ -7,10 +7,10 @@ local PlayerGuiDefault, this = ModuleUtil.New('PlayerGuiDefault', ClientBase) local player -- 姓名板 -local nameGUI +local nameGui -- 血条 -local healthGUI, background, healthBar +local healthGui, background, healthBar local RED_BAR = ResourceManager.GetTexture('Internal/Blood_Red') local GREEN_BAR = ResourceManager.GetTexture('Internal/Blood_Green') local ORANGE_BAR = ResourceManager.GetTexture('Internal/Blood_Orange') @@ -27,29 +27,29 @@ end -- 姓名板 function PlayerGuiDefault:InitNameGui() - nameGUI = player.NameGui - nameGUI.NameBarTxt.Text = player.Name + nameGui = player.NameGui + nameGui.NameBarTxt.Text = player.Name end -- 血条 function PlayerGuiDefault:InitHealthBarGui() - healthGUI = player.HealthGui - background = healthGUI.BackgroundImg + healthGui = player.HealthGui + background = healthGui.BackgroundImg healthBar = background.HealthBarImg end -- 初始化事件 function PlayerGuiDefault:InitListener() player.OnHealthChange:Connect(HealthChange) - world.OnRenderStepped:Connect(MainGUI) + world.OnRenderStepped:Connect(MainGui) end -- 姓名板的显示逻辑 function NameBarLogic() - nameGUI.Visible = player.DisplayName + nameGui.Visible = player.DisplayName if player.DisplayName then - local addedHeight = (healthGUI and healthGUI.ActiveSelf) and 1.1 or 1 - nameGUI.LocalPosition = Vector3(0, addedHeight + player.Avatar.Height, 0) + local addedHeight = (healthGui and healthGui.ActiveSelf) and 1.1 or 1 + nameGui.LocalPosition = Vector3(0, addedHeight + player.Avatar.Height, 0) end end @@ -73,18 +73,18 @@ end function HealthBarLogic(_delta) healthBarShowTime = healthBarShowTime - _delta if player.HealthDisplayMode == Enum.HealthDisplayMode.Always then - healthGUI.Visible = true + healthGui.Visible = true elseif player.HealthDisplayMode == Enum.HealthDisplayMode.Never then - healthGUI.Visible = false + healthGui.Visible = false elseif player.HealthDisplayMode == Enum.HealthDisplayMode.OnHit then - healthGUI.Visible = player.Health ~= player.MaxHealth + healthGui.Visible = player.Health ~= player.MaxHealth else - healthGUI.Visible = healthBarShowTime > 0 + healthGui.Visible = healthBarShowTime > 0 end end -- 每个渲染帧更新姓名板和血条的显示逻辑 -function MainGUI(_delta) +function MainGui(_delta) NameBarLogic() HealthBarLogic(_delta) end From 2d36df83039467d8d9d98338367a7a7d6449a679 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 18:54:54 +0800 Subject: [PATCH 21/39] Update avatar-ava.smap --- Smap/avatar-ava.smap | Bin 67356 -> 67131 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Smap/avatar-ava.smap b/Smap/avatar-ava.smap index 6de308a17405157aa2df3240bc7aade6137562a6..868639683fa77fab611332b577af06a594d355e8 100644 GIT binary patch delta 38959 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�Hr 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 Date: Tue, 18 May 2021 18:57:02 +0800 Subject: [PATCH 22/39] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E4=B8=A4=E4=B8=AA?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8=E9=BB=98=E8=AE=A4=E7=9A=84CSV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ocalization']['ResourcesTable'].LocalizationResourceTable.csv | 1 + ...orld']['Localization']['TextTable'].LocalizationTextTable.csv | 1 + 2 files changed, 2 insertions(+) create mode 100644 Csv/['World']['Localization']['ResourcesTable'].LocalizationResourceTable.csv create mode 100644 Csv/['World']['Localization']['TextTable'].LocalizationTextTable.csv diff --git a/Csv/['World']['Localization']['ResourcesTable'].LocalizationResourceTable.csv b/Csv/['World']['Localization']['ResourcesTable'].LocalizationResourceTable.csv new file mode 100644 index 0000000..410feec --- /dev/null +++ b/Csv/['World']['Localization']['ResourcesTable'].LocalizationResourceTable.csv @@ -0,0 +1 @@ +LocalizeKey,Note,Default diff --git a/Csv/['World']['Localization']['TextTable'].LocalizationTextTable.csv b/Csv/['World']['Localization']['TextTable'].LocalizationTextTable.csv new file mode 100644 index 0000000..410feec --- /dev/null +++ b/Csv/['World']['Localization']['TextTable'].LocalizationTextTable.csv @@ -0,0 +1 @@ +LocalizeKey,Note,Default From b3b95d5894916541c50cdf692a9ae848d7fc4946 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:01:27 +0800 Subject: [PATCH 23/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0TimeUtil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ility']['TimeUtilModule'].ModuleScript.lua | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua index 65d83de..dc5a3c4 100644 --- a/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua @@ -20,41 +20,42 @@ local DELTA_TIME = .05 --- Find all registered events to trigger local function CheckEvents() -- now = os.time() - local now = Timer.GetTimeMillisecond() - local i, event = 1 - while i <= #eventList do + local now = Timer.GetTime() + local event + for i = #eventList, 1, -1 do event = eventList[i] if event.triggerTime <= now then table.insert(activeEvents, event) if event.loop then event.triggerTime = event.triggerTime + event.delay - i = i + 1 else table.remove(eventList, i) end - else - i = i + 1 end end end --- Trigger events local function TriggerEvents() - local i = 1 - while i <= #activeEvents do + local event + for i = #activeEvents, 1, -1 do event = activeEvents[i] - invoke(event.func) + invoke( + function() + event.func() + end + ) table.remove(activeEvents, i) end + assert(#activeEvents == 0, string.format('[TimeUtil] 有未执行的事件%s个', #activeEvents)) end --- Update local function StartUpdate() - while running do - -- print(os.time()) + while running and wait(DELTA_TIME) do + -- --print(Timer.GetTime(), os.time()) CheckEvents() TriggerEvents() - wait(DELTA_TIME) end end @@ -65,6 +66,9 @@ end --- Run Update() function TimeUtil.Start() + if running then + return + end running = true invoke(StartUpdate) end @@ -82,22 +86,21 @@ end -- @see https://www.w3schools.com/jsref/met_win_settimeout.asp function TimeUtil.SetTimeout(_func, _seconds) assert(_func, '[TimeUtil] TimeUtil.SetTimeout() _func 不能为空') + assert(type(_func) == 'function', '[TimeUtil] TimeUtil.SetTimeout() _func 类型不是function') assert(_seconds >= 0, '[TimeUtil] TimeUtil.SetTimeout() 延迟时间需大于等于0') if _seconds == 0 then - print('[TimeUtil] TimeUtil.SetTimeout() 事件立即执行') + --print('[TimeUtil] TimeUtil.SetTimeout() 事件立即执行') invoke(_func) return end local id = #eventList + 1 - -- convert to milliseconds - local ms = math.floor(_seconds * 1000) - local timestamp = ms + Timer.GetTimeMillisecond() + local timestamp = _seconds + Timer.GetTime() table.insert( eventList, { id = id, func = _func, - delay = ms, + delay = _seconds, triggerTime = timestamp } ) @@ -112,17 +115,16 @@ end -- @see https://www.w3schools.com/jsref/met_win_setinterval.asp function TimeUtil.SetInterval(_func, _seconds) assert(_func, '[TimeUtil] TimeUtil.SetInterval() _func 不能为空') + assert(type(_func) == 'function', '[TimeUtil] TimeUtil.SetInterval() _func 类型不是function') assert(_seconds > 0, '[TimeUtil] TimeUtil.SetInterval() 延迟时间需大于0') local id = #eventList + 1 - -- convert to milliseconds - local ms = math.floor(_seconds * 1000) - local timestamp = ms + Timer.GetTimeMillisecond() + local timestamp = _seconds + Timer.GetTime() table.insert( eventList, { id = id, func = _func, - delay = ms, + delay = _seconds, triggerTime = timestamp, loop = true } From cb47ffdeb2adf2e7c3fd8f2fbe8d1d4e822ccb2d Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:04:37 +0800 Subject: [PATCH 24/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0SoundUtil=20by=20?= =?UTF-8?q?=E5=91=A8=E4=BB=BB=E7=BF=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...lity']['SoundUtilModule'].ModuleScript.lua | 214 +++++++++++++----- 1 file changed, 163 insertions(+), 51 deletions(-) diff --git a/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua index 81b6e87..3b109b7 100644 --- a/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua @@ -1,65 +1,177 @@ --- 音效播放模块 ----@module SoundUtil ----@copyright Lilith Games, Avatar Team ----@author Sharif Ma ----@class SoundUtil +--- @module SoundUtil +--- @copyright Lilith Games, Avatar Team +--- @author Dead Ratman local SoundUtil = {} -function SoundUtil:Init() - print('[SoundUtil] Init()') - self.SoundPlaying = {} - self.Table_Sound = Config.Sound +--音频 +local clipTable = nil + +--音效对象池 +local audioSourcePool = { + SE3D = {}, --3D音效 + SE2D = {} --2D音效 +} + +--3D音效对象池上限 +local SE3DMax = 8 +--2D音效对象池上限 +local SE2DMax = 3 + +--! Debug模式 +local DebugMode = true + +--- 打印日志 +local PrintLog = DebugMode and function(...) + --print('[SoundUtil]', ...) + end or function() + end + +--初始化音频表 +local function InitClipTable(_data) + clipTable[_data.ID] = { + id = _data.ID, + clip = ResourceManager.GetSoundClip(_data.Path), + isLoop = _data.IsLoop, + volume = _data.Volume, + minDistance = _data.MinDistance, + maxDistance = _data.MaxDistance + } + --PrintLog(table.dump(clipTable[_data.ID])) +end + +--初始化一个2D播放器 +local function Init2DAudioSource(_index, _uid) + audioSourcePool.SE2D[_uid][_index] = + world:CreateObject( + 'AudioSource', + 'AudioSource' .. _index, + world:GetPlayerByUserId(_uid).Local.Independent.GameCam.SENode, + world:GetPlayerByUserId(_uid).Local.Independent.GameCam.SENode.Position + ) + return audioSourcePool.SE2D[_uid][_index] end ----创建一个新音效并播放 ----@param _ID number 音效的ID ----@param _SoundSourceObj Object 音效的挂载物体,不填则为2D音效,挂载在主摄像机上 -function SoundUtil:PlaySound(_ID, _SoundSourceObj) - local Info, _Duration - _SoundSourceObj = _SoundSourceObj or world.CurrentCamera - Info = self.Table_Sound[_ID] - assert(Info, '[SoundUtil] 表中不存在该ID的音效') - _Duration = Info.Duration - local sameSoundPlayingNum = 0 - for k, v in pairs(self.SoundPlaying) do - if v == _ID then - sameSoundPlayingNum = sameSoundPlayingNum + 1 +--初始化一个3D播放器 +local function Init3DAudioSource(_index) + audioSourcePool.SE3D[_index] = world:CreateObject('AudioSource', 'AudioSource' .. _index, world.SENode) + return audioSourcePool.SE3D[_index] +end + +function SoundUtil.Init(_config) + if clipTable == nil then + clipTable = {} + for k, v in pairs(_config) do + InitClipTable(v) end end - if sameSoundPlayingNum > 0 and not Info.CoverPlay then - print(string.format('[SoundUtil] %s音效CoverPlay字段为false,不能覆盖播放', _ID)) - return +end + +--初始化音效播放器对象池 +function SoundUtil.InitAudioSource(_uid) + if _uid then + audioSourcePool.SE2D[_uid] = {} + for i = 1, SE2DMax do + Init2DAudioSource(i, _uid) + end + else + for i = 1, SE3DMax do + Init3DAudioSource(i) + end end +end - local Audio = world:CreateObject('AudioSource', 'Audio_' .. Info.FileName, _SoundSourceObj) - Audio.LocalPosition = Vector3.Zero - Audio.SoundClip = ResourceManager.GetSoundClip('Audio/' .. Info.FileName) - print('[SoundUtil] Audio.SoundClip', Audio.SoundClip) - Audio.Volume = Info.Volume - Audio.MaxDistance = 10 - Audio.MinDistance = 10 - Audio.Loop = Info.IsLoop - Audio:Play() - table.insert(self.SoundPlaying, _ID) - _Duration = _Duration or 1 - invoke( - function() - if Audio then - Audio:Destroy() +--释放多余播放器 +local function ReleaeseSource(_uid) + local index = 0 + if _uid then + index = SE2DMax + 1 + while table.nums(audioSourcePool.SE2D[_uid]) > index - 1 do + if audioSourcePool.SE2D[_uid][index].State == Enum.AudioSourceState.Stopped then + local ReleaesedSource = audioSourcePool.SE2D[_uid][index] + table.remove(audioSourcePool.SE2D[_uid], index) + ReleaesedSource:Destroy() + else + index = index + 1 end - end, - _Duration - ) - invoke( - function() - for k, v in pairs(self.SoundPlaying) do - if v == _ID then - table.remove(self.SoundPlaying, k) - end + end + else + index = SE3DMax + 1 + while table.nums(audioSourcePool.SE3D) > index - 1 do + if audioSourcePool.SE3D[index].State == Enum.AudioSourceState.Stopped then + local ReleaesedSource = audioSourcePool.SE3D[index] + table.remove(audioSourcePool.SE3D, index) + ReleaesedSource:Destroy() + else + index = index + 1 end - end, - _Duration - ) + end + end +end + +--播放2D音频 +function SoundUtil.Play2DSE(_uid, _SEID) + local index = nil + local source = nil + for k, v in pairs(audioSourcePool.SE2D[_uid]) do + if v.State == Enum.AudioSourceState.Stopped then + index = k + source = v + break + end + end + if source == nil then + index = table.nums(audioSourcePool.SE2D[_uid]) + 1 + source = Init2DAudioSource(table.nums(audioSourcePool.SE2D[_uid]) + 1, _uid) + end + --PrintLog('播放2D音频', _SEID) + source.MinDistance = clipTable[_SEID].minDistance + source.MaxDistance = clipTable[_SEID].maxDistance + source.Loop = clipTable[_SEID].isLoop + source.Volume = clipTable[_SEID].volume + source.SoundClip = clipTable[_SEID].clip + source:Play() + ReleaeseSource(_uid) + return index +end + +--播放3D音频 +function SoundUtil.Play3DSE(_pos, _SEID) + local index = nil + local source = nil + for k, v in pairs(audioSourcePool.SE3D) do + if v.State == Enum.AudioSourceState.Stopped then + index = k + source = v + break + end + end + if source == nil then + index = table.nums(audioSourcePool.SE3D) + 1 + source = Init3DAudioSource(table.nums(audioSourcePool.SE3D) + 1) + end + --PrintLog('播放3D音频', _SEID, table.dump(clipTable[_SEID]), _pos) + source.Position = _pos + source.MinDistance = clipTable[_SEID].minDistance + source.MaxDistance = clipTable[_SEID].maxDistance + source.Loop = clipTable[_SEID].isLoop + source.Volume = clipTable[_SEID].volume + source.SoundClip = clipTable[_SEID].clip + source:Play() + ReleaeseSource() + return index +end + +--停止播放2D音频 +function SoundUtil.Stop2DSE(_uid, _index) + audioSourcePool.SE2D[_uid][_index]:Stop() + ReleaeseSource(_uid) +end + +--停止播放3D音频 +function SoundUtil.Stop3DSE(_index) + audioSourcePool.SE3D[_index]:Stop() + ReleaeseSource() end return SoundUtil From b1efc59810f1638f584fbcf7da74ff3dd219b2c3 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:06:55 +0800 Subject: [PATCH 25/39] Update ['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua --- ...ld']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua index 3b109b7..d002aed 100644 --- a/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua @@ -59,6 +59,7 @@ local function Init3DAudioSource(_index) end function SoundUtil.Init(_config) + print('[SoundUtil] Init(_config)') if clipTable == nil then clipTable = {} for k, v in pairs(_config) do From d6ddba52330f16df16bd3db0104519b6600ccd04 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:08:49 +0800 Subject: [PATCH 26/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0ObjPoolUtil=20by=20?= =?UTF-8?q?=E8=A2=81=E6=99=A8=E6=9B=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ty']['ObjPoolUtilModule'].ModuleScript.lua | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua index b276648..defe937 100644 --- a/Code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Utility']['ObjPoolUtilModule'].ModuleScript.lua @@ -1,8 +1,7 @@ ---对象池工具模块 ----@module ObjPoolUtil +---@class ObjPoolUtil -- @copyright Lilith Games, Avatar Team -- @author Yen Yuan ----@class ObjPoolUtil local ObjPoolUtil = class('ObjPoolUtil') ---创建某一个对象的对象池 @@ -26,6 +25,17 @@ function ObjPoolUtil.static.Newpool(_folderName, _objName, _maxCount) return realPool end +---从池中预创建对象到世界下 +---@param _position Vector3 +function ObjPoolUtil:PreSpawn(_position) + for i = 1, self.maxCount do + local realObj = world:CreateInstance(self.obj, self.obj, self.folder, _position) + realObj.IsStatic = true + table.insert(self.pool, realObj) + realObj:SetActive(false) + end +end + ---从池中创建对象到世界下 ---@param _position Vector3 ---@param _rotation EulerDegree @@ -41,7 +51,8 @@ function ObjPoolUtil:Spawn(_position, _rotation) else realObj = self.pool[1] self.pool[1].Position = _position - self.pool[1].Rotation = _rotation + self.pool[1].Rotation = _rotation or EulerDegree(0, 0, 0) + self.pool[1].IsStatic = false self.pool[1]:SetActive(true) table.remove(self.pool, 1) return realObj @@ -54,11 +65,12 @@ function ObjPoolUtil:Despawn(_obj) if _obj == nil then error('[ObjPoolUtil] 传入对象为空') elseif #self.pool > self.maxCount then - error(string.format('[ObjPoolUtil] %s对象池已满,该对象会永久销毁', self.obj)) + print(string.format('[ObjPoolUtil] %s对象池已满,该对象会永久销毁', self.obj)) _obj:Destroy() else table.insert(self.pool, _obj) _obj:SetActive(false) + self.pool[1].IsStatic = true end end From 865199918266831096f725da0fa2003550185f95 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:10:57 +0800 Subject: [PATCH 27/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0NetUtil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tility']['NetUtilModule'].ModuleScript.lua | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua index ec3ddaa..7e4ccdd 100644 --- a/Code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Utility']['NetUtilModule'].ModuleScript.lua @@ -36,9 +36,9 @@ end -- @param _player 玩家对象 -- @param ... 事件参数 function NetUtil.Fire_C(_eventName, _player, ...) - if(_player == nil) then - return - end + if _player == nil then + return + end ValidateArgs(FireEnum.CLIENT, _eventName, _player) local args = {...} _player.C_Event[_eventName]:Fire(table.unpack(args)) @@ -85,6 +85,7 @@ ValidateArgs = _player and _player.ClassName == 'PlayerInstance', string.format('[NetUtil][Fire_C]第2个参数需要是玩家对象, 错误事件: %s', _eventName) ) + assert(_player.C_Event, '[NetUtil][Fire_C]第2个参数需要是玩家对象, 错误事件: %s', _eventName) assert( _player.C_Event[_eventName], string.format('[NetUtil][Fire_C] 客户端玩家不存在事件: %s, 玩家: %s', _player.Name, _eventName) @@ -98,15 +99,17 @@ ValidateArgs = end --- 打印事件日志 -PrintEventLog = showLog and function(_fireEnum, _eventName, _player, _args) +PrintEventLog = + showLog and + function(_fireEnum, _eventName, _player, _args) if _fireEnum == FireEnum.SERVER then --* Fire_S 参数打印 - print(string.format('[NetUtil][服务器] %s, 参数 = %s, %s', _eventName, #_args, table.dump(_args))) + print(string.format('[NetUtil][发出服务器事件] %s, 参数 = %s, %s', _eventName, #_args, table.dump(_args))) elseif _fireEnum == FireEnum.CLIENT then --* Fire_C 参数打印 print( string.format( - '[NetUtil][客户端] %s, 玩家=%s, 参数 = %s, %s', + '[NetUtil][发出客户端事件] %s, 玩家=%s, 参数 = %s, %s', _eventName, _player.Name, #_args, @@ -114,10 +117,11 @@ PrintEventLog = showLog and function(_fireEnum, _eventName, _player, _args) ) ) elseif _fireEnum == FireEnum.BROADCAST then - --* Broadcase 参数打印 - print(string.format('[NetUtil][客户端][广播] %s, 参数 = %s, %s', _eventName, #_args, table.dump(_args))) + --* Broadcast 参数打印 + print(string.format('[NetUtil][发出客户端广播事件] %s, 参数 = %s, %s', _eventName, #_args, table.dump(_args))) end - end or function() + end or + function() end return NetUtil From 90d789b041960332470d2382be4b6c1ee0df671b Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:16:25 +0800 Subject: [PATCH 28/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0ModuleUtil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Utility']['ModuleUtilModule'].ModuleScript.lua | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua index fc900a4..6fd959e 100644 --- a/Code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Utility']['ModuleUtilModule'].ModuleScript.lua @@ -11,23 +11,26 @@ local ModuleUtil = {} function ModuleUtil.LoadModules(_root, _scope) _scope = _scope or _G assert(_root, '[ModuleUtil] Node does NOT exist!') - local tmp = _root:GetChildren() + local tmp, name = _root:GetChildren() for _, v in pairs(tmp) do - name = (v.Name):gsub('Module', '') - -- print('[ModuleUtil] Load: ' .. name) - _scope[name] = require(v) + if v.ClassName == 'ModuleScriptObject' then + name = (v.Name):gsub('Module', '') + print('[ModuleUtil] Load Module: ', name) + _scope[name] = require(v) + end end end --- 加载XLS表格目录 -- @param _root 模块目录的节点 +-- @param _config 所有Excel生成Lua文件的所在table,不允许是_G function ModuleUtil.LoadXlsModules(_root, _config) assert(_root, '[ModuleUtil] Node does NOT exist!') assert(_config, '[ModuleUtil] Config does NOT exist!') - local tmp = _root:GetChildren() + local tmp, name = _root:GetChildren() for _, v in pairs(tmp) do name = (v.Name):gsub('XlsModule', '') - print('[ModuleUtil] Load: ' .. name) + print('[ModuleUtil] Load XLS: ', name) _config[name] = require(v) end end From bfa282131d14184b7853f68daaac0c793fe379b9 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:17:27 +0800 Subject: [PATCH 29/39] =?UTF-8?q?=E5=88=A0=E9=99=A4LogUtil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tility']['LogUtilModule'].ModuleScript.lua | 45 ------------------- 1 file changed, 45 deletions(-) delete mode 100644 Code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua diff --git a/Code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua deleted file mode 100644 index c4de8af..0000000 --- a/Code/['World']['Global']['Utility']['LogUtilModule'].ModuleScript.lua +++ /dev/null @@ -1,45 +0,0 @@ ---- Debug工具 --- @module Debug utilities --- @copyright Lilith Games, Avatar Team --- @author Yuancheng Zhang -local LogUtil = {} - ---- 日志级别枚举 -LogUtil.LevelEnum = { - -- 指出细粒度信息事件对调试应用程序是非常有帮助的 主要用于开发过程中打印一些运行信息 - DEBUG = 1, - -- 消息在粗粒度级别上突出强调应用程序的运行过程 - -- 打印一些你感兴趣的或者重要的信息 这个可以用于生产环境中输出程序运行的一些重要信息 - -- 但是不能滥用 避免打印过多的日志 - INFO = 2, - -- 表明会出现潜在错误的情形 有些信息不是错误信息 但是也要给程序员的一些提示 - -- 指出虽然发生错误事件 但仍然不影响系统的继续运行 - -- 打印错误和异常信息 如果不想输出太多的日志 可以使用这个级别 - ERROR = 3 -} - ---- 日志级别 -LogUtil.level = LogUtil.LevelEnum.DEBUG - ---- 开关 -LogUtil.debugMode = true - -function LogUtil.Test(...) - if LogUtil.debugMode and LogUtil.level <= LogUtil.LevelEnum.DEBUG then - print('[TEST]', ...) - end -end - -function LogUtil.Debug(...) - if LogUtil.debugMode and LogUtil.level <= LogUtil.LevelEnum.DEBUG then - print('[DEBUG]', ...) - end -end - -function LogUtil.Info(...) - if LogUtil.debugMode and LogUtil.level <= LogUtil.LevelEnum.INFO then - print('[INFO]', ...) - end -end - -return LogUtil From 9f921f6bd4e04118d1a5ea7f8e4a222d5e128d5c Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:18:43 +0800 Subject: [PATCH 30/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0GlobalFunc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...bal']['Utility']['GlobalFuncModule'].ModuleScript.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua index f5c4474..a294671 100644 --- a/Code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Utility']['GlobalFuncModule'].ModuleScript.lua @@ -1,7 +1,7 @@ --- 全局函数的定义 --- @module GlobalFunc Defines --- @copyright Lilith Games, Avatar Team ---- @author Sid Zhang +--- @author Sid Zhang, Yuancheng Zhang local GlobalFunc = {} --- 埋点上传日志 @@ -23,4 +23,11 @@ function GlobalFunc.UploadLogs(_tableName, ...) end end +-- 检查碰撞对象是否为NPC +-- Server-side 一般用于服务器端 +function GlobalFunc.CheckHitObjIsPlayer(_hitObj) + return _hitObj and _hitObj.ClassName == 'PlayerInstance' and _hitObj.Avatar and + _hitObj.Avatar.ClassName == 'PlayerAvatarInstance' +end + return GlobalFunc From 8fe0a72e16937838f525b4ad9495ebca26b23ad3 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:42:40 +0800 Subject: [PATCH 31/39] =?UTF-8?q?=E6=97=A0=E6=95=8C=E7=AE=80=E5=8C=96AutoA?= =?UTF-8?q?ssignTeamScript?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...lobal']['AutoAssignTeamScript'].Script.lua | 27 ++----------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/Code/['World']['Global']['AutoAssignTeamScript'].Script.lua b/Code/['World']['Global']['AutoAssignTeamScript'].Script.lua index 49b8ef4..98c605f 100644 --- a/Code/['World']['Global']['AutoAssignTeamScript'].Script.lua +++ b/Code/['World']['Global']['AutoAssignTeamScript'].Script.lua @@ -2,30 +2,7 @@ -- @script Auto assign -- @copyright Lilith Games, Avatar Team ---- 编辑器默认方法 +--- 编辑器默认方法, 删了报错 -- run once when script init -function autoAssign() - local container = world:FindTeams() - local min = 1 - local teamTojoin = {} - local playerfolder = world.Players - for i = 1, #container, 1 do - if container[i].CurrentMaxMemberNum > 0 then - temp = container[i].CurrentMemberNum / (container[i].CurrentMaxMemberNum) - if (temp < min and temp ~= 1) then - teamTojoin = {} - min = temp - table.insert(teamTojoin, container[i]) - elseif temp == min and temp ~= 1 then - table.insert(teamTojoin, container[i]) - end - end - end - local a = 1 - if #teamTojoin > 0 then - a = math.random(1, #teamTojoin) - return teamTojoin[a] - else - return nil - end +autoAssign = function() end From 68dd54caef3dec662b40fa0701abdfdcc809cc2f Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:45:07 +0800 Subject: [PATCH 32/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0LuaFunction=EF=BC=9A?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0UidCounter()=20by=20=E5=BC=A0=E5=BF=83?= =?UTF-8?q?=E6=82=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Code/['World']['Global']['LuaFunctionScript'].Script.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/['World']['Global']['LuaFunctionScript'].Script.lua b/Code/['World']['Global']['LuaFunctionScript'].Script.lua index 02fe3c5..764201a 100644 --- a/Code/['World']['Global']['LuaFunctionScript'].Script.lua +++ b/Code/['World']['Global']['LuaFunctionScript'].Script.lua @@ -957,12 +957,12 @@ function Stack:PrintElement() print(str) end - --- uid递增计数器 +--- @author Sid Zhang function UidCounter() local num = 0 return function() num = num + 1 - return tostring(os.clock())..'-'..tostring(num) + return string.format('%s-%s', os.clock(), num) end end From 566b64fafb5faa3475c648590f75c5527dbcc193 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 19:46:20 +0800 Subject: [PATCH 33/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0ModuleRequireScript?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ld']['Global']['ModuleRequireScript'].Script.lua | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Code/['World']['Global']['ModuleRequireScript'].Script.lua b/Code/['World']['Global']['ModuleRequireScript'].Script.lua index 6b39fcf..825eb1e 100644 --- a/Code/['World']['Global']['ModuleRequireScript'].Script.lua +++ b/Code/['World']['Global']['ModuleRequireScript'].Script.lua @@ -2,6 +2,10 @@ -- @script Module Defines -- @copyright Lilith Games, Avatar Team +-- Game Defines +GAME_ID = 'X0000' +print('GAME_ID = ', GAME_ID) + -- Utilities ModuleUtil = require(Utility.ModuleUtilModule) LuaJsonUtil = require(Utility.LuaJsonUtilModule) @@ -16,16 +20,17 @@ LinkedList = Utility.LinkedListModule ValueChangeUtil = require(Utility.ValueChangeUtilModule) TimeUtil = require(Utility.TimeUtilModule) CloudLogUtil = require(Utility.CloudLogUtilModule) +ObjPoolUtil = require(Utility.ObjPoolUtilModule) +SoundUtil = require(Utility.SoundUtilModule) --- Game Defines -GAME_ID = 'X0000' - --- Utility Initilization +-- Init Utilities TimeUtil.Init() CloudLogUtil.Init(GAME_ID) -- Framework ModuleUtil.LoadModules(Framework) +ModuleUtil.LoadModules(Framework.Server) +ModuleUtil.LoadModules(Framework.Client) -- Globle Defines ModuleUtil.LoadModules(Define) From decc82c0ff185216832ec43475fd4ee273b0d9c3 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 20:07:36 +0800 Subject: [PATCH 34/39] Update ['World']['Global']['Define']['ConstModule'].ModuleScript.lua --- ...'World']['Global']['Define']['ConstModule'].ModuleScript.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua b/Code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua index 2071385..c12cba4 100644 --- a/Code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Define']['ConstModule'].ModuleScript.lua @@ -6,7 +6,7 @@ local Const = {} -- e.g. (need DELETE) Const.MAX_PLAYERS = 4 ---语言枚举 +-- 语言枚举 Const.LanguageEnum = { CHS = 'CHS', -- 简体中文 CHT = 'CHT', -- 繁体中文 From 8557cbb4c39cc5dd1247c465e7a4c789c8e7ae27 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 20:09:28 +0800 Subject: [PATCH 35/39] =?UTF-8?q?=E6=B7=BB=E5=8A=A0DefaultModule=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E4=BA=8EGloba=E5=92=8CPlayer=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Define']['DefaultModule'].ModuleScript.lua | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Code/['World']['Global']['Define']['DefaultModule'].ModuleScript.lua diff --git a/Code/['World']['Global']['Define']['DefaultModule'].ModuleScript.lua b/Code/['World']['Global']['Define']['DefaultModule'].ModuleScript.lua new file mode 100644 index 0000000..3595d73 --- /dev/null +++ b/Code/['World']['Global']['Define']['DefaultModule'].ModuleScript.lua @@ -0,0 +1,27 @@ +--- 全局默认定义:用于定义数据,节点属性等 +--- @module Data Default +--- @copyright Lilith Games, Avatar Team +local Default = {} + +--! 说明:这个module当作脚本使用 + +--* Data.Global和Data.Player中的默认值,用于框架初始化 + +Data.Default = Data.Default or {} + +-- 全局变量定义 +Data.Default.Global = {} + +-- 玩家数据,初始化定义 +Data.Default.Player = { + -- 玩家ID, 框架默认 + uid = '', + -- 玩家属性 + attr = {}, + -- 背包 + bag = {}, + -- 统计数据 + stats = {} +} + +return Default From 9172e719fe38bc71492cd1df7933ae8499d3a771 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 20:10:53 +0800 Subject: [PATCH 36/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0Framework=EF=BC=9A?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=95=B0=E6=8D=AE=E5=90=8C=E6=AD=A5=E5=92=8C?= =?UTF-8?q?=E9=95=BF=E6=9C=9F=E5=AD=98=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ine']['GlobalDataModule'].ModuleScript.lua | 9 - ...nt']['ClientBaseModule'].ModuleScript.lua} | 11 +- ...]['ClientDataSyncModule'].ModuleScript.lua | 101 +++++++ ...'ClientHeartbeatModule'].ModuleScript.lua} | 26 +- ...Client']['ClientModule'].ModuleScript.lua} | 36 ++- ...Framework']['DataModule'].ModuleScript.lua | 18 ++ ...['FrameworkConfigModule'].ModuleScript.lua | 19 +- ...ework']['MetaDataModule'].ModuleScript.lua | 274 +++++++++++++++++ ...er']['ServerBaseModule'].ModuleScript.lua} | 11 +- ...]['ServerDataSyncModule'].ModuleScript.lua | 285 ++++++++++++++++++ ...'ServerHeartbeatModule'].ModuleScript.lua} | 48 +-- ...Server']['ServerModule'].ModuleScript.lua} | 41 ++- 12 files changed, 812 insertions(+), 67 deletions(-) delete mode 100644 Code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua rename Code/{['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua => ['World']['Global']['Framework']['Client']['ClientBaseModule'].ModuleScript.lua} (55%) create mode 100644 Code/['World']['Global']['Framework']['Client']['ClientDataSyncModule'].ModuleScript.lua rename Code/{['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua => ['World']['Global']['Framework']['Client']['ClientHeartbeatModule'].ModuleScript.lua} (83%) rename Code/{['World']['Global']['Framework']['ClientModule'].ModuleScript.lua => ['World']['Global']['Framework']['Client']['ClientModule'].ModuleScript.lua} (82%) create mode 100644 Code/['World']['Global']['Framework']['DataModule'].ModuleScript.lua create mode 100644 Code/['World']['Global']['Framework']['MetaDataModule'].ModuleScript.lua rename Code/{['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua => ['World']['Global']['Framework']['Server']['ServerBaseModule'].ModuleScript.lua} (54%) create mode 100644 Code/['World']['Global']['Framework']['Server']['ServerDataSyncModule'].ModuleScript.lua rename Code/{['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua => ['World']['Global']['Framework']['Server']['ServerHeartbeatModule'].ModuleScript.lua} (75%) rename Code/{['World']['Global']['Framework']['ServerModule'].ModuleScript.lua => ['World']['Global']['Framework']['Server']['ServerModule'].ModuleScript.lua} (80%) diff --git a/Code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua b/Code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua deleted file mode 100644 index 2e15412..0000000 --- a/Code/['World']['Global']['Define']['GlobalDataModule'].ModuleScript.lua +++ /dev/null @@ -1,9 +0,0 @@ ---- 全局变量的定义,全部定义在GlobalData这张表下面,用于全局可修改的参数 ---- @module GlobalData Defines ---- @copyright Lilith Games, Avatar Team -local GlobalData = {} - --- Test only -GlobalData.PlayerData = {} - -return GlobalData diff --git a/Code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Client']['ClientBaseModule'].ModuleScript.lua similarity index 55% rename from Code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua rename to Code/['World']['Global']['Framework']['Client']['ClientBaseModule'].ModuleScript.lua index 1deb376..f084843 100644 --- a/Code/['World']['Global']['Framework']['ClientBaseModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Client']['ClientBaseModule'].ModuleScript.lua @@ -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 diff --git a/Code/['World']['Global']['Framework']['Client']['ClientDataSyncModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Client']['ClientDataSyncModule'].ModuleScript.lua new file mode 100644 index 0000000..1b1cd4e --- /dev/null +++ b/Code/['World']['Global']['Framework']['Client']['ClientDataSyncModule'].ModuleScript.lua @@ -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 diff --git a/Code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Client']['ClientHeartbeatModule'].ModuleScript.lua similarity index 83% rename from Code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua rename to Code/['World']['Global']['Framework']['Client']['ClientHeartbeatModule'].ModuleScript.lua index 07f4be4..da70480 100644 --- a/Code/['World']['Global']['Framework']['ClientHeartbeatModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Client']['ClientHeartbeatModule'].ModuleScript.lua @@ -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 = { @@ -37,8 +37,8 @@ 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 @@ -46,14 +46,14 @@ local PrintHb = Setting.ShowHeartbeatLog and function(...) --- 初始化心跳包 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 @@ -64,7 +64,7 @@ end -- 停止心跳 function ClientHeartbeat.Stop() - print('[Heartbeat][Client] Stop()') + --print('[Heartbeat][Client] Stop()') running = false end @@ -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 @@ -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 @@ -162,7 +162,7 @@ end --- 退出游戏 function QuitGame() - print('[Heartbeat][Client] Game.Quit(), 玩家退出游戏') + --print('[Heartbeat][Client] Game.Quit(), 玩家退出游戏', localPlayer, localPlayer.UserId) Game.Quit() end diff --git a/Code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Client']['ClientModule'].ModuleScript.lua similarity index 82% rename from Code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua rename to Code/['World']['Global']['Framework']['Client']['ClientModule'].ModuleScript.lua index fc59abd..eaccec4 100644 --- a/Code/['World']['Global']['Framework']['ClientModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Client']['ClientModule'].ModuleScript.lua @@ -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 @@ -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() @@ -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 @@ -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) @@ -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 @@ -116,7 +123,7 @@ end --- 开始Update function StartUpdate() - print('[Client] StartUpdate()') + --print('[Client] StartUpdate()') assert(not running, '[Client] StartUpdate() 正在运行') running = true @@ -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 --时间函数缓存 diff --git a/Code/['World']['Global']['Framework']['DataModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['DataModule'].ModuleScript.lua new file mode 100644 index 0000000..621752a --- /dev/null +++ b/Code/['World']['Global']['Framework']['DataModule'].ModuleScript.lua @@ -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 diff --git a/Code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua index f0a515c..5e2b5a6 100644 --- a/Code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['FrameworkConfigModule'].ModuleScript.lua @@ -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, @@ -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, @@ -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 } } diff --git a/Code/['World']['Global']['Framework']['MetaDataModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['MetaDataModule'].ModuleScript.lua new file mode 100644 index 0000000..7a40ea6 --- /dev/null +++ b/Code/['World']['Global']['Framework']['MetaDataModule'].ModuleScript.lua @@ -0,0 +1,274 @@ +--- 游戏同步数据基类 +--- @module Sync Data Base, Both-side +--- @copyright Lilith Games, Avatar Team +--- @author Yuancheng Zhang +local MetaData = {} + +-- Localize global vars +local FrameworkConfig = FrameworkConfig + +--* 开关:Debug模式,开启后会打印日志 +local debugMode = false +--* 开关:数据校验 +local valid = true + +-- enum +MetaData.Enum = {} +-- 数据类型:全局 or 玩家 +MetaData.Enum.GLOBAL = 'Global' +MetaData.Enum.PLAYER = 'Player' + +-- 是否进行同步,数据初始化之后在开启同步 +MetaData.ServerSync = false +MetaData.ClientSync = false + +--! 说明:两种双向同步机制 +--* 1. Data.Global +-- a. 客户端和服务器持有相同的数据类型 Data.Global +-- b. C=>S,某一客户端更新,自动发送给服务器,服务器更新,然后再同步给全部客户端 +-- c. S=>C,服务器更新,广播给所有客户端,客户端各自更新 +--* 2. Data.Player +-- a. 客户端只持有自己的 Data.Player +-- b. 服务器持有全部玩家的 Data.Players +-- c. C=>S,客户端更新,自动发送给服务器,服务器更新对应玩家数据 +-- d. S=>C,服务器更新,自动发送给对应客户端,客户端更新玩家数据 + +--! 私有方法 + +--- 新建一个MetaData的proxy,用于数据同步 +-- @param _data 真实数据 +-- @param _path 当前节点索引路径 +-- @param _uid UserId +-- @return proxy 代理table,没有data,元表内包含方法和path +function NewData(_data, _path, _uid) + local proxy = {} + local mt = { + _data = _data, + _path = _path, + _uid = _uid, + __index = function(_t, _k) + local mt = getmetatable(_t) + local newpath = mt._path .. '.' .. _k + PrintLog('__index,', '_k = ', _k, ', _path = ', mt._path, ', newpath = ', newpath) + return _data[newpath] + end, + __newindex = function(_t, _k, _v) + local mt = getmetatable(_t) + local newpath = mt._path .. '.' .. _k + PrintLog('__newindex,', '_k =', _k, ', _v =', _v, ', _path = ', mt._path, ', newpath = ', newpath) + SetData(_data, newpath, _v, _uid, true) + end, + __pairs = function() + -- pairs()需要返回三个参数:next, _t, nil + -- https://www.lua.org/pil/7.3.html + -- 得到rd(raw data),从rd中进行遍历 + local rd = GetData(_data, _path) + return next, rd, nil + end + } + setmetatable(proxy, mt) + return proxy +end + +--- 获得原始数据 +-- @param _data 真实数据的存储位置 +-- @param _path 当前节点索引路径 +-- @return rawData 纯数据table,不包含元表 +function GetData(_data, _path) + local rawData = {} + GetDataAux(_data, _path, rawData) + return rawData +end + +--- GetData的辅助函数 +-- @param _data 真实数据的存储位置 +-- @param _path 当前节点索引路径 +-- @param _rawData 纯数据table,不包含元表 +function GetDataAux(_data, _path, _rawData) + local key, i + local q, elem = Queue:New(), {} + elem.path = _path + elem.rd = _rawData + q:Enqueue(elem) + while not q:IsEmpty() do + elem = q:Dequeue() + for k, v in pairs(_data) do + i = string.find(k, elem.path .. '.') + -- 筛选出当前直接层级的path,剪裁后作为rawData的key + if i == 1 and #elem.path < #k then + key = string.sub(k, #elem.path + 2, #k) + if not string.find(key, '%.') then + key = tonumber(key) or key + if type(v) == 'table' then + elem.rd[key] = {} + q:Enqueue( + { + path = k, + rd = elem.rd[key] + } + ) + else + elem.rd[key] = v + end + end + end + end + end +end + +--- 设置原始数据 +-- @param _data 真实数据的存储位置 +-- @param _path 当前节点索引路径 +-- @param _value 传入的数据 +-- @param _uid UserId +-- @param _sync true:同步数据 +function SetData(_data, _path, _value, _uid, _sync) + --* 数据同步:赋值的时候只要同步一次就可以的,存下newpath和_v,对方收到后赋值即可 + if _sync and (MetaData.ServerSync or MetaData.ClientSync) then + SyncData(_path, _value, _uid) + end + + local args, newpath = {} + + local q = Queue:New() + q:Enqueue({_data, _path, _value, _uid, _sync}) + + while not q:IsEmpty() do + _data, _path, _value, _uid, _sync = table.unpack(q:Dequeue()) + + --* 数据校验 + Validators(SetData)(_data, _path, _value, _uid, _sync) + + --* 检查现有数据 + if type(_data[_path]) == 'table' then + -- TODO: 这里可以优化,不必要每次都删除 + -- 如果现有数据是个table,删除所有子数据 + for k, _ in pairs(_data[_path]) do + -- 同等于 _data[_path][k] = nil,但是不同步 + newpath = _path .. '.' .. k + q:Enqueue({_data, newpath, nil, _uid, false}) + end + end + + --* 检查新数据 + if type(_value) == 'table' then + -- 若新数据是table,建立一个mt + _data[_path] = NewData(_data, _path, _uid) + for k, v in pairs(_value) do + -- 同等于 _data[_path][k] = v,但是不同步 + newpath = _path .. '.' .. k + q:Enqueue({_data, newpath, v, _uid, false}) + end + else + -- 一般数据,直接赋值 + _data[_path] = _value + end + end +end + +--- 数据同步 +-- @param _path 当前节点索引路径 +-- @param _value 传入的数据 +-- @param _uid UserId +function SyncData(_path, _value, _uid) + if MetaData.ServerSync and MetaData.ClientSync and localPlayer then + -- 服务器/客户端 同虚拟机 + local player = world:GetPlayerByUserId(_uid) + assert(player == localPlayer, string.format('[MetaData] 玩家不存在 uid = %s', _uid)) + PrintLog(string.format('[Server] 发出 player = %s, _path = %s, _value = %s', player, _path, table.dump(_value))) + NetUtil.Fire_C('DataSyncS2CEvent', player, _path, _value) + NetUtil.Fire_S('DataSyncC2SEvent', localPlayer, _path, _value) + elseif localPlayer == nil and string.isnilorempty(_uid) and MetaData.ServerSync then + -- 服务器 => 客户端,Global 全局数据 + NetUtil.Broadcast('DataSyncS2CEvent', _path, _value) + elseif localPlayer == nil and MetaData.ServerSync then + -- 服务器 => 客户端,Player 玩家数据 + local player = world:GetPlayerByUserId(_uid) + assert(player, string.format('[MetaData] 玩家不存在 uid = %s', _uid)) + PrintLog(string.format('[Server] 发出 player = %s, _path = %s, _value = %s', player, _path, table.dump(_value))) + NetUtil.Fire_C('DataSyncS2CEvent', player, _path, _value) + elseif localPlayer and localPlayer.UserId == _uid and MetaData.ClientSync then + -- 客户端 => 服务器 + PrintLog( + string.format('[Client] 发出 player = %s, _path = %s, _value = %s', localPlayer, _path, table.dump(_value)) + ) + NetUtil.Fire_S('DataSyncC2SEvent', localPlayer, _path, _value) + end +end + +--! 公开API + +--- 新建数据 +MetaData.New = NewData + +--- 设置数据 +MetaData.Set = SetData + +--- 从proxy中生成一个纯数据表格 +MetaData.Get = function(_proxy) + local mt = getmetatable(_proxy) + assert(mt, string.format('[MetaData] metatable为空,proxy = %s', table.dump(_proxy))) + return GetData(mt._data, mt._path) +end + +--! 辅助方法 + +--- 打印数据同步日志 +PrintLog = FrameworkConfig.DebugMode and debugMode and function(...) + --print('[MetaData]', ...) + end or function() + end + +-- 数据校验 +function Validators(func) + if not valid then + return function() + end + end + + if func == SetData then + return function(_data, _path, _value, _uid, _sync) + assert( + _data, + string.format( + '[MetaData] data为空 data = %s, path = %s, uid = %s, sync = %s, value = %s', + _data, + _path, + _uid, + _sync, + table.dump(_value) + ) + ) + assert( + not string.isnilorempty(_path), + string.format( + '[MetaData] path为空 data = %s, path = %s, uid = %s, sync = %s, value = %s', + _data, + _path, + _uid, + _sync, + table.dump(_value) + ) + ) + end + end +end + +return MetaData + +--! Command Test only +--[[ +Data.Global.a = 11 +Data.Global.b = {22, 33} +Data.Global.c = {c1 = {44, 55}, c2 = 66} +Data.Global.c.c3 = {c4 = 77} +Data.Global.d = {'88', Vector3(9,9,9)} +--print(table.dump(Data.Global)) +--print(table.dump(MetaData.Get(Data.Global))) + +--print(table.dump(Data.Player)) + +--print(table.dump(Data.Players)) + +--print(table.dump(Data.Players['pid:local_1'])) +]] diff --git a/Code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Server']['ServerBaseModule'].ModuleScript.lua similarity index 54% rename from Code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua rename to Code/['World']['Global']['Framework']['Server']['ServerBaseModule'].ModuleScript.lua index 213f46e..bec7b32 100644 --- a/Code/['World']['Global']['Framework']['ServerBaseModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Server']['ServerBaseModule'].ModuleScript.lua @@ -10,9 +10,18 @@ end --- 加载的时候运行的代码 function ServerBase:InitDefault(_module) - -- print(string.format('[ServerBase][%s] InitDefault()', self.name)) + -- --print(string.format('[ServerBase][%s] InitDefault()', self.name)) -- 初始化默认监听事件 EventUtil.LinkConnects(world.S_Event, _module, self) end +--- Debug模式下打印日志 +-- self.debug 针对模块本身的debug开关 +-- FrameworkConfig.DebugMode 框架中的全局debug开关 +function ServerBase:Log(...) + if self.debug and FrameworkConfig.DebugMode then + --print(string.format('[%s]', self.name), ...) + end +end + return ServerBase diff --git a/Code/['World']['Global']['Framework']['Server']['ServerDataSyncModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Server']['ServerDataSyncModule'].ModuleScript.lua new file mode 100644 index 0000000..69fe9a1 --- /dev/null +++ b/Code/['World']['Global']['Framework']['Server']['ServerDataSyncModule'].ModuleScript.lua @@ -0,0 +1,285 @@ +--- 游戏服务器数据同步 +--- @module Server Sync Data, Server-side +--- @copyright Lilith Games, Avatar Team +--- @author Yuancheng Zhang +local ServerDataSync = {} + +-- Localize global vars +local FrameworkConfig, MetaData, DataStore = FrameworkConfig, MetaData, DataStore + +-- 服务器端私有数据 +local rawDataGlobal = {} +local rawDataPlayers = {} + +-- 玩家数据定时保存时间间隔(秒) +local AUTO_SAVE_TIME = FrameworkConfig.DatabaseAutoSaveTime +-- 重新读取游戏数据时间间隔(秒) +local RELOAD_TIME = 1 + +-- 玩家数据表格 +local sheet + +--- 打印数据同步日志 +local PrintLog = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowDataSyncLog and function(...) + --print('[DataSync][Server]', ...) + end or function() + end + +--! 初始化 + +--- 数据初始化 +function ServerDataSync.Init() + --print('[DataSync][Server] Init()') + InitEventsAndListeners() + InitDefines() + sheet = DataStore:GetSheet('PlayerData') +end + +--- 初始化事件和绑定Handler +function InitEventsAndListeners() + if world.S_Event == nil then + world:CreateObject('FolderObject', 'S_Event', world) + end + + -- 数据同步事件 + world:CreateObject('CustomEvent', 'DataSyncC2SEvent', world.S_Event) + world.S_Event.DataSyncC2SEvent:Connect(DataSyncC2SEventHandler) + + -- 玩家加入事件 + local onPlayerJoinEvent = world.S_Event.OnPlayerJoinEvent + assert(onPlayerJoinEvent, '[DataSync][Server] 不存在 OnPlayerJoinEvent') + onPlayerJoinEvent:Connect(OnPlayerJoinEventHandler) + + -- 玩家离开事件 + local onPlayerLeaveEvent = world.S_Event.OnPlayerLeaveEvent + assert(onPlayerLeaveEvent, '[DataSync][Server] 不存在 OnPlayerLeaveEvent') + onPlayerLeaveEvent:Connect(OnPlayerLeaveEventHandler) + + -- 长期存储成功事件 + if not world.S_Event.LoadPlayerDataSuccessEvent then + world:CreateObject('CustomEvent', 'LoadPlayerDataSuccessEvent', world.S_Event) + end +end + +--- 校验数据定义 +function InitDefines() + --* 服务器全局数据 + InitDataGlobal() + + --* 服务器玩家数据, key是uid + Data.Players = {} +end + +--- 初始化Data.Global +function InitDataGlobal() + --* 服务器全局数据 + Data.Global = Data.Global or MetaData.New(rawDataGlobal, MetaData.Enum.GLOBAL, nil) + -- 默认赋值 + for k, v in pairs(Data.Default.Global) do + Data.Global[k] = v + end +end + +--- 初始化Data.Players中对应玩家数据 +function InitDataPlayer(_uid) + assert(not string.isnilorempty(_uid)) + --* 服务器端创建Data.Player + local path = MetaData.Enum.PLAYER .. _uid + rawDataPlayers[_uid] = {} + Data.Players[_uid] = MetaData.New(rawDataPlayers[_uid], path, _uid) + + -- 默认赋值 + for k, v in pairs(Data.Default.Player) do + Data.Players[_uid][k] = v + end + + -- 设置uid + Data.Players[_uid].uid = _uid +end + +--- 开始同步 +function ServerDataSync.Start() + --print('[DataSync][Server] 服务器数据同步开启') + MetaData.ServerSync = true + + -- 启动定时器 + TimeUtil.SetInterval(SaveAllGameDataAsync, AUTO_SAVE_TIME) +end + +--! 长期存储:读取 + +--- 下载玩家的游戏数据 +--- @param _uid string 玩家ID +function LoadGameDataAsync(_uid) + sheet = DataStore:GetSheet('PlayerData') + assert(sheet, '[DataSync][Server] DataPlayers的sheet不存在') + sheet:GetValue( + _uid, + function(_val, _msg) + LoadGameDataAsyncCb(_val, _msg, _uid) + end + ) +end + +--- 下载玩家的游戏数据回调 +--- @param _val table 数据 +--- @param _msg int 消息码 +--- @param _uid string 玩家ID +function LoadGameDataAsyncCb(_val, _msg, _uid) + local player = world:GetPlayerByUserId(_uid) + assert(player, string.format('[DataSync][Server] 玩家不存在, uid = %s', _uid)) + if _msg == 0 or _msg == 101 then + --print('[DataSync][Server] 获取玩家数据成功', player.Name) + local hasData = _val ~= nil + if hasData then + --print('[DataSync][Server] 玩家数据,存在', player.Name) + --若以前的数据存在,更新 + -- TODO: 数据兼容的处理 + local data = _val + assert(data.uid == _uid, string.format('[DataSync][Server] uid校验不通过, uid = %s', _uid)) + --若已在此服务器的数据总表存在,则更新数据 + for k, v in pairs(data) do + Data.Players[_uid][k] = data[k] + end + else + -- 不存在数据,用之前生成的默认数据 + --print('[DataSync][Server] 玩家数据,不存在', player.Name) + end + NetUtil.Fire_S('LoadPlayerDataSuccessEvent', player, hasData) + NetUtil.Fire_C('LoadPlayerDataSuccessEvent', player, hasData) + return + end + print( + string.format( + '[DataSync][Server] 获取玩家数据失败,%s秒后重试, uid = %s, player = %s, msg = %s', + RELOAD_TIME, + _uid, + player.Name, + _msg + ) + ) + --若失败,则1秒后重新再读取一次 + invoke( + function() + LoadGameDataAsync(_uid) + end, + RELOAD_TIME + ) +end + +--! 长期存储:保存 + +--- 上传玩家的游戏数据 +--- @param _userId string 玩家ID +--- @param _delete string 保存成功后是否删除缓存数据 +function SaveGameDataAsync(_uid, _delete) + sheet = DataStore:GetSheet('PlayerData') + assert(sheet, '[DataSync][Server] DataPlayers的sheet不存在') + assert(not string.isnilorempty(_uid), '[DataSync][Server] uid不存在或为空') + assert(Data.Players[_uid], string.format('[DataSync][Server] Data.Players[_uid]不存在 uid = %s', _uid)) + local newData = MetaData.Get(Data.Players[_uid]) + assert(newData, string.format('[DataSync][Server] 玩家数据不存在, uid = %s', _uid)) + assert(newData.uid == _uid, string.format('[DataSync][Server] uid校验不通过, uid = %s', _uid)) + sheet:SetValue( + _uid, + newData, + function(_val, _msg) + SaveGameDataAsyncCb(_val, _msg, _uid, _delete) + end + ) +end + +--- 上传玩家的游戏数据回调 +--- @param _val table 数据 +--- @param _msg int 消息码 +--- @param _uid string 玩家ID +function SaveGameDataAsyncCb(_val, _msg, _uid, _delete) + -- 保存成功 + if _msg == 0 then + --print('[DataSync][Server] 保存玩家数据,成功', _uid) + if _delete == true then + --print('[DataSync][Server] 删除服务器玩家数据', _uid) + rawDataPlayers[_uid] = nil + --* 删除玩家端数据 + Data.Players[_uid] = nil + end + return + end + + -- 保存失败 + --print(string.format('[DataSync][Server] 保存玩家数据失败,%s秒后重试, uid = %s, msg = %s', RELOAD_TIME, _uid, _msg)) + --若失败,则1秒后重新再读取一次 + invoke( + function() + SaveGameDataAsync(_uid, _delete) + end, + RELOAD_TIME + ) +end + +--- 存储全部玩家数据 +function SaveAllGameDataAsync() + if not MetaData.ServerSync then + --print('[DataSync][Server] ServerSync未开始') + return + end + --print('[DataSync][Server] 尝试保存全部玩家数据……') + for uid, data in pairs(Data.Players) do + if not string.isnilorempty(uid) and data then + SaveGameDataAsync(uid, false) + end + end +end + +--! Event handler + +--- 数据同步事件Handler +function DataSyncC2SEventHandler(_player, _path, _value) + if not MetaData.ServerSync then + return + end + + PrintLog(string.format('收到 player = %s, _path = %s, _value = %s', _player, _path, table.dump(_value))) + + local uid = _player.UserId + + if string.startswith(_path, MetaData.Enum.GLOBAL) then + --* Data.Global:收到客户端改变数据的时候需要同步给其他玩家 + MetaData.Set(rawDataGlobal, _path, _value, nil, true) + elseif string.startswith(_path, MetaData.Enum.PLAYER .. uid) then + --* Data.Players + MetaData.Set(rawDataPlayers[uid], _path, _value, uid, false) + else + error( + string.format( + '[DataSync][Server] _path错误 _player = %s, _path = %s, _value = %s', + _player, + _path, + table.dump(_data) + ) + ) + end +end + +--- 新玩家加入事件Handler +function OnPlayerJoinEventHandler(_player) + --print('[DataSync][Server] OnPlayerJoinEventHandler', _player, _player.UserId) + --* 向客户端同步Data.Global + NetUtil.Fire_C('DataSyncS2CEvent', _player, MetaData.Enum.GLOBAL, MetaData.Get(Data.Global)) + + local uid = _player.UserId + InitDataPlayer(uid) + + --* 获取长期存储,成功后向客户端同步 + LoadGameDataAsync(uid) +end + +--- 玩家离开事件Handler +function OnPlayerLeaveEventHandler(_player, _uid) + --print('[DataSync][Server] OnPlayerLeaveEventHandler', _player, _uid) + assert(not string.isnilorempty(_uid), '[ServerDataSync] OnPlayerLeaveEventHandler() uid不存在') + --* 保存长期存储:rawDataPlayers[_uid] 保存成功后删掉 + SaveGameDataAsync(_uid, true) +end + +return ServerDataSync diff --git a/Code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Server']['ServerHeartbeatModule'].ModuleScript.lua similarity index 75% rename from Code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua rename to Code/['World']['Global']['Framework']['Server']['ServerHeartbeatModule'].ModuleScript.lua index d79c0bf..d0e0f5b 100644 --- a/Code/['World']['Global']['Framework']['ServerHeartbeatModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Server']['ServerHeartbeatModule'].ModuleScript.lua @@ -5,17 +5,17 @@ local ServerHeartbeat = {} -- Localize global vars -local Setting = FrameworkConfig.Server +local FrameworkConfig = FrameworkConfig -- 心跳包间隔时间,单位:秒 -local HEARTBEAT_DELTA = Setting.HeartbeatDelta +local HEARTBEAT_DELTA = FrameworkConfig.Server.HeartbeatDelta -- 心跳阈值,单位:秒,范围定义如下: -- 0s -> threshold_1 : connected -- threshold_1 -> threshold_2 : disconnected, but player can rejoin -- threshold_2 -> longer : disconnected, remove player -local HEARTBEAT_THRESHOLD_1 = Setting.HeartbeatThreshold1 * 1000 -- second => ms -local HEARTBEAT_THRESHOLD_2 = Setting.HeartbeatThreshold2 * 1000 -- second => ms +local HEARTBEAT_THRESHOLD_1 = FrameworkConfig.Server.HeartbeatThreshold1 * 1000 -- second => ms +local HEARTBEAT_THRESHOLD_2 = FrameworkConfig.Server.HeartbeatThreshold2 * 1000 -- second => ms -- 玩家心跳连接状态 local HeartbeatEnum = { @@ -34,8 +34,8 @@ local diff -- 时间戳插值 local sTmpTs, cTmpTs -- 时间戳缓存 --- 打印心跳日志 -local PrintHb = Setting.ShowHeartbeatLog and function(...) - print('[Heartbeat][Server]', ...) +local PrintHb = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowHeartbeatLog and function(...) + --print('[Heartbeat][Server]', ...) end or function() end @@ -43,14 +43,14 @@ local PrintHb = Setting.ShowHeartbeatLog and function(...) --- 初始化心跳包 function ServerHeartbeat.Init() - print('[Heartbeat][Server] Init()') + --print('[Heartbeat][Server] Init()') CheckSetting() InitEventsAndListeners() end --- 开始发出心跳 function ServerHeartbeat.Start() - print('[Heartbeat][Server] Start()') + --print('[Heartbeat][Server] Start()') running = true while (running) do Update() @@ -60,7 +60,7 @@ end --- 停止心跳 function ServerHeartbeat.Stop() - print('[Heartbeat][Server] Stop()') + --print('[Heartbeat][Server] Stop()') running = false end @@ -100,9 +100,12 @@ function InitEventsAndListeners() -- 玩家退出,发出OnPlayerLeaveEvent world.OnPlayerRemoved:Connect( function(_player) - if cache[_player] then - print('[Heartbeat][Server] OnPlayerLeaveEvent, 玩家主动离开游戏,', _player) - NetUtil.Fire_S('OnPlayerLeaveEvent', _player) + local player = _player + local uid = player.UserId + if cache[player] then + --print('[Heartbeat][Server] OnPlayerLeaveEvent, 玩家主动离开游戏,', player, uid) + NetUtil.Fire_S('OnPlayerLeaveEvent', player, uid) + cache[player] = nil end end ) @@ -139,14 +142,15 @@ end function CheckPlayerJoin(_player) if not cache[_player] then --* 玩家新加入 OnPlayerJoinEvent - print('[Heartbeat][Server] OnPlayerJoinEvent, 新玩家加入,', _player) + --print('[Heartbeat][Server] OnPlayerJoinEvent, 新玩家加入,', _player) NetUtil.Fire_S('OnPlayerJoinEvent', _player) + print('已经广播了') cache[_player] = { state = HeartbeatEnum.CONNECT } elseif cache[_player].state == HeartbeatEnum.DISCONNECT then --* 玩家断线重连 OnPlayerReconnectEvent - print('[Heartbeat][Server] OnPlayerReconnectEvent, 玩家断线重连,', _player) + --print('[Heartbeat][Server] OnPlayerReconnectEvent, 玩家断线重连,', _player) NetUtil.Fire_S('OnPlayerReconnectEvent', _player) cache[_player].state = HeartbeatEnum.CONNECT end @@ -164,16 +168,18 @@ function CheckPlayerStates(_player, _sTimestam) cache[_player].state = HeartbeatEnum.CONNECT elseif cache[_player].state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then --* 玩家断线 OnPlayerDisconnectEvent - print('[Heartbeat][Server] OnPlayerDisconnectEvent, 玩家离线, 等待断线重连,', _player) + --print('[Heartbeat][Server] OnPlayerDisconnectEvent, 玩家离线, 等待断线重连,', _player, _player.UserId) NetUtil.Fire_S('OnPlayerDisconnectEvent', _player) cache[_player].state = HeartbeatEnum.DISCONNECT elseif cache[_player].state == HeartbeatEnum.DISCONNECT and diff >= HEARTBEAT_THRESHOLD_2 then - --* 玩家彻底断线,剔除玩家 OnPlayerLeaveEvent - print('[Heartbeat][Server] OnPlayerLeaveEvent, 剔除离线玩家,', _player) - NetUtil.Fire_S('OnPlayerLeaveEvent', _player) - print('[Heartbeat][Server] OnPlayerLeave, 发送客户端离线事件,', _player) - NetUtil.Fire_C('OnPlayerLeaveEvent', _player) - cache[_player] = nil + --* 玩家彻底断线,剔除玩家 + local player = _player + local uid = player.UserId + --print('[Heartbeat][Server] OnPlayerLeaveEvent, 剔除离线玩家,', player, uid) + NetUtil.Fire_S('OnPlayerLeaveEvent', player, uid) + --print('[Heartbeat][Server] OnPlayerLeaveEvent, 发送客户端离线事件,', player, uid) + NetUtil.Fire_C('OnPlayerLeaveEvent', player, uid) + cache[player] = nil end end diff --git a/Code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Server']['ServerModule'].ModuleScript.lua similarity index 80% rename from Code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua rename to Code/['World']['Global']['Framework']['Server']['ServerModule'].ModuleScript.lua index 199de55..d4ab259 100644 --- a/Code/['World']['Global']['Framework']['ServerModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Server']['ServerModule'].ModuleScript.lua @@ -16,14 +16,14 @@ local initDefaultList, initList, updateList = {}, {}, {} --- 运行服务器 function Server:Run() - print('[Server] Run()') + --print('[Server] Run()') InitServer() StartUpdate() end --- 停止Update function Server:Stop() - print('[Server] Stop()') + --print('[Server] Stop()') running = false ServerHeartbeat.Stop() end @@ -33,9 +33,10 @@ function InitServer() if initialized then return end - print('[Server] InitServer()') + --print('[Server] InitServer()') InitRandomSeed() InitHeartbeat() + InitDataSync() InitServerCustomEvents() InitCsvAndXls() GenInitAndUpdateList() @@ -46,7 +47,7 @@ end --- 初始化服务器的CustomEvent function InitServerCustomEvents() - print('[Server] InitServerCustomEvents()') + --print('[Server] InitServerCustomEvents()') if world.S_Event == nil then world:CreateObject('FolderObject', 'S_Event', world) end @@ -76,6 +77,12 @@ function InitHeartbeat() ServerHeartbeat.Init() end +--- 初始化数据同步 +function InitDataSync() + assert(ServerDataSync, '[Server][DataSync] 找不到ServerDataSync,请联系张远程') + ServerDataSync.Init() +end + --- 生成框架需要的节点 function InitCsvAndXls() if not world.Global.Csv then @@ -88,9 +95,15 @@ end --- 生成需要Init和Update的模块列表 function GenInitAndUpdateList() + -- TODO: 改成在FrameworkConfig中配置 + -- Init Default ModuleUtil.GetModuleListWithFunc(Module.S_Module, 'InitDefault', initDefaultList) + -- Init + ModuleUtil.GetModuleListWithFunc(Define, 'Init', initList) ModuleUtil.GetModuleListWithFunc(Module.S_Module, 'Init', initList) + -- Update ModuleUtil.GetModuleListWithFunc(Module.S_Module, 'Update', updateList) + -- Plugin for _, m in pairs(FrameworkConfig.Server.PluginModules) do ModuleUtil.GetModuleListWithFunc(m, 'InitDefault', initDefaultList) ModuleUtil.GetModuleListWithFunc(m, 'Init', initList) @@ -119,7 +132,7 @@ end --- 开始Update function StartUpdate() - print('[Server] StartUpdate()') + --print('[Server] StartUpdate()') assert(not running, '[Server] StartUpdate() 正在运行') running = true @@ -129,6 +142,9 @@ function StartUpdate() invoke(ServerHeartbeat.Start) end + -- 开启数据同步 + ServerDataSync.Start() + local dt = 0 -- delta time 每帧时间 local tt = 0 -- total time 游戏总时间 local now = Timer.GetTimeMillisecond --时间函数缓存 @@ -140,9 +156,24 @@ function StartUpdate() tt = tt + dt prev = curr UpdateServer(dt, tt) + --[[xpcall( + function() + --local a = 10 / nil + + end, + function(err) + ErrorShow(err) + error(err) + end + )]] end end +function ErrorShow(err) + world.Global.ErrorGUI:SetActive(true) + world.Global.ErrorGUI.Error.Text = err +end + --- Update函数 --- @param dt delta time 每帧时间 function UpdateServer(_dt, _tt) From e385f33f1db9c0112f2939dce707ec3514c65556 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 20:29:40 +0800 Subject: [PATCH 37/39] =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Code/['World']['Global']['LuaFunctionScript'].Script.lua | 2 +- ...]['Global']['Utility']['SoundUtilModule'].ModuleScript.lua | 2 +- ...']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/['World']['Global']['LuaFunctionScript'].Script.lua b/Code/['World']['Global']['LuaFunctionScript'].Script.lua index 764201a..6c88ae9 100644 --- a/Code/['World']['Global']['LuaFunctionScript'].Script.lua +++ b/Code/['World']['Global']['LuaFunctionScript'].Script.lua @@ -907,7 +907,7 @@ end function Stack:Pop() if self:IsEmpty() then - --print("Error: the stack is empty") + print('Error: the stack is empty') return end local value = self._stack[self._last] diff --git a/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua index d002aed..7342ee2 100644 --- a/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Utility']['SoundUtilModule'].ModuleScript.lua @@ -23,7 +23,7 @@ local DebugMode = true --- 打印日志 local PrintLog = DebugMode and function(...) - --print('[SoundUtil]', ...) + print('[SoundUtil]', ...) end or function() end diff --git a/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua b/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua index dc5a3c4..150d975 100644 --- a/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Utility']['TimeUtilModule'].ModuleScript.lua @@ -53,7 +53,7 @@ end --- Update local function StartUpdate() while running and wait(DELTA_TIME) do - -- --print(Timer.GetTime(), os.time()) + -- print(Timer.GetTime(), os.time()) CheckEvents() TriggerEvents() end @@ -89,7 +89,7 @@ function TimeUtil.SetTimeout(_func, _seconds) assert(type(_func) == 'function', '[TimeUtil] TimeUtil.SetTimeout() _func 类型不是function') assert(_seconds >= 0, '[TimeUtil] TimeUtil.SetTimeout() 延迟时间需大于等于0') if _seconds == 0 then - --print('[TimeUtil] TimeUtil.SetTimeout() 事件立即执行') + print('[TimeUtil] TimeUtil.SetTimeout() 事件立即执行') invoke(_func) return end From ea47bb9700217a3060fd17dfab5f0c9af62a4e09 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 20:30:25 +0800 Subject: [PATCH 38/39] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A1=86=E6=9E=B6?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=9A=E4=BC=98=E5=8C=96=E5=BF=83=E8=B7=B3?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=EF=BC=9B=E6=98=BE=E7=A4=BA=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ent']['ClientBaseModule'].ModuleScript.lua | 4 +-- ...]['ClientDataSyncModule'].ModuleScript.lua | 6 ++-- ...['ClientHeartbeatModule'].ModuleScript.lua | 24 ++++++------- ...'Client']['ClientModule'].ModuleScript.lua | 11 +++--- ...ework']['MetaDataModule'].ModuleScript.lua | 12 +++---- ...ver']['ServerBaseModule'].ModuleScript.lua | 4 +-- ...]['ServerDataSyncModule'].ModuleScript.lua | 35 ++++++++++--------- ...['ServerHeartbeatModule'].ModuleScript.lua | 27 +++++++------- ...'Server']['ServerModule'].ModuleScript.lua | 10 +++--- 9 files changed, 65 insertions(+), 68 deletions(-) diff --git a/Code/['World']['Global']['Framework']['Client']['ClientBaseModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Client']['ClientBaseModule'].ModuleScript.lua index f084843..32f20be 100644 --- a/Code/['World']['Global']['Framework']['Client']['ClientBaseModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Client']['ClientBaseModule'].ModuleScript.lua @@ -10,7 +10,7 @@ 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 @@ -20,7 +20,7 @@ end -- FrameworkConfig.DebugMode 框架中的全局debug开关 function ClientBase:Log(...) if self.debug and FrameworkConfig.DebugMode then - --print(string.format('[%s]', self.name), ...) + print(string.format('[%s]', self.name), ...) end end diff --git a/Code/['World']['Global']['Framework']['Client']['ClientDataSyncModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Client']['ClientDataSyncModule'].ModuleScript.lua index 1b1cd4e..22b413b 100644 --- a/Code/['World']['Global']['Framework']['Client']['ClientDataSyncModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Client']['ClientDataSyncModule'].ModuleScript.lua @@ -13,7 +13,7 @@ local rawDataPlayer = {} --- 打印数据同步日志 local PrintLog = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowDataSyncLog and function(...) - --print('[DataSync][Client]', ...) + print('[DataSync][Client]', ...) end or function() end @@ -21,7 +21,7 @@ local PrintLog = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowDataSyn --- 数据初始化 function ClientDataSync.Init() - --print('[DataSync][Client] Init()') + print('[DataSync][Client] Init()') InitEventsAndListeners() InitDataDefines() end @@ -63,7 +63,7 @@ end --- 开始同步 function ClientDataSync.Start() - --print('[DataSync][Client] 客户端数据同步开启') + print('[DataSync][Client] 客户端数据同步开启') MetaData.ClientSync = true end diff --git a/Code/['World']['Global']['Framework']['Client']['ClientHeartbeatModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Client']['ClientHeartbeatModule'].ModuleScript.lua index da70480..dcc685c 100644 --- a/Code/['World']['Global']['Framework']['Client']['ClientHeartbeatModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Client']['ClientHeartbeatModule'].ModuleScript.lua @@ -38,7 +38,7 @@ local sTmpTs, cTmpTs -- 时间戳缓存 --- 打印心跳日志 local PrintHb = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowHeartbeatLog and function(...) - --print('[Heartbeat][Client]', ...) + print('[Heartbeat][Client]', ...) end or function() end @@ -46,14 +46,14 @@ local PrintHb = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowHeartbea --- 初始化心跳包 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 @@ -64,7 +64,7 @@ end -- 停止心跳 function ClientHeartbeat.Stop() - --print('[Heartbeat][Client] Stop()') + print('[Heartbeat][Client] Stop()') running = false end @@ -127,13 +127,13 @@ end function CheckPlayerJoin(_player, _sTimestamp) if not cache.sTimestamp then --* 玩家新加入 OnPlayerJoinEvent - --print('[Heartbeat][Client] OnPlayerJoinEvent, 新玩家加入,', localPlayer, localPlayer.UserId) - NetUtil.Fire_C('OnPlayerJoinEvent', localPlayer) + print('[Heartbeat][Client] OnPlayerJoinEvent, 新玩家加入,', localPlayer, localPlayer.UserId) + NetUtil.Fire_C('OnPlayerJoinEvent', localPlayer, localPlayer.UserId) cache.state = HeartbeatEnum.CONNECT elseif cache.state == HeartbeatEnum.DISCONNECT then --* 玩家断线重连 OnPlayerReconnectEvent - --print('[Heartbeat][Client] OnPlayerReconnectEvent, 玩家断线重连,', localPlayer, localPlayer.UserId) - NetUtil.Fire_C('OnPlayerReconnectEvent', localPlayer) + print('[Heartbeat][Client] OnPlayerReconnectEvent, 玩家断线重连,', localPlayer, localPlayer.UserId) + NetUtil.Fire_C('OnPlayerReconnectEvent', localPlayer, localPlayer.UserId) cache.state = HeartbeatEnum.CONNECT end end @@ -150,19 +150,19 @@ function CheckPlayerState(_player, _cTimestamp) cache.state = HeartbeatEnum.CONNECT elseif cache.state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then --* 玩家断线,弱网环境 - --print('[Heartbeat][Client] OnPlayerDisconnectEvent, 玩家离线, 弱网环境,', localPlayer) - NetUtil.Fire_C('OnPlayerDisconnectEvent', localPlayer) + print('[Heartbeat][Client] OnPlayerDisconnectEvent, 玩家离线, 弱网环境,', localPlayer) + NetUtil.Fire_C('OnPlayerDisconnectEvent', localPlayer, localPlayer.UserId) cache.state = HeartbeatEnum.DISCONNECT elseif cache.state == HeartbeatEnum.DISCONNECT and diff >= HEARTBEAT_THRESHOLD_2 then --* 玩家断线, 退出游戏 -- QuitGame() - NetUtil.Fire_C('OnPlayerLeaveEvent', localPlayer) + NetUtil.Fire_C('OnPlayerLeaveEvent', localPlayer, localPlayer.UserId) end end --- 退出游戏 function QuitGame() - --print('[Heartbeat][Client] Game.Quit(), 玩家退出游戏', localPlayer, localPlayer.UserId) + print('[Heartbeat][Client] Game.Quit(), 玩家退出游戏', localPlayer, localPlayer.UserId) Game.Quit() end diff --git a/Code/['World']['Global']['Framework']['Client']['ClientModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Client']['ClientModule'].ModuleScript.lua index eaccec4..469bba8 100644 --- a/Code/['World']['Global']['Framework']['Client']['ClientModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Client']['ClientModule'].ModuleScript.lua @@ -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 @@ -33,7 +33,7 @@ function InitClient() if initialized then return end - --print('[Client] InitClient()') + print('[Client] InitClient()') InitRandomSeed() InitHeartbeat() InitDataSync() @@ -85,14 +85,11 @@ end 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 @@ -123,7 +120,7 @@ end --- 开始Update function StartUpdate() - --print('[Client] StartUpdate()') + print('[Client] StartUpdate()') assert(not running, '[Client] StartUpdate() 正在运行') running = true diff --git a/Code/['World']['Global']['Framework']['MetaDataModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['MetaDataModule'].ModuleScript.lua index 7a40ea6..59573aa 100644 --- a/Code/['World']['Global']['Framework']['MetaDataModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['MetaDataModule'].ModuleScript.lua @@ -215,7 +215,7 @@ end --- 打印数据同步日志 PrintLog = FrameworkConfig.DebugMode and debugMode and function(...) - --print('[MetaData]', ...) + print('[MetaData]', ...) end or function() end @@ -263,12 +263,12 @@ Data.Global.b = {22, 33} Data.Global.c = {c1 = {44, 55}, c2 = 66} Data.Global.c.c3 = {c4 = 77} Data.Global.d = {'88', Vector3(9,9,9)} ---print(table.dump(Data.Global)) ---print(table.dump(MetaData.Get(Data.Global))) +print(table.dump(Data.Global)) +print(table.dump(MetaData.Get(Data.Global))) ---print(table.dump(Data.Player)) +print(table.dump(Data.Player)) ---print(table.dump(Data.Players)) +print(table.dump(Data.Players)) ---print(table.dump(Data.Players['pid:local_1'])) +print(table.dump(Data.Players['pid:local_1'])) ]] diff --git a/Code/['World']['Global']['Framework']['Server']['ServerBaseModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Server']['ServerBaseModule'].ModuleScript.lua index bec7b32..7efdc36 100644 --- a/Code/['World']['Global']['Framework']['Server']['ServerBaseModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Server']['ServerBaseModule'].ModuleScript.lua @@ -10,7 +10,7 @@ end --- 加载的时候运行的代码 function ServerBase:InitDefault(_module) - -- --print(string.format('[ServerBase][%s] InitDefault()', self.name)) + -- print(string.format('[ServerBase][%s] InitDefault()', self.name)) -- 初始化默认监听事件 EventUtil.LinkConnects(world.S_Event, _module, self) end @@ -20,7 +20,7 @@ end -- FrameworkConfig.DebugMode 框架中的全局debug开关 function ServerBase:Log(...) if self.debug and FrameworkConfig.DebugMode then - --print(string.format('[%s]', self.name), ...) + print(string.format('[%s]', self.name), ...) end end diff --git a/Code/['World']['Global']['Framework']['Server']['ServerDataSyncModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Server']['ServerDataSyncModule'].ModuleScript.lua index 69fe9a1..84322a2 100644 --- a/Code/['World']['Global']['Framework']['Server']['ServerDataSyncModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Server']['ServerDataSyncModule'].ModuleScript.lua @@ -21,7 +21,7 @@ local sheet --- 打印数据同步日志 local PrintLog = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowDataSyncLog and function(...) - --print('[DataSync][Server]', ...) + print('[DataSync][Server]', ...) end or function() end @@ -29,7 +29,7 @@ local PrintLog = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowDataSyn --- 数据初始化 function ServerDataSync.Init() - --print('[DataSync][Server] Init()') + print('[DataSync][Server] Init()') InitEventsAndListeners() InitDefines() sheet = DataStore:GetSheet('PlayerData') @@ -99,7 +99,7 @@ end --- 开始同步 function ServerDataSync.Start() - --print('[DataSync][Server] 服务器数据同步开启') + print('[DataSync][Server] 服务器数据同步开启') MetaData.ServerSync = true -- 启动定时器 @@ -129,10 +129,10 @@ function LoadGameDataAsyncCb(_val, _msg, _uid) local player = world:GetPlayerByUserId(_uid) assert(player, string.format('[DataSync][Server] 玩家不存在, uid = %s', _uid)) if _msg == 0 or _msg == 101 then - --print('[DataSync][Server] 获取玩家数据成功', player.Name) + print('[DataSync][Server] 获取玩家数据成功', player.Name) local hasData = _val ~= nil if hasData then - --print('[DataSync][Server] 玩家数据,存在', player.Name) + print('[DataSync][Server] 玩家数据,存在', player.Name) --若以前的数据存在,更新 -- TODO: 数据兼容的处理 local data = _val @@ -143,7 +143,7 @@ function LoadGameDataAsyncCb(_val, _msg, _uid) end else -- 不存在数据,用之前生成的默认数据 - --print('[DataSync][Server] 玩家数据,不存在', player.Name) + print('[DataSync][Server] 玩家数据,不存在', player.Name) end NetUtil.Fire_S('LoadPlayerDataSuccessEvent', player, hasData) NetUtil.Fire_C('LoadPlayerDataSuccessEvent', player, hasData) @@ -196,9 +196,9 @@ end function SaveGameDataAsyncCb(_val, _msg, _uid, _delete) -- 保存成功 if _msg == 0 then - --print('[DataSync][Server] 保存玩家数据,成功', _uid) + print('[DataSync][Server] 保存玩家数据,成功', _uid) if _delete == true then - --print('[DataSync][Server] 删除服务器玩家数据', _uid) + print('[DataSync][Server] 删除服务器玩家数据', _uid) rawDataPlayers[_uid] = nil --* 删除玩家端数据 Data.Players[_uid] = nil @@ -207,7 +207,7 @@ function SaveGameDataAsyncCb(_val, _msg, _uid, _delete) end -- 保存失败 - --print(string.format('[DataSync][Server] 保存玩家数据失败,%s秒后重试, uid = %s, msg = %s', RELOAD_TIME, _uid, _msg)) + print(string.format('[DataSync][Server] 保存玩家数据失败,%s秒后重试, uid = %s, msg = %s', RELOAD_TIME, _uid, _msg)) --若失败,则1秒后重新再读取一次 invoke( function() @@ -220,10 +220,10 @@ end --- 存储全部玩家数据 function SaveAllGameDataAsync() if not MetaData.ServerSync then - --print('[DataSync][Server] ServerSync未开始') + print('[DataSync][Server] ServerSync未开始') return end - --print('[DataSync][Server] 尝试保存全部玩家数据……') + print('[DataSync][Server] 尝试保存全部玩家数据……') for uid, data in pairs(Data.Players) do if not string.isnilorempty(uid) and data then SaveGameDataAsync(uid, false) @@ -262,21 +262,22 @@ function DataSyncC2SEventHandler(_player, _path, _value) end --- 新玩家加入事件Handler -function OnPlayerJoinEventHandler(_player) - --print('[DataSync][Server] OnPlayerJoinEventHandler', _player, _player.UserId) +function OnPlayerJoinEventHandler(_player, _uid) + print('[DataSync][Server] OnPlayerJoinEventHandler', _player, _player.UserId, _uid) + --* 向客户端同步Data.Global NetUtil.Fire_C('DataSyncS2CEvent', _player, MetaData.Enum.GLOBAL, MetaData.Get(Data.Global)) - local uid = _player.UserId - InitDataPlayer(uid) + -- 初始化玩家数据 + InitDataPlayer(_uid) --* 获取长期存储,成功后向客户端同步 - LoadGameDataAsync(uid) + LoadGameDataAsync(_uid) end --- 玩家离开事件Handler function OnPlayerLeaveEventHandler(_player, _uid) - --print('[DataSync][Server] OnPlayerLeaveEventHandler', _player, _uid) + print('[DataSync][Server] OnPlayerLeaveEventHandler', _player, _uid) assert(not string.isnilorempty(_uid), '[ServerDataSync] OnPlayerLeaveEventHandler() uid不存在') --* 保存长期存储:rawDataPlayers[_uid] 保存成功后删掉 SaveGameDataAsync(_uid, true) diff --git a/Code/['World']['Global']['Framework']['Server']['ServerHeartbeatModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Server']['ServerHeartbeatModule'].ModuleScript.lua index d0e0f5b..2b25e73 100644 --- a/Code/['World']['Global']['Framework']['Server']['ServerHeartbeatModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Server']['ServerHeartbeatModule'].ModuleScript.lua @@ -35,7 +35,7 @@ local sTmpTs, cTmpTs -- 时间戳缓存 --- 打印心跳日志 local PrintHb = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowHeartbeatLog and function(...) - --print('[Heartbeat][Server]', ...) + print('[Heartbeat][Server]', ...) end or function() end @@ -43,14 +43,14 @@ local PrintHb = FrameworkConfig.DebugMode and FrameworkConfig.Debug.ShowHeartbea --- 初始化心跳包 function ServerHeartbeat.Init() - --print('[Heartbeat][Server] Init()') + print('[Heartbeat][Server] Init()') CheckSetting() InitEventsAndListeners() end --- 开始发出心跳 function ServerHeartbeat.Start() - --print('[Heartbeat][Server] Start()') + print('[Heartbeat][Server] Start()') running = true while (running) do Update() @@ -60,7 +60,7 @@ end --- 停止心跳 function ServerHeartbeat.Stop() - --print('[Heartbeat][Server] Stop()') + print('[Heartbeat][Server] Stop()') running = false end @@ -103,7 +103,7 @@ function InitEventsAndListeners() local player = _player local uid = player.UserId if cache[player] then - --print('[Heartbeat][Server] OnPlayerLeaveEvent, 玩家主动离开游戏,', player, uid) + print('[Heartbeat][Server] OnPlayerLeaveEvent, 玩家主动离开游戏,', player, uid) NetUtil.Fire_S('OnPlayerLeaveEvent', player, uid) cache[player] = nil end @@ -142,16 +142,15 @@ end function CheckPlayerJoin(_player) if not cache[_player] then --* 玩家新加入 OnPlayerJoinEvent - --print('[Heartbeat][Server] OnPlayerJoinEvent, 新玩家加入,', _player) - NetUtil.Fire_S('OnPlayerJoinEvent', _player) - print('已经广播了') + print('[Heartbeat][Server] OnPlayerJoinEvent, 新玩家加入,', _player) + NetUtil.Fire_S('OnPlayerJoinEvent', _player, _player.UserId) cache[_player] = { state = HeartbeatEnum.CONNECT } elseif cache[_player].state == HeartbeatEnum.DISCONNECT then --* 玩家断线重连 OnPlayerReconnectEvent - --print('[Heartbeat][Server] OnPlayerReconnectEvent, 玩家断线重连,', _player) - NetUtil.Fire_S('OnPlayerReconnectEvent', _player) + print('[Heartbeat][Server] OnPlayerReconnectEvent, 玩家断线重连,', _player) + NetUtil.Fire_S('OnPlayerReconnectEvent', _player, _player.UserId) cache[_player].state = HeartbeatEnum.CONNECT end end @@ -168,16 +167,16 @@ function CheckPlayerStates(_player, _sTimestam) cache[_player].state = HeartbeatEnum.CONNECT elseif cache[_player].state == HeartbeatEnum.CONNECT and diff >= HEARTBEAT_THRESHOLD_1 then --* 玩家断线 OnPlayerDisconnectEvent - --print('[Heartbeat][Server] OnPlayerDisconnectEvent, 玩家离线, 等待断线重连,', _player, _player.UserId) - NetUtil.Fire_S('OnPlayerDisconnectEvent', _player) + print('[Heartbeat][Server] OnPlayerDisconnectEvent, 玩家离线, 等待断线重连,', _player, _player.UserId) + NetUtil.Fire_S('OnPlayerDisconnectEvent', _player, _player.UserId) cache[_player].state = HeartbeatEnum.DISCONNECT elseif cache[_player].state == HeartbeatEnum.DISCONNECT and diff >= HEARTBEAT_THRESHOLD_2 then --* 玩家彻底断线,剔除玩家 local player = _player local uid = player.UserId - --print('[Heartbeat][Server] OnPlayerLeaveEvent, 剔除离线玩家,', player, uid) + print('[Heartbeat][Server] OnPlayerLeaveEvent, 剔除离线玩家,', player, uid) NetUtil.Fire_S('OnPlayerLeaveEvent', player, uid) - --print('[Heartbeat][Server] OnPlayerLeaveEvent, 发送客户端离线事件,', player, uid) + print('[Heartbeat][Server] OnPlayerLeaveEvent, 发送客户端离线事件,', player, uid) NetUtil.Fire_C('OnPlayerLeaveEvent', player, uid) cache[player] = nil end diff --git a/Code/['World']['Global']['Framework']['Server']['ServerModule'].ModuleScript.lua b/Code/['World']['Global']['Framework']['Server']['ServerModule'].ModuleScript.lua index d4ab259..992d896 100644 --- a/Code/['World']['Global']['Framework']['Server']['ServerModule'].ModuleScript.lua +++ b/Code/['World']['Global']['Framework']['Server']['ServerModule'].ModuleScript.lua @@ -16,14 +16,14 @@ local initDefaultList, initList, updateList = {}, {}, {} --- 运行服务器 function Server:Run() - --print('[Server] Run()') + print('[Server] Run()') InitServer() StartUpdate() end --- 停止Update function Server:Stop() - --print('[Server] Stop()') + print('[Server] Stop()') running = false ServerHeartbeat.Stop() end @@ -33,7 +33,7 @@ function InitServer() if initialized then return end - --print('[Server] InitServer()') + print('[Server] InitServer()') InitRandomSeed() InitHeartbeat() InitDataSync() @@ -47,7 +47,7 @@ end --- 初始化服务器的CustomEvent function InitServerCustomEvents() - --print('[Server] InitServerCustomEvents()') + print('[Server] InitServerCustomEvents()') if world.S_Event == nil then world:CreateObject('FolderObject', 'S_Event', world) end @@ -132,7 +132,7 @@ end --- 开始Update function StartUpdate() - --print('[Server] StartUpdate()') + print('[Server] StartUpdate()') assert(not running, '[Server] StartUpdate() 正在运行') running = true From ff8868cc800e332a9753d3f212adefe4f89e5247 Mon Sep 17 00:00:00 2001 From: Yuancheng Zhang Date: Tue, 18 May 2021 20:30:31 +0800 Subject: [PATCH 39/39] Update avatar-ava.smap --- Smap/avatar-ava.smap | Bin 67131 -> 72525 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Smap/avatar-ava.smap b/Smap/avatar-ava.smap index 868639683fa77fab611332b577af06a594d355e8..94641639fa0a396f2f9ffcf6231815ccba6e0d3b 100644 GIT binary patch delta 54807 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

    nn?C>joW7@gXo$1H+2WL& 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 Y0000000000q?Z>40Uid68UX+R0R0Re;s5{u delta 49405 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�Hr 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

    kxLf|=Q!9b(Z7MTWF|1`*b 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