2025-01-04 23:00:19 +08:00
|
|
|
|
---@class UGCGameState_C:BP_UGCGameState_C
|
|
|
|
|
---@field WrapperClass UClass
|
|
|
|
|
---@field ShootWeaponClass UClass
|
|
|
|
|
--Edit Below--
|
|
|
|
|
UGCGameSystem.UGCRequire('Script.Common.ue_enum_custom')
|
|
|
|
|
require('Script.Global.Global');
|
|
|
|
|
|
|
|
|
|
local UGCGameState = {};
|
|
|
|
|
UGCGameState.ServerTime = 0; --- 服务器时间
|
|
|
|
|
UGCGameState.ServerTimeDiff = 0; --- 服务器时间 - 客户端时间的差值;如果想在服务器求客户端时间:当前时间 - 该值;
|
|
|
|
|
UGCGameState.MapIndex = 0; --- 地图数据
|
|
|
|
|
---@type table<PlayerKey, any>
|
|
|
|
|
UGCGameState.ArchiveData = {}; --- 玩家存档数据
|
|
|
|
|
---@type table<PlayerKey, PlayerAccountInfo>
|
|
|
|
|
UGCGameState.AccountInfo = {}; --- 玩家账户信息
|
|
|
|
|
UGCGameState.CountDownTime = 0; --- 游戏进程数据
|
|
|
|
|
UGCGameState.MiniInitData = {}; --- 一些在最前面的数据需要特定传输的
|
|
|
|
|
UGCGameState.PlayerDisconnect = {}; --- 玩家是否掉线
|
|
|
|
|
UGCGameState.EnableShovel = false; --- 是否可以滑铲
|
|
|
|
|
|
|
|
|
|
UGCGameState.MiniState = nil;
|
|
|
|
|
|
|
|
|
|
function UGCGameState:ReceiveBeginPlay()
|
|
|
|
|
GlobalInit.InitGlobalVar();
|
|
|
|
|
self:InitServerTime();
|
|
|
|
|
self.bIsOpenShovelingAbility = DefaultSettings.OpenShovel and self.EnableShovel;
|
|
|
|
|
|
|
|
|
|
if GlobalBeginTool then GlobalBeginTool:ReceiveBeginPlay(); end
|
|
|
|
|
table.func(MiniManager, "Init", self);
|
2025-01-14 15:37:16 +08:00
|
|
|
|
if DefaultSettings.EnableTest then
|
|
|
|
|
table.print_G();
|
|
|
|
|
end
|
2025-01-04 23:00:19 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:ReceiveTick(DeltaTime)
|
|
|
|
|
if GlobalTickTool then GlobalTickTool:ReceiveTick(DeltaTime, self:GetServerTime()); end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:InitServerTime()
|
|
|
|
|
if IsServer then
|
|
|
|
|
self.ServerTime = 1; -- 设置好
|
|
|
|
|
DOREPONCE(self, "ServerTime");
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:ReceiveEndPlay()
|
|
|
|
|
DefaultSettings = nil;
|
|
|
|
|
EventTypes = nil;
|
|
|
|
|
GameState = nil;
|
|
|
|
|
LocalPlayerKey = nil;
|
|
|
|
|
LocalPlayerController = nil;
|
|
|
|
|
LocalTeamPlayers = nil;
|
|
|
|
|
EnemyTeamPlayers = nil;
|
|
|
|
|
UnableTable();
|
|
|
|
|
UnableTool();
|
|
|
|
|
UnableWidgetManager();
|
|
|
|
|
UGCGameSystem.GameState = nil;
|
|
|
|
|
---@type table<PlayerKey, SoloKingArchiveData>
|
|
|
|
|
ArchiveTable = nil;
|
|
|
|
|
AccountTable = nil;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:GetAvailableServerRPCs()
|
|
|
|
|
return "LoadMap"
|
|
|
|
|
, "CheckServerTime"
|
|
|
|
|
, "UIAlready"
|
|
|
|
|
, "MiniGameReceiveRPC"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:GetReplicatedProperties()
|
|
|
|
|
return { "MapIndex", "Lazy" }
|
|
|
|
|
, { "ArchiveData", "Lazy" }
|
|
|
|
|
, { "AccountInfo", "Lazy" }
|
|
|
|
|
, "CountDownTime"
|
|
|
|
|
, { "ServerTime", "Lazy" }
|
|
|
|
|
, { "LoadMapName", "Lazy" }
|
|
|
|
|
, { "CurrMiniType", "Lazy" }
|
|
|
|
|
, { "MiniInfo", "Lazy" }
|
|
|
|
|
, { "MiniInitData", "Lazy" }
|
|
|
|
|
, { "MiniState", "Lazy" }
|
|
|
|
|
, "EnableShovel"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- 玩家属性 -----------------------------------------
|
|
|
|
|
---@param InPlayerKey PlayerKey
|
|
|
|
|
function UGCGameState:HandleAccountInfo(InPlayerKey)
|
|
|
|
|
if InPlayerKey == nil then
|
|
|
|
|
self.AccountInfo = TableHelper.DeepCopyTable(AccountTable);
|
|
|
|
|
else
|
|
|
|
|
self.AccountInfo[InPlayerKey] = TableHelper.DeepCopyTable(AccountTable[InPlayerKey]);
|
|
|
|
|
end
|
|
|
|
|
DOREPONCE(self, "AccountInfo");
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:HandleArchiveData(InPlayerKey, IgnoreList)
|
|
|
|
|
if IgnoreList == nil then IgnoreList = {}; end
|
|
|
|
|
UGCLogSystem.LogTree(string.format("[UGCGameState:HandleArchiveData] PlayerKey = %s, IgnoreList =", tostring(InPlayerKey)), IgnoreList);
|
|
|
|
|
local List = {};
|
|
|
|
|
for i, v in pairs(IgnoreList) do List[v] = 1; end
|
|
|
|
|
if InPlayerKey == nil then
|
|
|
|
|
self.ArchiveData = {};
|
|
|
|
|
for i, v in pairs(ArchiveTable) do self:HandleOnePlayerArchiveData(i, List, IgnoreList); end
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:HandleArchiveData] 同步结束");
|
|
|
|
|
else
|
|
|
|
|
self.ArchiveData[InPlayerKey] = {};
|
|
|
|
|
for i, v in pairs(ArchiveTable[InPlayerKey]) do
|
|
|
|
|
if List[i] == nil then self.ArchiveData[InPlayerKey][i] = TableHelper.DeepCopyTable(v); end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
DOREPONCE(self, "ArchiveData");
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:HandleOnePlayerArchiveData(InPlayerKey, List, IgnoreList)
|
|
|
|
|
self.ArchiveData[InPlayerKey] = {};
|
|
|
|
|
for i, v in pairs(ArchiveTable[InPlayerKey]) do
|
|
|
|
|
if List[i] == nil then self.ArchiveData[InPlayerKey][i] = TableHelper.DeepCopyTable(v); end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnRep_ArchiveData()
|
|
|
|
|
if LocalPlayerKey == nil then return ; end
|
|
|
|
|
|
|
|
|
|
--- 保证就算复制一个也没问题~
|
|
|
|
|
for i, v in pairs(self.ArchiveData) do ArchiveTable[i] = v; end
|
|
|
|
|
UGCLogSystem.LogTree(string.format("[UGCGameState:OnRep_ArchiveData] ArchiveTable ="), ArchiveTable)
|
|
|
|
|
UGCEventSystem.SendEvent(EventTypes.UpdateArchiveData, ArchiveTable);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnRep_AccountInfo()
|
|
|
|
|
-- 检查当前玩了多少局
|
|
|
|
|
if LocalPlayerKey == nil then return end
|
|
|
|
|
-- 显示拍脸图
|
|
|
|
|
AccountTable = self.AccountInfo;
|
|
|
|
|
UGCLogSystem.LogTree(string.format("[UGCGameState:OnRep_AccountInfo] AccountTable ="), AccountTable)
|
|
|
|
|
UGCEventSystem.SendEvent(EventTypes.UpdateAccountInfo, AccountTable);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- 地图加载 -----------------------------------------
|
|
|
|
|
--- 已经加载了的地图名称
|
|
|
|
|
UGCGameState.LoadMapName = nil;
|
|
|
|
|
|
|
|
|
|
--- 加载地图(服务器/客户端都可以执行)
|
|
|
|
|
---@param Name string 地图索引
|
|
|
|
|
function UGCGameState:LoadMap(Name)
|
|
|
|
|
-- 找到对应地图,然后进行加载
|
|
|
|
|
if self.LoadMapName ~= nil then
|
|
|
|
|
self:UnloadMap({ self.LoadMapName });
|
|
|
|
|
end
|
|
|
|
|
self.LoadMapName = Name;
|
2025-01-07 21:21:33 +08:00
|
|
|
|
for i, v in pairs(LevelTable.LevelInfo) do
|
|
|
|
|
if v.MapName == Name then
|
|
|
|
|
self.MapIndex = i;
|
|
|
|
|
DOREPONCE(self, "MapIndex");
|
|
|
|
|
break;
|
|
|
|
|
end
|
|
|
|
|
end
|
2025-01-04 23:00:19 +08:00
|
|
|
|
UGCLogSystem.Log("[UGCGameState:LoadMap] 加载 %s", Name)
|
|
|
|
|
LevelStreamTool.LoadStreamLevels({ Name }, { Object = self, Func = self.LoadMapFinish }, false);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnRep_LoadMapName()
|
|
|
|
|
if self.LoadMapName == nil then return; end
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnRep_LoadMapName] LoadMapName = %s", self.LoadMapName);
|
|
|
|
|
UGCEventSystem.SendEvent(EventTypes.OnMapLoaded, self.LoadMapName);
|
|
|
|
|
table.func(MiniManager, "OnMapLoadComplete")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 随机加载地图
|
|
|
|
|
---@param
|
|
|
|
|
function UGCGameState:LoadRandomMap(InIndex)
|
|
|
|
|
if IsServer then
|
|
|
|
|
self:UnloadMap();
|
|
|
|
|
-- 判断当前是不是随即关卡
|
|
|
|
|
UGCLogSystem.LogTree(string.format("[UGCGameState:LoadMap] LevelTable.LevelInfo ="), LevelTable.LevelInfo)
|
|
|
|
|
if InIndex == nil or InIndex == LevelTable.ELevelType.Random then
|
|
|
|
|
self.MapIndex = LevelTable.GetRandomLevel(true, 1)[1];
|
|
|
|
|
else
|
|
|
|
|
self.MapIndex = InIndex;
|
|
|
|
|
end
|
|
|
|
|
local MapNames = {};
|
|
|
|
|
table.insert(MapNames, LevelTable.LevelInfo[self.MapIndex].MapName);
|
|
|
|
|
LevelStreamTool.LoadStreamLevels(MapNames, { Object = self, Func = self.LoadMapFinish }, false);
|
|
|
|
|
DOREPONCE(self, "MapIndex");
|
|
|
|
|
else
|
|
|
|
|
-- 发送 RPC 到服务器
|
|
|
|
|
UnrealNetwork.CallUnrealRPC(LocalPlayerController, self, "LoadMap", InIndex);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnRep_MapIndex()
|
|
|
|
|
if self.MapIndex == 0 then return; end
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnRep_MapIndex] 开始加载小地图 MapIndex = %d", self.MapIndex);
|
|
|
|
|
-- 加载小地图
|
|
|
|
|
self:LoadMinimap(self.MapIndex);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 卸载地图
|
|
|
|
|
function UGCGameState:UnloadMap()
|
|
|
|
|
if self.MapIndex ~= 0 then
|
|
|
|
|
local MapNames = {};
|
|
|
|
|
table.insert(MapNames, LevelTable.LevelInfo[self.MapIndex].MapName)
|
|
|
|
|
LevelStreamTool.UnLoadStreamLevels(MapNames, { Object = self, Func = self.UnLoadMapFinish }, false);
|
|
|
|
|
self.MapIndex = 0;
|
|
|
|
|
self.LoadMapName = nil;
|
|
|
|
|
-- 重置 ClientAlready
|
|
|
|
|
self.bInitOnce = false;
|
|
|
|
|
DOREPONCE(self, "MapIndex");
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 地图加载完成
|
|
|
|
|
function UGCGameState:LoadMapFinish()
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:LoadMapFinish] 地图加载完成");
|
|
|
|
|
self:OnMapLoaded();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:UnLoadMapFinish()
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:UnLoadMapFinish] 地图卸载成功")
|
|
|
|
|
table.func(MiniManager, "OnMapUnLoadedComplete")
|
|
|
|
|
DOREPONCE(self, "LoadMapName");
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 加载小地图
|
|
|
|
|
function UGCGameState:LoadMinimap(InIndex)
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:LoadMinimap] 开始加载 %s 的小地图", LevelTable.LevelInfo[InIndex].MapName);
|
|
|
|
|
local MinimapInfo = LevelTable.LevelInfo[InIndex].MiniMapInfo;
|
|
|
|
|
if not table.isEmpty(MinimapInfo) then
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:LoadMinimap] 开始添加");
|
|
|
|
|
UGCWidgetManagerSystem.ChangeMap(MinimapInfo.MapPath, MinimapInfo.MapCentre, MinimapInfo.MapSize, MinimapInfo.MapScale);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnMapLoaded()
|
|
|
|
|
--- 加载地图上的东西
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnMapLoaded] 执行")
|
|
|
|
|
-- 检测一下是否有默认地图
|
|
|
|
|
table.func(MiniManager, "OnMapLoadComplete")
|
|
|
|
|
-- 此时同步一下即可,已经加载完毕了
|
|
|
|
|
DOREPONCE(self, "LoadMapName");
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- 游戏进程 -----------------------------------------
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnBeforeGameStart(InTime)
|
|
|
|
|
if MiniManager then
|
|
|
|
|
table.func(MiniManager, "OnBeforeGameStart", InTime);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 游戏结束
|
|
|
|
|
function UGCGameState:OnGameEnded()
|
|
|
|
|
-- 打开结算界面
|
|
|
|
|
if IsServer then
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnGameEnded] 执行结束");
|
|
|
|
|
UGCEventSystem.SetTimer(self, function()
|
|
|
|
|
for _, PC in pairs(UGCGameSystem.GetAllPlayerController(false)) do
|
|
|
|
|
local Success = UGCGameSystem.SendPlayerSettlement(PC.PlayerKey);
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnGameEnded] 执行是否成功:%s", tostring(Success))
|
|
|
|
|
|
|
|
|
|
local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PC.PlayerKey)
|
|
|
|
|
if Pawn and UE.IsValid(Pawn) then
|
|
|
|
|
UGCPawnSystem.LeavePawnState(Pawn, EPawnState.Move);
|
|
|
|
|
Pawn:K2_DestroyActor();
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end, 0.2);
|
|
|
|
|
UE.CloseServer();
|
|
|
|
|
else
|
|
|
|
|
if not WidgetManager:IsVisiblePanel(WidgetConfig.EUIType.GameEnd) then
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnGameEnded] 显示 GameEnd 界面")
|
|
|
|
|
WidgetManager:ShowPanel(WidgetConfig.EUIType.GameEnd, false, self.MiniInfo.GameWinner, self.MiniInfo.RoundWinners)
|
|
|
|
|
WidgetManager:ClosePanel(WidgetConfig.EUIType.Main);
|
|
|
|
|
end
|
|
|
|
|
UGCLogSystem.LogTree(string.format("[UGCGameState:OnGameEnded] AllPanel ="), WidgetManager.AllPanel);
|
|
|
|
|
-- 清空一些资源
|
|
|
|
|
WidgetManager:DestroyPanel(WidgetConfig.EUIType.AllWeapon);
|
|
|
|
|
WidgetManager:DestroyPanel(WidgetConfig.EUIType.AllWeapon_Spectator);
|
|
|
|
|
WidgetManager:DestroyPanel(WidgetConfig.EUIType.CustomSelectWeapon);
|
|
|
|
|
WidgetManager:DestroyPanel(WidgetConfig.EUIType.ShowPK);
|
|
|
|
|
WidgetManager:DestroyPanel(WidgetConfig.EUIType.ShowRankInheritance);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 倒计时
|
|
|
|
|
function UGCGameState:OnGameProgress_Tick(InTime)
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnGameProgress_Tick] 执行,InTime = %s", tostring(InTime));
|
|
|
|
|
self.CountDownTime = InTime;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnRep_CountDownTime()
|
|
|
|
|
UGCEventSystem.SendEvent(EventTypes.GameCountDownTimeChange, self.CountDownTime);
|
|
|
|
|
table.func(MiniManager, "OnMiniGameTimeCount", self.CountDownTime)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 当前游戏时间,以服务器为基准(因为服务器不会改变)
|
|
|
|
|
---客户端准备好之后会发送一个 RPC 过来,之后就是
|
|
|
|
|
function UGCGameState:CheckServerTime(InPlayerKey, InTime)
|
|
|
|
|
if IsServer then
|
|
|
|
|
local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(InPlayerKey)
|
|
|
|
|
UnrealNetwork.CallUnrealRPC(PC, self, "CheckClientTime", UE.GetCurrentTime());
|
|
|
|
|
self:OnClientAlready(InPlayerKey);
|
|
|
|
|
else
|
|
|
|
|
UnrealNetwork.CallUnrealRPC(LocalPlayerController, self, "CheckServerTime", InPlayerKey, InTime);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnRep_ServerTime()
|
|
|
|
|
-- 接收到之后就立刻发送 RPC 到服务器,或者也可以等一会
|
|
|
|
|
if self.ServerTime == 1 then
|
|
|
|
|
if LocalPlayerKey == nil or LocalPlayerController == nil then
|
|
|
|
|
UGCEventSystem.SetTimer(self, function()
|
|
|
|
|
self:CheckServerTime(LocalPlayerKey, UE.GetCurrentTime())
|
|
|
|
|
end, 1.);
|
|
|
|
|
return ;
|
|
|
|
|
end
|
|
|
|
|
self:CheckServerTime(LocalPlayerKey, UE.GetCurrentTime())
|
|
|
|
|
elseif self.ServerTime == 0 then
|
|
|
|
|
else
|
|
|
|
|
local Diff = self.ServerTime - UE.GetCurrentTime();
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnRep_ServerTime] Diff = %f", Diff)
|
|
|
|
|
self:OnClientAlready(LocalPlayerKey);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:CheckClientTime(InTime)
|
|
|
|
|
self.ServerTimeDiff = InTime - UE.GetCurrentTime();
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:CheckClientTime] self.ServerTimeDiff = %f", self.ServerTimeDiff);
|
|
|
|
|
self:OnClientAlready(LocalPlayerKey);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
UGCGameState.bInitOnce = {};
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnClientAlready(PlayerKey)
|
|
|
|
|
if self.bInitOnce[PlayerKey] then return end
|
|
|
|
|
self.bInitOnce[PlayerKey] = true;
|
|
|
|
|
UGCEventSystem.SendEvent(EventTypes.ClientAlready);
|
|
|
|
|
|
|
|
|
|
local ServerTime = self:GetServerTime()
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnClientAlready] 执行 ServerTime = %f", ServerTime);
|
|
|
|
|
if GlobalBeginTool then
|
|
|
|
|
GlobalBeginTool:ReceiveClientAlready();
|
|
|
|
|
GlobalBeginTool = nil;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
table.func(MiniManager, "OnClientAlready");
|
|
|
|
|
local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(PlayerKey);
|
|
|
|
|
if PC and UE.IsValid(PC) and (not PC:IsPureSpectator()) then
|
|
|
|
|
PC:SendLast10Games();
|
|
|
|
|
PC:SendSelectWeapons();
|
2025-01-16 13:35:17 +08:00
|
|
|
|
-- 发送武器配件数据
|
|
|
|
|
PC:SendWeaponParts();
|
2025-01-04 23:00:19 +08:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
UGCGameState.bInitOnce_UIAlready = false;
|
|
|
|
|
|
|
|
|
|
function UGCGameState:UIAlready()
|
|
|
|
|
if self.bInitOnce_UIAlready then return ; end
|
|
|
|
|
self.bInitOnce_UIAlready = true;
|
|
|
|
|
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:UIAlready] 执行")
|
|
|
|
|
|
|
|
|
|
table.func(MiniManager, "OnUIAlready");
|
|
|
|
|
if IsClient then
|
|
|
|
|
UnrealNetwork.CallUnrealRPC(LocalPlayerController, self, "UIAlready");
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- S & C : 获取服务器时间
|
|
|
|
|
---@return float|nil
|
|
|
|
|
function UGCGameState:GetServerTime()
|
|
|
|
|
if IsServer then
|
|
|
|
|
return UE.GetCurrentTime();
|
|
|
|
|
else
|
|
|
|
|
if self.ServerTimeDiff == 0 then
|
|
|
|
|
return nil;
|
|
|
|
|
else
|
|
|
|
|
return self.ServerTimeDiff + UE.GetCurrentTime();
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 提前重置操作
|
|
|
|
|
function UGCGameState:BeforeReset(InTime)
|
|
|
|
|
for i, Pawn in pairs(UGCGameSystem.GetAllPlayerPawn()) do
|
|
|
|
|
if Pawn and UE.IsValid(Pawn) then
|
|
|
|
|
if Pawn then Pawn:K2_DestroyActor(); end
|
|
|
|
|
UE.RespawnPlayer(d, InTime);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
self:ResetKill();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:ResetKill()
|
|
|
|
|
-- 重置其他的
|
|
|
|
|
for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do v:ResetGame(); end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 重置游戏
|
|
|
|
|
function UGCGameState:ResetGame()
|
|
|
|
|
if IsServer then
|
|
|
|
|
UnrealNetwork.CallUnrealRPC_Multicast(self, "ResetGame");
|
|
|
|
|
-- 重置击杀数
|
|
|
|
|
for i, v in pairs(UGCGameSystem.GetAllPlayerState(false)) do
|
|
|
|
|
v:ResetKillNum();
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
WidgetManager:GetPanel(WidgetConfig.EUIType.Main, function(Widget)
|
|
|
|
|
table.func(Widget, "OnGameStart");
|
|
|
|
|
end)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- 界面 UI -----------------------------------------
|
|
|
|
|
--- 显示 UI
|
|
|
|
|
---@param InUIType EUIType
|
|
|
|
|
---@param IsShow boolean
|
|
|
|
|
function UGCGameState:ShowUIByType(InUIType, IsShow, ...)
|
|
|
|
|
if IsServer then
|
|
|
|
|
UnrealNetwork.CallUnrealRPC_Multicast(self, "ShowUIByType", InUIType, IsShow, ...);
|
|
|
|
|
else
|
|
|
|
|
if IsShow then
|
|
|
|
|
WidgetManager:ShowPanel(InUIType, false, ...);
|
|
|
|
|
else
|
|
|
|
|
WidgetManager:ClosePanel(InUIType);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- 场景物品 -----------------------------------------
|
|
|
|
|
|
|
|
|
|
---@type BP_ResourceBase_C
|
|
|
|
|
UGCGameState.ResourceActor = nil;
|
|
|
|
|
|
|
|
|
|
--- 加载资源类,服务器,客户端都需要加载一次
|
|
|
|
|
---@return BP_ResourceBase_C
|
|
|
|
|
function UGCGameState:LoadResource()
|
|
|
|
|
if self.ResourceActor == nil then self.ResourceActor = UE.FindActorByClass(ObjectPath.BP_ResourceBase); end
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:LoadResource] %s", UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/UGCPlayerPawn.UGCPlayerPawn_C'))
|
|
|
|
|
return self.ResourceActor;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- 清除场景上的 Wrappers
|
|
|
|
|
function UGCGameState:ClearWrappers()
|
|
|
|
|
local InTable = {};
|
|
|
|
|
UE.FindActorsByClass(self:GetWrapperClass(), InTable, function(InIndex, InActor)
|
|
|
|
|
return InActor:GetOwner() == nil;
|
|
|
|
|
end);
|
|
|
|
|
for i, v in pairs(InTable) do v:K2_DestroyActor(); end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- BUFF -----------------------------------------
|
|
|
|
|
|
|
|
|
|
---@type AActor
|
|
|
|
|
UGCGameState.MapCenterActor = nil;
|
|
|
|
|
|
|
|
|
|
--- 获取中心点
|
|
|
|
|
---@return AActor
|
|
|
|
|
function UGCGameState:GetCenterPointLocation()
|
|
|
|
|
if self.MapCenterActor ~= nil then return self.MapCenterActor:K2_GetActorLocation() end
|
|
|
|
|
local CenterActors = {};
|
|
|
|
|
UE.FindActorsByClass(ObjectPath.BP_ActorStart, CenterActors, function(InIndex, InActor)
|
|
|
|
|
return InActor:ActorHasTag("MapCenter");
|
|
|
|
|
end);
|
|
|
|
|
UGCLogSystem.LogTree(string.format("[UGCGameState:GetCenterPointLocation] CenterActors ="), CenterActors)
|
|
|
|
|
self.MapCenterActor = CenterActors[1];
|
|
|
|
|
if self.MapCenterActor ~= nil then
|
|
|
|
|
return self.MapCenterActor:K2_GetActorLocation();
|
|
|
|
|
end
|
|
|
|
|
return nil;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- 武器 -----------------------------------------
|
|
|
|
|
--- 获取武器基类
|
|
|
|
|
---@return UClass 武器基类
|
|
|
|
|
function UGCGameState:GetShootWeaponClass() return self.ShootWeaponClass; end
|
|
|
|
|
---@return UClass
|
|
|
|
|
function UGCGameState:GetWrapperClass() return self.WrapperClass; end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- FUNCTIONAL -----------------------------------------
|
|
|
|
|
|
|
|
|
|
--- 发送自定义事件
|
|
|
|
|
function UGCGameState:SendEvent(IsSend, InPlayerKey, InEvent, ...)
|
|
|
|
|
if IsServer then
|
|
|
|
|
if IsSend then
|
|
|
|
|
if InPlayerKey == nil then
|
|
|
|
|
UnrealNetwork.CallUnrealRPC_Multicast(self, "SendEvent", false, nil, InEvent, ...);
|
|
|
|
|
else
|
|
|
|
|
UnrealNetwork.CallUnrealRPC(UGCGameSystem.GetPlayerControllerByPlayerKey(InPlayerKey), UGCGameSystem.GameState, "SendEvent", false, InPlayerKey, InEvent, ...);
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
UGCEventSystem.SendEvent(InEvent, InPlayerKey, ...)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
-- 从客户端发送出去
|
|
|
|
|
if IsSend then
|
|
|
|
|
UnrealNetwork.CallUnrealRPC(DefaultSettings.LocalPlayerController, UGCGameSystem.GameState, "SendEvent", false, DefaultSettings.LocalPlayerKey, InEvent, ...);
|
|
|
|
|
else
|
|
|
|
|
UGCEventSystem.SendEvent(InEvent, InPlayerKey, ...);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- MINI -----------------------------------------
|
|
|
|
|
--- 当前选择的 MiniType
|
|
|
|
|
UGCGameState.CurrMiniType = -1;
|
|
|
|
|
|
|
|
|
|
---@param InMiniType int32
|
|
|
|
|
function UGCGameState:SelectMiniType(InMiniType)
|
|
|
|
|
self.CurrMiniType = InMiniType;
|
|
|
|
|
DOREPONCE(self, "CurrMiniType");
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnRep_CurrMiniType()
|
|
|
|
|
if self.CurrMiniType < 0 then return ; end
|
|
|
|
|
table.func(MiniManager, "LoadMiniGame", self.CurrMiniType)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 发送 MiniGame RPC
|
|
|
|
|
---@param InFuncName string 函数名称
|
|
|
|
|
---@vararg any
|
|
|
|
|
function UGCGameState:SendMiniGameRPC(InFuncName, ...)
|
|
|
|
|
if IsServer then
|
|
|
|
|
UnrealNetwork.CallUnrealRPC_Multicast(self, "MiniGameReceiveRPC", InFuncName, true, ...);
|
|
|
|
|
else
|
|
|
|
|
UnrealNetwork.CallUnrealRPC(LocalPlayerController, self, "MiniGameReceiveRPC", InFuncName, false, ...);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Mini Game 接收到 RPC
|
|
|
|
|
---@param InFuncName string 函数名称
|
|
|
|
|
---@param SendFromServer bool 是否发自服务器
|
|
|
|
|
function UGCGameState:MiniGameReceiveRPC(InFuncName, SendFromServer, ...)
|
|
|
|
|
if table.hasFunc(MiniManager, InFuncName) then
|
|
|
|
|
table.func(MiniManager, InFuncName, ...)
|
|
|
|
|
else
|
|
|
|
|
if MiniManager ~= nil and MiniManager.CurrMiniMode then
|
|
|
|
|
table.func(MiniManager.CurrMiniMode, InFuncName, ...)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 小游戏需要同步的数据
|
|
|
|
|
UGCGameState.MiniInfo = {};
|
|
|
|
|
|
|
|
|
|
function UGCGameState:SetMiniInfo(InMiniInfo)
|
|
|
|
|
self.MiniInfo = InMiniInfo;
|
|
|
|
|
DOREPONCE(self, "MiniInfo");
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnRep_MiniInfo(InOld)
|
|
|
|
|
if table.isEmpty(self.MiniInfo) then return ; end
|
|
|
|
|
-- 发送出去
|
|
|
|
|
UGCLogSystem.LogTree(string.format("[UGCGameState:OnRep_MiniInfo] MiniInfo"), self.MiniInfo)
|
|
|
|
|
if MiniManager then
|
|
|
|
|
MiniManager.MiniInfo = self.MiniInfo;
|
|
|
|
|
table.func(MiniManager, "OnRep_MiniInfo", InOld)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 设置初始化数据,初始化数据不会更改,可以直接获取
|
|
|
|
|
function UGCGameState:SetMiniInitData(InKey, InVal)
|
|
|
|
|
self.MiniInitData[InKey] = InVal;
|
|
|
|
|
DOREPONCE(self, "MiniInitData");
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:GetMiniInitData(InKey)
|
|
|
|
|
return self.MiniInitData[InKey];
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- 获取 MiniGame 的数据
|
|
|
|
|
function UGCGameState:GetMiniInfo(Name)
|
|
|
|
|
if MiniManager then
|
|
|
|
|
return table.func(MiniManager, "GetMiniInfo", Name);
|
|
|
|
|
end
|
|
|
|
|
return nil;
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------------- 自定义函数 -----------------------------------------
|
|
|
|
|
|
|
|
|
|
--- 滑铲
|
|
|
|
|
function UGCGameState:OnRep_EnableShovel()
|
|
|
|
|
if UGCEventSystem then
|
|
|
|
|
UGCEventSystem.SendEvent(EventTypes.ChangeEnableShovel, self.EnableShovel);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function UGCGameState:SetMiniState(InState)
|
|
|
|
|
self.MiniState = InState;
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:SetMiniState] InState = %s", InState);
|
|
|
|
|
DOREPONCE(self, "MiniState");
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
UGCGameState.UITimer = nil;
|
|
|
|
|
|
|
|
|
|
function UGCGameState:OnRep_MiniState()
|
|
|
|
|
if UGCEventSystem == nil then return ; end
|
|
|
|
|
if self.UITimer ~= nil then
|
|
|
|
|
UGCEventSystem.StopTimer(self.UITimer);
|
|
|
|
|
self.UITimer = nil;
|
|
|
|
|
end
|
|
|
|
|
if self.MiniState <= MiniGameState.MINI_PREPARE then
|
|
|
|
|
self.UITimer = UGCEventSystem.SetTimerLoop(self, function()
|
|
|
|
|
if LocalPlayerController and LocalPlayerController:IsPureSpectator() then
|
|
|
|
|
if not WidgetManager:IsVisiblePanel(WidgetConfig.EUIType.AllWeapon_Spectator) then
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnRep_MiniState] 尝试显示 AllWeapon_Spectator");
|
|
|
|
|
WidgetManager:ShowPanel(WidgetConfig.EUIType.AllWeapon_Spectator, false);
|
|
|
|
|
else
|
|
|
|
|
if self.UITimer then
|
|
|
|
|
UGCEventSystem.StopTimer(self.UITimer);
|
|
|
|
|
self.UITimer = nil;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
if not WidgetManager:IsVisiblePanel(WidgetConfig.EUIType.AllWeapon) then
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnRep_MiniState] 尝试显示 AllWeapon");
|
|
|
|
|
WidgetManager:ShowPanel(WidgetConfig.EUIType.AllWeapon, false);
|
|
|
|
|
else
|
|
|
|
|
if self.UITimer then
|
|
|
|
|
UGCEventSystem.StopTimer(self.UITimer);
|
|
|
|
|
self.UITimer = nil;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end, 2);
|
|
|
|
|
elseif self.MiniState > MiniGameState.MINI_END then
|
|
|
|
|
self.UITimer = UGCEventSystem.SetTimerLoop(self, function()
|
|
|
|
|
if not WidgetManager:IsVisiblePanel(WidgetConfig.EUIType.GameEnd) then
|
|
|
|
|
UGCLogSystem.Log("[UGCGameState:OnRep_MiniState] 尝试显示 GameEnd");
|
|
|
|
|
WidgetManager:ShowPanel(WidgetConfig.EUIType.GameEnd, false, self.MiniInfo.GameWinner, self.MiniInfo.RoundWinners);
|
|
|
|
|
else
|
|
|
|
|
if self.UITimer then
|
|
|
|
|
UGCEventSystem.StopTimer(self.UITimer);
|
|
|
|
|
self.UITimer = nil;
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end, 2);
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return UGCGameState;
|