-- Compiled with @isentinel/roblox-ts v4.0.11 local TS = _G[script] local store = TS.import(script, TS.getModule(script, "@lisachandra", "core").store).store local includes = TS.import(script, TS.getModule(script, "@lisachandra", "core").utils.string).includes local is = TS.import(script, TS.getModule(script, "@lisachandra", "core").utils.type).is local Components = TS.import(script, TS.getModule(script, "@lisachandra", "matter")).Components --[[ * * Defines and registers custom Centurion types for entities. These types are used for command * argument parsing and validation. ]] local _centurion = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out) local ListTypeBuilder = _centurion.ListTypeBuilder local TransformResult = _centurion.TransformResult local TypeBuilder = _centurion.TypeBuilder local isEmpty = TS.import(script, TS.getModule(script, "@rbxts", "object-utils")).isEmpty local RegExp = TS.import(script, TS.getModule(script, "@rbxts", "RegExp")) local Players = TS.import(script, TS.getModule(script, "@rbxts", "services")).Players local prefixRegexp = RegExp("^@([^()]+)(?:\\((.*)\\))?$") local function getEntitySuggestionsFunction(includeEntities, includePlayers, includePrefix) if includeEntities == nil then includeEntities = false end if includePlayers == nil then includePlayers = false end if includePrefix == nil then includePrefix = true end return function(_text, _executor) local entities = {} if includeEntities then for entityId in store.world do local _arg0 = tostring(entityId) table.insert(entities, _arg0) end end local _array = {} local _length = #_array table.move(entities, 1, #entities, _length + 1, _array) local suggestions = _array if includePrefix then table.insert(suggestions, 1, "@me") end if includePlayers then local _exp = Players:GetPlayers() -- ▼ ReadonlyArray.map ▼ local _newValue = table.create(#_exp) local _callback = function(player) return player.Name end for _k, _v in _exp do _newValue[_k] = _callback(_v, _k - 1, _exp) end -- ▲ ReadonlyArray.map ▲ local playerNames = _newValue for _, playerName in playerNames do table.insert(suggestions, playerName) end end return suggestions end end local Entities local function parsePrefix(prefix, args, executor) local executorEntityId = executor:GetAttribute("serverEntityId") local accumulator = {} repeat local _fallthrough = false if prefix == "all" then _fallthrough = true end if _fallthrough or prefix == "others" then for entityId in store.world do if prefix == "others" and entityId == executorEntityId then continue end table.insert(accumulator, entityId) end break end if prefix == "except" then _fallthrough = true end if _fallthrough or prefix == "only" then local input = string.split(args, ";") local result = Entities.transform(input, executor) local _result = result if _result ~= nil then _result = _result.value end if not (type(_result) == "table") then return nil end for _, entityId in result.value do table.insert(accumulator, entityId) end break end if prefix == "me" then table.insert(accumulator, executorEntityId) break end if prefix == "query" then local _exp = string.split(args, ";") -- ▼ ReadonlyArray.map ▼ local _newValue = table.create(#_exp) local _callback = function(key) if not is(key) or not Components[key] then return nil end return Components[key] end for _k, _v in _exp do _newValue[_k] = _callback(_v, _k - 1, _exp) end -- ▲ ReadonlyArray.map ▲ -- ▼ ReadonlyArray.filterUndefined ▼ local _length = 0 for _i in _newValue do if _i > _length then _length = _i end end local _result = {} local _resultLength = 0 for _i = 1, _length do local _v = _newValue[_i] if _v ~= nil then _resultLength += 1 _result[_resultLength] = _v end end -- ▲ ReadonlyArray.filterUndefined ▲ local components = _result if isEmpty(components) then return nil end for entityId in store.world:query(unpack(components)) do table.insert(accumulator, entityId) end break end do return nil end until true return accumulator end --* Base entity type. Transforms text input into an entity ID, verifying its existence in the world. local Entity = TypeBuilder:create("entity"):transform(function(text, executor) if text == "@me" then -- eslint-disable-next-line no-param-reassign -- allowed text = executor.Name end -- Attempt to get the entity ID from the player's attribute or parse it as a number. local _result = Players:FindFirstChild(text) if _result ~= nil then _result = _result:GetAttribute("serverEntityId") end local _condition = _result if _condition == nil then _condition = tonumber(text) end local entityId = _condition -- Check if the entity ID is a number and exists in the world. return if type(entityId) == "number" and store.world:contains(entityId) then TransformResult.ok(entityId) else TransformResult.err(`{text} Entity not found.`) end):suggestions(getEntitySuggestionsFunction(true, true, true)):markForRegistration():build() --[[ * * Registered Centurion list type for entity IDs, supporting prefix syntax (`@me`, `@all`, * `@others`, `@query`, `@except`, `@only`). * * @remarks * Prefixes are resolved via `parsePrefix`; bare entity IDs fall through to the single `Entity` * transform. ]] Entities = ListTypeBuilder:create("entities"):transform(function(input, executor) local entities = {} for _, text in input do if includes(text, "@") then local match = prefixRegexp:exec(text) local _prefix = match if _prefix ~= nil then _prefix = _prefix[2] end local prefix = _prefix local _result = match if _result ~= nil then _result = _result[3] end local _condition = _result if _condition == nil then _condition = "" end local args = _condition local parsedEntities = if prefix ~= nil then parsePrefix(prefix, args, executor) else nil if not parsedEntities then return TransformResult.err(`Prefix '{text}' is not valid.`) end if prefix == "except" then -- ▼ ReadonlyArray.filter ▼ local _newValue = {} local _callback = function(entity) local _entity = entity return not (table.find(parsedEntities, _entity) ~= nil) end local _length = 0 for _k, _v in entities do if _callback(_v, _k - 1, entities) == true then _length += 1 _newValue[_length] = _v end end -- ▲ ReadonlyArray.filter ▲ entities = _newValue elseif prefix == "only" then -- ▼ ReadonlyArray.filter ▼ local _newValue = {} local _callback = function(entity) local _entity = entity return table.find(parsedEntities, _entity) ~= nil end local _length = 0 for _k, _v in entities do if _callback(_v, _k - 1, entities) == true then _length += 1 _newValue[_length] = _v end end -- ▲ ReadonlyArray.filter ▲ entities = _newValue else for _1, parsedEntity in parsedEntities do table.insert(entities, parsedEntity) end end end local result = Entity.transform(text, executor) local _result = result if _result ~= nil then _result = _result.value end if type(_result) == "number" then local _entities = entities local _value = result.value table.insert(_entities, _value) end end -- Filter duplicate entries -- ▼ ReadonlyArray.filter ▼ local _newValue = {} local _callback = function(entityId, index) local _entities = entities local _entityId = entityId return (table.find(_entities, _entityId) or 0) - 1 == index end local _length = 0 for _k, _v in entities do if _callback(_v, _k - 1, entities) == true then _length += 1 _newValue[_length] = _v end end -- ▲ ReadonlyArray.filter ▲ entities = _newValue return TransformResult.ok(entities) end):suggestions(function(_text, executor) local suggestions = getEntitySuggestionsFunction(true, true, true)("", executor) -- ▼ Array.unshift ▼ table.insert(suggestions, 1, "@only()") table.insert(suggestions, 1, "@except()") table.insert(suggestions, 1, "@query()") table.insert(suggestions, 1, "@others") table.insert(suggestions, 1, "@all") -- ▲ Array.unshift ▲ return suggestions end):markForRegistration():build() return { Entity = Entity, Entities = Entities, }