-- Compiled with roblox-ts v3.0.0 local TS = _G[script] local Reflect = TS.import(script, TS.getModule(script, "@flamework", "core").out).Reflect local BaseComponent = TS.import(script, TS.getModule(script, "@flamework", "components").out).BaseComponent local _core = TS.import(script, TS.getModule(script, "@flamework", "core").out) local Controller = _core.Controller local Modding = _core.Modding local Service = _core.Service local remotes = TS.import(script, script.Parent.Parent, "remotes").remotes local _utilities = TS.import(script, script.Parent.Parent, "utilities") local GetConstructorIdentifier = _utilities.GetConstructorIdentifier local GetParentConstructor = _utilities.GetParentConstructor local IsClient = _utilities.IsClient local IsServer = _utilities.IsServer local logWarning = _utilities.logWarning local _action = TS.import(script, script.Parent, "network", "action") local ACTION_GUARD_FAILED = _action.ACTION_GUARD_FAILED local PLAYER_NOT_CONNECTED = _action.PLAYER_NOT_CONNECTED local SharedRemoteAction = _action.SharedRemoteAction local _event = TS.import(script, script.Parent, "network", "event") local IsSharedComponentRemoteEvent = _event.IsSharedComponentRemoteEvent local SharedRemoteEventClientToServer = _event.SharedRemoteEventClientToServer local SharedRemoteEventServerToClient = _event.SharedRemoteEventServerToClient local Pointer = TS.import(script, script.Parent, "pointer").Pointer local _shared_component = TS.import(script, script.Parent, "shared-component") local GetInstanceWithId = _shared_component.GetInstanceWithId local SharedComponent = _shared_component.SharedComponent local SharedComponentHandler do SharedComponentHandler = setmetatable({}, { __tostring = function() return "SharedComponentHandler" end, }) SharedComponentHandler.__index = SharedComponentHandler function SharedComponentHandler.new(...) local self = setmetatable({}, SharedComponentHandler) return self:constructor(...) or self end function SharedComponentHandler:constructor(components) self.components = components self.classParentCache = {} end function SharedComponentHandler:onInit() local _ = IsClient and self:onClientSetup() local _1 = IsServer and self:onServerSetup() end function SharedComponentHandler:getOrderedParents(ctor, omitBaseComponent) if omitBaseComponent == nil then omitBaseComponent = true end local _classParentCache = self.classParentCache local _ctor = ctor local cache = _classParentCache[_ctor] if cache then return cache end local classes = { ctor } local nextParent = ctor while true do nextParent = GetParentConstructor(nextParent) if not (nextParent ~= nil) then break end if not omitBaseComponent or nextParent ~= BaseComponent then local _nextParent = nextParent table.insert(classes, _nextParent) end end local _classParentCache_1 = self.classParentCache local _ctor_1 = ctor _classParentCache_1[_ctor_1] = classes return classes end function SharedComponentHandler:printInfo(info) local _binding = info local ServerId = _binding.InstanceId local Identifier = _binding.Identifier local SharedIdentifier = _binding.SharedIdentifier local PointerID = _binding.PointerID return `ServerId: {ServerId}\n Identifier: {Identifier}\n SharedIdentifier: {SharedIdentifier}\n PointerID: {PointerID}` end function SharedComponentHandler:resolveComponent(info, callWarning) if callWarning == nil then callWarning = true end local _info = info if type(_info) == "string" then local _instances = SharedComponent.instances local _info_1 = info local component = _instances[_info_1] if not component then if callWarning then logWarning(`Attempt to get component, but component does not exist\n ID: {info}`) end return nil end return component end local _binding = info local ServerId = _binding.InstanceId local Identifier = _binding.Identifier local SharedIdentifier = _binding.SharedIdentifier local PointerID = _binding.PointerID if not Modding.getObjectFromId(SharedIdentifier) then if callWarning then logWarning(`Attempt to get component, but shared component does not exist\n Info: {self:printInfo(info)}`) end return nil end if ServerId == "" then if callWarning then logWarning(`Attempt to get component with missing serverID\n Info: {self:printInfo(info)}`) end return nil end local instance = GetInstanceWithId(ServerId) if not instance then if callWarning then logWarning(`Attempt to get component with missing serverID\n Info: {self:printInfo(info)}`) end return nil end -- Try get component from pointer if PointerID ~= "" and PointerID then local pointer = Pointer.GetPointer(PointerID) if not pointer then if callWarning then logWarning(`Attempt to get component with missing pointer\n Info: {self:printInfo(info)}`) end return nil end local _exitType, _returns = TS.try(function() local component = self.components:getComponent(instance, pointer:GetComponentMetadata()) if component then return TS.TRY_RETURN, { component } end end, function(error) if callWarning then logWarning(`{error}\n PointerID: {PointerID}`) end end) if _exitType then return unpack(_returns) end return nil end -- Try get component from indentifier if Modding.getObjectFromId(Identifier) then local component = self.components:getComponent(instance, Identifier) if component then return component end end -- Try get component from shared identifier local sharedComponent = self.components:getComponents(instance, SharedIdentifier) if #sharedComponent > 1 then if callWarning then -- ▼ ReadonlyArray.map ▼ local _newValue = table.create(#sharedComponent) local _callback = function(s) return GetConstructorIdentifier(getmetatable(s)) end for _k, _v in sharedComponent do _newValue[_k] = _callback(_v, _k - 1, sharedComponent) end -- ▲ ReadonlyArray.map ▲ logWarning(`Attempt to get component when an instance has multiple sharedComponent\n \ Instance: {instance}\n \ FoundComponents: {table.concat(_newValue, ", ")}\n\ Info: {self:printInfo(info)}`) end return nil end return sharedComponent[1] end function SharedComponentHandler:onClientSetup() remotes._shared_component_dispatch:connect(TS.async(function(actions, componentInfo) local component = TS.await(self:waitForComponent(componentInfo)) component:__DispatchFromServer(actions) end)) remotes._shared_component_remote_event_Client:connect(TS.async(function(componentInfo, eventName, args) local component = TS.await(self:waitForComponent(componentInfo)) local remote = component:__GetRemote(eventName) if not IsSharedComponentRemoteEvent(remote) then return nil end if not SharedRemoteEventServerToClient:Indefinitely(remote) then return nil end if not remote:GetGuard()(args) then return nil end remote:GetSignal():Fire(unpack(args)) end)) remotes._shared_component_disconnected:connect(TS.async(function(componentInfo) local component = TS.await(self:waitForComponent(componentInfo)) component:__Disconnected() end)) end SharedComponentHandler.waitForComponent = TS.async(function(self, id) local _instances = SharedComponent.instances local _id = id if _instances[_id] ~= nil then local _instances_1 = SharedComponent.instances local _id_1 = id return _instances_1[_id_1] end local thread = coroutine.running() local connection = SharedComponent.onAddedInstances:Connect(function(component, newId) if id ~= newId then return nil end coroutine.resume(thread, component) end) local res = coroutine.yield() connection:Disconnect() return res end) function SharedComponentHandler:onServerSetup() remotes._shared_component_remote_event_Server:connect(TS.async(function(player, componentInfo, eventName, args) local component = self:resolveComponent(componentInfo) if not component then return nil end if not component:IsConnectedPlayer(player) then return nil end local remote = component:__GetRemote(eventName) if not IsSharedComponentRemoteEvent(remote) then return nil end if not SharedRemoteEventClientToServer:Indefinitely(remote) then return nil end if not remote:GetGuard()(args) then return nil end remote:GetSignal():Fire(player, unpack(args)) end)) remotes._shared_component_remote_function_Server:onRequest(TS.async(function(player, componentInfo, remoteName, args) local component = self:resolveComponent(componentInfo) if not component then return nil end if not component:IsConnectedPlayer(player) then return PLAYER_NOT_CONNECTED end local remote = component:__GetRemote(remoteName) if not IsSharedComponentRemoteEvent(remote) then return nil end if not SharedRemoteAction:Indefinitely(remote) then return nil end if not remote:GetGuard()(args) then return ACTION_GUARD_FAILED end local _result = remote:GetCallback() if _result ~= nil then _result = _result(player, unpack(args)) end return _result end)) remotes._shared_component_connection:onRequest(TS.async(function(player, componentInfo, action) local component = self:resolveComponent(componentInfo, action == 0) if not component then return { false, "", nil } end if action == 0 then if component:IsConnectedPlayer(player) then return { false, "", nil } end local success = component:__OnPlayerConnect(player) return if success then { true, component:GetID(), component.__GenerateHydrateData() } else ({ false, "", nil }) end if action == 1 then if not component:IsConnectedPlayer(player) then return { false, "", nil } end component:__OnPlayerDisconnect(player) return { true, "", nil } end return { false, "", nil } end)) end end --(Flamework) SharedComponentHandler metadata Reflect.defineMetadata(SharedComponentHandler, "identifier", "$s:source/shared-component-handler@SharedComponentHandler") Reflect.defineMetadata(SharedComponentHandler, "flamework:parameters", { "$c:components@Components" }) Reflect.defineMetadata(SharedComponentHandler, "flamework:implements", { "$:flamework@OnInit" }) Reflect.decorate(SharedComponentHandler, "$:flamework@Controller", Controller, { { loadOrder = 0, } }) Reflect.decorate(SharedComponentHandler, "$:flamework@Service", Service, { { loadOrder = 0, } }) return { SharedComponentHandler = SharedComponentHandler, }