diff --git a/aftman.toml b/aftman.toml index 2be58536559..00bc123b9c1 100644 --- a/aftman.toml +++ b/aftman.toml @@ -7,7 +7,6 @@ luau-lsp = "Quenty/luau-lsp@1.58.0-quenty.1" lune = "lune-org/lune@0.8.9" mantle = "blake-mealey/mantle@0.10.7" moonwave-extractor = "UpliftGames/moonwave@1.3.0" -remodel = "rojo-rbx/remodel@0.9.1" rojo = "quenty/rojo@7.7.0-rc.1-quenty.4" run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0" selene = "Kampfkarren/selene@0.29.0" diff --git a/src/boundingboxutils/src/Shared/CompiledBoundingBoxUtils.lua b/src/boundingboxutils/src/Shared/CompiledBoundingBoxUtils.lua index 955198da156..a57ffa72db0 100644 --- a/src/boundingboxutils/src/Shared/CompiledBoundingBoxUtils.lua +++ b/src/boundingboxutils/src/Shared/CompiledBoundingBoxUtils.lua @@ -7,6 +7,8 @@ local CompiledBoundingBoxUtils = {} +export type CompiledBoundingBox = CFrame + --[=[ Compiles a bounding box into a CFrame rotation matrix for easy usage. @@ -15,7 +17,7 @@ local CompiledBoundingBoxUtils = {} @param size Vector3 @return CFrame ]=] -function CompiledBoundingBoxUtils.compileBBox(cframe: CFrame, size: Vector3): CFrame +function CompiledBoundingBoxUtils.compileBBox(cframe: CFrame, size: Vector3): CompiledBoundingBox -- stylua: ignore return CFrame.fromMatrix( cframe.Position, @@ -31,7 +33,7 @@ end @param bbox CFrame @return boolean ]=] -function CompiledBoundingBoxUtils.testPointBBox(point: Vector3, bbox: CFrame): boolean +function CompiledBoundingBoxUtils.testPointBBox(point: Vector3, bbox: CompiledBoundingBox): boolean local objPos = bbox * point -- stylua: ignore diff --git a/src/datastore/src/Server/DataStore.lua b/src/datastore/src/Server/DataStore.lua index 4dda89b943c..5ed0a90fe6a 100644 --- a/src/datastore/src/Server/DataStore.lua +++ b/src/datastore/src/Server/DataStore.lua @@ -314,7 +314,7 @@ function DataStore.PromiseViewUpToDate(self: DataStore): Promise.Promise<()> return promise end -function DataStore._setupAutoSaving(self: DataStore) +function DataStore._setupAutoSaving(self: DataStore): () local startTime = os.clock() self._maid:GiveTask(Rx.combineLatest({ @@ -364,7 +364,7 @@ function DataStore._setupAutoSaving(self: DataStore) end)) end -function DataStore._syncData(self: DataStore, doMergeNewData: boolean, doCloseSession: boolean?) +function DataStore._syncData(self: DataStore, doMergeNewData: boolean, doCloseSession: boolean?): Promise.Promise<()> if self:DidLoadFail() then warn("[DataStore] - Not syncing, failed to load") return Promise.rejected("Load not successful, not syncing") diff --git a/src/datastore/src/Server/GameDataStoreService.lua b/src/datastore/src/Server/GameDataStoreService.lua index b621b1e754c..8fd59778120 100644 --- a/src/datastore/src/Server/GameDataStoreService.lua +++ b/src/datastore/src/Server/GameDataStoreService.lua @@ -18,16 +18,31 @@ local ServiceBag = require("ServiceBag") local GameDataStoreService = {} GameDataStoreService.ServiceName = "GameDataStoreService" -function GameDataStoreService:Init(serviceBag: ServiceBag.ServiceBag) - assert(not self._serviceBag, "Already initialized") +export type GameDataStoreService = typeof(setmetatable( + {} :: { + _serviceBag: ServiceBag.ServiceBag, + _maid: Maid.Maid, + _dataStorePromise: Promise.Promise?, + _robloxDataStorePromise: Promise.Promise?, + _bindToCloseService: any, + }, + {} :: typeof({ __index = GameDataStoreService }) +)) + +function GameDataStoreService.Init(self: GameDataStoreService, serviceBag: ServiceBag.ServiceBag): () + assert(not (self :: any)._serviceBag, "Already initialized") self._serviceBag = assert(serviceBag, "No serviceBag") + self._maid = Maid.new() self._bindToCloseService = self._serviceBag:GetService(require("BindToCloseService")) - - self._maid = Maid.new() end -function GameDataStoreService:PromiseDataStore(): Promise.Promise +--[=[ + Promises a DataStore for the current game that is synchronized every 5 seconds. + + @return Promise +]=] +function GameDataStoreService.PromiseDataStore(self: GameDataStoreService): Promise.Promise if self._dataStorePromise then return self._dataStorePromise end @@ -48,11 +63,12 @@ function GameDataStoreService:PromiseDataStore(): Promise.Promise return dataStore end) + assert(self._dataStorePromise, "Typechecking assertion") return self._dataStorePromise end -function GameDataStoreService:_promiseRobloxDataStore(): Promise.Promise +function GameDataStoreService._promiseRobloxDataStore(self: GameDataStoreService): Promise.Promise if self._robloxDataStorePromise then return self._robloxDataStorePromise end @@ -60,14 +76,16 @@ function GameDataStoreService:_promiseRobloxDataStore(): Promise.Promise self._robloxDataStorePromise = self._maid:GivePromise(DataStorePromises.promiseDataStore("GameDataStore", "Version1")) + assert(self._robloxDataStorePromise, "Typechecking assertion") + return self._robloxDataStorePromise end -function GameDataStoreService:_getKey(): string +function GameDataStoreService._getKey(_self: GameDataStoreService): string return "version1" end -function GameDataStoreService:Destroy() +function GameDataStoreService.Destroy(self: GameDataStoreService) self._maid:DoCleaning() end diff --git a/src/datastore/src/Server/Modules/DataStoreDeleteToken.lua b/src/datastore/src/Server/Modules/DataStoreDeleteToken.lua index 1a4b399337a..1281513f9ef 100644 --- a/src/datastore/src/Server/Modules/DataStoreDeleteToken.lua +++ b/src/datastore/src/Server/Modules/DataStoreDeleteToken.lua @@ -9,4 +9,6 @@ local require = require(script.Parent.loader).load(script) local Symbol = require("Symbol") -return Symbol.named("dataStoreDeleteToken") +export type DataStoreDeleteToken = Symbol.Symbol + +return Symbol.named("dataStoreDeleteToken") :: DataStoreDeleteToken diff --git a/src/datastore/src/Server/Modules/DataStoreStage.lua b/src/datastore/src/Server/Modules/DataStoreStage.lua index 48877fc9569..9fae4162110 100644 --- a/src/datastore/src/Server/Modules/DataStoreStage.lua +++ b/src/datastore/src/Server/Modules/DataStoreStage.lua @@ -111,8 +111,12 @@ end @param key string @param value any ]=] -function DataStoreStage.Store(self: DataStoreStage, key: string, value: any) - assert(type(key) == "string", "Bad key") +function DataStoreStage.Store( + self: DataStoreStage, + key: DataStoreStageKey, + value: any | DataStoreDeleteToken.DataStoreDeleteToken +): () + assert(type(key) == "string" or type(key) == "number", "Bad key") if value == nil then value = DataStoreDeleteToken @@ -133,7 +137,7 @@ end end) ``` - @param key string | number + @param key DataStoreStageKey @param defaultValue T? @return Promise ]=] @@ -166,7 +170,7 @@ end @param defaultValue any @return Promise ]=] -function DataStoreStage.LoadAll(self: DataStoreStage, defaultValue) +function DataStoreStage.LoadAll(self: DataStoreStage, defaultValue: T?): Promise.Promise return self:PromiseViewUpToDate():Then(function() if self._viewSnapshot == nil then return defaultValue @@ -187,10 +191,10 @@ end saveslot:Store("Money", 0) ``` - @param key string | number + @param key DataStoreStageKey @return DataStoreStage ]=] -function DataStoreStage.GetSubStore(self: DataStoreStage, key: DataStoreStageKey) +function DataStoreStage.GetSubStore(self: DataStoreStage, key: DataStoreStageKey): DataStoreStage assert(type(key) == "string" or type(key) == "number", "Bad key") if self._stores[key] then @@ -243,10 +247,10 @@ end --[=[ Explicitely deletes data at the key - @param key string | number + @param key DataStoreStageKey ]=] -function DataStoreStage.Delete(self: DataStoreStage, key: string) - assert(type(key) == "string", "Bad key") +function DataStoreStage.Delete(self: DataStoreStage, key: DataStoreStageKey): () + assert(type(key) == "string" or type(key) == "number", "Bad key") self:_storeAtKey(key, DataStoreDeleteToken) end @@ -254,7 +258,7 @@ end --[=[ Queues up a wipe of all values. This will completely set the data to nil. ]=] -function DataStoreStage.Wipe(self: DataStoreStage) +function DataStoreStage.Wipe(self: DataStoreStage): () self:Overwrite(DataStoreDeleteToken) end @@ -263,12 +267,16 @@ end If no key is passed than it will observe the whole view snapshot - @param key string | number? + @param key DataStoreStageKey? @param defaultValue T? @return Observable ]=] -function DataStoreStage.Observe(self: DataStoreStage, key, defaultValue) - assert(type(key) == "string" or type(key) == "number" or key == nil, "Bad key") +function DataStoreStage.Observe( + self: DataStoreStage, + key: DataStoreStageKey?, + defaultValue: T? +): Observable.Observable + assert(type(key) == "string" or type(key) == "number", "Bad key") if key == nil then return Observable.new(function(sub) @@ -293,7 +301,7 @@ function DataStoreStage.Observe(self: DataStoreStage, key, defaultValue) end) return maid - end) + end) :: any end return Observable.new(function(sub) @@ -315,16 +323,16 @@ function DataStoreStage.Observe(self: DataStoreStage, key, defaultValue) end) return maid - end) + end) :: any end --[=[ Adds a callback to be called before save. This may return a promise. @param callback function -- May return a promise - @return function -- Call to remove + @return () -> () -- Call to remove ]=] -function DataStoreStage.AddSavingCallback(self: DataStoreStage, callback: DataStoreCallback?) +function DataStoreStage.AddSavingCallback(self: DataStoreStage, callback: DataStoreCallback?): () -> () assert(type(callback) == "function", "Bad callback") table.insert(self._savingCallbacks, callback) @@ -340,7 +348,7 @@ end Removes a saving callback from the data store stage @param callback function ]=] -function DataStoreStage.RemoveSavingCallback(self: DataStoreStage, callback: DataStoreCallback?) +function DataStoreStage.RemoveSavingCallback(self: DataStoreStage, callback: DataStoreCallback?): () assert(type(callback) == "function", "Bad callback") local index = table.find(self._savingCallbacks, callback) @@ -434,7 +442,7 @@ end @param parentWriter DataStoreWriter ]=] -function DataStoreStage.MarkDataAsSaved(self: DataStoreStage, parentWriter: DataStoreWriter.DataStoreWriter) +function DataStoreStage.MarkDataAsSaved(self: DataStoreStage, parentWriter: DataStoreWriter.DataStoreWriter): () -- Update all children first for key, subwriter in pairs(parentWriter:GetSubWritersMap()) do local store = self._stores[key] @@ -504,7 +512,7 @@ end @return Promise ]=] -function DataStoreStage.PromiseViewUpToDate(self: DataStoreStage) +function DataStoreStage.PromiseViewUpToDate(self: DataStoreStage): Promise.Promise<()> if not self._loadParent then error("[DataStoreStage.Load] - Failed to load, no loadParent!") end @@ -525,7 +533,7 @@ end @param data any ]=] -function DataStoreStage.Overwrite(self: DataStoreStage, data) +function DataStoreStage.Overwrite(self: DataStoreStage, data: any | DataStoreDeleteToken.DataStoreDeleteToken): () -- Ensure that we at least start loading (and thus the autosave loop) for write self:PromiseViewUpToDate() @@ -578,7 +586,7 @@ end @param data any ]=] -function DataStoreStage.OverwriteMerge(self: DataStoreStage, data) +function DataStoreStage.OverwriteMerge(self: DataStoreStage, data: any): () -- Ensure that we at least start loading (and thus the autosave loop) for write self:PromiseViewUpToDate() @@ -775,7 +783,7 @@ end function DataStoreStage._updateStoresAndComputeBaseDataSnapshotValueFromDiffSnapshot( self: DataStoreStage, key: DataStoreStageKey, - value + value: any | DataStoreDeleteToken.DataStoreDeleteToken ) assert(type(key) == "string" or type(key) == "number", "Bad key") diff --git a/src/datastore/src/Server/Modules/DataStoreWriter.lua b/src/datastore/src/Server/Modules/DataStoreWriter.lua index 0eedb38c0aa..1d1bbdc2bda 100644 --- a/src/datastore/src/Server/Modules/DataStoreWriter.lua +++ b/src/datastore/src/Server/Modules/DataStoreWriter.lua @@ -95,7 +95,7 @@ end --[=[ Adds a recursive child writer to use at the key `name` - @param name string | number + @param name DataStoreStageKey @param writer DataStoreWriter ]=] function DataStoreWriter.AddSubWriter(self: DataStoreWriter, name: DataStoreStageKey, writer: DataStoreWriter) @@ -109,7 +109,7 @@ end --[=[ Gets a sub writer - @param name string | number + @param name DataStoreStageKey @return DataStoreWriter ]=] function DataStoreWriter.GetWriter(self: DataStoreWriter, name: DataStoreStageKey): DataStoreWriter? diff --git a/src/datastore/src/Server/PlayerDataStoreService.lua b/src/datastore/src/Server/PlayerDataStoreService.lua index 5746f47c17c..fa6740a008f 100644 --- a/src/datastore/src/Server/PlayerDataStoreService.lua +++ b/src/datastore/src/Server/PlayerDataStoreService.lua @@ -25,6 +25,8 @@ export type PlayerDataStoreService = typeof(setmetatable( _dataStoreName: string, _dataStoreScope: string, _dataStoreManagerPromise: Promise.Promise, + _bindToCloseService: any, + _promiseStarted: Promise.Promise<()>, }, {} :: typeof({ __index = PlayerDataStoreService }) )) @@ -33,7 +35,7 @@ export type PlayerDataStoreService = typeof(setmetatable( Initializes the PlayerDataStoreService. Should be done via [ServiceBag.Init]. @param serviceBag ServiceBag ]=] -function PlayerDataStoreService:Init(serviceBag: ServiceBag.ServiceBag) +function PlayerDataStoreService.Init(self: PlayerDataStoreService, serviceBag: ServiceBag.ServiceBag): () self._serviceBag = assert(serviceBag, "No serviceBag") self._maid = Maid.new() @@ -49,7 +51,7 @@ end --[=[ Initializes the datastore service for players. Should be done via [ServiceBag.Start]. ]=] -function PlayerDataStoreService:Start() +function PlayerDataStoreService.Start(self: PlayerDataStoreService): () -- Give time for configuration self._promiseStarted:Resolve() end @@ -63,7 +65,7 @@ end @param dataStoreName string ]=] -function PlayerDataStoreService:SetDataStoreName(dataStoreName: string): () +function PlayerDataStoreService.SetDataStoreName(self: PlayerDataStoreService, dataStoreName: string): () assert(type(dataStoreName) == "string", "Bad dataStoreName") assert(self._promiseStarted, "Not initialized") assert(self._promiseStarted:IsPending(), "Already started, cannot configure") @@ -80,7 +82,7 @@ end @param dataStoreScope string ]=] -function PlayerDataStoreService:SetDataStoreScope(dataStoreScope: string): () +function PlayerDataStoreService.SetDataStoreScope(self: PlayerDataStoreService, dataStoreScope: string): () assert(type(dataStoreScope) == "string", "Bad dataStoreScope") assert(self._promiseStarted, "Not initialized") assert(self._promiseStarted:IsPending(), "Already started, cannot configure") @@ -93,7 +95,10 @@ end @param player Player @return Promise ]=] -function PlayerDataStoreService:PromiseDataStore(player: Player): Promise.Promise +function PlayerDataStoreService.PromiseDataStore( + self: PlayerDataStoreService, + player: Player +): Promise.Promise return self:PromiseManager():Then(function(manager) return manager:GetDataStore(player) end) @@ -104,7 +109,10 @@ end @param callback function -- May return a promise @return Promise ]=] -function PlayerDataStoreService:PromiseAddRemovingCallback(callback) +function PlayerDataStoreService.PromiseAddRemovingCallback( + self: PlayerDataStoreService, + callback: () -> Promise.Promise? +): Promise.Promise<()> return self:PromiseManager():Then(function(manager) manager:AddRemovingCallback(callback) end) @@ -114,7 +122,9 @@ end Retrieves the manager @return Promise ]=] -function PlayerDataStoreService:PromiseManager(): Promise.Promise +function PlayerDataStoreService.PromiseManager( + self: PlayerDataStoreService +): Promise.Promise if self._dataStoreManagerPromise then return self._dataStoreManagerPromise end @@ -135,11 +145,12 @@ function PlayerDataStoreService:PromiseManager(): Promise.Promise?, + _robloxDataStorePromise: Promise.Promise?, + _bindToCloseService: any, + _customKey: string?, + }, + {} :: typeof({ __index = PrivateServerDataStoreService }) +)) + +function PrivateServerDataStoreService.Init(self: PrivateServerDataStoreService, serviceBag: ServiceBag.ServiceBag): () + assert(not (self :: any)._serviceBag, "Already initialized") self._serviceBag = assert(serviceBag, "No serviceBag") + self._maid = Maid.new() self._bindToCloseService = self._serviceBag:GetService(require("BindToCloseService")) - - self._maid = Maid.new() end -function PrivateServerDataStoreService:PromiseDataStore(): Promise.Promise +--[=[ + Promises a DataStore for the current private server. If this is not a private server, it returns a datastore + that is keyed towards "main". + + @return Promise +]=] +function PrivateServerDataStoreService.PromiseDataStore( + self: PrivateServerDataStoreService +): Promise.Promise if self._dataStorePromise then return self._dataStorePromise end self._dataStorePromise = self:_promiseRobloxDataStore():Then(function(robloxDataStore) - local dataStore = DataStore.new(robloxDataStore, self:_getKey()) - self._maid:GiveTask(dataStore) + local dataStore = self._maid:Add(DataStore.new(robloxDataStore, self:_getKey())) if game.PrivateServerOwnerId ~= 0 then dataStore:Store("LastPrivateServerOwnerId", game.PrivateServerOwnerId) @@ -45,11 +63,12 @@ function PrivateServerDataStoreService:PromiseDataStore(): Promise.Promise +function PrivateServerDataStoreService._promiseRobloxDataStore( + self: PrivateServerDataStoreService +): Promise.Promise if self._robloxDataStorePromise then return self._robloxDataStorePromise end @@ -66,11 +87,12 @@ function PrivateServerDataStoreService:_promiseRobloxDataStore(): Promise.Promis -- This could potentially self._robloxDataStorePromise = self._maid:GivePromise(DataStorePromises.promiseDataStore("PrivateServerDataStores", "Version1")) + assert(self._robloxDataStorePromise, "Typechecking assertion") return self._robloxDataStorePromise end -function PrivateServerDataStoreService:_getKey(): string +function PrivateServerDataStoreService._getKey(self: PrivateServerDataStoreService): string if self._customKey then return self._customKey end @@ -81,7 +103,7 @@ function PrivateServerDataStoreService:_getKey(): string end end -function PrivateServerDataStoreService:Destroy(): () +function PrivateServerDataStoreService.Destroy(self: PrivateServerDataStoreService): () self._maid:DoCleaning() end diff --git a/src/debounce/src/Shared/DebounceTimer.lua b/src/debounce/src/Shared/DebounceTimer.lua index 872a6858255..8b8bf17074d 100644 --- a/src/debounce/src/Shared/DebounceTimer.lua +++ b/src/debounce/src/Shared/DebounceTimer.lua @@ -32,14 +32,14 @@ end Gets the length @param length number ]=] -function DebounceTimer.SetLength(self: DebounceTimer, length: number) +function DebounceTimer.SetLength(self: DebounceTimer, length: number): () self._length = length or error("No length") end --[=[ Restarts the timer ]=] -function DebounceTimer.Restart(self: DebounceTimer) +function DebounceTimer.Restart(self: DebounceTimer): () self._startTime = os.clock() end diff --git a/src/defaultvalueutils/src/Shared/DefaultValueUtils.lua b/src/defaultvalueutils/src/Shared/DefaultValueUtils.lua index a3ff07d405e..8c28c805bbf 100644 --- a/src/defaultvalueutils/src/Shared/DefaultValueUtils.lua +++ b/src/defaultvalueutils/src/Shared/DefaultValueUtils.lua @@ -43,7 +43,7 @@ local DEFAULT_VALUES = { @param typeOfName string @return any ]=] -function DefaultValueUtils.getDefaultValueForType(typeOfName: string) +function DefaultValueUtils.getDefaultValueForType(typeOfName: string): any if DEFAULT_VALUES[typeOfName] ~= nil then return DEFAULT_VALUES[typeOfName] elseif typeOfName == "table" then diff --git a/src/settings-inputkeymap/src/Client/InputKeyMapSettingClient.lua b/src/settings-inputkeymap/src/Client/InputKeyMapSettingClient.lua index 8f382d63023..6877685e3f4 100644 --- a/src/settings-inputkeymap/src/Client/InputKeyMapSettingClient.lua +++ b/src/settings-inputkeymap/src/Client/InputKeyMapSettingClient.lua @@ -6,6 +6,7 @@ local require = require(script.Parent.loader).load(script) local BaseObject = require("BaseObject") +local InputKeyMapList = require("InputKeyMapList") local InputKeyMapSettingConstants = require("InputKeyMapSettingConstants") local InputKeyMapSettingUtils = require("InputKeyMapSettingUtils") local ServiceBag = require("ServiceBag") @@ -15,7 +16,10 @@ local InputKeyMapSettingClient = setmetatable({}, BaseObject) InputKeyMapSettingClient.ClassName = "InputKeyMapSettingClient" InputKeyMapSettingClient.__index = InputKeyMapSettingClient -function InputKeyMapSettingClient.new(serviceBag: ServiceBag.ServiceBag, inputKeyMapList) +function InputKeyMapSettingClient.new( + serviceBag: ServiceBag.ServiceBag, + inputKeyMapList: InputKeyMapList.InputKeyMapList +) local self = setmetatable(BaseObject.new(), InputKeyMapSettingClient) self._serviceBag = assert(serviceBag, "No serviceBag") diff --git a/src/settings-inputkeymap/src/Client/SettingsInputKeyMapServiceClient.lua b/src/settings-inputkeymap/src/Client/SettingsInputKeyMapServiceClient.lua index 4ca060fdca7..89a27de029b 100644 --- a/src/settings-inputkeymap/src/Client/SettingsInputKeyMapServiceClient.lua +++ b/src/settings-inputkeymap/src/Client/SettingsInputKeyMapServiceClient.lua @@ -1,4 +1,4 @@ ---!nonstrict +--!strict --[=[ @class SettingsInputKeyMapServiceClient ]=] diff --git a/src/soundgroups/src/Client/SoundGroupServiceClient.lua b/src/soundgroups/src/Client/SoundGroupServiceClient.lua index 28a89d99b65..e7976a9304b 100644 --- a/src/soundgroups/src/Client/SoundGroupServiceClient.lua +++ b/src/soundgroups/src/Client/SoundGroupServiceClient.lua @@ -1,4 +1,4 @@ ---!nonstrict +--!strict --[=[ @class SoundGroupServiceClient ]=] diff --git a/src/soundgroups/src/Server/SoundGroupService.lua b/src/soundgroups/src/Server/SoundGroupService.lua index 2ed9013bd95..355d1ac0a2e 100644 --- a/src/soundgroups/src/Server/SoundGroupService.lua +++ b/src/soundgroups/src/Server/SoundGroupService.lua @@ -1,4 +1,4 @@ ---!nonstrict +--!strict --[=[ @class SoundGroupService ]=] diff --git a/src/soundplayer/src/Client/Loops/LoopedSoundPlayer.lua b/src/soundplayer/src/Client/Loops/LoopedSoundPlayer.lua index 9f597656e4d..4a17db19e5e 100644 --- a/src/soundplayer/src/Client/Loops/LoopedSoundPlayer.lua +++ b/src/soundplayer/src/Client/Loops/LoopedSoundPlayer.lua @@ -47,7 +47,7 @@ export type LoopedSoundPlayer = )) & SpringTransitionModel.SpringTransitionModel -function LoopedSoundPlayer.new(soundId: (string | number)?, soundParent: Instance?): LoopedSoundPlayer +function LoopedSoundPlayer.new(soundId: SoundUtils.SoundId?, soundParent: Instance?): LoopedSoundPlayer assert(soundId == nil or SoundUtils.isConvertableToRbxAsset(soundId), "Bad soundId") local self: LoopedSoundPlayer = setmetatable(SpringTransitionModel.new() :: any, LoopedSoundPlayer) diff --git a/src/sounds/src/Shared/SoundUtils.lua b/src/sounds/src/Shared/SoundUtils.lua index 2077e3d48c0..12a1962e30d 100644 --- a/src/sounds/src/Shared/SoundUtils.lua +++ b/src/sounds/src/Shared/SoundUtils.lua @@ -21,7 +21,7 @@ export type SoundOptions = { SoundId: number | string, } -export type SoundId = string | number | SoundOptions +export type SoundId = RbxAssetUtils.RbxAssetIdConvertable | SoundOptions | Sound local SoundUtils = {} @@ -52,10 +52,37 @@ function SoundUtils.playFromId(id: SoundId): Sound return sound end +--[=[ + Clones a soundId from a base id and applies properties from an overwrite id. +]=] +function SoundUtils.cloneMerge(baseId: SoundId, overwriteId: SoundId): SoundId + assert(SoundUtils.isConvertableToRbxAsset(baseId), "Bad id") + assert(SoundUtils.isConvertableToRbxAsset(overwriteId), "Bad overwriteId") + + local conversion = SoundUtils.toRbxAssetId(overwriteId) + assert(conversion, "Bad conversion") + + local sound = SoundUtils.createSoundFromId(baseId) + sound.SoundId = conversion + + SoundUtils.applyPropertiesFromId(sound, overwriteId) + + return sound +end + --[=[ Creates a new sound object from the given id ]=] -function SoundUtils.createSoundFromId(id: string | number | SoundOptions): Sound +function SoundUtils.createSoundFromId(id: SoundId): Sound + if typeof(id) == "Instance" and id:IsA("Sound") then + local copy = Instance.fromExisting(id) + copy.Archivable = false + + SoundUtils.applyPropertiesFromId(copy, id) + + return copy + end + local soundId = SoundUtils.toRbxAssetId(id) assert(type(soundId) == "string", "Bad id") @@ -67,7 +94,7 @@ function SoundUtils.createSoundFromId(id: string | number | SoundOptions): Sound return sound end -function SoundUtils.applyPropertiesFromId(sound: Sound, id: string | number | SoundOptions): () +function SoundUtils.applyPropertiesFromId(sound: Sound, id: SoundId): () local soundId = assert(SoundUtils.toRbxAssetId(id), "Unable to convert id to rbxassetid") sound.Name = string.format("Sound_%s", soundId) @@ -97,7 +124,7 @@ end --[=[ Plays back a template given asset id in the parent ]=] -function SoundUtils.playFromIdInParent(id: string | number | SoundOptions, parent: Instance): Sound +function SoundUtils.playFromIdInParent(id: SoundId, parent: Instance): Sound assert(typeof(parent) == "Instance", "Bad parent") local sound = SoundUtils.createSoundFromId(id) @@ -159,17 +186,21 @@ end @return string? @within SoundUtils ]=] -function SoundUtils.toRbxAssetId(soundId: string | number | SoundOptions): string? +function SoundUtils.toRbxAssetId(soundId: SoundId): string? if type(soundId) == "table" then return RbxAssetUtils.toRbxAssetId(soundId.SoundId) + elseif typeof(soundId) == "Instance" then + return soundId.SoundId else return RbxAssetUtils.toRbxAssetId(soundId) end end -function SoundUtils.isConvertableToRbxAsset(soundId: string | number | SoundOptions): boolean +function SoundUtils.isConvertableToRbxAsset(soundId: SoundId): boolean if type(soundId) == "table" then return RbxAssetUtils.isConvertableToRbxAsset(soundId.SoundId) + elseif typeof(soundId) == "Instance" then + return RbxAssetUtils.isConvertableToRbxAsset(soundId.SoundId) else return RbxAssetUtils.isConvertableToRbxAsset(soundId) end diff --git a/src/spawning/src/Client/SpawnServiceClient.lua b/src/spawning/src/Client/SpawnServiceClient.lua index 30be56d1de9..2ec09436846 100644 --- a/src/spawning/src/Client/SpawnServiceClient.lua +++ b/src/spawning/src/Client/SpawnServiceClient.lua @@ -1,4 +1,4 @@ ---!nonstrict +--!strict --[=[ @class SpawnServiceClient ]=] diff --git a/src/tie/src/Shared/Members/Properties/TiePropertyDefinition.lua b/src/tie/src/Shared/Members/Properties/TiePropertyDefinition.lua index e67ac22d14c..b9207bc2b53 100644 --- a/src/tie/src/Shared/Members/Properties/TiePropertyDefinition.lua +++ b/src/tie/src/Shared/Members/Properties/TiePropertyDefinition.lua @@ -1,4 +1,4 @@ ---!nonstrict +--!strict --[=[ @class TiePropertyDefinition ]=] @@ -9,16 +9,31 @@ local TieMemberDefinition = require("TieMemberDefinition") local TiePropertyImplementation = require("TiePropertyImplementation") local TiePropertyInterface = require("TiePropertyInterface") local TieRealmUtils = require("TieRealmUtils") +local TieRealms = require("TieRealms") local TiePropertyDefinition = setmetatable({}, TieMemberDefinition) TiePropertyDefinition.ClassName = "TiePropertyDefinition" TiePropertyDefinition.__index = TiePropertyDefinition -function TiePropertyDefinition.new(tieDefinition, propertyName: string, defaultValue: any, memberTieRealm) +export type TiePropertyDefinition = + typeof(setmetatable( + {} :: { + _defaultValue: any, + }, + {} :: typeof({ __index = TieMemberDefinition }) + )) + & TieMemberDefinition.TieMemberDefinition + +function TiePropertyDefinition.new( + tieDefinition: any, + propertyName: string, + defaultValue: any, + memberTieRealm: TieRealms.TieRealm +): TiePropertyDefinition assert(TieRealmUtils.isTieRealm(memberTieRealm), "Bad memberTieRealm") - local self = - setmetatable(TieMemberDefinition.new(tieDefinition, propertyName, memberTieRealm), TiePropertyDefinition) + local self: TiePropertyDefinition = + setmetatable(TieMemberDefinition.new(tieDefinition, propertyName, memberTieRealm) :: any, TiePropertyDefinition) self._defaultValue = defaultValue @@ -29,7 +44,7 @@ function TiePropertyDefinition:GetDefaultValue() return self._defaultValue end -function TiePropertyDefinition:IsRequiredForImplementation(currentRealm): boolean +function TiePropertyDefinition:IsRequiredForImplementation(currentRealm: TieRealms.TieRealm): boolean -- Override if getmetatable(TiePropertyDefinition).IsRequiredForImplementation(self, currentRealm) then if self:GetDefaultValue() ~= nil then @@ -42,14 +57,14 @@ function TiePropertyDefinition:IsRequiredForImplementation(currentRealm): boolea return false end -function TiePropertyDefinition:Implement(implParent: Instance, initialValue, _actualSelf, tieRealm) +function TiePropertyDefinition:Implement(implParent: Instance, initialValue, _actualSelf, tieRealm: TieRealms.TieRealm) assert(typeof(implParent) == "Instance", "Bad implParent") assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm") return TiePropertyImplementation.new(self, implParent, initialValue, tieRealm) end -function TiePropertyDefinition:GetInterface(implParent: Instance, _actualSelf, tieRealm) +function TiePropertyDefinition:GetInterface(implParent: Instance, _actualSelf, tieRealm: TieRealms.TieRealm) assert(typeof(implParent) == "Instance", "Bad implParent") assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm") diff --git a/src/tie/src/Shared/Members/Properties/TiePropertyImplementation.lua b/src/tie/src/Shared/Members/Properties/TiePropertyImplementation.lua index 801f1a0696c..c30a2f37f56 100644 --- a/src/tie/src/Shared/Members/Properties/TiePropertyImplementation.lua +++ b/src/tie/src/Shared/Members/Properties/TiePropertyImplementation.lua @@ -1,4 +1,4 @@ ---!nonstrict +--!strict --[=[ @class TiePropertyImplementation ]=] @@ -18,8 +18,18 @@ local TiePropertyImplementation = setmetatable({}, BaseObject) TiePropertyImplementation.ClassName = "TiePropertyImplementation" TiePropertyImplementation.__index = TiePropertyImplementation -function TiePropertyImplementation.new(memberDefinition, folder: Folder, initialValue, _actualSelf) - local self = setmetatable(BaseObject.new(), TiePropertyImplementation) +export type TiePropertyImplementation = + typeof(setmetatable( + {} :: { + _folder: Instance, + _memberDefinition: any, + }, + {} :: typeof({ __index = TiePropertyImplementation }) + )) + & BaseObject.BaseObject + +function TiePropertyImplementation.new(memberDefinition, folder: Instance, initialValue, _actualSelf) + local self = setmetatable(BaseObject.new() :: any, TiePropertyImplementation) self._memberDefinition = assert(memberDefinition, "No memberDefinition") self._folder = assert(folder, "No folder") @@ -51,8 +61,8 @@ function TiePropertyImplementation.new(memberDefinition, folder: Folder, initial return self end -function TiePropertyImplementation:SetImplementation(implementation) - self._maid._current = nil +function TiePropertyImplementation.SetImplementation(self: TiePropertyImplementation, implementation) + self._maid._current = nil :: Maid.Maid? local maid = Maid.new() @@ -66,7 +76,11 @@ function TiePropertyImplementation:SetImplementation(implementation) self._maid._current = maid end -function TiePropertyImplementation:_updateImplementation(maid, implementation) +function TiePropertyImplementation._updateImplementation( + self: TiePropertyImplementation, + maid: Maid.Maid, + implementation +) if ValueObject.isValueObject(implementation) then local checkType = implementation:GetCheckType() @@ -80,7 +94,7 @@ function TiePropertyImplementation:_updateImplementation(maid, implementation) end if type(implementation) == "table" and implementation.Changed then - local copy = self:_changeToClassIfNeeded("BindableFunction", implementation) + local copy: BindableFunction = self:_changeToClassIfNeeded("BindableFunction") :: any copy.OnInvoke = function() return TieUtils.encode(implementation) end @@ -89,14 +103,14 @@ function TiePropertyImplementation:_updateImplementation(maid, implementation) end if typeof(implementation) == "Instance" and implementation:IsA("ValueBase") then - local resultingType = ValueBaseUtils.getValueBaseType(implementation.ClassName) + local resultingType = ValueBaseUtils.getValueBaseType(implementation.ClassName :: any) if resultingType and AttributeUtils.isValidAttributeType(resultingType) and resultingType ~= "nil" then self:_removeClassIfNeeded() local attributeValue = AttributeValue.new(self._folder, self._memberDefinition:GetMemberName()) self:_syncMember(maid, attributeValue, implementation) else - local copy = self:_changeToClassIfNeeded(implementation.ClassName, implementation) + local copy = self:_changeToClassIfNeeded(implementation.ClassName) self:_syncMember(maid, copy, implementation) copy.Parent = self._folder end @@ -121,23 +135,28 @@ function TiePropertyImplementation:_updateImplementation(maid, implementation) ) end - local copy = self:_changeToClassIfNeeded(className, implementation) - copy.Value = implementation + local copy = self:_changeToClassIfNeeded(className); + (copy :: any).Value = implementation copy.Parent = self._folder end -function TiePropertyImplementation:_changeToClassIfNeeded(className) +function TiePropertyImplementation._changeToClassIfNeeded(self: TiePropertyImplementation, className: string): Instance return TiePropertyImplementationUtils.changeToClassIfNeeded(self._memberDefinition, self._folder, className) end -function TiePropertyImplementation:_removeClassIfNeeded() +function TiePropertyImplementation._removeClassIfNeeded(self: TiePropertyImplementation) local implementation = self._folder:FindFirstChild(self._memberDefinition:GetMemberName()) if implementation then implementation:Destroy() end end -function TiePropertyImplementation:_syncMember(maid, copy, implementation) +function TiePropertyImplementation._syncMember( + _self: TiePropertyImplementation, + maid: Maid.Maid, + copy: any, + implementation +) copy.Value = implementation.Value maid:GiveTask(implementation.Changed:Connect(function() diff --git a/src/tie/src/Shared/Members/Properties/TiePropertyImplementationUtils.lua b/src/tie/src/Shared/Members/Properties/TiePropertyImplementationUtils.lua index b16f4fd29d5..bfe20b4e4db 100644 --- a/src/tie/src/Shared/Members/Properties/TiePropertyImplementationUtils.lua +++ b/src/tie/src/Shared/Members/Properties/TiePropertyImplementationUtils.lua @@ -1,11 +1,15 @@ ---!nonstrict +--!strict --[=[ @class TiePropertyImplementationUtils ]=] local TiePropertyImplementationUtils = {} -function TiePropertyImplementationUtils.changeToClassIfNeeded(memberDefinition, folder: Folder, className: string) +function TiePropertyImplementationUtils.changeToClassIfNeeded( + memberDefinition, + folder: Instance, + className: string +): Instance local memberName = memberDefinition:GetMemberName() folder:SetAttribute(memberName, nil) diff --git a/src/tie/src/Shared/Members/Properties/TiePropertyInterface.lua b/src/tie/src/Shared/Members/Properties/TiePropertyInterface.lua index 2cbbe210c7b..ebac408d320 100644 --- a/src/tie/src/Shared/Members/Properties/TiePropertyInterface.lua +++ b/src/tie/src/Shared/Members/Properties/TiePropertyInterface.lua @@ -17,6 +17,7 @@ local String = require("String") local Symbol = require("Symbol") local TieMemberInterface = require("TieMemberInterface") local TiePropertyImplementationUtils = require("TiePropertyImplementationUtils") +local TieRealms = require("TieRealms") local TieUtils = require("TieUtils") local ValueBaseUtils = require("ValueBaseUtils") @@ -26,7 +27,12 @@ local TiePropertyInterface = setmetatable({}, TieMemberInterface) TiePropertyInterface.ClassName = "TiePropertyInterface" TiePropertyInterface.__index = TiePropertyInterface -function TiePropertyInterface.new(implParent, adornee: Instance, memberDefinition, interfaceTieRealm) +function TiePropertyInterface.new( + implParent: Instance, + adornee: Instance, + memberDefinition, + interfaceTieRealm: TieRealms.TieRealm +) local self = setmetatable( TieMemberInterface.new(implParent, adornee, memberDefinition, interfaceTieRealm), TiePropertyInterface diff --git a/src/tie/src/Shared/Members/TieMemberDefinition.lua b/src/tie/src/Shared/Members/TieMemberDefinition.lua index db2a8ae45e1..7465af80585 100644 --- a/src/tie/src/Shared/Members/TieMemberDefinition.lua +++ b/src/tie/src/Shared/Members/TieMemberDefinition.lua @@ -1,4 +1,4 @@ ---!nonstrict +--!strict --[=[ Base class for a member definition/declaration. @@ -14,10 +14,23 @@ local TieMemberDefinition = {} TieMemberDefinition.ClassName = "TieMemberDefinition" TieMemberDefinition.__index = TieMemberDefinition -function TieMemberDefinition.new(tieDefinition, memberName: string, memberTieRealm) +export type TieMemberDefinition = typeof(setmetatable( + {} :: { + _tieDefinition: any, + _memberName: string, + _memberTieRealm: TieRealms.TieRealm, + }, + {} :: typeof({ __index = TieMemberDefinition }) +)) + +function TieMemberDefinition.new( + tieDefinition: any, + memberName: string, + memberTieRealm: TieRealms.TieRealm +): TieMemberDefinition assert(TieRealmUtils.isTieRealm(memberTieRealm), "Bad memberTieRealm") - local self = setmetatable({}, TieMemberDefinition) + local self: TieMemberDefinition = setmetatable({} :: any, TieMemberDefinition) self._tieDefinition = assert(tieDefinition, "No tieDefinition") self._memberName = assert(memberName, "Bad memberName") @@ -38,7 +51,7 @@ function TieMemberDefinition:GetFriendlyName(): string return string.format("%s.%s", self._tieDefinition:GetName(), self._memberName) end -function TieMemberDefinition:IsRequiredForInterface(currentRealm): boolean +function TieMemberDefinition:IsRequiredForInterface(currentRealm: TieRealms.TieRealm): boolean assert(TieRealmUtils.isTieRealm(currentRealm), "Bad currentRealm") if self._memberTieRealm == TieRealms.SHARED then @@ -51,7 +64,7 @@ function TieMemberDefinition:IsRequiredForInterface(currentRealm): boolean end end -function TieMemberDefinition:IsAllowedOnInterface(currentRealm): boolean +function TieMemberDefinition:IsAllowedOnInterface(currentRealm: TieRealms.TieRealm): boolean assert(TieRealmUtils.isTieRealm(currentRealm), "Bad currentRealm") if self._memberTieRealm == TieRealms.SHARED then @@ -64,7 +77,7 @@ function TieMemberDefinition:IsAllowedOnInterface(currentRealm): boolean end end -function TieMemberDefinition:IsRequiredForImplementation(currentRealm): boolean +function TieMemberDefinition:IsRequiredForImplementation(currentRealm: TieRealms.TieRealm): boolean assert(TieRealmUtils.isTieRealm(currentRealm), "Bad currentRealm") if currentRealm == TieRealms.SHARED then @@ -77,7 +90,7 @@ function TieMemberDefinition:IsRequiredForImplementation(currentRealm): boolean end end -function TieMemberDefinition:IsAllowedForImplementation(currentRealm): boolean +function TieMemberDefinition:IsAllowedForImplementation(currentRealm: TieRealms.TieRealm): boolean assert(TieRealmUtils.isTieRealm(currentRealm), "Bad currentRealm") if self._memberTieRealm == TieRealms.SHARED then @@ -90,7 +103,7 @@ function TieMemberDefinition:IsAllowedForImplementation(currentRealm): boolean end end -function TieMemberDefinition:GetMemberTieRealm() +function TieMemberDefinition:GetMemberTieRealm(): TieRealms.TieRealm return self._memberTieRealm end diff --git a/src/tie/src/Shared/Members/TieMemberInterface.lua b/src/tie/src/Shared/Members/TieMemberInterface.lua index 0a4adc8b4ac..3f2678f320f 100644 --- a/src/tie/src/Shared/Members/TieMemberInterface.lua +++ b/src/tie/src/Shared/Members/TieMemberInterface.lua @@ -9,12 +9,18 @@ local Rx = require("Rx") local RxBrioUtils = require("RxBrioUtils") local RxInstanceUtils = require("RxInstanceUtils") local TieRealmUtils = require("TieRealmUtils") +local TieRealms = require("TieRealms") local TieMemberInterface = {} TieMemberInterface.ClassName = "TieMemberInterface" TieMemberInterface.__index = TieMemberInterface -function TieMemberInterface.new(implParent, adornee, memberDefinition, interfaceTieRealm) +function TieMemberInterface.new( + implParent: Instance?, + adornee: Instance?, + memberDefinition, + interfaceTieRealm: TieRealms.TieRealm +) assert(TieRealmUtils.isTieRealm(interfaceTieRealm), "Bad interfaceTieRealm") local self = setmetatable({}, TieMemberInterface) diff --git a/src/tie/src/Shared/Realms/TieRealmUtils.lua b/src/tie/src/Shared/Realms/TieRealmUtils.lua index 700409d3703..e0a5d269ce5 100644 --- a/src/tie/src/Shared/Realms/TieRealmUtils.lua +++ b/src/tie/src/Shared/Realms/TieRealmUtils.lua @@ -31,7 +31,7 @@ end @return TieRealm ]=] -function TieRealmUtils.inferTieRealm(): "server" | "client" +function TieRealmUtils.inferTieRealm(): TieRealms.TieRealm if RunService:IsServer() then return TieRealms.SERVER elseif RunService:IsClient() then diff --git a/src/tie/src/Shared/Realms/TieRealms.lua b/src/tie/src/Shared/Realms/TieRealms.lua index f76d35bf35b..02290a3b3be 100644 --- a/src/tie/src/Shared/Realms/TieRealms.lua +++ b/src/tie/src/Shared/Realms/TieRealms.lua @@ -12,9 +12,9 @@ local Table = require("Table") export type TieRealm = "shared" | "client" | "server" export type TieRealms = { - SHARED: "shared", - CLIENT: "client", - SERVER: "server", + SHARED: TieRealm, + CLIENT: TieRealm, + SERVER: TieRealm, } return Table.readonly({ diff --git a/src/tie/src/Shared/TieDefinition.lua b/src/tie/src/Shared/TieDefinition.lua index f70049d6a81..eb3951c35e6 100644 --- a/src/tie/src/Shared/TieDefinition.lua +++ b/src/tie/src/Shared/TieDefinition.lua @@ -1,4 +1,4 @@ ---!nonstrict +--!strict --[=[ Constructs a new interface declaration which allows for interface usage between both Roblox API users and OOP users, as well as without accessing a @@ -48,6 +48,7 @@ local require = require(script.Parent.loader).load(script) local Brio = require("Brio") local Maid = require("Maid") local Observable = require("Observable") +local Promise = require("Promise") local Rx = require("Rx") local RxBrioUtils = require("RxBrioUtils") local RxCollectionServiceUtils = require("RxCollectionServiceUtils") @@ -67,19 +68,55 @@ local ValueObject = require("ValueObject") local UNSET_VALUE = Symbol.named("unsetValue") +local IMPL_CLIENT_SET = table.freeze({ + ["Configuration"] = true, +}) + +local IMPL_SERVER_SET = table.freeze({ + ["Camera"] = true, +}) + +local IMPL_SHARED_SET = table.freeze({ + ["Camera"] = true, + ["Configuration"] = true, +}) + export type TieRealm = TieRealms.TieRealm local TieDefinition = {} TieDefinition.ClassName = "TieDefinition" TieDefinition.__index = TieDefinition +export type TieDefinitionType = "method" | "signal" | "property" +export type TieDefinitionTypes = { + METHOD: TieDefinitionType, + SIGNAL: TieDefinitionType, + PROPERTY: TieDefinitionType, +} TieDefinition.Types = Table.readonly({ METHOD = Symbol.named("method"), SIGNAL = Symbol.named("signal"), PROPERTY = Symbol.named("property"), -- will default to nil -}) +}) :: TieDefinitionTypes + +TieDefinition.Realms = TieRealms :: TieRealms.TieRealms -TieDefinition.Realms = TieRealms +export type TieDefinition = typeof(setmetatable( + {} :: { + _definitionName: string, + _memberMap: { [string]: any }, + _defaultTieRealm: TieRealms.TieRealm, + _validContainerNameSetWeakCache: { [TieRealms.TieRealm]: { [string]: boolean } }, + + Server: TieDefinition, + Client: TieDefinition, + }, + {} :: typeof({ __index = TieDefinition }) +)) + +export type TieMemberMap = { + [string | TieRealms.TieRealm]: TieDefinitionType | TieMemberMap | any, +} --[=[ Constructs a new TieDefinition with the given members @@ -88,11 +125,11 @@ TieDefinition.Realms = TieRealms @param members any @return TieDefinition ]=] -function TieDefinition.new(definitionName: string, members) - local self = setmetatable({}, TieDefinition) +function TieDefinition.new(definitionName: string, members: TieMemberMap): TieDefinition + local self: TieDefinition = setmetatable({} :: any, TieDefinition) self._definitionName = assert(definitionName, "No definitionName") - self._validContainerNameSetWeakCache = setmetatable({}, { __mode = "kv" }) + self._validContainerNameSetWeakCache = setmetatable({} :: any, { __mode = "kv" }) self._memberMap = {} self._defaultTieRealm = TieRealms.SHARED @@ -103,18 +140,18 @@ function TieDefinition.new(definitionName: string, members) _defaultTieRealm = TieRealms.SERVER, }, { __index = self, - }) + }) :: any self.Client = setmetatable({ _defaultTieRealm = TieRealms.CLIENT, }, { __index = self, - }) + }) :: any return self end -function TieDefinition:_addMembers(members, realm) +function TieDefinition._addMembers(self: TieDefinition, members, realm) for memberName, memberTypeOrDefaultValue in members do if TieRealmUtils.isTieRealm(memberName) then self:_addMembers(memberTypeOrDefaultValue, memberName) @@ -131,7 +168,7 @@ function TieDefinition:_addMembers(members, realm) end end -function TieDefinition:_addMember(memberName: string, memberTypeOrDefaultValue, realm: TieRealm) +function TieDefinition._addMember(self: TieDefinition, memberName: string, memberTypeOrDefaultValue, realm: TieRealm) if memberTypeOrDefaultValue == TieDefinition.Types.METHOD then self._memberMap[memberName] = TieMethodDefinition.new(self, memberName, realm) elseif memberTypeOrDefaultValue == TieDefinition.Types.SIGNAL then @@ -147,15 +184,20 @@ end Gets all valid interfaces for this adornee @param adornee Instance @param tieRealm TieRealm? - @return { TieInterface } + @return { TieInterface } ]=] -function TieDefinition:GetImplementations(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.GetImplementations( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): { TieInterface.TieInterface } assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") tieRealm = tieRealm or self._defaultTieRealm + assert(tieRealm, "Typechecking assertion") - local implementations = {} + local implementations: { TieInterface.TieInterface } = {} for _, item in self:GetImplementationParents(adornee, tieRealm) do table.insert(implementations, TieInterface.new(self, item, nil, tieRealm)) @@ -164,7 +206,7 @@ function TieDefinition:GetImplementations(adornee: Instance, tieRealm: TieRealm? return implementations end -function TieDefinition:GetNewImplClass(tieRealm: TieRealm): string +function TieDefinition.GetNewImplClass(_self: TieDefinition, tieRealm: TieRealm): string assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm") if tieRealm == TieRealms.CLIENT then @@ -174,20 +216,7 @@ function TieDefinition:GetNewImplClass(tieRealm: TieRealm): string end end -local IMPL_CLIENT_SET = table.freeze({ - ["Configuration"] = true, -}) - -local IMPL_SERVER_SET = table.freeze({ - ["Camera"] = true, -}) - -local IMPL_SHARED_SET = table.freeze({ - ["Camera"] = true, - ["Configuration"] = true, -}) - -function TieDefinition:GetImplClassSet(tieRealm: TieRealm): { [string]: boolean } +function TieDefinition.GetImplClassSet(_self: TieDefinition, tieRealm: TieRealm): { [string]: boolean } if tieRealm == TieRealms.CLIENT then -- Shared implements both... return IMPL_CLIENT_SET @@ -200,11 +229,16 @@ function TieDefinition:GetImplClassSet(tieRealm: TieRealm): { [string]: boolean end end -function TieDefinition:GetImplementationParents(adornee: BasePart, tieRealm: TieRealm?): { Instance } +function TieDefinition.GetImplementationParents( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): { Instance } assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") tieRealm = tieRealm or self._defaultTieRealm + assert(tieRealm, "Typechecking assertion") local validContainerNameSet = self:GetValidContainerNameSet(tieRealm) @@ -226,17 +260,21 @@ end @param adornee Instance @param tieRealm TieRealm? - @return Observable> + @return Observable>> ]=] -function TieDefinition:ObserveChildrenBrio(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.ObserveChildrenBrio( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): Observable.Observable>> assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") return RxInstanceUtils.observeChildrenBrio(adornee):Pipe({ RxBrioUtils.flatMapBrio(function(child) return self:ObserveBrio(child, tieRealm) - end), - }) + end) :: any, + }) :: any end --[=[ @@ -246,7 +284,11 @@ end @param tieRealm TieRealm? @return Promise ]=] -function TieDefinition:Promise(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.Promise( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): Promise.Promise> assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") @@ -255,11 +297,22 @@ function TieDefinition:Promise(adornee: Instance, tieRealm: TieRealm?) return Rx.toPromise(self:Observe(adornee, tieRealm):Pipe({ Rx.where(function(value) return value ~= nil - end), - })) + end) :: any, + }) :: any) end -function TieDefinition:Wait(adornee: Instance, tieRealm: TieRealm?) +--[=[ + Waits for the implementation + + @param adornee Adornee + @param tieRealm TieRealm? + @return TieInterface +]=] +function TieDefinition.Wait( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): TieInterface.TieInterface return self:Promise(adornee, tieRealm):Wait() end @@ -270,16 +323,20 @@ end @param tieRealm TieRealm? @return { TieInterface } ]=] -function TieDefinition:GetChildren(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.GetChildren( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): { TieInterface.TieInterface } assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") assert(typeof(adornee) == "Instance", "Bad adornee") - local implementations = {} + local implementations: { TieInterface.TieInterface } = {} -- TODO: Make this faster for _, item in adornee:GetChildren() do for _, option in self:GetImplementations(item, tieRealm) do - table.insert(implementations, option) + table.insert(implementations, option :: any) end end @@ -293,7 +350,11 @@ end @param tieRealm TieRealm? @return TieInterface | nil ]=] -function TieDefinition:Find(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.Find( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): TieInterface.TieInterface? assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") @@ -307,15 +368,19 @@ end @param tieRealm TieRealm? @return TieInterface | nil ]=] -function TieDefinition:ObserveAllTaggedBrio(tagName: string, tieRealm: TieRealm?) +function TieDefinition.ObserveAllTaggedBrio( + self: TieDefinition, + tagName: string, + tieRealm: TieRealm? +): Observable.Observable>> assert(type(tagName) == "string", "Bad tagName") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") return RxCollectionServiceUtils.observeTaggedBrio(tagName):Pipe({ RxBrioUtils.flatMapBrio(function(instance) return self:ObserveBrio(instance, tieRealm) - end), - }) + end) :: any, + }) :: any end --[=[ @@ -324,11 +389,16 @@ end @param tieRealm TieRealm? @return TieInterface ]=] -function TieDefinition:FindFirstImplementation(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.FindFirstImplementation( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): TieInterface.TieInterface? assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") tieRealm = tieRealm or self._defaultTieRealm + assert(tieRealm, "Typechecking assertion") local validContainerNameSet = self:GetValidContainerNameSet(tieRealm) for _, item in adornee:GetChildren() do @@ -348,11 +418,12 @@ end @param tieRealm TieRealm? @return boolean ]=] -function TieDefinition:HasImplementation(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.HasImplementation(self: TieDefinition, adornee: Instance, tieRealm: TieRealm?): boolean assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") tieRealm = tieRealm or self._defaultTieRealm + assert(tieRealm, "Typechecking assertion") -- TODO: Maybe something faster for containerName, _ in pairs(self:GetValidContainerNameSet(tieRealm)) do @@ -375,18 +446,22 @@ end @param tieRealm TieRealm? @return Observable> ]=] -function TieDefinition:ObserveIsImplemented(adornee: Instance, tieRealm: TieRealm?): Observable.Observable +function TieDefinition.ObserveIsImplemented( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): Observable.Observable assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") return self:ObserveLastImplementationBrio(adornee, tieRealm):Pipe({ RxBrioUtils.map(function(result) return result and true or false - end), - RxBrioUtils.emitOnDeath(false), + end) :: any, + RxBrioUtils.emitOnDeath(false) :: any, Rx.defaultsTo(false) :: any, Rx.distinct() :: any, - }) + }) :: any end --[=[ @@ -395,7 +470,8 @@ end @param tieRealm TieRealm? @return Observable> ]=] -function TieDefinition:ObserveIsImplementation( +function TieDefinition.ObserveIsImplementation( + self: TieDefinition, implParent: Instance, tieRealm: TieRealm? ): Observable.Observable @@ -403,15 +479,16 @@ function TieDefinition:ObserveIsImplementation( assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") tieRealm = tieRealm or self._defaultTieRealm + assert(tieRealm, "Typechecking assertion") - return self:_observeImplementation(implParent, tieRealm):Pipe({ + return self:_observeImplementedInterface(implParent, tieRealm):Pipe({ RxBrioUtils.map(function(result) return result and true or false - end), - RxBrioUtils.emitOnDeath(false), - Rx.defaultsTo(false), - Rx.distinct(), - }) + end) :: any, + RxBrioUtils.emitOnDeath(false) :: any, + Rx.defaultsTo(false) :: any, + Rx.distinct() :: any, + }) :: any end --[=[ @@ -421,7 +498,8 @@ end @param tieRealm TieRealm? @return Observable> ]=] -function TieDefinition:ObserveIsImplementedOn( +function TieDefinition.ObserveIsImplementedOn( + self: TieDefinition, implParent: Instance, adornee: Instance, tieRealm: TieRealm? @@ -431,20 +509,21 @@ function TieDefinition:ObserveIsImplementedOn( assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") tieRealm = tieRealm or self._defaultTieRealm + assert(tieRealm, "Typechecking assertion") return RxInstanceUtils.observePropertyBrio(implParent, "Parent", function(parent) return parent == adornee end):Pipe({ RxBrioUtils.switchMapBrio(function() - return self:_observeImplementation(implParent, tieRealm) - end), + return self:_observeImplementedInterface(implParent, tieRealm) + end) :: any, RxBrioUtils.map(function(result) return result and true or false - end), - RxBrioUtils.emitOnDeath(false), - Rx.defaultsTo(false), - Rx.distinct(), - }) + end) :: any, + RxBrioUtils.emitOnDeath(false) :: any, + Rx.defaultsTo(false) :: any, + Rx.distinct() :: any, + }) :: any end --[=[ @@ -452,20 +531,25 @@ end @param adornee Instance @param tieRealm TieRealm? - @return Observable>> + @return Observable>> ]=] -function TieDefinition:ObserveBrio(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.ObserveBrio( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): Observable.Observable>> assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") tieRealm = tieRealm or self._defaultTieRealm + assert(tieRealm, "Typechecking assertion") return self:ObserveValidContainerChildrenBrio(adornee, tieRealm):Pipe({ RxBrioUtils.switchMapBrio(function(implParent) - return self:_observeImplementation(implParent, tieRealm) - end), - RxBrioUtils.onlyLastBrioSurvives(), - }) + return self:_observeImplementedInterface(implParent, tieRealm) + end) :: any, + RxBrioUtils.onlyLastBrioSurvives() :: any, + }) :: any end --[=[ @@ -473,15 +557,19 @@ end @param adornee Instance @param tieRealm TieRealm? - @return Observable | nil>> + @return Observable?>> ]=] -function TieDefinition:Observe(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.Observe( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): Observable.Observable?> assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") return self:ObserveBrio(adornee, tieRealm):Pipe({ - RxStateStackUtils.topOfStack(), - }) + RxStateStackUtils.topOfStack() :: any, + }) :: any end TieDefinition.ObserveLastImplementation = TieDefinition.Observe @@ -491,22 +579,38 @@ TieDefinition.ObserveLastImplementationBrio = TieDefinition.ObserveBrio Observes valid implementations wrapped in a brio if it exists. @param adornee Instance @param tieRealm TieRealm? - @return Observable>> + @return Observable>> ]=] -function TieDefinition:ObserveImplementationsBrio(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.ObserveImplementationsBrio( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm? +): Observable.Observable>> assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") tieRealm = tieRealm or self._defaultTieRealm + assert(tieRealm, "Typechecking assertion") return self:ObserveValidContainerChildrenBrio(adornee, tieRealm):Pipe({ RxBrioUtils.flatMapBrio(function(implParent) - return self:_observeImplementation(implParent, tieRealm) - end), - }) + return self:_observeImplementedInterface(implParent, tieRealm) + end) :: any, + }) :: any end -function TieDefinition:ObserveValidContainerChildrenBrio(adornee: Instance, tieRealm: TieRealm?) +--[=[ + Observes valid container children for this adornee that could be implementations. + + @param adornee Instance + @param tieRealm TieRealm + @return Observable> +]=] +function TieDefinition.ObserveValidContainerChildrenBrio( + self: TieDefinition, + adornee: Instance, + tieRealm: TieRealm +): Observable.Observable> assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm") @@ -519,7 +623,11 @@ function TieDefinition:ObserveValidContainerChildrenBrio(adornee: Instance, tieR end) end -function TieDefinition:_observeImplementation(implParent: Instance, tieRealm: TieRealm?) +function TieDefinition._observeImplementedInterface( + self: TieDefinition, + implParent: Instance, + tieRealm: TieRealm +): Observable.Observable>> assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm") return Observable.new(function(sub) @@ -580,7 +688,7 @@ function TieDefinition:_observeImplementation(implParent: Instance, tieRealm: Ti update() return maid - end) + end) :: any end --[=[ @@ -596,7 +704,12 @@ end @param tieRealm TieRealm? @return TieImplementation ]=] -function TieDefinition:Implement(adornee: Instance, implementer, tieRealm: TieRealm?) +function TieDefinition.Implement( + self: TieDefinition, + adornee: Instance, + implementer: T, + tieRealm: TieRealm? +): TieImplementation.TieImplementation assert(typeof(adornee) == "Instance", "Bad adornee") assert(type(implementer) == "table" or implementer == nil, "Bad implementer") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") @@ -620,11 +733,12 @@ end @param tieRealm TieRealm? @return TieInterface ]=] -function TieDefinition:Get(adornee: Instance, tieRealm: TieRealm?) +function TieDefinition.Get(self: TieDefinition, adornee: Instance, tieRealm: TieRealm?): TieInterface.TieInterface assert(typeof(adornee) == "Instance", "Bad adornee") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") tieRealm = tieRealm or self._defaultTieRealm + assert(tieRealm, "Typechecking assertion") return TieInterface.new(self, nil, adornee, tieRealm) end @@ -633,7 +747,7 @@ end Gets the name of the definition @return string ]=] -function TieDefinition:GetName(): string +function TieDefinition.GetName(self: TieDefinition): string return self._definitionName end @@ -643,7 +757,7 @@ end @param tieRealm TieRealm @return { [string]: boolean } ]=] -function TieDefinition:GetValidContainerNameSet(tieRealm: TieRealm?): { [string]: boolean } +function TieDefinition.GetValidContainerNameSet(self: TieDefinition, tieRealm: TieRealm): { [string]: boolean } -- TODO: Still generate unique datamodel key here? if self._validContainerNameSetWeakCache[tieRealm] then return self._validContainerNameSetWeakCache[tieRealm] @@ -683,7 +797,7 @@ end @param tieRealm TieRealm @return string ]=] -function TieDefinition:GetNewContainerName(tieRealm: TieRealm): string +function TieDefinition.GetNewContainerName(self: TieDefinition, tieRealm: TieRealm): string assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm") -- TODO: Handle server/actor @@ -700,7 +814,7 @@ function TieDefinition:GetNewContainerName(tieRealm: TieRealm): string end end -function TieDefinition:GetMemberMap() +function TieDefinition.GetMemberMap(self: TieDefinition) return self._memberMap end @@ -711,7 +825,7 @@ end @param tieRealm TieRealm? -- Optional tie realm @return boolean ]=] -function TieDefinition:IsImplementation(implParent: Instance, tieRealm: TieRealm?): boolean +function TieDefinition.IsImplementation(self: TieDefinition, implParent: Instance, tieRealm: TieRealm?): boolean assert(typeof(implParent) == "Instance", "Bad implParent") assert(TieRealmUtils.isTieRealm(tieRealm) or tieRealm == nil, "Bad tieRealm") diff --git a/src/tie/src/Shared/TieImplementation.lua b/src/tie/src/Shared/TieImplementation.lua index 2562baa9278..31488951ef6 100644 --- a/src/tie/src/Shared/TieImplementation.lua +++ b/src/tie/src/Shared/TieImplementation.lua @@ -18,6 +18,21 @@ local TieImplementation = setmetatable({}, BaseObject) TieImplementation.ClassName = "TieImplementation" TieImplementation.__index = TieImplementation +export type TieImplementation = + typeof(setmetatable( + {} :: { + _tieDefinition: any, + _adornee: Instance, + _actualSelf: any, + _implementationTieRealm: TieRealms.TieRealm, + _implParent: Instance, + _memberImplementations: { [string]: any }, + _memberMap: { [string]: any }, + }, + {} :: typeof({ __index = TieImplementation }) + )) + & T + --[=[ Constructs a new implementation. Use [TieDefinition.Implement] instead of using this directly. @@ -26,15 +41,15 @@ TieImplementation.__index = TieImplementation @param implementer table @param implementationTieRealm TieRealm ]=] -function TieImplementation.new( +function TieImplementation.new( tieDefinition, adornee: Instance, implementer, implementationTieRealm: TieRealms.TieRealm -) +): TieImplementation assert(TieRealmUtils.isTieRealm(implementationTieRealm), "Bad implementationTieRealm") - local self = setmetatable(BaseObject.new(), TieImplementation) + local self: TieImplementation = setmetatable(BaseObject.new() :: any, TieImplementation) self._tieDefinition = assert(tieDefinition, "No definition") self._adornee = assert(adornee, "No adornee") @@ -56,22 +71,22 @@ function TieImplementation.new( self._maid:DoCleaning() for key, _ in pairs(self) do - rawset(self, key, nil) + rawset(self :: any, key, nil) end end) return self end -function TieImplementation:GetImplementationTieRealm() +function TieImplementation.GetImplementationTieRealm(self: TieImplementation): TieRealms.TieRealm return self._implementationTieRealm end -function TieImplementation:GetImplParent() +function TieImplementation.GetImplParent(self: TieImplementation): Instance return self._implParent end -function TieImplementation:__index(index) +function TieImplementation.__index(self: TieImplementation, index) if TieImplementation[index] then return TieImplementation[index] end @@ -85,12 +100,12 @@ function TieImplementation:__index(index) or index == "_memberMap" or index == "_actualSelf" then - return rawget(self, index) + return rawget(self :: any, index) end - local memberMap = rawget(self, "_memberMap") + local memberMap = rawget(self :: any, "_memberMap") local memberDefinition = memberMap[index] - local implementationTieRealm = rawget(self, "_implementationTieRealm") + local implementationTieRealm = rawget(self :: any, "_implementationTieRealm") if memberDefinition then if memberDefinition:IsAllowedForImplementation(self._implementationTieRealm) then @@ -109,7 +124,7 @@ function TieImplementation:__index(index) end end -function TieImplementation:__newindex(index, value) +function TieImplementation.__newindex(self: TieImplementation, index, value) if index == "_implParent" or index == "_adornee" @@ -119,7 +134,7 @@ function TieImplementation:__newindex(index, value) or index == "_memberMap" or index == "_actualSelf" then - rawset(self, index, value) + rawset(self :: any, index, value) elseif self._memberImplementations[index] then self._memberImplementations[index]:SetImplementation(value, self._actualSelf) elseif TieImplementation[index] then @@ -129,7 +144,7 @@ function TieImplementation:__newindex(index, value) end end -function TieImplementation:_buildMemberImplementations(implementer) +function TieImplementation._buildMemberImplementations(self: TieImplementation, implementer) for _, memberDefinition in self._memberMap do local memberName = memberDefinition:GetMemberName() local found = nil @@ -159,7 +174,7 @@ function TieImplementation:_buildMemberImplementations(implementer) self._implParent.Name = self._tieDefinition:GetNewContainerName(self._implementationTieRealm) end -function TieImplementation:_getErrorMessageForNotAllowedMember(memberDefinition) +function TieImplementation._getErrorMessageForNotAllowedMember(self: TieImplementation, memberDefinition) local errorMessage = string.format( "[TieImplementation] - Member implements %s only member %s (we are a %s implementation)", memberDefinition:GetMemberTieRealm(), @@ -182,7 +197,7 @@ function TieImplementation:_getErrorMessageForNotAllowedMember(memberDefinition) return errorMessage end -function TieImplementation:_getErrorMessageRequiredMember(memberDefinition) +function TieImplementation._getErrorMessageRequiredMember(self: TieImplementation, memberDefinition) local errorMessage = string.format( "[TieImplementation] - Missing %s member %s (we are a %s implementation)", memberDefinition:GetMemberTieRealm(), diff --git a/src/tie/src/Shared/TieInterface.lua b/src/tie/src/Shared/TieInterface.lua index 0a9e0a32ee9..3cafa7865c9 100644 --- a/src/tie/src/Shared/TieInterface.lua +++ b/src/tie/src/Shared/TieInterface.lua @@ -7,16 +7,36 @@ local require = require(script.Parent.loader).load(script) +local Observable = require("Observable") local TieMethodInterfaceUtils = require("TieMethodInterfaceUtils") local TiePropertyInterface = require("TiePropertyInterface") +local TieRealms = require("TieRealms") local TieSignalInterface = require("TieSignalInterface") local TieInterface = {} TieInterface.ClassName = "TieInterface" TieInterface.__index = TieInterface -function TieInterface.new(definition, implParent: Instance?, adornee: Instance?, interfaceTieRealm) - local self = setmetatable({}, TieInterface) +export type TieInterface = + typeof(setmetatable( + {} :: { + _definition: any, + _implParent: Instance?, + _adornee: Instance?, + _interfaceTieRealm: string, + _memberDefinitionMap: { [string]: any }, + }, + {} :: typeof({ __index = TieInterface }) + )) + & T + +function TieInterface.new( + definition, + implParent: Instance?, + adornee: Instance?, + interfaceTieRealm: TieRealms.TieRealm +): TieInterface + local self: TieInterface = setmetatable({} :: any, TieInterface) assert(implParent or adornee, "ImplParent or adornee required") @@ -34,11 +54,11 @@ end @return boolean ]=] -function TieInterface:IsImplemented(): boolean - local implParent = rawget(self, "_implParent") - local adornee = rawget(self, "_adornee") - local definition = rawget(self, "_definition") - local interfaceTieRealm = rawget(self, "_interfaceTieRealm") +function TieInterface.IsImplemented(self: TieInterface): boolean + local implParent = rawget(self :: any, "_implParent") + local adornee = rawget(self :: any, "_adornee") + local definition = rawget(self :: any, "_definition") + local interfaceTieRealm = rawget(self :: any, "_interfaceTieRealm") if implParent then if adornee then @@ -62,13 +82,13 @@ end @return Instance? ]=] -function TieInterface:GetTieAdornee(): Instance? - local adornee = rawget(self, "_adornee") +function TieInterface.GetTieAdornee(self: TieInterface): Instance? + local adornee = rawget(self :: any, "_adornee") if adornee then return adornee end - local implParent = rawget(self, "_implParent") + local implParent = rawget(self :: any, "_implParent") if implParent then return implParent.Parent end @@ -81,11 +101,11 @@ end @return Observable ]=] -function TieInterface:ObserveIsImplemented() - local implParent = rawget(self, "_implParent") - local adornee = rawget(self, "_adornee") - local definition = rawget(self, "_definition") - local interfaceTieRealm = rawget(self, "_interfaceTieRealm") +function TieInterface.ObserveIsImplemented(self: TieInterface): Observable.Observable + local implParent = rawget(self :: any, "_implParent") + local adornee = rawget(self :: any, "_adornee") + local definition = rawget(self :: any, "_definition") + local interfaceTieRealm = rawget(self :: any, "_interfaceTieRealm") if implParent then if adornee then @@ -98,13 +118,13 @@ function TieInterface:ObserveIsImplemented() return definition:ObserveIsImplemented(adornee, interfaceTieRealm) end -function TieInterface:__index(index) - local interfaceTieRealm = rawget(self, "_interfaceTieRealm") +function TieInterface.__index(self: TieInterface, index) + local interfaceTieRealm = rawget(self :: any, "_interfaceTieRealm") - local member = (rawget(self, "_memberDefinitionMap") :: any)[index] - local definition = rawget(self, "_definition") - local adornee = rawget(self, "_adornee") - local implParent = rawget(self, "_implParent") + local member = (rawget(self :: any, "_memberDefinitionMap") :: any)[index] + local definition = rawget(self :: any, "_definition") + local adornee = rawget(self :: any, "_adornee") + local implParent = rawget(self :: any, "_implParent") if member then if member:IsAllowedOnInterface(interfaceTieRealm) then diff --git a/src/transitionmodel/src/Shared/TransitionModel.lua b/src/transitionmodel/src/Shared/TransitionModel.lua index fd8108e1e97..2b66e7daaf9 100644 --- a/src/transitionmodel/src/Shared/TransitionModel.lua +++ b/src/transitionmodel/src/Shared/TransitionModel.lua @@ -45,7 +45,7 @@ function TransitionModel.new(): TransitionModel local self: TransitionModel = setmetatable(BasicPane.new() :: any, TransitionModel) self._isShowingComplete = self._maid:Add(ValueObject.new(false, "boolean")) - self._isHidingComplete = self._maid:Add(ValueObject.new(false, "boolean")) + self._isHidingComplete = self._maid:Add(ValueObject.new(true, "boolean")) self._showCallback = nil self._hideCallback = nil diff --git a/tools/nevermore-vscode/snippets/luau.code-snippets b/tools/nevermore-vscode/snippets/luau.code-snippets index c6cdbce7c14..d3241c4dfca 100644 --- a/tools/nevermore-vscode/snippets/luau.code-snippets +++ b/tools/nevermore-vscode/snippets/luau.code-snippets @@ -233,8 +233,15 @@ "local ${1:Service} = {}", "${1:Service}.ServiceName = \"${1:Service}\"", "", - "function ${1:Service}:Init(serviceBag: ServiceBag.ServiceBag)", - "\tassert(not self._serviceBag, \"Already initialized\")", + "export type ${1:Service} = typeof(setmetatable(", + "\t{} :: {", + "\t\t_serviceBag: ServiceBag.ServiceBag,", + "\t},", + "\t{} :: typeof({ __index = ${1:Service} })", + "))", + "", + "function ${1:Service}.Init(self: ${1:Service}, serviceBag: ServiceBag.ServiceBag)", + "\tassert(not (self :: any)._serviceBag, \"Already initialized\")", "\tself._serviceBag = assert(serviceBag, \"No serviceBag\")", "", "\t${2}",