Clients/Client2018/content/internal/AppShell/Modules/Shell/ControllerStateManager.lua

181 lines
5.3 KiB
Lua

--[[
// ControllerStateManager.lua
// Handles controller state changes
]]
local CoreGui = game:GetService("CoreGui")
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
local Modules = GuiRoot:FindFirstChild("Modules")
local ShellModules = Modules:FindFirstChild("Shell")
local PlatformService = nil
pcall(function() PlatformService = game:GetService('PlatformService') end)
local ThirdPartyUserService = nil
pcall(function() ThirdPartyUserService = game:GetService('ThirdPartyUserService') end)
local UserInputService = game:GetService('UserInputService')
local GuiService = game:GetService('GuiService')
local Http = require(ShellModules:FindFirstChild('Http'))
local NoActionOverlay = require(ShellModules:FindFirstChild('NoActionOverlay'))
local ScreenManager = require(ShellModules:FindFirstChild('ScreenManager'))
local Alerts = require(ShellModules:FindFirstChild('Alerts'))
local Utility = require(ShellModules:FindFirstChild('Utility'))
local EventHub = require(ShellModules:FindFirstChild('EventHub'))
local XboxAppState = require(ShellModules:FindFirstChild('AppState'))
local ControllerStateManager = {}
local LostUserGamepadCn = nil
local GainedUserGamepadCn = nil
local noActionOverlay = nil
local DATAMODEL_TYPE = {
APP_SHELL = 0;
GAME = 1;
}
local PRESENCE_POLL_INTERVAL = Utility.GetFastVariable("XboxPresencePolling")
local AnyButtonBeganConnection = nil
local SelectionChangedConnection = nil
local ViewChangedConnection = nil
local AnyActionDone = false
local LastTimerInfo = {flag = true};
local function restartPresenceUpdateTimer()
LastTimerInfo.flag = false;
local info = { flag = true }
spawn(function()
AnyActionDone = true
while info.flag do
if AnyActionDone then
Http:RegisterAppPresence()
end
AnyActionDone = false
wait(PRESENCE_POLL_INTERVAL)
end
end)
Utility.DisconnectEvent(AnyButtonBeganConnection)
AnyButtonBeganConnection = UserInputService.InputBegan:connect(function(inputObject)
AnyActionDone = true
end)
Utility.DisconnectEvent(SelectionChangedConnection)
SelectionChangedConnection = GuiService:GetPropertyChangedSignal('SelectedCoreObject'):connect(function()
AnyActionDone = true
end)
LastTimerInfo = info
end
local function stopPresenceUpdateTimer()
LastTimerInfo.flag = false;
Utility.DisconnectEvent(AnyButtonBeganConnection)
Utility.DisconnectEvent(SelectionChangedConnection)
end
local function closeOverlay(dataModelType)
if not noActionOverlay then return end
if dataModelType == DATAMODEL_TYPE.GAME then
UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.None
--Close overlay, don't focus on below screen
noActionOverlay:Hide()
else
ScreenManager:CloseCurrent()
end
noActionOverlay = nil
end
local function showErrorOverlay(alert, dataModelType)
if noActionOverlay then return end
noActionOverlay = NoActionOverlay(alert)
if dataModelType == DATAMODEL_TYPE.GAME then
UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.ForceHide
noActionOverlay:Show()
else
ScreenManager:OpenScreen(noActionOverlay, false)
end
end
local function onLostUserGamepad(dataModelType)
local userDisplayName = ""
if dataModelType == DATAMODEL_TYPE.APP_SHELL then
userDisplayName = XboxAppState.store:getState().XboxUser.gamertag
else
if ThirdPartyUserService then
userDisplayName = ThirdPartyUserService:GetUserDisplayName()
end
end
-- create alert
local alert = Alerts.LostConnection["Controller"]
alert.Msg = string.format(alert.Msg, userDisplayName)
showErrorOverlay(alert, dataModelType)
end
local function onGainedUserGamepad(dataModelType)
closeOverlay(dataModelType)
end
local function disconnectEvents()
LostUserGamepadCn = Utility.DisconnectEvent(LostUserGamepadCn)
GainedUserGamepadCn = Utility.DisconnectEvent(GainedUserGamepadCn)
end
local function initAppPresenceReporting()
restartPresenceUpdateTimer()
Utility.DisconnectEvent(ViewChangedConnection)
ViewChangedConnection = PlatformService.ViewChanged:connect(
function(value)
if value == DATAMODEL_TYPE.APP_SHELL then
restartPresenceUpdateTimer()
else
stopPresenceUpdateTimer()
end
end
)
end
--ControllerStateManager initialized from AppHome.lua(when in app shell)/NotificationScript2.lua(when in game)
--Note: The ControllerStateManager module scirpt is required on different DMs (app shell & game).
--Thus, whenever we enter a new game, this module will run once as it's required on a new game DM.
function ControllerStateManager:Initialize()
if not PlatformService then return end
local dataModelType = PlatformService.DatamodelType
disconnectEvents()
if ThirdPartyUserService then
LostUserGamepadCn = ThirdPartyUserService.ActiveGamepadRemoved:connect(function()
onLostUserGamepad(dataModelType)
end)
GainedUserGamepadCn = ThirdPartyUserService.ActiveGamepadAdded:connect(function()
onGainedUserGamepad(dataModelType)
end)
end
if dataModelType == DATAMODEL_TYPE.APP_SHELL then
EventHub:addEventListener(EventHub.Notifications["AuthenticationSuccess"], "AchievementManager",
function()
initAppPresenceReporting();
end
)
end
end
function ControllerStateManager:CheckUserConnected()
if not PlatformService then return end
local isGamepadConnected = UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad1)
if not isGamepadConnected then
onLostUserGamepad(PlatformService.DatamodelType)
end
end
return ControllerStateManager