From e5adda93ac2741ff48fe2115234cd7d8464a22b6 Mon Sep 17 00:00:00 2001 From: jun022222222 <44199090+jun022222222@users.noreply.github.com> Date: Sun, 8 Sep 2024 03:34:00 +0900 Subject: [PATCH 001/189] Made mats, colors list selectable (#1599) Minor Changes BrickColor List and Material List change to Selectable --- MainModule/Server/Commands/Players.luau | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index 1f4c03df61..35c71d4bdf 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -214,12 +214,14 @@ return function(Vargs, env) for i, bc in brickColorNames do bc = BrickColor.new(bc) table.insert(children, { - Class = "TextLabel"; + Class = "TextBox"; Size = UDim2.new(1, -10, 0, 30); Position = UDim2.new(0, 5, 0, 30*(i-1)); BackgroundTransparency = 1; TextXAlignment = "Left"; Text = ` {bc.Name}`; + TextEditable = false; + ClearTextOnFocus = false; ToolTip = string.format("RGB: %d, %d, %d | Num: %d", bc.r*255, bc.g*255, bc.b*255, bc.Number); ZIndex = 11; Children = { @@ -260,7 +262,7 @@ return function(Vargs, env) for i, mat in mats do mats[i] = {Text = mat; Desc = `Enum value: {Enum.Material[mat].Value}`} end - Remote.MakeGui(plr, "List", {Title = "Materials"; Tab = mats;}) + Remote.MakeGui(plr, "List", {Title = "Materials"; Tab = mats; TextSelectable = true;}) end }; @@ -1209,4 +1211,4 @@ return function(Vargs, env) end; }; }; -end \ No newline at end of file +end From 6e525436fcf234f040d260e87c32a661fb7482cd Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 7 Sep 2024 19:34:42 +0100 Subject: [PATCH 002/189] Add to CL --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 7c1e374c67..d1274d25e5 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -14,6 +14,7 @@ return { "(Git/EasternBloxxer) Made dex fetch api dump on server start (#1591)"; "(Git/ScriptedConnor) Fix TopBarShift for :setmessage (#1593)"; "(Git/ScriptedConnor) Add Text Selections to the :players Command (#1597)"; + "(Git/jun022222222) Made mats & colors list selectable (#1599)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From a80ee4dcde70dd9f8b71fdb8aa2987165db8d9ee Mon Sep 17 00:00:00 2001 From: omwot <140683870+omwot@users.noreply.github.com> Date: Sun, 8 Sep 2024 16:22:03 -0400 Subject: [PATCH 003/189] Improve Modern-Theme (#1598) * Improve modern theme * Improve compatability with light themes * Attach an author userid to client gui messages --- MainModule/Client/Core/UI.luau | 10 +- MainModule/Client/UI/Default/UserPanel.luau | 8 +- .../AdonisModernComponents/Hint.luau | 13 +- .../Packages/Winro/{init.luay => init.luau} | 0 .../Client/UI/Modern/DISABLED_Notif.luau | 89 ----- MainModule/Client/UI/Modern/Hint.luau | 2 +- MainModule/Client/UI/Modern/List.luau | 356 ++++++++++++++++++ MainModule/Client/UI/Modern/Message.luau | 68 ---- MainModule/Client/UI/Modern/Message.rbxm | Bin 0 -> 15815 bytes MainModule/Client/UI/Modern/Notif.rbxm | Bin 0 -> 13109 bytes MainModule/Client/UI/Modern/Notification.rbxm | Bin 0 -> 17443 bytes .../Client/UI/Modern/NotificationHolder.rbxm | Bin 0 -> 7295 bytes MainModule/Client/UI/Modern/Notify.luau | 81 ---- MainModule/Client/UI/Modern/Notify.rbxm | Bin 0 -> 13962 bytes MainModule/Client/UI/Modern/Window.rbxm | Bin 0 -> 47334 bytes MainModule/Client/UI/Modern/YesNoPrompt.luau | 77 ++++ .../Client/UI/ModernLight/Base_Theme.txt | 1 + .../Client/UI/ModernLight/Notification.rbxm | Bin 0 -> 17413 bytes MainModule/Client/UI/ModernLight/Window.rbxm | Bin 0 -> 47300 bytes MainModule/Server/Commands/Moderators.luau | 36 +- MainModule/Server/Core/Functions.luau | 14 +- 21 files changed, 483 insertions(+), 272 deletions(-) rename MainModule/Client/UI/Modern/Components/Packages/Winro/{init.luay => init.luau} (100%) delete mode 100644 MainModule/Client/UI/Modern/DISABLED_Notif.luau create mode 100644 MainModule/Client/UI/Modern/List.luau delete mode 100644 MainModule/Client/UI/Modern/Message.luau create mode 100644 MainModule/Client/UI/Modern/Message.rbxm create mode 100644 MainModule/Client/UI/Modern/Notif.rbxm create mode 100644 MainModule/Client/UI/Modern/Notification.rbxm create mode 100644 MainModule/Client/UI/Modern/NotificationHolder.rbxm delete mode 100644 MainModule/Client/UI/Modern/Notify.luau create mode 100644 MainModule/Client/UI/Modern/Notify.rbxm create mode 100644 MainModule/Client/UI/Modern/Window.rbxm create mode 100644 MainModule/Client/UI/Modern/YesNoPrompt.luau create mode 100644 MainModule/Client/UI/ModernLight/Base_Theme.txt create mode 100644 MainModule/Client/UI/ModernLight/Notification.rbxm create mode 100644 MainModule/Client/UI/ModernLight/Window.rbxm diff --git a/MainModule/Client/Core/UI.luau b/MainModule/Client/Core/UI.luau index b220208b22..695747bc37 100644 --- a/MainModule/Client/Core/UI.luau +++ b/MainModule/Client/Core/UI.luau @@ -271,9 +271,17 @@ return function(Vargs, GetEnv) end --// Get rid of an old Config folder and throw the new combination Config folder in - local new = foundConfigs[1].Found:Clone() + local found = foundConfigs[1].Found + local new = found:Clone() local oldFolder = new:FindFirstChild'Config' + -- Keep a reference to the original element in case the script relies on a dependancy + -- found in the UI theme's directory + local originalReferenceValue = Instance.new("ObjectValue") + originalReferenceValue.Value = found + originalReferenceValue.Name = "OriginalReference" + originalReferenceValue.Parent = new + if oldFolder then oldFolder:Destroy() end confFolder.Parent = new diff --git a/MainModule/Client/UI/Default/UserPanel.luau b/MainModule/Client/UI/Default/UserPanel.luau index 920b815788..b56aa20aee 100644 --- a/MainModule/Client/UI/Default/UserPanel.luau +++ b/MainModule/Client/UI/Default/UserPanel.luau @@ -153,7 +153,7 @@ return function(data, env) TextColor3 = Color3.new(1, 1, 1); Text = ""; PlaceholderText = "Search"; - TextStrokeTransparency = 0.8; + TextStrokeTransparency = 1; }) local items = tabWindow:Add("ScrollingFrame", { @@ -882,7 +882,7 @@ return function(data, env) TextColor3 = Color3.new(1, 1, 1); Text = ""; PlaceholderText = "Search"; - TextStrokeTransparency = 0.8; + TextStrokeTransparency = 1; }) local function getBinds() @@ -1144,7 +1144,7 @@ return function(data, env) TextColor3 = Color3.new(1, 1, 1); Text = ""; PlaceholderText = "Search"; - TextStrokeTransparency = 0.8; + TextStrokeTransparency = 1; }) local aliases = aliasTab:Add("ScrollingFrame", { @@ -1785,4 +1785,4 @@ return function(data, env) gTable = window.gTable window:Ready() end -end +end \ No newline at end of file diff --git a/MainModule/Client/UI/Modern/Components/AdonisModernComponents/Hint.luau b/MainModule/Client/UI/Modern/Components/AdonisModernComponents/Hint.luau index 86658c699d..f9e151bae6 100644 --- a/MainModule/Client/UI/Modern/Components/AdonisModernComponents/Hint.luau +++ b/MainModule/Client/UI/Modern/Components/AdonisModernComponents/Hint.luau @@ -21,6 +21,9 @@ Hint.validateProps = t.strictInterface({ BodyText = t.optional(t.string), }) +local FONT_FACE = Font.fromId(12187364147) +local FONT_SIZE = 18 + function Hint:render() local props = self.props @@ -71,11 +74,11 @@ function Hint:render() AutomaticSize = Enum.AutomaticSize.XY, BackgroundTransparency = 1, LayoutOrder = 1, - FontFace = Font.fromEnum(Enum.Font.SourceSans), + FontFace = FONT_FACE, RichText = true, Text = props.BodyText, TextColor3 = Color3.fromRGB(255, 255, 255), - TextSize = 18, + TextSize = FONT_SIZE, TextWrapped = true, TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top, @@ -85,11 +88,11 @@ function Hint:render() AutomaticSize = Enum.AutomaticSize.XY, BackgroundTransparency = 1, LayoutOrder = 0, - FontFace = Font.fromEnum(Enum.Font.SourceSansBold), + FontFace = FONT_FACE, RichText = true, Text = props.TitleText, TextColor3 = Color3.fromRGB(255, 255, 255), - TextSize = 18, + TextSize = FONT_SIZE, TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top, }), @@ -112,4 +115,4 @@ function Hint:render() }) end -return Hint +return Hint \ No newline at end of file diff --git a/MainModule/Client/UI/Modern/Components/Packages/Winro/init.luay b/MainModule/Client/UI/Modern/Components/Packages/Winro/init.luau similarity index 100% rename from MainModule/Client/UI/Modern/Components/Packages/Winro/init.luay rename to MainModule/Client/UI/Modern/Components/Packages/Winro/init.luau diff --git a/MainModule/Client/UI/Modern/DISABLED_Notif.luau b/MainModule/Client/UI/Modern/DISABLED_Notif.luau deleted file mode 100644 index 244b091707..0000000000 --- a/MainModule/Client/UI/Modern/DISABLED_Notif.luau +++ /dev/null @@ -1,89 +0,0 @@ -client = nil -service = nil - -local Components = script.Parent.Components.AdonisModernComponents -local Packages = Components.Parent.Packages - -local Maid = require(Packages.Maid) -local Signal = require(Packages.Signal) -local Roact = require(Packages.Roact) -local new = Roact.createElement - -local FadeInOutAnimationWrapper = require(Components.FadeInOutAnimationWrapper) -local Hint = require(Components.Hint) - -local CurrentAppMaid = nil - -return function(Data) - - -- Remove existing - if CurrentAppMaid then - CurrentAppMaid:Destroy() - CurrentAppMaid = nil - end - - -- ### REASON WHY THIS SCRIPT DISABLED: ####### Adonis does not call with an empty message arg, we cannot know when to clean up - -- -- Ensure there is a message - -- if typeof(Data.Message) ~= 'string' then - -- return - -- end - - -- ### REASON WHY THIS SCRIPT DISABLED: ####### "gTable" is not provided for some reason - -- -- Cleanup - -- Data.gTable.CustomDestroy = function() - -- if CurrentAppMaid then - -- CurrentAppMaid:Destroy() - -- end - -- end - - local AppMaid = Maid.new() - local FadeInSignal = Signal.new() - local FadeOutSignal = Signal.new() - - CurrentAppMaid = AppMaid - - AppMaid.FadeInSignal = FadeInSignal - AppMaid.FadeOutSignal = FadeOutSignal - - -- ////////// Create Message App - local App = new("ScreenGui", { - DisplayOrder = Data.DisplayOrder or 100, - IgnoreGuiInset = true, - ZIndexBehavior = Enum.ZIndexBehavior.Sibling, - }, { - - AnimationContainer = new(FadeInOutAnimationWrapper, { - FadeInSignal = FadeInSignal, - FadeOutSignal = FadeOutSignal, - FadeInVelocity = 3, - FadeOutVelocity = 4, - OnFadeOutCompleted = function() - AppMaid:Destroy() - end, - }, { - - Hint = new(Hint, { - BodyText = Data.Message, - Image = Data.Image, - TitleText = Data.Title, - BackgroundColor3 = Color3.new(), - }), - }), - }) - - -- ////////// Perform Animation Tasks - - local Handle = Roact.mount(App, service.UnWrap(service.PlayerGui), "AdonisUI.Notif") - - AppMaid.RemoveHandle = function() - Handle = Roact.unmount(Handle) - end - - FadeInSignal:Fire() - - if Data.Time then - task.wait(Data.Time) - FadeOutSignal:Fire() - end - -end diff --git a/MainModule/Client/UI/Modern/Hint.luau b/MainModule/Client/UI/Modern/Hint.luau index 9b44f3df69..72f1ac1a08 100644 --- a/MainModule/Client/UI/Modern/Hint.luau +++ b/MainModule/Client/UI/Modern/Hint.luau @@ -63,4 +63,4 @@ return function(Data) end FadeOutSignal:Fire() -end +end \ No newline at end of file diff --git a/MainModule/Client/UI/Modern/List.luau b/MainModule/Client/UI/Modern/List.luau new file mode 100644 index 0000000000..a2519a0987 --- /dev/null +++ b/MainModule/Client/UI/Modern/List.luau @@ -0,0 +1,356 @@ +client, service = nil, nil + +return function(data, env) + if env then + setfenv(1, env) + end + + local Name = data.Name + local Title = data.Title + local TitleButtons = data.TitleButtons or {} + local Icon = data.Icon + local Tabs = data.Tabs + local Tab = data.Table or data.Tab + local Update = data.Update + local UpdateArg = data.UpdateArg + local UpdateArgs = data.UpdateArgs + local AutoUpdate = data.AutoUpdate + local LoadTime = data.LoadTime + local gIndex = data.gIndex + local gTable = data.gTable + local Dots = data.Dots + local Size = data.Size + local Sanitize = data.Sanitize + local Stacking = data.Stacking + local PagesEnabled = (data.PagesEnabled ~= nil and data.PagesEnabled) or (data.PagesEnabled == nil and true) + local PageSize = data.PageSize or 100 + local PageNumber = data.PageNumber or 1 + local PageCounter = PageNumber or 1 + local RichText = data.RichTextSupported or data.RichTextAllowed or data.RichText + local TextSelectable = data.TextSelectable + local TimeOptions = data.TimeOptions + local getListTab, getPage + local doSearch, genList + local window, scroller, search + local lastPageButton, nextPageButton, pageCounterLabel; + local currentListTab + local pageDebounce + local genDebounce = false + + function getPage(tab, pageNum) + if not PagesEnabled then + return tab + end + + local pageNum = pageNum or 1 + local startPos = (pageNum-1) * PageSize + local endPos = pageNum *PageSize + local pageList = {} + + for i = startPos, endPos do + if tab[i] ~= nil then + table.insert(pageList, tab[i]) + end + end + + return pageList + end + + function getListTab(Tab) + local newTab = {} + + for i, v in ipairs(Tab) do + if type(v) == "table" then + newTab[i] = { + Text = v.Text; + Desc = v.Desc; + Color = v.Color; + Time = v.Time; + Filter = v.Filter; + Duplicates = v.Duplicates; + OnClick = v.OnClick; + } + elseif type(v) == "string" then + newTab[i] = { + Text = v; + Desc = v; + } + end + end + + if Stacking then + local oldNewTab = newTab + newTab = {} + local lastTab + for _, ent in ipairs(oldNewTab) do + ent.Text = service.EscapeControlCharacters(service.Trim(ent.Text)) + ent.Desc = service.EscapeControlCharacters(service.Trim(ent.Desc)) + if not lastTab then + lastTab = ent + table.insert(newTab, ent) + else + if lastTab.Text == ent.Text and lastTab.Desc == ent.Desc then + lastTab.Duplicates = (lastTab.Duplicates and lastTab.Duplicates+1) or 2 + else + lastTab = ent + table.insert(newTab, ent) + end + end + end + end + + for _, v in ipairs(newTab) do + v.Text = (data.Sanitize and service.SanitizeString(v.Text)) or v.Text + + if v.Duplicates then + v.Text = `(x{v.Duplicates}) {v.Text}` + end + + if v.Time then + v.Text = `[{type(v.Time) == "number" and service.FormatTime(v.Time, TimeOptions) or v.Time}] {v.Text}` + end + end + + return newTab + end + + function doSearch(tab, text) + local found = {} + text = string.lower(tostring(text)):gsub("%%", "%%%%"):gsub("%[", "%%["):gsub("%]", "%%]") + for _, v in ipairs(tab) do + if text == "" or (type(v) == "string" and string.find(string.lower(v),text)) or (type(v) == "table" and ((v.Text and string.find(string.lower(tostring(v.Text)), text)) or (v.Filter and string.find(string.lower(v.Filter),text)))) then + table.insert(found, v) + end + end + + return found + end + + function genList(Tab) + local gotList = Tab + + if not genDebounce then + genDebounce = true + + if search.Text ~= "" then + PageCounter = 1 + gotList = getListTab(doSearch(Tab, search.Text)) + else + PageCounter = PageNumber + search.Text = "" + search.PlaceholderText = "Search (" .. (#Tab == 1 and "1 Item" or #Tab .. " Items") .. ")"; + gotList = getListTab(Tab) + end + + if PagesEnabled and #gotList > PageSize then + + + scroller.Size = UDim2.new(1, -10, 1, -60) + nextPageButton.Visible = true + pageCounterLabel.Visible = true + if currentListTab then + local maxPages = math.ceil(#currentListTab/PageSize) + pageCounterLabel.Text = `Page: {PageCounter}/{maxPages}` + else + pageCounterLabel.Text = `Page: {PageCounter}` + end + + if PageCounter > 1 then + lastPageButton.Visible = true + else + lastPageButton.Visible = false + end + else + scroller.Size = UDim2.new(1, -10, 1, -30) + nextPageButton.Visible = false + lastPageButton.Visible = false + pageCounterLabel.Visible = false + end + + scroller:ClearAllChildren() + + currentListTab = gotList + scroller:GenerateList(getPage(gotList, PageCounter), { + RichTextAllowed = RichText; + TextSelectable = TextSelectable; + }) + + genDebounce = false + end + end + + window = client.UI.Make("Window", { + Name = data.Name or "List"; + Title = Title; + Icon = Icon; + Size = Size or {300, 250}; + MinSize = {200, 120}; + OnRefresh = Update and function() + Tab = client.Remote.Get("UpdateList", Update, unpack(UpdateArgs or {UpdateArg})) + if Tab then + currentListTab = Tab + genList(Tab) + end + end; + RichTextSupport = data.RichTextSupport or data.SupportRichText or false; + }) + + scroller = window:Add("ScrollingFrame", { + List = {}; + ScrollBarThickness = 2; + BackgroundTransparency = 1; + Position = UDim2.new(0, 5, 0, 30); + Size = UDim2.new(1,-10,1,-30); -- UDim2.new(1,-10,1,-60); when paging + --LabelProps = { + -- TextXAlignment = "Left"; + --} + }) + + pageCounterLabel = window:Add("TextLabel", { + Size = UDim2.new(0, 60, 0, 20); + Position = UDim2.new(0.5, -30, 1, -25); + Text = "Page: 1"; + BackgroundTransparency = 1; + TextTransparency = 0.5; + TextWrapped = false; + ClipsDescendants = false; + TextXAlignment = "Center"; + }) + + nextPageButton = window:Add("TextButton", { + Size = UDim2.new(0, 50, 0, 20); + Position = UDim2.new(1, -60, 1, -25); + Text = ">"; + Visible = false; + Debounce = true; + OnClick = function() + if not pageDebounce then + pageDebounce = true + local origLTrans = nextPageButton.BackgroundTransparency + lastPageButton.BackgroundTransparency = origLTrans + 0.35 + + local origNTrans = nextPageButton.BackgroundTransparency + nextPageButton.BackgroundTransparency = origNTrans + 0.35 + + lastPageButton.TextTransparency = 0.8 + nextPageButton.TextTransparency = 0.8 + + if currentListTab then + local maxPages = math.ceil(#currentListTab/PageSize); + PageCounter = math.clamp(PageCounter+1, 1, maxPages); + + pageCounterLabel.Text = `Page: {PageCounter}/{maxPages}` + + if PageCounter > 1 then + lastPageButton.Visible = true + end + + if PageCounter == maxPages then + nextPageButton.Visible = false + end + + scroller:ClearAllChildren() + + scroller.CanvasPosition = Vector2.new(0, 0) + scroller:GenerateList(getPage(currentListTab, PageCounter), { + RichTextAllowed = RichText; + TextSelectable = TextSelectable; + }) + end + + lastPageButton.BackgroundTransparency = origLTrans + nextPageButton.BackgroundTransparency = origNTrans + + lastPageButton.TextTransparency = 0 + nextPageButton.TextTransparency = 0 + + pageDebounce = false + end + end + }) + + lastPageButton = window:Add("TextButton", { + Size = UDim2.new(0, 50, 0, 20); + Position = UDim2.new(0, 10, 1, -25); + Text = "<"; + Visible = false; + Debounce = true; + OnClick = function() + if not pageDebounce then + pageDebounce = true + local origLTrans = nextPageButton.BackgroundTransparency + lastPageButton.BackgroundTransparency = origLTrans + 0.2 + + local origNTrans = nextPageButton.BackgroundTransparency + nextPageButton.BackgroundTransparency = origNTrans + 0.2 + + lastPageButton.TextTransparency = 0.8 + nextPageButton.TextTransparency = 0.8 + + if currentListTab then + local maxPages = math.ceil(#currentListTab/PageSize) + PageCounter = math.clamp(PageCounter-1, 1, maxPages) + + pageCounterLabel.Text = `Page: {PageCounter}/{maxPages}` + + if PageCounter == 1 then + lastPageButton.Visible = false + end + + if PageCounter == maxPages then + nextPageButton.Visible = false + else + nextPageButton.Visible = true + end + + scroller:ClearAllChildren() + + scroller.CanvasPosition = Vector2.new(0, 0) + scroller:GenerateList(getPage(currentListTab, PageCounter), { + RichTextAllowed = RichText; + TextSelectable = TextSelectable; + }) + end + + lastPageButton.BackgroundTransparency = origLTrans + nextPageButton.BackgroundTransparency = origNTrans + + lastPageButton.TextTransparency = 0 + nextPageButton.TextTransparency = 0 + + pageDebounce = false + end + end + }) + + for i, v in ipairs(TitleButtons) do + window:AddTitleButton(v) + end + + search = window:Add("TextBox", { + Size = UDim2.new(1, -10, 0, 20); + Position = UDim2.new(0, 5, 0, 5); + BackgroundTransparency = 0.5; + BorderSizePixel = 0; + Text = ""; + PlaceholderText = "Search"; + TextStrokeTransparency = 1; + }) + + search:GetPropertyChangedSignal("Text"):Connect(function() + currentListTab = Tab + genList(Tab) + end) + + --window:SetPosition(UDim2.new(0.25, 0, 0.5, -window.AbsoluteSize.Y/2)) + gTable = window.gTable + window:Ready() + currentListTab = Tab + genList(Tab) + + if Update and AutoUpdate then + while gTable.Active and wait(AutoUpdate) do + window:Refresh() + end + end +end \ No newline at end of file diff --git a/MainModule/Client/UI/Modern/Message.luau b/MainModule/Client/UI/Modern/Message.luau deleted file mode 100644 index 97281d143f..0000000000 --- a/MainModule/Client/UI/Modern/Message.luau +++ /dev/null @@ -1,68 +0,0 @@ -client = nil -service = nil - -local Components = script.Parent.Components.AdonisModernComponents -local Packages = Components.Parent.Packages - -local Maid = require(Packages.Maid) -local Signal = require(Packages.Signal) -local Roact = require(Packages.Roact) -local new = Roact.createElement - -local FadeInOutAnimationWrapper = require(Components.FadeInOutAnimationWrapper) -local Message = require(Components.Message) - -return function (Data) - - local AppMaid = Maid.new() - local FadeInSignal = Signal.new() - local FadeOutSignal = Signal.new() - - AppMaid.FadeInSignal = FadeInSignal - AppMaid.FadeOutSignal = FadeOutSignal - - -- ////////// Create Message App - local App = new('ScreenGui', { - DisplayOrder = Data.DisplayOrder or 100, - IgnoreGuiInset = true, - ZIndexBehavior = Enum.ZIndexBehavior.Sibling, - }, { - - AnimationContainer = new(FadeInOutAnimationWrapper, { - FadeInSignal = FadeInSignal, - FadeOutSignal = FadeOutSignal, - FadeInVelocity = 3, - FadeOutVelocity = 4, - OnFadeOutCompleted = function() - AppMaid:Destroy() - end - }, { - - Message = new(Message, { - BodyText = Data.Message, - Image = Data.Image, - TitleText = Data.Title, - }), - }), - }) - - -- ////////// Perform Animation Tasks - - local Handle = Roact.mount(App, service.UnWrap(service.PlayerGui), 'AdonisUI.Notification') - - AppMaid.RemoveHandle = function() - Handle = Roact.unmount(Handle) - end - - FadeInSignal:Fire() - - if Data.Time then - task.wait(Data.Time) - else - - -- Estimated read time - task.wait((('%s%s'):format(Data.Message or '', Data.Title or ''):len() / 19) + 2.5) - end - - FadeOutSignal:Fire() -end diff --git a/MainModule/Client/UI/Modern/Message.rbxm b/MainModule/Client/UI/Modern/Message.rbxm new file mode 100644 index 0000000000000000000000000000000000000000..6a0c9c54932fa7d67d60862d9b975373562c7c9e GIT binary patch literal 15815 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 literal 0 HcmV?d00001 diff --git a/MainModule/Client/UI/Modern/Notif.rbxm b/MainModule/Client/UI/Modern/Notif.rbxm new file mode 100644 index 0000000000000000000000000000000000000000..a99e2d98f2a673b29a0cb51b7b475f2484f3542e GIT binary patch literal 13109 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 literal 0 HcmV?d00001 diff --git a/MainModule/Client/UI/Modern/NotificationHolder.rbxm b/MainModule/Client/UI/Modern/NotificationHolder.rbxm new file mode 100644 index 0000000000000000000000000000000000000000..e84be1b9830d758d5aa4091cb452260a73e174a3 GIT binary patch literal 7295 zcmb7J-ESOM6+bh(Yj-zJZ0D;XO`Ds~+St4PENMgCWbL(6mpF0!(Gsc(#=CdzX~uK6 zGqe6^i|}I+4^)LGBm@tAsS2Wzs!BW{m8yS00Tl_ULR26jUeH98!W*35-JM-e*LLb7 z-QC%l-#Pc5k9*F!vrl?z$x$0;zW=|2nUfi!b|QL!M?^D|3;FZ><81v#c*NkV!#pN8 zDvn*WgM2km&nVjs{3PEEysDhOF~1=A`Vk(WuoItY9^*uM1Th^vW>l%_$oZmYSAqzhgxpj7@MHu(kl-t< zgMm`I*Q$1eC1B6+6Nm?eUC`zb55_9TvEAh<&svocLk0}-wWJt~wJc6wxBcL{wW+F& zwRE(u1^Qtvi_^1Ksl@Ul(T8T|Zq8ohC$KvxJciFBJn}){*-Obl^S&>G z>C!{Tqa_*!SP&N40{mT53R5mv%YICE#AFu_P^h24Av)Sj(t=AN}$%>l5$1Dbs zaa*u+_h}1o?86q(1Um*6*7Fd{gFQfDCX#;LcJIhiEjplvwsJfk0Bx8J7Za+aBkc-b zkMRJ7Ilwr*VK;M%;GJJG5QeV|T^gOr7lsPi@j@Y=9UUDS$v&PRdMrCKd1>&8{P6hj zFm!OxiA|=`&LVE7HxR)4VUre7|St zG=0`3-BKo)ST%Z%V zM<_W=gT<=nQ#d@aVml=k!%_!DHY@VNuX+{F_Blg2n_^k1l32GkMW94U2|EzBD+1}Q z`a+e3V=d=?M+X#z36zCZE3k{40oE*k-hTNvG&Si~SJ~6YNaSvh(b;Ua%Shfb*2H3k zb(c?)=;^&c9g^Av{ny|XEEeq5;hZbidj|W(Kk1&4%P;xL;RMK=BVco{)0J=bi$|%u z`}PJU-ZlEO*)5_cjKAeeC0V-6C|4GPo)1`Z@e~RhCw`E2(2=YL8eO$TCKd3XGrn6d6i-%Zf9#QR)|#FFI+-?b{g zGJnqTA(m9YrhePxYV{Ha0vERaNvbH9y=9kwZ+^ON`NDEMX_YpGa&OYX$H{yx(N%se zVP2&QR}-;f`8M6PibYlB2rescjJk`Tn?m^iF})?po)?3oZ2k2WySO4$5uqa1SENH9 zc~aQEaFy_sTD?iP{35ULP3r3TS#rx&fnByaN|U5$IIx`O>GgFxSP>O2cuO?sNIz}d zwOlbWIM|!xFdwJEg%x|0w$vT5DuuQ5aB|BMFI71yVYZvy z6ItWxtn%$oX(D%9^i|B{uM_lj(|C}^9us4KN+vImIYo&+I+ZO^@*)+Vv)z(fzewhr zsVgk+b~2HCgB}(EnGU4{b-qJJujrGBbA$aS5=uJ0w9B7T;`CGRQOc}P;yvp8gkGah z+KhqJ;od){I{snM(d4)1X5PMtcM9Zq#FnC%@hb#;vQ;13dA?i=)nbeebY<%0AB zPi3iV{seZ%%sc7U6yK-pXVFrc!2%_1njC?rNe2i z%k|xX)c>^ZbD`kQcAJx20dBhU6>HsX%03IhOyLm-M~gJ4R8Y4sr(Wfv)JUvU8w2ZU z<%tY7p;jx*q#MOeG*g;qXNz!k;WRVt@~V75O)PyE@zUX)%4->yE7qE=ynEDb~}5tMlCpY-tD_cZfO-H zRMJ5eKfggTY};rqxUFbnALS>F)6a2WVU=;KcxRcN<(4Ltqr8!hNYzN)cszj(@zi8n z@GRG_ptUM)CL^YE42d#RcsSB{Tp>r)=XvGs-FIKTb!+a`x8C{%j1+J8!Geag#=_@U zt%tUMtG94~t^uL&ti2%}#Dqp)<8KVmy&i~#Z^w00FuiImOJjh4drKP@j#rll2Ds

y@U!*H#cL%qb7hAT8dJ**m50ezl|)N6Eq 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 BA^HFS literal 0 HcmV?d00001 diff --git a/MainModule/Client/UI/Modern/Window.rbxm b/MainModule/Client/UI/Modern/Window.rbxm new file mode 100644 index 0000000000000000000000000000000000000000..ef4de2ddde80a8e981f2ae5235c0ce609fa3a04c GIT binary patch literal 47334 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 literal 0 HcmV?d00001 diff --git a/MainModule/Client/UI/Modern/YesNoPrompt.luau b/MainModule/Client/UI/Modern/YesNoPrompt.luau new file mode 100644 index 0000000000..37911f107e --- /dev/null +++ b/MainModule/Client/UI/Modern/YesNoPrompt.luau @@ -0,0 +1,77 @@ +client, service = nil +local Packages = script.Parent.Components.Packages + +local Signal = require(Packages.Signal) +local Winro = require(Packages.Winro) +local Roact = require(Packages.Roact) +local new = Roact.createElement + +local Dialog = Winro.App.Window.Dialog + +export type YesNoPromptProps = { + Delay: number?, + Icon: string?, + Name: string, + Question: string, + Size: {number}, + Title: string +} + +return function(data: YesNoPromptProps, env): "No" | "Yes" + + local Variables = client.Variables + local themeData = Variables.LastServerTheme or {Desktop = "Default"; Mobile = "Mobilius"} + local theme = Variables.CustomTheme or (service.IsMobile() and themeData.Mobile) or themeData.Desktop + + local answerSignal = Signal.new() + + local app = new("ScreenGui", { + ZIndexBehavior = Enum.ZIndexBehavior.Sibling, + DisplayOrder = 500, + }, { + Dialog = new(Dialog, { + TitleText = data.Name, + BodyText = data.Question, + Size = UDim2.new(0, 400, 0, 100), + AutomaticSize = Enum.AutomaticSize.Y, + + Buttons = { + [1] = { + Text = 'Yes', + Style = 'Accent', + [Roact.Event.Activated] = function() + answerSignal:Fire(true) + end, + }, + [2] = { + Text = 'No', + Style = 'Standard', + [Roact.Event.Activated] = function() + answerSignal:Fire(false) + end, + }, + }, + TitleBarProps = { + Icon = data.Icon and { + Image = data.Icon; + ImageRectSize = Vector2.new(); + ImageRectOffset = Vector2.new(); + } or nil, + Text = data.Name or "Confirmation", + CanClose = false + }, + WindowProps = { + FooterHeight = 80, + } + }) + }) + + local handle = Roact.mount(new(Winro.Theme.Provider, { + Theme = theme == "Modern" and Winro.Theme.Themes.DarkTheme or Winro.Theme.Themes.LightTheme, + }, app), service.UnWrap(service.PlayerGui), "Adonis.YesNoPrompt") + + local answer = answerSignal:Wait() + Roact.unmount(handle) + + return if answer then "Yes" else "No" +end \ No newline at end of file diff --git a/MainModule/Client/UI/ModernLight/Base_Theme.txt b/MainModule/Client/UI/ModernLight/Base_Theme.txt new file mode 100644 index 0000000000..c3cd62c2b9 --- /dev/null +++ b/MainModule/Client/UI/ModernLight/Base_Theme.txt @@ -0,0 +1 @@ +Modern \ No newline at end of file diff --git a/MainModule/Client/UI/ModernLight/Notification.rbxm b/MainModule/Client/UI/ModernLight/Notification.rbxm new file mode 100644 index 0000000000000000000000000000000000000000..0871a179e5d407e11576233341f7730013c7243a GIT binary patch literal 17413 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 WMvTdk6T@l}E`{*q9{WH4IQV}La!C*X literal 0 HcmV?d00001 diff --git a/MainModule/Client/UI/ModernLight/Window.rbxm b/MainModule/Client/UI/ModernLight/Window.rbxm new file mode 100644 index 0000000000000000000000000000000000000000..5c596a8a956c67b7f5baadc35cc13abc918332b4 GIT binary patch literal 47300 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 TT`X3fFmJ|=u8mu}b}#t<#)!gr literal 0 HcmV?d00001 diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index cd62232ac0..ba67a168cb 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -253,7 +253,7 @@ return function(Vargs, env) Description = "Makes a message"; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) - Functions.Message(`Message from {service.FormatPlayer(plr)}`, service.BroadcastFilter(assert(args[1], "Missing message"), plr), service.GetPlayers(), true) + Functions.Message(plr, `Message from {service.FormatPlayer(plr)}`, service.BroadcastFilter(assert(args[1], "Missing message"), plr), nil, service.GetPlayers(), true) end }; @@ -283,7 +283,7 @@ return function(Vargs, env) Description = "Makes a small message"; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) - Functions.Notify(`Message from {service.FormatPlayer(plr)}`, service.BroadcastFilter(assert(args[1], "Missing message"), plr), service.GetPlayers()) + Functions.Notify(`Message from @{plr.Name}`, service.BroadcastFilter(assert(args[1], "Missing message"), plr), service.GetPlayers(), nil, plr) end }; @@ -1434,7 +1434,7 @@ return function(Vargs, env) local head = plr.Character and (plr.Character:FindFirstChild("Head") or plr.Character:FindFirstChild("HumanoidRootPart")) assert(head and head:IsA("BasePart"), "You don't have a character head or root part") if not args[1] then return Functions.Hint("A name is required!", {plr}) end - + if workspace:FindFirstChild(`Camera: {args[1]}`) then Functions.Hint(`{args[1]} Already Exists!`, {plr}) else @@ -1462,7 +1462,7 @@ return function(Vargs, env) end end }; - + RemoveCamera = { Prefix = Settings.Prefix; Commands = {"removecam", "delcam", "removecamera", "deletecamera"}; @@ -1473,13 +1473,13 @@ return function(Vargs, env) for i,v in Variables.Cameras do if string.lower(args[1]) == v.Name then local cam = workspace:FindFirstChild(v) - + Variables.Cameras[i] = nil - + if cam and cam:IsA("Part") then cam:Destroy() end - + Functions.Hint(`Deleted camera {v.Name}`, {plr}) end end @@ -1935,11 +1935,11 @@ return function(Vargs, env) local entry = type(v) == "string" and v local reason = "No reason provided" local moderator = "%UNKNOWN%" - - local banType = if typeof(v) == 'table' and v.BanType == "Server" then - "SERVER" + + local banType = if typeof(v) == 'table' and v.BanType == "Server" then + "SERVER" else "GLOBAL"; - + count +=1 if type(v) == "table" then if v.Name and v.UserId then @@ -6774,7 +6774,7 @@ return function(Vargs, env) Duration = math.huge end end - + for _, v in service.GetPlayers(plr, args[1]) do if Admin.CheckAuthority(plr, v, "mute", false) then --Remote.LoadCode(v,[[service.StarterGui:SetCoreGuiEnabled("Chat", false) client.Variables.ChatEnabled = false client.Variables.Muted = true]]) @@ -6791,15 +6791,15 @@ return function(Vargs, env) Target = v.UserId; Moderator = plr.UserId; }) - + Functions.Hint(`Muted {service.FormatPlayer(v)}`, {plr}) - + Functions.Notification("Notification", `You have been muted!`, {v}, 10, "MatIcon://Warning") end - + if Duration then local endTime = os.time()+Duration - + service.TrackTask(`Thread: MuteDuration :: {tostring(v.UserId)}`, function() while true do if os.time() < endTime then @@ -6834,9 +6834,9 @@ return function(Vargs, env) Target = v.UserId; Moderator = plr.UserId; }) - + Functions.Hint(`Unmuted {service.FormatPlayer(v)}`, {plr}) - + Functions.Notification("Notification", `You have been unmuted!`, {v}, 10, "MatIcon://Warning") end end diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index e9c8f575da..6e8692fc11 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -7,7 +7,9 @@ return function(Vargs, GetEnv) local service = Vargs.Service local logError - local AuditLogsDataStore = service.DataStoreService:GetDataStore("AdonisAuditLogsDataStore") + local AuditLogsDataStore; pcall(function() + AuditLogsDataStore = service.DataStoreService:GetDataStore("AdonisAuditLogsDataStore") + end) local Functions, Admin, Anti, Core, HTTP, Logs, Remote, Process, Variables, Settings local function Init() Functions = server.Functions; @@ -533,7 +535,7 @@ return function(Vargs, GetEnv) --// This is for player commands that take in service.GetPlayers() to make sure someone isnt passing in a message that is insanely long local PlrLevel = if plr then Admin.GetLevel(plr) else 0 - local AllowUnsafeSelectors = PlrLevel > 0 or options.AllowUnsafeSelectors + local AllowUnsafeSelectors = PlrLevel > 0 or options.AllowUnsafeSelectors local MaxSelectors = Variables.MaxSafeSelectors or 400 -- 400 seems like a good "max" that won't ever be reached local index = 0 @@ -965,12 +967,13 @@ return function(Vargs, GetEnv) Scroll = scroll; Time = duration; Image = image; + UserId = sender and sender.UserId or nil; }) end) end end; - Notify = function(title, message, players, duration) + Notify = function(title, message, players, duration, author) duration = duration or (#tostring(message) / 19) + 2.5 for _, v in players do @@ -980,6 +983,7 @@ return function(Vargs, GetEnv) Title = title; Message = message; Time = duration; + UserId = author and author.UserId or nil; }) end) end @@ -1349,7 +1353,7 @@ return function(Vargs, GetEnv) end if not buf then - local result = string.gsub(string.gsub(string.gsub(arg, spat, ""), epat, ""), escquotpat, "%2") + local result = string.gsub(string.gsub(string.gsub(arg, spat, ""), epat, ""), escquotpat, "%2") str ..= result .. key table.insert(tab,result) end @@ -1678,4 +1682,4 @@ return function(Vargs, GetEnv) task.spawn(xpcall, function() server.Functions.NuclearExplode = require(server.Dependencies.FastNuke); end, warn) -end +end \ No newline at end of file From 21b704e66d456deaaec14fc48b99604b0277dc32 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 8 Sep 2024 21:22:58 +0100 Subject: [PATCH 004/189] Add --- MainModule/Server/Shared/Credits.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Credits.luau b/MainModule/Server/Shared/Credits.luau index a8c4451aa1..e207dd3aa2 100644 --- a/MainModule/Server/Shared/Credits.luau +++ b/MainModule/Server/Shared/Credits.luau @@ -97,6 +97,7 @@ return { {Text = "@Mars7383", Desc = "Open Source Contributor"}; {Text = "@PurpleCreativity",Desc = "Open Source Contributor"}; {Text = "@ScriptedConnor", Desc = "Open Source Contributor"}; + {Text = "@omwot", Desc = "Open Source Contributor"}; }; Misc = { From 2f6059e7fbb9a7900ddfcad00843f5b04068169e Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 8 Sep 2024 21:23:43 +0100 Subject: [PATCH 005/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index d1274d25e5..e4d26aa041 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -6,14 +6,15 @@ return { "[v261 Pre-release 2024-08-29 14:32 UTC] @Dimenpsyonal"; "#Not for release until the following issues are resolved:"; "#Audit logs need be integrated into datastore"; - "(Git/Mars7383) Fix typo in Loadstring dependency affecting :ss (#1587)"; - "(Git/bsqi) Fix Join command (#1584)"; "(Git/24rr) New System: Audit Logs (#1568)"; "(Git/24rr) New Command: coordinates (#1568)"; + "(Git/bsqi) Fix Join command (#1584)"; + "(Git/Mars7383) Fix typo in Loadstring dependency affecting :ss (#1587)"; "(Git/PurpleCreativity) Remove ;cut command (#1590)"; "(Git/EasternBloxxer) Made dex fetch api dump on server start (#1591)"; "(Git/ScriptedConnor) Fix TopBarShift for :setmessage (#1593)"; "(Git/ScriptedConnor) Add Text Selections to the :players Command (#1597)"; + "(Git/omwot) Improve Modern theme (#1598)"; "(Git/jun022222222) Made mats & colors list selectable (#1599)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; From 35acc6f35ae1eaef8dff45f221b82724326f4304 Mon Sep 17 00:00:00 2001 From: jun022222222 <44199090+jun022222222@users.noreply.github.com> Date: Mon, 9 Sep 2024 05:24:56 +0900 Subject: [PATCH 006/189] Replace Coords.luau (#1595) * Update Fly.client.lua * Replace Coords.luau * Delete Fly.client.lua --- MainModule/Client/UI/{ => Default}/Coords.luau | 0 .../Server/Dependencies/Assets/Fly.client.luau | 12 ++++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) rename MainModule/Client/UI/{ => Default}/Coords.luau (100%) diff --git a/MainModule/Client/UI/Coords.luau b/MainModule/Client/UI/Default/Coords.luau similarity index 100% rename from MainModule/Client/UI/Coords.luau rename to MainModule/Client/UI/Default/Coords.luau diff --git a/MainModule/Server/Dependencies/Assets/Fly.client.luau b/MainModule/Server/Dependencies/Assets/Fly.client.luau index 5ca19bc08d..2315183ab0 100644 --- a/MainModule/Server/Dependencies/Assets/Fly.client.luau +++ b/MainModule/Server/Dependencies/Assets/Fly.client.luau @@ -42,6 +42,10 @@ function Check() end end +function tranVec(num) + return Vector3.new(num, num, num) +end + function getCF(part, isFor) local cframe = part.CFrame local noRot = CFrame.new(cframe.p) @@ -63,10 +67,10 @@ function Start() end) bPos.Position = part.Position - bPos.MaxForce = math.huge + bPos.MaxForce = tranVec(math.huge) bGyro.CFrame = part.CFrame - bGyro.MaxTorque = 9e9 + bGyro.MaxTorque = tranVec(9e9) antiLoop = antiReLoop @@ -146,11 +150,11 @@ function Stop() human.PlatformStand = false if bPos then - bPos.MaxForce = 0 + bPos.MaxForce = tranVec(0) end if bGyro then - bGyro.MaxTorque = 0 + bGyro.MaxTorque = tranVec(0) end if conn then From ce792a9d143bd1172dec9734032c0a87ff7b7839 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 8 Sep 2024 21:25:38 +0100 Subject: [PATCH 007/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index e4d26aa041..32207f2780 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -13,6 +13,7 @@ return { "(Git/PurpleCreativity) Remove ;cut command (#1590)"; "(Git/EasternBloxxer) Made dex fetch api dump on server start (#1591)"; "(Git/ScriptedConnor) Fix TopBarShift for :setmessage (#1593)"; + "(Git/jun022222222) Replace Coords.luau (#1595)"; "(Git/ScriptedConnor) Add Text Selections to the :players Command (#1597)"; "(Git/omwot) Improve Modern theme (#1598)"; "(Git/jun022222222) Made mats & colors list selectable (#1599)"; From 825f7a45a2b2581b6895feee3c75d22a7d00bbc5 Mon Sep 17 00:00:00 2001 From: bufferization Date: Mon, 9 Sep 2024 04:27:22 +0800 Subject: [PATCH 008/189] feat: Added a search player bar on the `:privatechat` command (#1594) * Added a search player bar on the `:privatechat` command. This is useful on servers that has hundreds of players. Was also requested by a community member. * removed unusual link --- MainModule/Client/UI/Default/PrivateChat.luau | 96 ++++++++++++------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/MainModule/Client/UI/Default/PrivateChat.luau b/MainModule/Client/UI/Default/PrivateChat.luau index 199922ebc3..a60b8db2bd 100644 --- a/MainModule/Client/UI/Default/PrivateChat.luau +++ b/MainModule/Client/UI/Default/PrivateChat.luau @@ -4,25 +4,18 @@ return function(data, env) if env then setfenv(1, env) end - local Owner = data.FromPlayer; local SessionKey = data.SessionKey; local SessionName = data.SessionName; local CanManageUsers = data.CanManageUsers; - local debounce = false - local gTable - local newMessage + local debounce, gTable, selectedPlayer = false, nil, nil + local peerList, messageObjs = {}, {} local window, chatlog, reply, playerList, send, layout, sessionEvent; - local peerList = {}; - local messageObjs = {}; - - local selectedPlayer = nil; local function sendIt() local text = service.Trim(reply.Text) - if text ~= "" then client.Remote.Send("Session", SessionKey, "SendMessage", text) end @@ -30,33 +23,63 @@ return function(data, env) local function promptAddUser() local list = {} - for _,v in service.Players:GetPlayers() do - local good = true; - for _, peer in peerList do - if peer.UserId == v.UserId then - good = false; - break; - end - end + local searchBar, playerList - if good then - table.insert(list, { - Text = service.FormatPlayer(v); - Data = service.UnWrap(v); - }) - end - end - - local answer = client.UI.Make("SelectionPrompt", { + local window = client.UI.Make("Window", { Name = "Add User"; - Options = list; - }); + Title = "Add User"; + Size = {300, 400}; + }) + + searchBar = window:Add("TextBox", { + Size = UDim2.new(1, -10, 0, 30); + Position = UDim2.new(0, 5, 0, 5); + Text = ""; + PlaceholderText = "Search player..."; + ClearTextOnFocus = false; + }) + + playerList = window:Add("ScrollingFrame", { + Size = UDim2.new(1, -10, 1, -45); + Position = UDim2.new(0, 5, 0, 40); + BackgroundTransparency = 0.9; + }) - if answer then - client.Remote.Send("Session", SessionKey, "AddPlayerToSession", answer) + local function updateList() + playerList:ClearAllChildren() + local searchText = searchBar.Text:lower() + local yPos = 0 + for _, v in service.Players:GetPlayers() do + local good = true + for _, peer in peerList do + if peer.UserId == v.UserId then + good = false + break + end + end + if good and (searchText == "" or v.Name:lower():find(searchText) or v.DisplayName:lower():find(searchText)) then + local button = playerList:Add("TextButton", { + Text = service.FormatPlayer(v); + Size = UDim2.new(1, 0, 0, 30); + Position = UDim2.new(0, 0, 0, yPos); + BackgroundTransparency = 0.5; + }) + button.MouseButton1Click:Connect(function() + window:Close() + client.Remote.Send("Session", SessionKey, "AddPlayerToSession", service.UnWrap(v)) + end) + yPos = yPos + 35 + end + end + playerList.CanvasSize = UDim2.new(0, 0, 0, yPos) end - end; + searchBar:GetPropertyChangedSignal("Text"):Connect(updateList) + updateList() + + window:Ready() + end + local function updatePeerList(peers) playerList:ClearAllChildren() peerList = peers @@ -206,7 +229,6 @@ return function(data, env) table.remove(messageObjs, 1) end end - local function systemMessage(msg) newMessage({ PlayerName = "* SYSTEM *"; @@ -237,15 +259,15 @@ return function(data, env) Size = UDim2.new(1, -105, 1, -45); CanvasSize = UDim2.new(0, 0, 0, 0); BackgroundTransparency = 0.9; - --AutomaticCanvasSize = "Y"; + AutomaticCanvasSize = "Y"; }) reply = window:Add("TextBox", { - Text = ""; --"Enter reply"; + Text = ""; PlaceholderText = ""; Size = UDim2.new(1, -70, 0, 30); Position = UDim2.new(0, 5, 1, -35); - ClearTextOnFocus = false;--true; + ClearTextOnFocus = false; TextScaled = true; }) @@ -324,7 +346,7 @@ return function(data, env) PlayerName = p.Name; PlayerDisplayName = p.DisplayName; Message = data.Message; - Icon = p.Icon or 0; --// replace with user avatar later + Icon = p.Icon or 0; }); end end @@ -335,8 +357,8 @@ return function(data, env) if cmd == "PlayerSentMessage" then local p = vargs[1] local message = vargs[2] - if newMessage then + print('sdf') newMessage({ PlayerName = p.Name; PlayerDisplayName = p.DisplayName; From cbf2d425585387ef62d72658b33959c4ef181d14 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 8 Sep 2024 21:28:19 +0100 Subject: [PATCH 009/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 32207f2780..65079518c4 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -11,12 +11,13 @@ return { "(Git/bsqi) Fix Join command (#1584)"; "(Git/Mars7383) Fix typo in Loadstring dependency affecting :ss (#1587)"; "(Git/PurpleCreativity) Remove ;cut command (#1590)"; - "(Git/EasternBloxxer) Made dex fetch api dump on server start (#1591)"; + "(Git/EasternBloxxer) Make dex fetch api dump on server start (#1591)"; "(Git/ScriptedConnor) Fix TopBarShift for :setmessage (#1593)"; "(Git/jun022222222) Replace Coords.luau (#1595)"; "(Git/ScriptedConnor) Add Text Selections to the :players Command (#1597)"; "(Git/omwot) Improve Modern theme (#1598)"; - "(Git/jun022222222) Made mats & colors list selectable (#1599)"; + "(Git/jun022222222) Make mats & colors list selectable (#1599)"; + "(Git/24rr) Add a search player bar for :privatechat (#1594)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From f3386ca97fcaf56e6285378bf68ce59d5dbeb456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ev=E2=81=BF=20=E2=98=95?= <14357936+cl1ents@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:08:35 +0200 Subject: [PATCH 010/189] Update "MakeLocalScript" and "LoadLocalScript" commands (#1603) Fixes an issue where local scripts wouldn't run on the client due to replication issue. Also improved code to avoid redundancy. --- MainModule/Server/Commands/Admins.luau | 33 ++++++++++++++------------ 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index c744644d41..f263ffd7ce 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -943,16 +943,7 @@ return function(Vargs, env) AdminLevel = "Admins"; NoFilter = true; Function = function(plr: Player, args: {string}) - local bytecode = Core.Bytecode(assert(args[1], "Missing Script code (argument #2)")) - assert(string.find(bytecode, "\27Lua"), `LocalScript unable to be created: {string.gsub(bytecode, "Loadstring%.LuaX:%d+:", "")}`) - - local cl = Core.NewScript("LocalScript", `script.Parent = game:GetService('Players').LocalPlayer.PlayerScripts; {args[1]}`, true) - cl.Name = "[Adonis] LocalScript" - cl.Disabled = true - cl.Parent = plr:FindFirstChildOfClass("Backpack") - task.wait() - cl.Disabled = false - Functions.Hint("Ran LocalScript on your client", {plr}) + Commands.LoadLocalScript.Function(plr, {`@{plr.Name}`, args[1]}) end }; @@ -970,14 +961,26 @@ return function(Vargs, env) assert(string.find(bytecode, "\27Lua"), `LocalScript unable to be created: {string.gsub(bytecode, "Loadstring%.LuaX:%d+:", "")}`) local new = Core.NewScript("LocalScript", `script.Parent = game:GetService('Players').LocalPlayer.PlayerScripts; {args[2]}`, true) - for i, v in service.GetPlayers(plr, args[1]) do + local function cloneScript(targetPlayer) + local playerName = if targetPlayer == plr then "your client" else service.FormatPlayer(targetPlayer) + + local backpack = targetPlayer:FindFirstChildOfClass("Backpack") + if not backpack then + Functions.Hint(`Couldn't run LocalScript on {playerName} (Backpack missing?)`, {plr}) + return + end + local cl = new:Clone() cl.Name = "[Adonis] LocalScript" cl.Disabled = true - cl.Parent = v:FindFirstChildOfClass("Backpack") - task.wait() + cl.Parent = targetPlayer:FindFirstChildOfClass("Backpack") + task.wait(.1) cl.Disabled = false - Functions.Hint(`Ran LocalScript on {service.FormatPlayer(v)}`, {plr}) + Functions.Hint(`Ran LocalScript on {playerName}`, {plr}) + end + + for i, v in service.GetPlayers(plr, args[1]) do + task.spawn(cloneScript, v) end end }; @@ -1553,4 +1556,4 @@ return function(Vargs, env) end }; } -end \ No newline at end of file +end From 169b34a66cd0f37c8a118c00ee1291ebde676460 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Tue, 17 Sep 2024 17:09:44 +0100 Subject: [PATCH 011/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 65079518c4..062a2fd468 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -18,6 +18,7 @@ return { "(Git/omwot) Improve Modern theme (#1598)"; "(Git/jun022222222) Make mats & colors list selectable (#1599)"; "(Git/24rr) Add a search player bar for :privatechat (#1594)"; + "(Git/cl1ents) Update "MakeLocalScript" and "LoadLocalScript" commands (#1603)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 6605dd5cf60c531a68dff86e90885404672926a3 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:14:11 +0100 Subject: [PATCH 012/189] Remove --- MainModule/Server/Shared/Changelog.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 062a2fd468..1b552a847d 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -18,7 +18,7 @@ return { "(Git/omwot) Improve Modern theme (#1598)"; "(Git/jun022222222) Make mats & colors list selectable (#1599)"; "(Git/24rr) Add a search player bar for :privatechat (#1594)"; - "(Git/cl1ents) Update "MakeLocalScript" and "LoadLocalScript" commands (#1603)"; + "(Git/cl1ents) Update MakeLocalScript and LoadLocalScript commands (#1603)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 1e28a3e6654d3448f66422d7d4ba83db616f77b1 Mon Sep 17 00:00:00 2001 From: Purple_Creativity <113302593+PurpleCreativity@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:46:34 +0200 Subject: [PATCH 013/189] Update Anti.luau (#1605) --- MainModule/Server/Core/Anti.luau | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Core/Anti.luau b/MainModule/Server/Core/Anti.luau index 5cf6d61d85..accd3a746d 100644 --- a/MainModule/Server/Core/Anti.luau +++ b/MainModule/Server/Core/Anti.luau @@ -49,8 +49,15 @@ return function(Vargs, GetEnv) RemovePlayer = function(p, info) info = tostring(info) or "No Reason Given" - - pcall(function() service.UnWrap(p):Kick(`:: Adonis Anti Cheat :: {info}`) end) + + if service.RunService:IsStudio() then + warn(`:: Adonis Anti Cheat :: Anticheat triggered for {p.Name}, not kicking because in studio; {info}`) + return; + end + + pcall(function() + service.UnWrap(p):Kick(`:: Adonis Anti Cheat :: {info}`) + end) task.wait(1) From 3df75bacba626d0f8c015c9ba3b77a72aea0ef77 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 4 Oct 2024 12:47:08 +0100 Subject: [PATCH 014/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 1b552a847d..c53d9465cc 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -19,6 +19,7 @@ return { "(Git/jun022222222) Make mats & colors list selectable (#1599)"; "(Git/24rr) Add a search player bar for :privatechat (#1594)"; "(Git/cl1ents) Update MakeLocalScript and LoadLocalScript commands (#1603)"; + "(Git/PurpleCreativity) Prevent Anti.RemovePlayer from kicking if in studio (#1605)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 20013dbe4f9accc650463f2ee3aaf18da770c6c4 Mon Sep 17 00:00:00 2001 From: Expertcoderz Date: Tue, 8 Oct 2024 17:08:40 +0000 Subject: [PATCH 015/189] Add :ckick command (#1614) - Command: `CustomKick` - Supporting client Function: `CustomKick` - Supporting asset: `RobloxPromptGui` --- MainModule/Client/Core/Functions.luau | 27 +- MainModule/Server/Commands/Admins.luau | 57 +- .../Dependencies/Assets/RobloxPromptGui.rbxmx | 1291 +++++++++++++++++ 3 files changed, 1366 insertions(+), 9 deletions(-) create mode 100644 MainModule/Server/Dependencies/Assets/RobloxPromptGui.rbxmx diff --git a/MainModule/Client/Core/Functions.luau b/MainModule/Client/Core/Functions.luau index dfc50ea9f0..5b639f20dc 100644 --- a/MainModule/Client/Core/Functions.luau +++ b/MainModule/Client/Core/Functions.luau @@ -1074,7 +1074,7 @@ return function(Vargs, GetEnv) cam[prop] = value end end; - + SetFPS = function(fps) service.StopLoop("SetFPS") local fps = tonumber(fps) @@ -1082,14 +1082,14 @@ return function(Vargs, GetEnv) if fps then service.StartLoop("SetFPS",0.1,function() local osclock = os.clock() - repeat while osclock + 1/fps > os.clock() do end + repeat while osclock + 1/fps > os.clock() do end task.wait() - osclock = os.clock() + osclock = os.clock() until service.IsLooped("SetFPS") == false end) end end; - + RestoreFPS = function() service.StopLoop("SetFPS") end; @@ -1206,6 +1206,23 @@ return function(Vargs, GetEnv) end end; + CustomKick = function() + service.TweenService:Create(service.New("BlurEffect", { + Parent = service.Lighting; Size = 10; + }), TweenInfo.new(0.5, Enum.EasingStyle.Sine), {Size = 30}):Play() + + service.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false) + + for _, v in service.PlayerGui:GetChildren() do + if v.Name ~= "RobloxPromptGui" then + pcall(v.Destroy, v) + end + end + + task.wait(0.5) + Functions.HardCrash() + end; + KillClient = function() client.Kill("KillClient called") end; @@ -1424,7 +1441,7 @@ return function(Vargs, GetEnv) local ang = 0.1 local oldmag = torso.AssemblyLinearVelocity.Magnitude local mv = .002 - if wave then + if wave then ang += ((torso.AssemblyLinearVelocity.Magnitude/10)*.05)+.05 wave = false else diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index f263ffd7ce..ba310f7329 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -963,13 +963,13 @@ return function(Vargs, env) local new = Core.NewScript("LocalScript", `script.Parent = game:GetService('Players').LocalPlayer.PlayerScripts; {args[2]}`, true) local function cloneScript(targetPlayer) local playerName = if targetPlayer == plr then "your client" else service.FormatPlayer(targetPlayer) - + local backpack = targetPlayer:FindFirstChildOfClass("Backpack") - if not backpack then + if not backpack then Functions.Hint(`Couldn't run LocalScript on {playerName} (Backpack missing?)`, {plr}) return end - + local cl = new:Clone() cl.Name = "[Adonis] LocalScript" cl.Disabled = true @@ -978,7 +978,7 @@ return function(Vargs, env) cl.Disabled = false Functions.Hint(`Ran LocalScript on {playerName}`, {plr}) end - + for i, v in service.GetPlayers(plr, args[1]) do task.spawn(cloneScript, v) end @@ -1262,6 +1262,55 @@ return function(Vargs, env) end }; + CustomKick = { + Prefix = Settings.Prefix; + Commands = {"ckick", "customkick", "customcrash"}; + Args = {"player", "title", "message"}; + Description = "Disconnects (crashes) the target player with a custom Roblox dialog"; + AdminLevel = "Admins"; + Function = function(plr: Player, args: {string}) + assert(args[3], "Argument(s) missing or nil") + + local title = service.BroadcastFilter(args[2], plr) + assert(title == args[2], "Title was filtered: "..title) + + local msg = service.BroadcastFilter(args[3], plr) + assert(msg == args[3], "Message was filtered: "..msg) + + for _, v in service.GetPlayers(plr, args[1], { + IsKicking = true; + NoFakePlayer = false; + }) + do + if not Admin.CheckAuthority(plr, v, "custom-kick") then + continue + end + + local plrgui = v:FindFirstChildOfClass("PlayerGui") + if not plrgui then + Remote.MakeGui(plr, "Output", { + Message = `Failed to custom-kick {service.FormatPlayer(v)} (PlayerGui not found)`; + }) + continue + end + + local promptGui = Deps.Assets.RobloxPromptGui:Clone() + promptGui.promptOverlay.ErrorPrompt.TitleFrame.ErrorTitle.Text = title + promptGui.promptOverlay.ErrorPrompt.MessageArea.ErrorFrame.ErrorMessage.Text = msg + promptGui.Parent = plrgui + + Remote.Send(v, "Function", "CustomKick") + task.delay(5, function() + if v.Parent == service.Players then + -- make sure they're really kicked + v:Kick("Unexpected Error") + end + end) + Functions.Hint(`Custom-kicking {service.FormatPlayer(v)}`, {plr}) + end + end + }; + Shutdown = { Prefix = Settings.Prefix; Commands = {"shutdown"}; diff --git a/MainModule/Server/Dependencies/Assets/RobloxPromptGui.rbxmx b/MainModule/Server/Dependencies/Assets/RobloxPromptGui.rbxmx new file mode 100644 index 0000000000..7a999e067e --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/RobloxPromptGui.rbxmx @@ -0,0 +1,1291 @@ + + true + null + nil + + + + false + 0 + true + false + 9 + true + RobloxPromptGui + false + null + 1 + 2 + 0 + 0 + 0 + 0 + false + -1 + + 0 + + + + true + + 0 + 0 + + + true + 0 + + 0 + 0 + 0 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 1 + 0 + false + false + false + true + 0 + promptOverlay + null + null + null + null + + 0 + 0 + 0 + -36 + + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 1 + 36 + + 0 + -1 + 0 + + true + 1 + + + + false + + 0.5 + 0.5 + + + false + 0 + + 0.223529413 + 0.23137255 + 0.239215687 + + 0 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 0 + 0 + false + false + false + true + 0 + ErrorPrompt + null + null + null + null + + 0.5 + 0 + 0.5 + 0 + + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 0 + 400 + 0 + 208 + + 0 + -1 + 0 + + true + 8 + + + + + 0 + false + 1 + 0 + 0 + 0 + PromptLayout + + 0 + 0 + + 2 + -1 + + 1 + 0 + false + + + + + + 0 + false + PromptScale + 1 + -1 + + + + + + false + + 0 + 0 + + + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 0 + 0 + false + false + false + true + 1 + TitleFrame + null + null + null + null + + 0 + 0 + 0 + 0 + + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 0 + 50 + + 0 + -1 + 0 + + true + 8 + + + + + 0 + false + TitleFramePadding + + 0 + 11 + + + 0 + 0 + + + 0 + 0 + + + 0 + 11 + + -1 + + + + + + false + + 0 + 0 + + + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 1 + 0 + false + false + false + + rbxasset://fonts/families/SourceSansPro.json + 600 + + rbxasset://fonts/SourceSansPro-Semibold.ttf + + true + 0 + 1 + + + -1 + ErrorTitle + null + null + null + null + + + 0 + 0 + 0 + 0 + + false + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 0 + 28 + + 0 + -1 + + Banned + + 1 + 1 + 1 + + 0 + false + 25 + + 0 + 0 + 0 + + 1 + 0 + 0 + false + 2 + 1 + true + 8 + + + + + + false + + 0 + 0 + + + true + 0 + + 0.741176486 + 0.745098054 + 0.745098054 + + 0 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 0 + 0 + false + false + false + true + 2 + SplitLine + null + null + null + null + + 0 + 0 + 0 + 0 + + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + -40 + 0 + 1 + + 0 + -1 + 0 + + true + 8 + + + + + false + + 0 + 0 + + + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 0 + 0 + false + false + false + true + 3 + MessageArea + null + null + null + null + + 0 + 0 + 0 + 0 + + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 1 + -51 + + 0 + -1 + 0 + + true + 8 + + + + + 0 + false + MessageAreaPadding + + 0 + 20 + + + 0 + 20 + + + 0 + 20 + + + 0 + 20 + + -1 + + + + + + false + + 0 + 0 + + + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 1 + 0 + false + false + false + true + 0 + ErrorFrame + null + null + null + null + + 0 + 0 + 0 + 0 + + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 1 + 0 + + 0 + -1 + 0 + + true + 8 + + + + + 0 + false + 1 + 0 + 0 + 0 + ErrorFrameLayout + + 0 + 20 + + 2 + -1 + + 1 + 0 + false + + + + + false + + 0 + 0 + + + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 1 + 0 + false + false + false + + rbxasset://fonts/families/SourceSansPro.json + 400 + + rbxasset://fonts/SourceSansPro-Regular.ttf + + true + 1 + 1 + + + -1 + ErrorMessage + null + null + null + null + + + 0 + 0 + 0 + 0 + + false + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 1 + -56 + + 0 + -1 + + You have been banned from this experience by an administrator. + + 0.741176486 + 0.745098054 + 0.745098054 + + 0 + false + 20 + + 0 + 0 + 0 + + 1 + 0 + 0 + true + 2 + 1 + true + 8 + + + + + false + + 0 + 0 + + + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 1 + 0 + false + false + false + true + 2 + ButtonArea + null + null + null + null + + 0 + 0 + 0 + 0 + + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 0 + 36 + + 0 + -1 + 0 + + true + 8 + + + + + 0 + + 0 + 10 + 0 + 0 + + + 0 + 360 + 0 + 36 + + false + 0 + 0 + 0 + ButtonLayout + 2 + -1 + 0 + + 0 + + + + + true + + 0.5 + 0.5 + + + true + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 1 + 0 + false + false + false + + rbxasset://textures/ui/ErrorPrompt/PrimaryButton.png + + 1 + 1 + 1 + + + 0 + 0 + + + 0 + 0 + + 0 + true + 1 + false + LeaveButton + null + null + null + null + + 0 + 0 + 0 + 0 + + + 0 + null + 0 + 1 + true + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 1 + 0 + + 0 + + + 8 + 8 + + + 9 + 9 + + + 1 + -1 + 0 + + + 1 + 0 + 1 + 0 + + true + 8 + + + + false + + 0 + 0 + + + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 1 + 0 + false + false + false + + rbxasset://fonts/families/SourceSansPro.json + 400 + + rbxasset://fonts/SourceSansPro-Regular.ttf + + true + 0 + 1 + + + -1 + ButtonText + null + null + null + null + + + 0 + 0 + 0 + 0 + + false + null + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 1 + 0 + + 0 + -1 + + Leave + + 0.137254909 + 0.145098045 + 0.152941182 + + 0 + false + 20 + + 0 + 0 + 0 + + 1 + 0 + 0 + false + 2 + 1 + true + 8 + + + + + false + + 0 + 0 + + + true + 0 + + 0 + 0 + 0 + + 0.699999988 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 0 + 0 + true + false + false + + + 1 + 1 + 1 + + + 0 + 0 + + + 0 + 0 + + 0 + true + 0 + ShimmerFrame + null + null + null + null + + 0 + 0 + 0 + 0 + + 0 + null + 0 + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 1 + 0 + + 0 + + + 0 + 0 + + + 0 + 0 + + + 1 + -1 + + + 1 + 0 + 1 + 0 + + false + 8 + + + + false + + 0 + 0 + + + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 0 + 0 + false + false + false + rbxasset://textures/ui/LuaApp/graphic/shimmer_darkTheme.png + + 1 + 1 + 1 + + + 0 + 0 + + + 0 + 0 + + 0 + true + 0 + Shimmer + null + null + null + null + + -1 + 0 + 0 + 0 + + 0 + null + 0 + 0 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 2 + 0 + + 0 + + + 0 + 0 + + + 0 + 0 + + + 1 + -1 + + + 1 + 0 + 1 + 0 + + true + 8 + + + + + false + + 0 + 0 + + + true + 0 + + 0.639215708 + 0.635294139 + 0.647058845 + + 1 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 0 + 0 + false + false + false + rbxasset://textures/ui/ErrorPrompt/ShimmerOverlay.png + + 0.223529413 + 0.23137255 + 0.239215687 + + + 0 + 0 + + + 0 + 0 + + 0 + true + 0 + ShimmerOverlay + null + null + null + null + + 0 + 0 + 0 + 0 + + 0 + null + 0 + 1 + false + 0 + 0 + 0 + 0 + false + null + 0 + + 1 + 0 + 1 + 0 + + 0 + + + 8 + 8 + + + 9 + 9 + + + 1 + -1 + + + 1 + 0 + 1 + 0 + + true + 9 + + + + + + + + + + + \ No newline at end of file From 1f4aabcf0c099f0f39825a49d9e741fb4e01567b Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 12 Oct 2024 14:10:52 +0300 Subject: [PATCH 016/189] Add reproduce field to bug report template (#1616) --- .github/ISSUE_TEMPLATE/Bug_Report.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.yml b/.github/ISSUE_TEMPLATE/Bug_Report.yml index 73d0bde9bd..c3fb237c68 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.yml +++ b/.github/ISSUE_TEMPLATE/Bug_Report.yml @@ -48,6 +48,14 @@ body: placeholder: ex. When I ran :shutdown, I expected the server to shut down, but instead... validations: required: true + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce: + description: What are the steps to reproduce this issue? + placeholder: ex. 1. Attempt to ban Sceleratis 2. Get hacked by Sceleratis instead 3. Have your disappointment be immeasurable + validations: + required: true - type: dropdown id: device attributes: From 10a5c372912a21982f2f18db3e15f5ff4e42191f Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 15 Oct 2024 03:30:52 +0300 Subject: [PATCH 017/189] Change small typo (#1622) --- .github/ISSUE_TEMPLATE/Bug_Report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.yml b/.github/ISSUE_TEMPLATE/Bug_Report.yml index c3fb237c68..7ff67693d8 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.yml +++ b/.github/ISSUE_TEMPLATE/Bug_Report.yml @@ -51,7 +51,7 @@ body: - type: textarea id: reproduce attributes: - label: Steps to reproduce: + label: Steps to reproduce description: What are the steps to reproduce this issue? placeholder: ex. 1. Attempt to ban Sceleratis 2. Get hacked by Sceleratis instead 3. Have your disappointment be immeasurable validations: From 81a96d9f26fa3e297c5f467754aad94a9b00833b Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 15 Oct 2024 08:59:58 +0300 Subject: [PATCH 018/189] Fix future bug that would break Adonis (#1621) --- default.project.json | 49 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/default.project.json b/default.project.json index b23918e4fa..454591ad7f 100644 --- a/default.project.json +++ b/default.project.json @@ -1,30 +1,31 @@ { - "name": "Adonis", - "tree": { - "$className": "DataModel", + "name": "Adonis", + "emitLegacyScripts": true, + "tree": { + "$className": "DataModel", - "ServerScriptService": { - "$className": "ServerScriptService", + "ServerScriptService": { + "$className": "ServerScriptService", - "Adonis_Rojo": { - "$className": "Folder", - "MainModule": { - "$path": "MainModule" - }, + "Adonis_Rojo": { + "$className": "Folder", + "MainModule": { + "$path": "MainModule" + }, - "LICENSE": { - "$path": "LICENSE.luau" - }, - - "Adonis_Loader": { - "$className": "Model", - "$path": "Loader", + "LICENSE": { + "$path": "LICENSE.luau" + }, + + "Adonis_Loader": { + "$className": "Model", + "$path": "Loader", - "LICENSE": { - "$path": "LICENSE.luau" - } - } - } - } - } + "LICENSE": { + "$path": "LICENSE.luau" + } + } + } + } + } } From b08daa5fab1ed91f604de40d74fe4f04c1d9e656 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 15 Oct 2024 09:02:58 +0300 Subject: [PATCH 019/189] Make HTTP constant URLs to Variables (#1618) * Add URLs to Variables.lua * Use Variables for HTTP check * Use Variables for IP info --- MainModule/Server/Commands/Players.luau | 2 +- MainModule/Server/Core/HTTP.luau | 2 +- MainModule/Server/Core/Variables.luau | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index 35c71d4bdf..f817d73245 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -984,7 +984,7 @@ return function(Vargs, env) local elevated = Admin.CheckAdmin(plr) local serverInfo = select(2, xpcall(function() - local res = Variables.IPInfo or service.HttpService:JSONDecode(service.HttpService:GetAsync("https://ipinfo.io/json")) + local res = Variables.IPInfo or service.HttpService:JSONDecode(service.HttpService:GetAsync(Variables.IPInfoUrl)) if not Variables.IPInfo then Variables.IPInfo = res end diff --git a/MainModule/Server/Core/HTTP.luau b/MainModule/Server/Core/HTTP.luau index 177f3bf004..cf4a6cecf8 100644 --- a/MainModule/Server/Core/HTTP.luau +++ b/MainModule/Server/Core/HTTP.luau @@ -43,7 +43,7 @@ return function(Vargs, GetEnv) if service.RunService:IsStudio() then return service.HttpService.HttpEnabled else - local success, res = pcall(service.HttpService.GetAsync, service.HttpService, "https://www.google.com/humans.txt") + local success, res = pcall(service.HttpService.GetAsync, service.HttpService, Variables.HTTPCheckUrl) if not success and res:find("Http requests are not enabled.") then return false end diff --git a/MainModule/Server/Core/Variables.luau b/MainModule/Server/Core/Variables.luau index 23eddafc90..f47b73c351 100644 --- a/MainModule/Server/Core/Variables.luau +++ b/MainModule/Server/Core/Variables.luau @@ -65,6 +65,8 @@ return function(Vargs, GetEnv) LockMessage = "Not Whitelisted", DonorPass = {1348327, 1990427, 1911740, 167686, 98593, "6878510605", 5212082, 5212081}, --// Strings are items; numbers are gamepasses WebPanel_Initiated = false, + HTTPCheckUrl = "https://www.google.com/humans.txt", + IPInfoUrl = "https://ipinfo.io/json", AnimatedFaces = { -- R15 (Hopefully) 14719428401, 12936561806, 12936887700, 12937016609, 12937135097, 12939014597, 12945364777, 12945456452, 14374800823, 14367118483, 13674780763, @@ -77,6 +79,7 @@ return function(Vargs, GetEnv) -- R6 14366393007 }, + LightingSettings = { Ambient = Lighting.Ambient, OutdoorAmbient = Lighting.OutdoorAmbient, From c7411aac8f842e0efd2df1099b7a0b28aa8e5b45 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 15 Oct 2024 11:00:48 +0300 Subject: [PATCH 020/189] Convert README XML to Lua (#1619) * Create README.lua * Delete Loader/Config/Themes/README.rbxmx --- Loader/Config/Themes/README.lua | 6 ++++++ Loader/Config/Themes/README.rbxmx | 22 ---------------------- 2 files changed, 6 insertions(+), 22 deletions(-) create mode 100644 Loader/Config/Themes/README.lua delete mode 100644 Loader/Config/Themes/README.rbxmx diff --git a/Loader/Config/Themes/README.lua b/Loader/Config/Themes/README.lua new file mode 100644 index 0000000000..eb7efbb9d9 --- /dev/null +++ b/Loader/Config/Themes/README.lua @@ -0,0 +1,6 @@ +--[[ + If you wish to create a custom theme for your Adonis GUIs, place it in this folder. + You can find instructions about how to do this at our wiki: + https://github.com/Epix-Incorporated/Adonis/wiki/Guide:-Creating-a-theme +--]] +return function() end diff --git a/Loader/Config/Themes/README.rbxmx b/Loader/Config/Themes/README.rbxmx deleted file mode 100644 index 84f5923714..0000000000 --- a/Loader/Config/Themes/README.rbxmx +++ /dev/null @@ -1,22 +0,0 @@ - - true - null - nil - - - - - README - {ED4805A5-4DFA-4CD0-9EB8-6FC6A1A3DA26} - - -1 - - - - From f7b084394f50b59a742b612d858839ed541ac9a7 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Tue, 15 Oct 2024 09:05:15 +0100 Subject: [PATCH 021/189] Update changelog --- MainModule/Server/Shared/Changelog.luau | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index c53d9465cc..55cdfc0460 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -4,6 +4,7 @@ return { "*Report bugs/issues on our GitHub repository*"; ""; "[v261 Pre-release 2024-08-29 14:32 UTC] @Dimenpsyonal"; + "(Git/Expertcoderz) Add :ckick command (#1614)"; "#Not for release until the following issues are resolved:"; "#Audit logs need be integrated into datastore"; "(Git/24rr) New System: Audit Logs (#1568)"; @@ -20,6 +21,8 @@ return { "(Git/24rr) Add a search player bar for :privatechat (#1594)"; "(Git/cl1ents) Update MakeLocalScript and LoadLocalScript commands (#1603)"; "(Git/PurpleCreativity) Prevent Anti.RemovePlayer from kicking if in studio (#1605)"; + "(Git/ccuser44) Make HTTP constant URLs to Variables (#1618)"; + "(Git/ccuser44) Convert README XML to Lua (#1619)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From b0490329868ae8241534625c4e7cab1d02a30ce1 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:58:01 +0300 Subject: [PATCH 022/189] Remove service.CloneTable (#1628) * Remote redundant table cloning function * Switch to vanilla function * Convert to vanilla functions * Switch to vanilla function * Remove `CloneTable` * Convert legacy usage of function * Add backwards compatibility for Clonetable --- MainModule/Client/Core/UI.luau | 15 +++++++-------- MainModule/Server/Core/Admin.luau | 5 ++--- MainModule/Server/Core/Logs.luau | 2 +- MainModule/Server/Plugins/Misc_Features.luau | 3 +++ MainModule/Server/Server.luau | 18 +----------------- MainModule/Server/Shared/Service.luau | 16 ++-------------- 6 files changed, 16 insertions(+), 43 deletions(-) diff --git a/MainModule/Client/Core/UI.luau b/MainModule/Client/Core/UI.luau index 695747bc37..478c6037f0 100644 --- a/MainModule/Client/Core/UI.luau +++ b/MainModule/Client/Core/UI.luau @@ -42,7 +42,7 @@ return function(Vargs, GetEnv) local GetEnv = env.GetEnv local Anti, Core, Functions, Process, Remote, UI, Variables, Deps - local CloneTable, TrackTask + local TrackTask local function Init() UI = client.UI; Anti = client.Anti; @@ -53,7 +53,6 @@ return function(Vargs, GetEnv) Remote = client.Remote; Deps = client.Deps; - CloneTable = service.CloneTable; TrackTask = service.TrackTask; UI.Init = nil; @@ -147,19 +146,19 @@ return function(Vargs, GetEnv) data = data or {} local ran, func = pcall(require, module) - local newEnv = GetEnv(env, { + local newEnv = GetEnv(env, { -- // Is this really necessary? script = module, - client = CloneTable(client), - service = CloneTable(service) + client = setmetatable(table.clone(client), {__index = function(_, k) return client[k] end}), + service = setmetatable(table.clone(service), {__index = function(_, k) return service[k] end}) }) if newEnv.service.Threads then - newEnv.service.Threads = CloneTable(service.Threads) + newEnv.service.Threads = table.clone(service.Threads) end - for i,v in newEnv.client do + for i,v in newEnv.client do -- // Is this really necessary? if type(v) == "table" and i ~= "Variables" and i ~= "Handlers" then - newEnv.client[i] = CloneTable(v) + newEnv.client[i] = setmetatable(table.clone(v), {__index = function(_, k) return v[k] end}) end end diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau index 51e4e7078f..0707f416ab 100644 --- a/MainModule/Server/Core/Admin.luau +++ b/MainModule/Server/Core/Admin.luau @@ -12,7 +12,6 @@ return function(Vargs, GetEnv) local server = Vargs.Server; local service = Vargs.Service; - local cloneTable = service.CloneTable; local Functions, Admin, Anti, Core, HTTP, Logs, Remote, Process, Variables, Settings, Commands local AddLog, TrackTask, Defaults @@ -544,9 +543,9 @@ return function(Vargs, GetEnv) end Admin.GroupsCache[uid] = cacheTab - return cloneTable(cacheTab.Groups) + return table.clone(cacheTab.Groups) else - return cloneTable((existCache and existCache.Groups) or {}) + return table.clone((existCache and existCache.Groups) or {}) end end end; diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index 15db151f7d..ef5ba2b772 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -162,7 +162,7 @@ return function(Vargs, GetEnv) end else local isTable = type(m) == "table" - local newTab = if isTable then service.CloneTable(m) else m + local newTab = if isTable then table.clone(m) else m if (isTable and not newTab.NoSave) or not isTable then if isTable and newTab.Player then diff --git a/MainModule/Server/Plugins/Misc_Features.luau b/MainModule/Server/Plugins/Misc_Features.luau index 958e2e5da9..9736a0fcb3 100644 --- a/MainModule/Server/Plugins/Misc_Features.luau +++ b/MainModule/Server/Plugins/Misc_Features.luau @@ -30,6 +30,9 @@ return function(Vargs, GetEnv) end, ...) end server.cPcall, service.cPcall = cPcall, cPcall + service.CloneTable = function(tbl) + return getmetatable(tbl) and setmetatable(table.clone(tbl), {__index = function(_, k) return tbl[k] end}) or table.clone(tbl) + end Remote.UnEncrypted = setmetatable({}, { __newindex = function(_, ind, val) warn("Unencrypted remote commands are deprecated; moving", ind, "to Remote.Commands. Replace `Remote.Unencrypted` with `Remote.Commands`!") diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index 3772fc0b56..a20cd1e1c9 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -134,20 +134,6 @@ local warn = function(...) warn(":: Adonis ::", ...) end -local function CloneTable(tab, recursive) - local clone = table.clone(tab) - - if recursive then - for i,v in pairs(clone) do - if type(v) == "table" then - clone[i] = CloneTable(v, recursive) - end - end - end - - return clone -end - local function Pcall(func, ...) local pSuccess, pError = pcall(func, ...) if not pSuccess then @@ -534,7 +520,7 @@ return service.NewProxy({ local setTab = require(server.Deps.DefaultSettings) server.Defaults = setTab server.Settings = data.Settings or setTab.Settings or {} - server.OriginalSettings = CloneTable(server.Settings, true) + server.OriginalSettings = service.DeepCopy(server.Settings, true) server.Descriptions = data.Descriptions or setTab.Descriptions or {} server.Messages = data.Messages or setTab.Settings.Messages or {} server.Order = data.Order or setTab.Order or {} @@ -674,8 +660,6 @@ return service.NewProxy({ --// Server Specific Service Functions ServiceSpecific.GetPlayers = server.Functions.GetPlayers - --// Experimental, may have issues with Adonis tables that are protected metatables - --ServiceSpecific.CloneTable = CloneTable --// Initialize Cores local runLast = {} diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index 8ed46d7d65..40239f35ea 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -550,18 +550,6 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end end; },{ - CloneTable = function(tab) - local new = (getmetatable(tab) ~= nil and setmetatable({},{ - __index = function(t, ind) - return tab[ind] - end - })) or {} - for i,v in tab do - new[i] = v - end - return new - end; - DeepCopy = function(tab) local new = (getmetatable(tab) ~= nil and setmetatable({},{ __index = function(t, ind) @@ -1075,7 +1063,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end end - return service.CloneTable(cache.results) + return table.clone(cache.results) end end; @@ -1195,7 +1183,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end end - return service.CloneTable(existingCache.results) + return table.clone(existingCache.results) end end; From 71c788c0216cfbe6638944c4ab5a143a430c2d5d Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:37:28 +0300 Subject: [PATCH 023/189] Remove bloat & Fix stuff (#1623) * Remove legacy http check function * Convert usage of legacy function * Add support for legacy function usage * Fix typo * Convert spaces to tab * Convert spaces to tabs * Move Trello functions to plugin * Update Urgent_Messages.luau * Add log * Add plugin load log * Update Debug_Specific.luau * Update Cross_Server.luau * Update Anti_Cheat.luau * Add plugin load log * Remove cruft * Remove cruft * Remove cruft * Fix log order * Simplify script * Fix indentation * Optimise Glitcher.rbxmx * Optimise and fix Illegal.client.luau * Optimise * Fix deprecated usage * Optimise Clipper.rbxmx * Convert deprecated usage * Remove cruft * Remove cruft * Remove cruft * Remove cruft * Remove cruft * Remove cruft * Remove cruft * Remove cruft * Remove cruft * Remove cruft * Fix things * Temporarily turn on lint * Remove unused * Re-disable lint --- .github/build.project.json | 25 ++-- Loader/Config/init.meta.json | 2 +- MainModule/Client/Client.luau | 2 - MainModule/Client/Core/Core.luau | 31 ----- MainModule/Client/Core/Functions.luau | 31 ----- MainModule/Client/Core/Process.luau | 36 ----- MainModule/Client/Core/Remote.luau | 32 ----- MainModule/Client/Core/UI.luau | 34 +---- MainModule/Server/Commands/Players.luau | 2 +- MainModule/Server/Core/Admin.luau | 29 +--- MainModule/Server/Core/Core.luau | 1 - MainModule/Server/Core/HTTP.luau | 125 ------------------ MainModule/Server/Core/Logs.luau | 7 +- MainModule/Server/Core/Process.luau | 8 -- MainModule/Server/Core/Remote.luau | 2 - .../Dependencies/Assets/ClickTeleport.rbxmx | 8 +- .../Server/Dependencies/Assets/Clipper.rbxmx | 38 +++--- .../Server/Dependencies/Assets/Glitcher.rbxmx | 53 +++----- .../Dependencies/Assets/Illegal.client.luau | 57 ++++---- .../Dependencies/Assets/Quacker.server.luau | 3 +- .../Dependencies/Assets/Seize.client.luau | 2 +- .../Server/Dependencies/Assets/Sfling.rbxmx | 3 +- .../Dependencies/Assets/Spinner.client.luau | 4 +- MainModule/Server/Plugins/Adonis_Agents.luau | 2 + MainModule/Server/Plugins/Anti_Cheat.luau | 5 +- MainModule/Server/Plugins/Cross_Server.luau | 1 - MainModule/Server/Plugins/Debug_Specific.luau | 1 - .../Server/Plugins/FindExistingObjects.luau | 3 +- MainModule/Server/Plugins/Misc_Features.luau | 5 +- .../Server/Plugins/Server-SoftShutdown.luau | 3 +- .../Server/Plugins/Urgent_Messages.luau | 2 - MainModule/Server/Server.luau | 18 +-- MainModule/Server/Shared/Service.luau | 14 -- 33 files changed, 100 insertions(+), 489 deletions(-) diff --git a/.github/build.project.json b/.github/build.project.json index 902d7fdaac..1247ef206f 100644 --- a/.github/build.project.json +++ b/.github/build.project.json @@ -1,13 +1,14 @@ { - "name": "Adonis_Rojo", - "tree": { - "$className": "Folder", - "MainModule": { - "$path": "../MainModule" - }, - "Adonis_Loader": { - "$className": "Model", - "$path": "../Loader" - } - } -} \ No newline at end of file + "name": "Adonis_Rojo", + "emitLegacyScripts": true, + "tree": { + "$className": "Folder", + "MainModule": { + "$path": "../MainModule" + }, + "Adonis_Loader": { + "$className": "Model", + "$path": "../Loader" + } + } +} diff --git a/Loader/Config/init.meta.json b/Loader/Config/init.meta.json index 24b2bc3b5a..eec46840df 100644 --- a/Loader/Config/init.meta.json +++ b/Loader/Config/init.meta.json @@ -1,3 +1,3 @@ { - "className": "Configuration" + "className": "Configuration" } diff --git a/MainModule/Client/Client.luau b/MainModule/Client/Client.luau index 0791c910e3..8c2d7705c1 100644 --- a/MainModule/Client/Client.luau +++ b/MainModule/Client/Client.luau @@ -277,7 +277,6 @@ local LoadModule = function(module, yield, envVars, noEnv) if plugran then if type(plug) == "function" then if yield then - --Pcall(setfenv(plug,GetEnv(getfenv(plug), envVars))) local ran, err = service.TrackTask( `Plugin: {module}`, ((noEnv or isRaw or isValue) and plug) or setfenv(plug, GetEnv(getfenv(plug), envVars)), @@ -288,7 +287,6 @@ local LoadModule = function(module, yield, envVars, noEnv) GetEnv ) else - -- service.Threads.RunTask(`PLUGIN: {module,setfenv(plug,GetEnv(getfenv(plug), envVars))}`) local ran, err = service.TrackTask( `Thread: Plugin: {module}`, ((noEnv or isRaw or isValue) and plug) or setfenv(plug, GetEnv(getfenv(plug), envVars)), diff --git a/MainModule/Client/Core/Core.luau b/MainModule/Client/Core/Core.luau index cf4e57cbf4..4c0d2a50b9 100644 --- a/MainModule/Client/Core/Core.luau +++ b/MainModule/Client/Core/Core.luau @@ -72,37 +72,6 @@ return function(Vargs, GetEnv) --service.Threads.RunTask("_G API Manager",client.Core.StartAPI) end - --[[client = service.ReadOnly(client, { - [client.Variables] = true; - [client.Handlers] = true; - G_API = true; - G_Access = true; - G_Access_Key = true; - G_Access_Perms = true; - Allowed_API_Calls = true; - HelpButtonImage = true; - Finish_Loading = true; - RemoteEvent = true; - ScriptCache = true; - Returns = true; - PendingReturns = true; - EncodeCache = true; - DecodeCache = true; - Received = true; - Sent = true; - Service = true; - Holder = true; - GUIs = true; - LastUpdate = true; - RateLimits = true; - - Init = true; - RunLast = true; - RunAfterInit = true; - RunAfterLoaded = true; - RunAfterPlugins = true; - }, true)--]] - Core.RunLast = nil end diff --git a/MainModule/Client/Core/Functions.luau b/MainModule/Client/Core/Functions.luau index 5b639f20dc..e298cc0800 100644 --- a/MainModule/Client/Core/Functions.luau +++ b/MainModule/Client/Core/Functions.luau @@ -50,37 +50,6 @@ return function(Vargs, GetEnv) end local function RunLast() - --[[client = service.ReadOnly(client, { - [client.Variables] = true; - [client.Handlers] = true; - G_API = true; - G_Access = true; - G_Access_Key = true; - G_Access_Perms = true; - Allowed_API_Calls = true; - HelpButtonImage = true; - Finish_Loading = true; - RemoteEvent = true; - ScriptCache = true; - Returns = true; - PendingReturns = true; - EncodeCache = true; - DecodeCache = true; - Received = true; - Sent = true; - Service = true; - Holder = true; - GUIs = true; - LastUpdate = true; - RateLimits = true; - - Init = true; - RunLast = true; - RunAfterInit = true; - RunAfterLoaded = true; - RunAfterPlugins = true; - }, true)--]] - Functions.RunLast = nil; end diff --git a/MainModule/Client/Core/Process.luau b/MainModule/Client/Core/Process.luau index 1cd734c037..e9b303049c 100644 --- a/MainModule/Client/Core/Process.luau +++ b/MainModule/Client/Core/Process.luau @@ -50,37 +50,6 @@ return function(Vargs, GetEnv) end local function RunLast() - --[[client = service.ReadOnly(client, { - [client.Variables] = true; - [client.Handlers] = true; - G_API = true; - G_Access = true; - G_Access_Key = true; - G_Access_Perms = true; - Allowed_API_Calls = true; - HelpButtonImage = true; - Finish_Loading = true; - RemoteEvent = true; - ScriptCache = true; - Returns = true; - PendingReturns = true; - EncodeCache = true; - DecodeCache = true; - Received = true; - Sent = true; - Service = true; - Holder = true; - GUIs = true; - LastUpdate = true; - RateLimits = true; - - Init = true; - RunLast = true; - RunAfterInit = true; - RunAfterLoaded = true; - RunAfterPlugins = true; - }, true)--]] - Process.RunLast = nil; end @@ -131,7 +100,6 @@ return function(Vargs, GetEnv) local comString = Remote.Decrypt(com,Core.Key) local command = (data.Mode == "Get" and Remote.Returnables[comString]) or Remote.Commands[comString] if command then - --local ran,err = pcall(command, args) --task service.Threads.RunTask(`REMOTE:{comString}`,command,args) local rets = {service.TrackTask(`Remote: {comString}`, command, false, args)} if not rets[1] then logError(rets[2]) @@ -152,10 +120,6 @@ return function(Vargs, GetEnv) if Message and Message ~= "nil" and Message ~= "" and (string.find(Message,":: Adonis ::") or string.find(Message,script.Name) or Script == script) then logError(`{Message} - {Trace}`) end - - --if (Script == nil or (not Trace or Trace == "")) and not (Trace and string.find(Trace,"CoreGui.RobloxGui")) then - --Anti.Detected("log",`Scriptless/Traceless error found. Script: {Script} - Trace: {Trace}`) - --end end; Chat = function(msg) diff --git a/MainModule/Client/Core/Remote.luau b/MainModule/Client/Core/Remote.luau index 4d5a7df68a..110c08766d 100644 --- a/MainModule/Client/Core/Remote.luau +++ b/MainModule/Client/Core/Remote.luau @@ -77,37 +77,6 @@ return function(Vargs, GetEnv) end local function RunLast() - --[[client = service.ReadOnly(client, { - [client.Variables] = true; - [client.Handlers] = true; - G_API = true; - G_Access = true; - G_Access_Key = true; - G_Access_Perms = true; - Allowed_API_Calls = true; - HelpButtonImage = true; - Finish_Loading = true; - RemoteEvent = true; - ScriptCache = true; - Returns = true; - PendingReturns = true; - EncodeCache = true; - DecodeCache = true; - Received = true; - Sent = true; - Service = true; - Holder = true; - GUIs = true; - LastUpdate = true; - RateLimits = true; - - Init = true; - RunLast = true; - RunAfterInit = true; - RunAfterLoaded = true; - RunAfterPlugins = true; - }, true)--]] - Remote.RunLast = nil; end @@ -477,7 +446,6 @@ return function(Vargs, GetEnv) Remote.PendingReturns[key] = true Remote.Send("GetReturn",com,key,...) print(string.format("GETTING RETURNS? %s", tostring(returns))) - --returns = returns or {event:Wait()} waiter.Event:Wait(); print(string.format("WE GOT IT! %s", tostring(returns))) diff --git a/MainModule/Client/Core/UI.luau b/MainModule/Client/Core/UI.luau index 478c6037f0..46c11e93f7 100644 --- a/MainModule/Client/Core/UI.luau +++ b/MainModule/Client/Core/UI.luau @@ -59,36 +59,6 @@ return function(Vargs, GetEnv) end local function RunLast() - --[[client = service.ReadOnly(client, { - [client.Variables] = true; - [client.Handlers] = true; - G_API = true; - G_Access = true; - G_Access_Key = true; - G_Access_Perms = true; - Allowed_API_Calls = true; - HelpButtonImage = true; - Finish_Loading = true; - RemoteEvent = true; - ScriptCache = true; - Returns = true; - PendingReturns = true; - EncodeCache = true; - DecodeCache = true; - Received = true; - Sent = true; - Service = true; - Holder = true; - GUIs = true; - LastUpdate = true; - RateLimits = true; - - Init = true; - RunLast = true; - RunAfterInit = true; - RunAfterLoaded = true; - RunAfterPlugins = true; - }, true)--]] UI.DefaultTheme = Remote.Get("Setting","DefaultTheme"); UI.RunLast = nil; end @@ -194,7 +164,6 @@ return function(Vargs, GetEnv) GetNew = function(theme, name) local foundConfigs = {} local endConfig = {} - local endConfValues = {} local confFolder = Instance.new("Folder") local debounce = false @@ -206,7 +175,7 @@ return function(Vargs, GetEnv) if folder then local baseValue = folder:FindFirstChild("Base_Theme") local baseTheme = baseValue and baseValue.Value - local foundGUI = folder:FindFirstChild(name) --local foundGUI = (baseValue and folder:FindFirstChild(name)) or UIFolder.Default:FindFirstChild(name) + local foundGUI = folder:FindFirstChild(name) if foundGUI then local config = foundGUI:FindFirstChild("Config") @@ -326,7 +295,6 @@ return function(Vargs, GetEnv) end local mult = foundConf.AllowMultiple - --local keep = foundConf.CanKeepAlive local allowMult = mult and mult.Value or true local found, num = UI.Get(name) diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index f817d73245..d65a042d3d 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -973,7 +973,7 @@ return function(Vargs, env) ObjectCount = #Variables.Objects; CameraCount = #Variables.Cameras; NilPlayerCount = nilPlayers; - HttpEnabled = HTTP.CheckHttp(); + HttpEnabled = HTTP.HttpEnabled; LoadstringEnabled = HTTP.LoadstringEnabled; } end diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau index 0707f416ab..fa1050032b 100644 --- a/MainModule/Server/Core/Admin.luau +++ b/MainModule/Server/Core/Admin.luau @@ -285,10 +285,6 @@ return function(Vargs, GetEnv) end end - --[[Settings.HeadAdmins = Settings.Ranks.HeadAdmins.Users; - Settings.Admins = Settings.Ranks.Admins.Users; - Settings.Moderators = Settings.Ranks.Moderators.Users;--]] - if Settings.CustomRanks then local Ranks = Settings.Ranks for name, users in Settings.CustomRanks do @@ -786,10 +782,6 @@ return function(Vargs, GetEnv) local checkTable = Admin.CheckTable local doCheck = Admin.DoCheck - --[[if data and data.AdminLevelOverride then - return data.AdminLevelOverride - end--]] - for _, admin in Admin.SpecialLevels do if doCheck(p, admin.Player) then return admin.Level, admin.Rank @@ -865,13 +857,6 @@ return function(Vargs, GetEnv) Level = level, Rank = rankName } - - --[[if doSave then - local data = Core.GetPlayer(p) - if data then - data.AdminLevelOverride = level; - end - end--]] end elseif level == "Reset" then Admin.SpecialLevels[tostring(p.UserId)] = nil @@ -987,12 +972,10 @@ return function(Vargs, GetEnv) end; CheckDonor = function(p) - --if not Settings.DonorPerks then return false end local key = tostring(p.UserId) if Variables.CachedDonors[key] then return true else - --if p.UserId<0 or (tonumber(p.AccountAge) and tonumber(p.AccountAge)<0) then return false end local pGroup = Admin.GetPlayerGroup(p, 886423) for _, pass in Variables.DonorPass do if p.Parent ~= service.Players then @@ -1059,7 +1042,7 @@ return function(Vargs, GetEnv) BanType = banType } - table.insert(Settings.Banned, value)--`{p.Name}:{p.UserId}` + table.insert(Settings.Banned, value) if doSave then Core.DoSave({ @@ -1185,12 +1168,6 @@ return function(Vargs, GetEnv) local cmdArgs = com.Args or com.Arguments local args = Admin.GetArgs(coma, #cmdArgs, ...) - --local task,ran,error = service.Threads.TimeoutRunTask(`SERVER_COMMAND: {coma}`,com.Function,60*5,false,args) - --[[local ran, error = TrackTask(`Command: {coma}`, com.Function, false, args) - if error then - --logError("SERVER","Command",error) - end]] - TrackTask(`Command: {coma}`, com.Function, function(err) warn(`Encountered an error while running a command: {coma}\n{err}\n{debug.traceback()}`) end, false, args) @@ -1226,8 +1203,6 @@ return function(Vargs, GetEnv) }, } ) - - --local task,ran,error = service.Threads.TimeoutRunTask(`COMMAND:{plr.Name}: {coma}`,com.Function,60*5,plr,args) end end; @@ -1496,7 +1471,6 @@ return function(Vargs, GetEnv) end end - --if not foundPlayerAlias then for alias, cmd in Variables.Aliases do local tAlias = stripArgPlaceholders(alias) if not CheckAliasBlacklist(tAlias) then @@ -1506,7 +1480,6 @@ return function(Vargs, GetEnv) end end end - --end return msg end; diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index 4252e9ab7e..9358ff3cd0 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -511,7 +511,6 @@ return function(Vargs, GetEnv) TrackTask(`Thread: Setup Existing Player: {p}`, function() Process.PlayerAdded(p) - --Core.MakeClient(p:FindFirstChildOfClass("PlayerGui") or p:WaitForChild("PlayerGui", 120)) end) end; diff --git a/MainModule/Server/Core/HTTP.luau b/MainModule/Server/Core/HTTP.luau index cf4a6cecf8..198a90b32b 100644 --- a/MainModule/Server/Core/HTTP.luau +++ b/MainModule/Server/Core/HTTP.luau @@ -30,7 +30,6 @@ return function(Vargs, GetEnv) if Settings.Trello_Enabled then HTTP.Trello.API = require(server.Deps.TrelloAPI)(Settings.Trello_AppKey, Settings.Trello_Token) - service.StartLoop("TRELLO_UPDATER", Settings.HttpWait, HTTP.Trello.Update, true) end HTTP.Init = nil; @@ -52,10 +51,6 @@ return function(Vargs, GetEnv) end)(); LoadstringEnabled = pcall(loadstring, ""); - CheckHttp = function() - return HTTP.HttpEnabled - end; - WebPanel = { Moderators = {}; Admins = {}; @@ -197,126 +192,6 @@ return function(Vargs, GetEnv) } }; - Update = function() - if not HTTP.Trello.API or not Settings.Trello_Enabled then - return; - end - - if not HTTP.CheckHttp() then - warn("Unable to connect to Trello. Make sure HTTP Requests are enabled in Game Settings.") - return; - else - local data = { - Bans = {}; - Mutes = {}; - Music = {}; - Whitelist = {}; - Blacklist = {}; - InsertList = {}; - Agents = {}; - Ranks = { - ["Moderators"] = {}, - ["Admins"] = {}, - ["HeadAdmins"] = {}, - ["Creators"] = {} - }; - } - - local function grabData(board) - local lists: {List} = HTTP.Trello.API.getListsAndCards(board, true) - if #lists == 0 then error("L + ratio") end --TODO: Improve TrelloAPI error handling so we don't need to assume no lists = failed request - - for _, list in lists do - local foundOverride = false - - for _, override in HTTP.Trello.Overrides do - if table.find(override.Lists, list.name) then - foundOverride = true - for _, card in list.cards do - override.Process(card, data) - end - break - end - end - - -- Allow lists for custom ranks - if not foundOverride and not data.Ranks[list.name] then - local rank = Settings.Ranks[list.name] - - if rank and not rank.IsExternal then - local users = {} - for _, card in list.cards do - table.insert(users, card.name) - end - data.Ranks[list.name] = users - end - end - end - end - - local success = true - local boards = { - Settings.Trello_Primary, - unpack(Settings.Trello_Secondary) - } - for i,v in boards do - if not v or service.Trim(v) == "" then - continue - end - local ran, err = pcall(grabData, v) - if not ran then - warn("Unable to reach Trello. Ensure your board IDs, Trello key, and token are all correct. If issue persists, try increasing HttpWait in your Adonis settings.") - success = false - break - end - end - - -- Only replace existing values if all data was fetched successfully - if success then - HTTP.Trello.Bans = data.Bans - HTTP.Trello.Music = data.Music - HTTP.Trello.InsertList = data.InsertList - HTTP.Trello.Mutes = data.Mutes - HTTP.Trello.Agents = data.Agents - - Variables.Blacklist.Lists.Trello = data.Blacklist - Variables.Whitelist.Lists.Trello = data.Whitelist - - --// Clear any custom ranks that were not fetched from Trello - for rank, info in Settings.Ranks do - if rank.IsExternal and not data.Ranks[rank] then - Settings.Ranks[rank] = nil - end - end - - for rank, users in data.Ranks do - local name = string.format("[Trello] %s", server.Functions.Trim(rank)) - Settings.Ranks[name] = { - Level = Settings.Ranks[rank].Level or 1; - Users = users, - IsExternal = true, - Hidden = Settings.Trello_HideRanks; - } - end - - for i, v in service.GetPlayers() do - local isBanned, Reason = Admin.CheckBan(v) - if isBanned then - v:Kick(string.format("%s | Reason: %s", Variables.BanMessage, (Reason or "No reason provided"))) - continue - end - - Admin.UpdateCachedLevel(v) - end - - Logs.AddLog(Logs.Script,{ - Text = "Updated Trello data"; - Desc = "Data was retreived from Trello"; - }) - end - end - end; - GetOverrideLists = function() local lists = {} for _, override in HTTP.Trello.Overrides do diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index ef5ba2b772..1bee9183fc 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -138,13 +138,8 @@ return function(Vargs, GetEnv) return end - local logsToSave = {Logs.Commands} --{} + local logsToSave = {Logs.Commands} local maxLogs = Logs.OldCommandLogsLimit - --local numLogsToSave = 200; --// Save the last X logs from this server - - --for i = #Logs.Commands, i = math.max(#Logs.Commands - numLogsToSave, 1), -1 do - -- table.insert(logsToSave, Logs.Commands[i]); - --end Core.UpdateData("OldCommandLogs", function(oldLogs) if type(oldLogs) == "string" then diff --git a/MainModule/Server/Core/Process.luau b/MainModule/Server/Core/Process.luau index 9c0ba40584..98b3a9871a 100644 --- a/MainModule/Server/Core/Process.luau +++ b/MainModule/Server/Core/Process.luau @@ -957,7 +957,6 @@ return function(Vargs, GetEnv) if Remote.Clients[key] then Remote.Clients[key].FinishedLoading = true if p.Character and p.Character.Parent == workspace then - --service.Threads.TimeoutRunTask(`{p.Name};CharacterAdded`,Process.CharacterAdded,60,p) local ran, err = TrackTask(`{p.Name} CharacterAdded`, Process.CharacterAdded, false, p, p.Character, {FinishedLoading = true}) if not ran then logError(err) @@ -1108,13 +1107,6 @@ return function(Vargs, GetEnv) end end - --// Check muted - --[=[for ind,admin in Settings.Muted do - if Admin.DoCheck(p, admin) then - Remote.LoadCode(p, [[service.StarterGui:SetCoreGuiEnabled("Chat",false) client.Variables.ChatEnabled = false client.Variables.Muted = true]]) - end - end--]=] - task.spawn(Functions.Donor, p) --// Fire added event diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index ececa12a36..5d4563efd3 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -980,7 +980,6 @@ return function(Vargs, GetEnv) PrivateMessage = function(p: Player,args: {[number]: any}) if type(args[1]) ~= "string" then return end - -- 'Reply from '..localplayer.Name,player,localplayer,ReplyBox.Text local target = Variables.PMtickets[args[1]] if target or Admin.CheckAdmin(p) then if target then @@ -1219,7 +1218,6 @@ return function(Vargs, GetEnv) local pEvent = service.Players.PlayerRemoving:Connect(function(plr) if plr == p then event:Fire() end end) task.delay(600, function() if not finished then event:Fire() end end) print(string.format("WAITING FOR RETURN %s", tostring(returns))); - --returns = returns or {event:Wait()} Yield:Wait(); Yield:Destroy(); diff --git a/MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx b/MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx index a80acfcaea..a1602fc675 100644 --- a/MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx +++ b/MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx @@ -33,7 +33,7 @@ local function onButton1Down(mouse) local rootPart = humanoid.RootPart if not rootPart then return end local FlightPos, FlightGyro = rootPart:FindFirstChild("ADONIS_FLIGHT_POSITION"), rootPart:FindFirstChild("ADONIS_FLIGHT_GYRO") - local pos = mouse.Hit.p + local pos = mouse.Hit.Position if FlightPos and FlightGyro then FlightPos.Position = rootPart.Position @@ -41,14 +41,14 @@ local function onButton1Down(mouse) end task.wait() - rootPart:PivotTo(CFrame.new(Vector3.new(pos.x, pos.y + 4, pos.z))) + rootPart:PivotTo(CFrame.new(Vector3.new(pos.X, pos.Y + 4, pos.Z))) if FlightPos and FlightGyro then FlightPos.Position = rootPart.Position FlightGyro.CFrame = rootPart.CFrame end elseif mode == "Walk" then - humanoid:MoveTo(mouse.Hit.p) + humanoid:MoveTo(mouse.Hit.Position) end end @@ -57,7 +57,7 @@ local function rotate() if not rootPart then return end repeat - rootPart:PivotTo(CFrame.new(rootPart.Position, Vector3.new(mouse.Hit.p.X, rootPart.Position.Y, mouse.Hit.p.Z))) + rootPart:PivotTo(CFrame.new(rootPart.Position, Vector3.new(mouse.Hit.Position.X, rootPart.Position.Y, mouse.Hit.Position.Z))) task.wait() until not holding or not use end diff --git a/MainModule/Server/Dependencies/Assets/Clipper.rbxmx b/MainModule/Server/Dependencies/Assets/Clipper.rbxmx index 6aedb2ffe6..71215654e0 100644 --- a/MainModule/Server/Dependencies/Assets/Clipper.rbxmx +++ b/MainModule/Server/Dependencies/Assets/Clipper.rbxmx @@ -15,16 +15,17 @@ -1 diff --git a/MainModule/Server/Dependencies/Assets/Illegal.client.luau b/MainModule/Server/Dependencies/Assets/Illegal.client.luau index 87689ce722..0551a7df11 100644 --- a/MainModule/Server/Dependencies/Assets/Illegal.client.luau +++ b/MainModule/Server/Dependencies/Assets/Illegal.client.luau @@ -1,39 +1,39 @@ local msgs={ { -Msg='We need more..... philosophy... ya know?', +Msg="We need more..... philosophy... ya know?", Color=Enum.ChatColor.Green },{ -Msg='OH MY GOD STOP TRYING TO EAT MY SOUL', +Msg="OH MY GOD STOP TRYING TO EAT MY SOUL", Color=Enum.ChatColor.Red },{ -Msg='I.... CANT.... FEEL.... MY FACE', +Msg="I.... CANT.... FEEL.... MY FACE", Color=Enum.ChatColor.Red },{ -Msg='DO YOU SEE THE TURTLE?!?!', +Msg="DO YOU SEE THE TURTLE?!?!", Color=Enum.ChatColor.Red },{ -Msg='Omg puff the magic dragon!!!!', +Msg="Omg puff the magic dragon!!!!", Color=Enum.ChatColor.Green },{ -Msg='Omg double wat', +Msg="Omg double wat", Color=Enum.ChatColor.Blue },{ -Msg='WHO STOLE MY LEGS', +Msg="WHO STOLE MY LEGS", Color=Enum.ChatColor.Red },{ -Msg='I... I think I might be dead....', +Msg="I... I think I might be dead....", Color=Enum.ChatColor.Blue },{ Msg="I'M GOING TO EAT YOUR FACE", Color=Enum.ChatColor.Red },{ -Msg='Hey... Like... What if, like, listen, are you listening? What if.. like.. earth.. was a ball?', +Msg="Hey... Like... What if, like, listen, are you listening? What if.. like.. earth.. was a ball?", Color=Enum.ChatColor.Green },{ -Msg='WHY IS EVERYBODY TALKING SO LOUD AHHHHHH', +Msg="WHY IS EVERYBODY TALKING SO LOUD AHHHHHH", Color=Enum.ChatColor.Red },{ -Msg='Woooo man do you see the elephent... theres an elephent man..its... PURPLE OHMY GOD ITS A SIGN FROM LIKE THE WARDROBE..', +Msg="Woooo man do you see the elephent... theres an elephent man..its... PURPLE OHMY GOD ITS A SIGN FROM LIKE THE WARDROBE..", Color=Enum.ChatColor.Blue }} @@ -41,10 +41,10 @@ local Chat = game:GetService("Chat") local head = script.Parent.Parent.Head local humanoid = script.Parent.Parent:FindFirstChildOfClass("Humanoid") local torso = script.Parent -local val = Instance.new('StringValue') -val.Parent = head -local old = math.random() +local old = math.huge local stop = false +local val = Instance.new("StringValue") +val.Parent = head humanoid.Died:Connect(function() stop = true @@ -53,22 +53,21 @@ humanoid.Died:Connect(function() end) task.spawn(function() - while not stop and head and val and val.Parent==head do - local new=math.random(1,#msgs) - for k,m in pairs(msgs) do - if new==k then - if old ~= new then - old=new - print(m.Msg) - Chat:Chat(head,m.Msg,m.Color) - end - end + while not stop and head and val and val.Parent == head do + local new = math.random(1, #msgs) + + if old ~= new then + local m = msgs[new] + old = new + print(m.Msg) + Chat:Chat(head, m.Msg, m.Color) end + task.wait(5) end end) -humanoid.WalkSpeed=-16 +humanoid.WalkSpeed = -16 local startspaz = false @@ -76,28 +75,28 @@ task.spawn(function() repeat task.wait(0.1) workspace.CurrentCamera.FieldOfView = math.random(20, 80) - humanoid.Health:TakeDamage(0.5) + humanoid:TakeDamage(0.5) if startspaz then humanoid.PlatformStand = true torso.AssemblyLinearVelocity = Vector3.new(math.random(-10, 10), -5, math.random(-10, 10)) torso.AssemblyAngularVelocity = Vector3.new(math.random(-5, 5), math.random(-5, 5), math.random(-5, 5)) end - until stop or not humanoid or not humanoid.Parent or humanoid.Health<=0 or not torso + until stop or not humanoid or not humanoid.Parent or humanoid.Health <= 0 or not torso end) task.wait(10) local bg = Instance.new("BodyGyro") bg.Name = "SPINNER" -bg.maxTorque = Vector3.new(0,math.huge,0) +bg.maxTorque = Vector3.new(0, math.huge, 0) bg.P = 11111 bg.cframe = torso.CFrame bg.Parent = torso task.spawn(function() repeat task.wait(1/44) - bg.cframe = bg.cframe * CFrame.Angles(0,math.rad(30),0) + bg.cframe *= CFrame.Angles(0, math.rad(30), 0) until stop or not bg or bg.Parent ~= torso end) diff --git a/MainModule/Server/Dependencies/Assets/Quacker.server.luau b/MainModule/Server/Dependencies/Assets/Quacker.server.luau index e16db13f37..5301e27d70 100644 --- a/MainModule/Server/Dependencies/Assets/Quacker.server.luau +++ b/MainModule/Server/Dependencies/Assets/Quacker.server.luau @@ -2,8 +2,7 @@ while true do task.wait(math.random(5, 20)) if script.Parent ~= nil then - local name = `Quack{math.random(1, 4)}` - script.Parent:FindFirstChild(name):Play() + script.Parent:FindFirstChild(`Quack{math.random(1, 4)}`):Play() else break end diff --git a/MainModule/Server/Dependencies/Assets/Seize.client.luau b/MainModule/Server/Dependencies/Assets/Seize.client.luau index 547dfed03f..269ffeef87 100644 --- a/MainModule/Server/Dependencies/Assets/Seize.client.luau +++ b/MainModule/Server/Dependencies/Assets/Seize.client.luau @@ -1,5 +1,5 @@ local root = script.Parent -local humanoid = script.Parent.Parent:FindFirstChildOfClass("Humanoid") +local humanoid = root.Parent:FindFirstChildOfClass("Humanoid") local origvel = root.AssemblyLinearVelocity local origrot = root.AssemblyAngularVelocity diff --git a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx b/MainModule/Server/Dependencies/Assets/Sfling.rbxmx index 69f0912bae..caa6fd505e 100644 --- a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx +++ b/MainModule/Server/Dependencies/Assets/Sfling.rbxmx @@ -18,12 +18,13 @@ local strength = script:WaitForChild("Strength").Value for i = 1, 100 do task.wait(0.1) humanoid.Sit = true - local ex = Instance.new("Explosion", cam) + local ex = Instance.new("Explosion") ex.Position = torso.Position + Vector3.new(math.random(-5, 5), -10, math.random(-5, 5)) ex.BlastRadius = 35 ex.BlastPressure = strength ex.ExplosionType = Enum.ExplosionType.Craters ex.DestroyJointRadiusPercent = 0 + ex.Parent = cam end script:Destroy()]]> -1 diff --git a/MainModule/Server/Dependencies/Assets/Spinner.client.luau b/MainModule/Server/Dependencies/Assets/Spinner.client.luau index c8abb2762b..3a72663733 100644 --- a/MainModule/Server/Dependencies/Assets/Spinner.client.luau +++ b/MainModule/Server/Dependencies/Assets/Spinner.client.luau @@ -1,6 +1,6 @@ local torso = script.Parent local bg = torso:FindFirstChild("ADONIS_SPIN_GYRO") repeat - task.wait(1/44) - bg.CFrame *= CFrame.Angles(0,math.rad(12),0) + task.wait(1/44) + bg.CFrame *= CFrame.Angles(0,math.rad(12),0) until not bg or bg.Parent ~= torso diff --git a/MainModule/Server/Plugins/Adonis_Agents.luau b/MainModule/Server/Plugins/Adonis_Agents.luau index dc5fa198c9..faaf6e6b5b 100644 --- a/MainModule/Server/Plugins/Adonis_Agents.luau +++ b/MainModule/Server/Plugins/Adonis_Agents.luau @@ -51,4 +51,6 @@ return function(Vargs, GetEnv) command.Agent = true end end + + Logs:AddLog("Script", "Adonis Agents module loaded") end diff --git a/MainModule/Server/Plugins/Anti_Cheat.luau b/MainModule/Server/Plugins/Anti_Cheat.luau index d051e4d267..168fb0576d 100644 --- a/MainModule/Server/Plugins/Anti_Cheat.luau +++ b/MainModule/Server/Plugins/Anti_Cheat.luau @@ -1,7 +1,6 @@ --// Anti-Exploit return function(Vargs, GetEnv) - local server = Vargs.Server; local service = Vargs.Service; @@ -23,8 +22,6 @@ return function(Vargs, GetEnv) end local function RunAfterPlugins(data) - Logs:AddLog("Script", "Anti Plugin Module RunAfterPlugins Finished"); - local function onPlayerAdded(player) if not player.Character then player.CharacterAdded:Wait() @@ -33,7 +30,6 @@ return function(Vargs, GetEnv) if Admin.GetLevel(player) < Settings.Ranks.Moderators.Level or Core.DebugMode then Anti.CharacterCheck(player) end - end if not Settings.Detection then @@ -54,6 +50,7 @@ return function(Vargs, GetEnv) end service.Players.PlayerAdded:Connect(onPlayerAdded) + Logs:AddLog("Script", "Anti Plugin Module RunAfterPlugins Finished") end local antiNotificationDebounce, antiNotificationResetTick = {}, os.clock() + 60 diff --git a/MainModule/Server/Plugins/Cross_Server.luau b/MainModule/Server/Plugins/Cross_Server.luau index 9b44cf5302..409b3e34f7 100644 --- a/MainModule/Server/Plugins/Cross_Server.luau +++ b/MainModule/Server/Plugins/Cross_Server.luau @@ -2,7 +2,6 @@ --// This module is for stuff specific to cross server communication --// NOTE: THIS IS NOT A *CONFIG/USER* PLUGIN! ANYTHING IN THE MAINMODULE PLUGIN FOLDERS IS ALREADY PART OF/LOADED BY THE SCRIPT! DO NOT ADD THEM TO YOUR CONFIG>PLUGINS FOLDER! return function(Vargs, GetEnv) - local server = Vargs.Server; local service = Vargs.Service; diff --git a/MainModule/Server/Plugins/Debug_Specific.luau b/MainModule/Server/Plugins/Debug_Specific.luau index 6c0b49c13a..9337518eef 100644 --- a/MainModule/Server/Plugins/Debug_Specific.luau +++ b/MainModule/Server/Plugins/Debug_Specific.luau @@ -4,7 +4,6 @@ --// NOTE: THIS IS NOT A *CONFIG/USER* PLUGIN! ANYTHING IN THE MAINMODULE PLUGIN FOLDERS IS ALREADY PART OF/LOADED BY THE SCRIPT! DO NOT ADD THEM TO YOUR CONFIG>PLUGINS FOLDER! return function(Vargs, GetEnv) - local server = Vargs.Server; local service = Vargs.Service; diff --git a/MainModule/Server/Plugins/FindExistingObjects.luau b/MainModule/Server/Plugins/FindExistingObjects.luau index e027e2c44e..0a6df51b50 100644 --- a/MainModule/Server/Plugins/FindExistingObjects.luau +++ b/MainModule/Server/Plugins/FindExistingObjects.luau @@ -5,7 +5,6 @@ --]] return function(Vargs, GetEnv) - local server = Vargs.Server; local service = Vargs.Service; @@ -31,4 +30,6 @@ return function(Vargs, GetEnv) }) end end + + Logs:AddLog("Script", "Current Adonis objects successfully loaded in to instance lists"); end diff --git a/MainModule/Server/Plugins/Misc_Features.luau b/MainModule/Server/Plugins/Misc_Features.luau index 9736a0fcb3..dea7c71543 100644 --- a/MainModule/Server/Plugins/Misc_Features.luau +++ b/MainModule/Server/Plugins/Misc_Features.luau @@ -47,7 +47,7 @@ return function(Vargs, GetEnv) local Len = (type(pLen) == "number" and pLen) or random(5,10) --// reru local Res = {} for Idx = 1, Len do - Res[Idx] = format('%02x', random(255)) + Res[Idx] = format("%02x", random(255)) end return table.concat(Res) end @@ -64,6 +64,9 @@ return function(Vargs, GetEnv) Variables.Aliases[k] = v end end + HTTP.CheckHttp = function() + return HTTP.HttpEnabled + end Logs:AddLog("Script", "Misc Features Module Loaded") end diff --git a/MainModule/Server/Plugins/Server-SoftShutdown.luau b/MainModule/Server/Plugins/Server-SoftShutdown.luau index 18adbd7c6d..d4fb41e545 100644 --- a/MainModule/Server/Plugins/Server-SoftShutdown.luau +++ b/MainModule/Server/Plugins/Server-SoftShutdown.luau @@ -3,7 +3,6 @@ --// GitHub@Expertcoderz was here to make things look better return function(Vargs, GetEnv) - local server = Vargs.Server local service = Vargs.Service @@ -257,4 +256,6 @@ return function(Vargs, GetEnv) end end } + + Logs:AddLog("Script", "Soft Shutdown Module Loaded"); end diff --git a/MainModule/Server/Plugins/Urgent_Messages.luau b/MainModule/Server/Plugins/Urgent_Messages.luau index aa8339188d..254ca7b2b2 100644 --- a/MainModule/Server/Plugins/Urgent_Messages.luau +++ b/MainModule/Server/Plugins/Urgent_Messages.luau @@ -1,6 +1,4 @@ - return function(Vargs, GetEnv) - local server = Vargs.Server; local service = Vargs.Service; diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index a20cd1e1c9..e4835ebb45 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -195,15 +195,7 @@ local function LoadModule(module, yield, envVars, noEnv, isCore) GetEnv ) return err - - --[[elseif yield then (all pcalls yield by default for a quite a while time now) - --Pcall(setfenv(plug,GetEnv(getfenv(plug), envVars))) - local ran,err = service.TrackTask(`Plugin: {module}`, (noEnv and plug) or setfenv(plug, GetEnv(getfenv(plug), envVars)),function(err) - warn(`Module encountered an error while loading: {module}\n{err}\n{debug.traceback()}`) - end, GetVargTable()) - return err;]] else - --service.Threads.RunTask(`PLUGIN: {module}`,setfenv(plug,GetEnv(getfenv(plug), envVars))) local ran, err = service.TrackTask( `Plugin: {module}`, ((noEnv or isRaw or isValue) and plug) or setfenv(plug, GetEnv(getfenv(plug), envVars)), @@ -254,11 +246,7 @@ local function LoadPackage(package, folder, runNow) end; local function CleanUp() - --local env = getfenv(2) - --local ran,ret = pcall(function() return env.script:GetFullName() end) print("Beginning Adonis cleanup & shutdown process...") - --warn(`CleanUp called from {tostring((ran and ret) or "Unknown")}`) - --local loader = server.Core.ClientLoader local data = service.UnWrap(server.Data) if type(data) == "table" and typeof(service.UnWrap(data.Config)) == "Instance" then local Settings: ModuleScript = service.UnWrap(data.Config):FindFirstChild("Settings") @@ -285,9 +273,6 @@ local function CleanUp() table.remove(RbxEvents, i) end end) - --loader.Archivable = false - --loader.Disabled = true - --loader:Destroy() if server.Core and server.Core.RemoteEvent then pcall(server.Core.DisconnectEvent) end @@ -644,7 +629,6 @@ return service.NewProxy({ }) end - --// Load services for ind, serv in ipairs(SERVICES_WE_USE) do local temp = service[serv] @@ -723,7 +707,7 @@ return service.NewProxy({ local code = Instance.new("StringValue") code.Name = service.HttpService:GenerateGUID(false) - code.Value = server.Functions.Base64Encode(module:sub(1, 4) == "\27Lua" or server.Core.Bytecode(module)) + code.Value = server.Functions.Base64Encode(module:sub(1, 4) == "\27Lua" or server.Core.Bytecode(module)) code.Parent = server.Client.Plugins end end diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index 40239f35ea..b85ea9b9a7 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -1269,26 +1269,12 @@ return function(errorHandler, eventChecker, fenceSpecific, env) tab.Kill = kill RunningLoops[index] = tab - if noYield then service.TrackTask(`Thread: Loop: {name}`, loop, false) else service.TrackTask(`Loop: {name}`, loop, false) end - --[[local task = service.Threads.RunTask(`LOOP:{name}`, loop) - - if not noYield then - task.Finished:wait() - kill() - end--]] - - --[[if noYield then - Routine(loop) - else - loop() - end--]] - return tab end; StopLoop = function(name) From 22dff415114d2348f1951c10f1fa8a16d7ed7847 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:39:32 +0300 Subject: [PATCH 024/189] Move Trello commands to a plugin (#1624) * Create Trello.luau * Remove Remote.Commands.TrelloOperation * Remove Trello commands * Remove Trello commands * Remove Trello commands * Move Trello functions to plugin * Move Trello functions to plugin --- MainModule/Server/Commands/Admins.luau | 44 --- MainModule/Server/Commands/HeadAdmins.luau | 51 ---- MainModule/Server/Commands/Moderators.luau | 34 --- MainModule/Server/Core/Remote.luau | 37 --- MainModule/Server/Plugins/Trello.luau | 303 +++++++++++++++++++++ 5 files changed, 303 insertions(+), 166 deletions(-) create mode 100644 MainModule/Server/Plugins/Trello.luau diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index ba310f7329..dd12dd9099 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -1384,50 +1384,6 @@ return function(Vargs, env) end }; - TrelloBan = { - Prefix = Settings.Prefix; - Commands = {"trelloban"}; - Args = {"player/user", "reason"}; - Description = "Adds a user to the Trello ban list (Trello needs to be configured)"; - Filter = true; - CrossServerDenied = true; - TrelloRequired = true; - AdminLevel = "Admins"; - Function = function(plr: Player, args: {string}, data: {any}) - local trello = HTTP.Trello.API - if not Settings.Trello_Enabled or trello == nil then - Functions.Notification("Trelloban", "Trello has not been configured.", {plr}, 10, "MatIcon://Description") - return - end - - local lists = trello.getLists(Settings.Trello_Primary) - local list = trello.getListObj(lists, {"Banlist", "Ban List", "Bans"}) - - local level = data.PlayerData.Level - local reason = string.format("Administrator: %s\nReason: %s", service.FormatPlayer(plr), (args[2] or "N/A")) - - for _, v in service.GetPlayers(plr, args[1], { - IsKicking = true; - NoFakePlayer = false; - }) - do - if level > Admin.GetLevel(v) then - trello.makeCard( - list.id, - string.format("%s:%d", (v and tostring(v.Name) or tostring(v)), v.UserId), - reason - ) - - pcall(function() v:Kick(reason) end) - Functions.LogAdminAction(plr, "Trello Ban", v.Name, `Reason: {args[2] or "N/A"}`) - Functions.Notification("Notification", `Trello-banned {service.FormatPlayer(v, true)}`, {plr}, 5, "MatIcons://Gavel") - end - end - - HTTP.Trello.Update() - end; - }; - BanMenu = { Prefix = Settings.Prefix; Commands = {"banmenu"}; diff --git a/MainModule/Server/Commands/HeadAdmins.luau b/MainModule/Server/Commands/HeadAdmins.luau index 7d25965f59..af7e8622ed 100644 --- a/MainModule/Server/Commands/HeadAdmins.luau +++ b/MainModule/Server/Commands/HeadAdmins.luau @@ -244,57 +244,6 @@ return function(Vargs, env) end; }; - MakeList = { - Prefix = Settings.Prefix; - Commands = {"makelist", "newlist", "newtrellolist", "maketrellolist"}; - Args = {"name"}; - Description = "Adds a list to the Trello board set in Settings. AppKey and Token MUST be set and have write perms for this to work."; - TrelloRequired = true; - AdminLevel = "HeadAdmins"; - Function = function(plr: Player, args: {string}) - assert(args[1], "You need to supply a list name.") - - local trello = HTTP.Trello.API - if not Settings.Trello_Enabled or trello == nil then return Functions.Hint('Trello has not been configured in settings', {plr}) end - - local list = trello.Boards.MakeList(Settings.Trello_Primary, args[1]) - Functions.Hint(`Made list {list.name}`, {plr}) - end - }; - - ViewList = { - Prefix = Settings.Prefix; - Commands = {"viewlist", "viewtrellolist"}; - Args = {"name"}; - Description = "Views the specified Trello list from the primary board set in Settings."; - TrelloRequired = true; - AdminLevel = "HeadAdmins"; - Function = function(plr: Player, args: {string}) - local trello = HTTP.Trello.API - if not Settings.Trello_Enabled or trello == nil then return Functions.Hint('Trello has not been configured in settings', {plr}) end - local list = assert(trello.Boards.GetList(Settings.Trello_Primary, assert(args[1], "Enter a valid list name")), "List not found.") - - local cards = trello.Lists.GetCards(list.id) - local temp = table.create(#cards) - for _, v in cards do - table.insert(temp, {Text = v.name, Desc = v.desc}) - end - Remote.MakeGui(plr, "List", {Title = list.name; Tab = temp}) - end - }; - - MakeCard = { - Prefix = Settings.Prefix; - Commands = {"makecard", "maketrellocard", "createcard"}; - Args = {}; - Description = "Opens a gui to make new Trello cards. AppKey and Token MUST be set and have write perms for this to work."; - TrelloRequired = true; - AdminLevel = "HeadAdmins"; - Function = function(plr: Player, args: {string}) - Remote.MakeGui(plr, "CreateCard") - end - }; - FullClear = { Prefix = Settings.Prefix; Commands = {"fullclear", "clearinstances", "fullclr"}; diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index ba67a168cb..d62a1eed11 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -1168,40 +1168,6 @@ return function(Vargs, env) end }; - ShowTrelloBansList = { - Prefix = Settings.Prefix; - Commands = {"trellobans", "trellobanlist", "syncedtrellobans", "showtrellobans"}; - Args = {}; - Description = "Shows bans synced from Trello."; - TrelloRequired = true; - AdminLevel = "Moderators"; - ListUpdater = function(plr: Player) - local tab = table.create(#HTTP.Trello.Bans) - for _, banData in HTTP.Trello.Bans do - table.insert(tab, { - Text = banData.Name, - Desc = banData.Reason or "No reason specified", - }) - end - table.insert(tab, 1, `# Banned Users: {#HTTP.Trello.Bans}`) - table.insert(tab, 2, "―――――――――――――――――――――――") - return tab - end; - Function = function(plr: Player, args: {string}) - local trello = HTTP.Trello.API - if not Settings.Trello_Enabled or trello == nil then - Functions.Notification("Trello Synced Ban List", "Trello has not been enabled.", {plr}) - else - Remote.MakeGui(plr, "List", { - Title = "Trello Synced Bans List"; - Icon = server.MatIcons.Gavel; - Tab = Logs.ListUpdaters.ShowTrelloBansList(plr); - Update = "ShowTrelloBansList"; - }) - end - end; - }; - HandTo = { Prefix = Settings.Prefix; Commands = {"handto"}; diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index 5d4563efd3..9319b84eb3 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -895,43 +895,6 @@ return function(Vargs, GetEnv) end end; - TrelloOperation = function(p: Player, args: {[number]: any}) - local adminLevel = Admin.GetLevel(p) - - local data = args[1] - if data.Action == "MakeCard" then - local command = Commands.MakeCard - if command and Admin.CheckComLevel(adminLevel, command.AdminLevel) then - local trello = HTTP.Trello.API - - local listName = data.List - local name = data.Name - local desc = data.Desc - - for _, overrideList in HTTP.Trello.GetOverrideLists() do - if service.Trim(string.lower(overrideList)) == service.Trim(string.lower(listName)) then - Functions.Hint("You cannot create a card in that list", {p}) - return - end - end - - local lists = trello.getLists(Settings.Trello_Primary) - local list = trello.getListObj(lists, listName) - if list then - local card = trello.makeCard(list.id, name, desc) - Functions.Hint(`Made card "{card.name}" in list "{list.name}"`, {p}) - Logs.AddLog(Logs.Script,{ - Text = `{p} performed Trello operation`; - Desc = "Player created a Trello card"; - Player = p; - }) - else - Functions.Hint(`"{listName}" does not exist"`, {p}) - end - end - end - end; - ClientLoaded = function(p: Player, args: {[number]: any}) local key = tostring(p.UserId) local client = Remote.Clients[key] diff --git a/MainModule/Server/Plugins/Trello.luau b/MainModule/Server/Plugins/Trello.luau new file mode 100644 index 0000000000..50a6112c3d --- /dev/null +++ b/MainModule/Server/Plugins/Trello.luau @@ -0,0 +1,303 @@ +return function(Vargs, GetEnv) + local server = Vargs.Server; + local service = Vargs.Service; + + local Settings = server.Settings + local Functions, Commands, Admin, Anti, Core, HTTP, Logs, Remote, Process, Variables, Deps = + server.Functions, server.Commands, server.Admin, server.Anti, server.Core, server.HTTP, server.Logs, server.Remote, server.Process, server.Variables, server.Deps + + HTTP.Trello.Update = function() + if not HTTP.Trello.API or not Settings.Trello_Enabled then + return + end + + if not HTTP.HttpEnabled then + warn("Unable to connect to Trello. Make sure HTTP Requests are enabled in Game Settings.") + return + else + local data = { + Bans = {}; + Mutes = {}; + Music = {}; + Whitelist = {}; + Blacklist = {}; + InsertList = {}; + Agents = {}; + Ranks = { + ["Moderators"] = {}, + ["Admins"] = {}, + ["HeadAdmins"] = {}, + ["Creators"] = {} + }; + } + + local function grabData(board) + local lists: {List} = HTTP.Trello.API.getListsAndCards(board, true) + if #lists == 0 then error("L + ratio") end --TODO: Improve TrelloAPI error handling so we don't need to assume no lists = failed request + + for _, list in lists do + local foundOverride = false + + for _, override in HTTP.Trello.Overrides do + if table.find(override.Lists, list.name) then + foundOverride = true + for _, card in list.cards do + override.Process(card, data) + end + break + end + end + + -- Allow lists for custom ranks + if not foundOverride and not data.Ranks[list.name] then + local rank = Settings.Ranks[list.name] + + if rank and not rank.IsExternal then + local users = {} + for _, card in list.cards do + table.insert(users, card.name) + end + data.Ranks[list.name] = users + end + end + end + end + + local success = true + local boards = { + Settings.Trello_Primary, + unpack(Settings.Trello_Secondary) + } + for i,v in boards do + if not v or service.Trim(v) == "" then + continue + end + local ran, err = pcall(grabData, v) + if not ran then + warn("Unable to reach Trello. Ensure your board IDs, Trello key, and token are all correct. If issue persists, try increasing HttpWait in your Adonis settings.") + success = false + break + end + end + + -- Only replace existing values if all data was fetched successfully + if success then + HTTP.Trello.Bans = data.Bans + HTTP.Trello.Music = data.Music + HTTP.Trello.InsertList = data.InsertList + HTTP.Trello.Mutes = data.Mutes + HTTP.Trello.Agents = data.Agents + + Variables.Blacklist.Lists.Trello = data.Blacklist + Variables.Whitelist.Lists.Trello = data.Whitelist + + --// Clear any custom ranks that were not fetched from Trello + for rank, info in Settings.Ranks do + if rank.IsExternal and not data.Ranks[rank] then + Settings.Ranks[rank] = nil + end + end + + for rank, users in data.Ranks do + local name = string.format("[Trello] %s", server.Functions.Trim(rank)) + Settings.Ranks[name] = { + Level = Settings.Ranks[rank].Level or 1; + Users = users, + IsExternal = true, + Hidden = Settings.Trello_HideRanks; + } + end + + for i, v in service.GetPlayers() do + local isBanned, Reason = Admin.CheckBan(v) + if isBanned then + v:Kick(string.format("%s | Reason: %s", Variables.BanMessage, (Reason or "No reason provided"))) + continue + end + + Admin.UpdateCachedLevel(v) + end + + Logs.AddLog(Logs.Script,{ + Text = "Updated Trello data"; + Desc = "Data was retreived from Trello"; + }) + end + end + end + + Remote.Commands.TrelloOperation = function(p: Player, args: {[number]: any}) + local adminLevel = Admin.GetLevel(p) + + local data = args[1] + if data.Action == "MakeCard" then + local command = Commands.MakeCard + if command and Admin.CheckComLevel(adminLevel, command.AdminLevel) then + local trello = HTTP.Trello.API + + local listName = data.List + local name = data.Name + local desc = data.Desc + + for _, overrideList in HTTP.Trello.GetOverrideLists() do + if service.Trim(string.lower(overrideList)) == service.Trim(string.lower(listName)) then + Functions.Hint("You cannot create a card in that list", {p}) + return + end + end + + local lists = trello.getLists(Settings.Trello_Primary) + local list = trello.getListObj(lists, listName) + if list then + local card = trello.makeCard(list.id, name, desc) + Functions.Hint(`Made card "{card.name}" in list "{list.name}"`, {p}) + Logs.AddLog(Logs.Script,{ + Text = `{p} performed Trello operation`; + Desc = "Player created a Trello card"; + Player = p; + }) + else + Functions.Hint(`"{listName}" does not exist"`, {p}) + end + end + end + end + + -- // Moderator commands + Commands.ShowTrelloBansList = { + Prefix = Settings.Prefix; + Commands = {"trellobans", "trellobanlist", "syncedtrellobans", "showtrellobans"}; + Args = {}; + Description = "Shows bans synced from Trello."; + TrelloRequired = true; + AdminLevel = "Moderators"; + ListUpdater = function(plr: Player) + local tab = table.create(#HTTP.Trello.Bans) + for _, banData in HTTP.Trello.Bans do + table.insert(tab, { + Text = banData.Name, + Desc = banData.Reason or "No reason specified", + }) + end + table.insert(tab, 1, `# Banned Users: {#HTTP.Trello.Bans}`) + table.insert(tab, 2, "―――――――――――――――――――――――") + return tab + end; + Function = function(plr: Player, args: {string}) + local trello = HTTP.Trello.API + if not Settings.Trello_Enabled or trello == nil then + Functions.Notification("Trello Synced Ban List", "Trello has not been enabled.", {plr}) + else + Remote.MakeGui(plr, "List", { + Title = "Trello Synced Bans List"; + Icon = server.MatIcons.Gavel; + Tab = Logs.ListUpdaters.ShowTrelloBansList(plr); + Update = "ShowTrelloBansList"; + }) + end + end; + } + + -- // Admin commands + Commands.TrelloBan = { + Prefix = Settings.Prefix; + Commands = {"trelloban"}; + Args = {"player/user", "reason"}; + Description = "Adds a user to the Trello ban list (Trello needs to be configured)"; + Filter = true; + CrossServerDenied = true; + TrelloRequired = true; + AdminLevel = "Admins"; + Function = function(plr: Player, args: {string}, data: {any}) + local trello = HTTP.Trello.API + if not Settings.Trello_Enabled or trello == nil then + Functions.Notification("Trelloban", "Trello has not been configured.", {plr}, 10, "MatIcon://Description") + return + end + + local lists = trello.getLists(Settings.Trello_Primary) + local list = trello.getListObj(lists, {"Banlist", "Ban List", "Bans"}) + + local level = data.PlayerData.Level + local reason = string.format("Administrator: %s\nReason: %s", service.FormatPlayer(plr), (args[2] or "N/A")) + + for _, v in service.GetPlayers(plr, args[1], { + IsKicking = true; + NoFakePlayer = false; + }) + do + if level > Admin.GetLevel(v) then + trello.makeCard( + list.id, + string.format("%s:%d", (v and tostring(v.Name) or tostring(v)), v.UserId), + reason + ) + + pcall(function() v:Kick(reason) end) + Functions.LogAdminAction(plr, "Trello Ban", v.Name, `Reason: {args[2] or "N/A"}`) + Functions.Notification("Notification", `Trello-banned {service.FormatPlayer(v, true)}`, {plr}, 5, "MatIcons://Gavel") + end + end + + HTTP.Trello.Update() + end; + } + + -- // HeadAdmin commands + Commands.MakeList = { + Prefix = Settings.Prefix; + Commands = {"makelist", "newlist", "newtrellolist", "maketrellolist"}; + Args = {"name"}; + Description = "Adds a list to the Trello board set in Settings. AppKey and Token MUST be set and have write perms for this to work."; + TrelloRequired = true; + AdminLevel = "HeadAdmins"; + Function = function(plr: Player, args: {string}) + assert(args[1], "You need to supply a list name.") + + local trello = HTTP.Trello.API + if not Settings.Trello_Enabled or trello == nil then return Functions.Hint('Trello has not been configured in settings', {plr}) end + + local list = trello.Boards.MakeList(Settings.Trello_Primary, args[1]) + Functions.Hint(`Made list {list.name}`, {plr}) + end + } + + Commands.ViewList = { + Prefix = Settings.Prefix; + Commands = {"viewlist", "viewtrellolist"}; + Args = {"name"}; + Description = "Views the specified Trello list from the primary board set in Settings."; + TrelloRequired = true; + AdminLevel = "HeadAdmins"; + Function = function(plr: Player, args: {string}) + local trello = HTTP.Trello.API + if not Settings.Trello_Enabled or trello == nil then return Functions.Hint('Trello has not been configured in settings', {plr}) end + local list = assert(trello.Boards.GetList(Settings.Trello_Primary, assert(args[1], "Enter a valid list name")), "List not found.") + + local cards = trello.Lists.GetCards(list.id) + local temp = table.create(#cards) + for _, v in cards do + table.insert(temp, {Text = v.name, Desc = v.desc}) + end + Remote.MakeGui(plr, "List", {Title = list.name; Tab = temp}) + end + } + + Commands.MakeCard = { + Prefix = Settings.Prefix; + Commands = {"makecard", "maketrellocard", "createcard"}; + Args = {}; + Description = "Opens a gui to make new Trello cards. AppKey and Token MUST be set and have write perms for this to work."; + TrelloRequired = true; + AdminLevel = "HeadAdmins"; + Function = function(plr: Player, args: {string}) + Remote.MakeGui(plr, "CreateCard") + end + } + + -- // Initialization + if Settings.Trello_Enabled then + service.StartLoop("TRELLO_UPDATER", Settings.HttpWait, HTTP.Trello.Update, true) + end + Logs:AddLog("Script", "Trello Module Loaded") +end From 683546f5ae9f45572772ff96984d4c28e427b1f2 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:40:11 +0300 Subject: [PATCH 025/189] Remove unnecessary table.isfrozen check (#1627) * Remove unnecessary check * Remove unnecessary check * Remove unnecessary check * Remove unnecessary metatable lock check --- MainModule/Client/Core/Core.luau | 4 ++-- MainModule/Server/Core/Core.luau | 4 ++-- MainModule/Server/Dependencies/RebootHandler.rbxmx | 2 +- MainModule/Server/Shared/FiOne.luau | 9 +-------- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/MainModule/Client/Core/Core.luau b/MainModule/Client/Core/Core.luau index 4c0d2a50b9..e20b40b8e3 100644 --- a/MainModule/Client/Core/Core.luau +++ b/MainModule/Client/Core/Core.luau @@ -376,11 +376,11 @@ return function(Vargs, GetEnv) }) if not rawget(_G, "Adonis") then - if table.isfrozen and not table.isfrozen(_G) or not table.isfrozen then + if not table.isfrozen(_G) then rawset(_G, "Adonis", AdonisGTable) StartLoop("APICheck", 1, function() if rawget(_G, "Adonis") ~= AdonisGTable then - if table.isfrozen and not table.isfrozen(_G) or not table.isfrozen then + if not table.isfrozen(_G) then rawset(_G, "Adonis", AdonisGTable) else warn("⚠️ ADONIS CRITICAL WARNING! MALICIOUS CODE IS TRYING TO CHANGE THE ADONIS _G API AND IT CAN'T BE SET BACK! PLEASE SHUTDOWN THE SERVER AND REMOVE THE MALICIOUS CODE IF POSSIBLE! 0x02412") diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index 9358ff3cd0..8875a7838b 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -1585,11 +1585,11 @@ return function(Vargs, GetEnv) }) if not rawget(_G, "Adonis") then - if table.isfrozen and not table.isfrozen(_G) or not table.isfrozen then + if not table.isfrozen(_G) then rawset(_G, "Adonis", AdonisGTable) StartLoop("APICheck", 1, function() if rawget(_G, "Adonis") ~= AdonisGTable then - if table.isfrozen and not table.isfrozen(_G) or not table.isfrozen then + if not table.isfrozen(_G) then rawset(_G, "Adonis", AdonisGTable) else warn("⚠️ ADONIS CRITICAL WARNING! MALICIOUS CODE IS TRYING TO CHANGE THE ADONIS _G API AND IT CAN'T BE SET BACK! PLEASE SHUTDOWN THE SERVER AND REMOVE THE MALICIOUS CODE IF POSSIBLE!") diff --git a/MainModule/Server/Dependencies/RebootHandler.rbxmx b/MainModule/Server/Dependencies/RebootHandler.rbxmx index a2303b43d8..02ee5ff485 100644 --- a/MainModule/Server/Dependencies/RebootHandler.rbxmx +++ b/MainModule/Server/Dependencies/RebootHandler.rbxmx @@ -36,7 +36,7 @@ warn("CLEANING") - if table.isfrozen and not table.isfrozen(_G) or not table.isfrozen then + if not table.isfrozen(_G) then rawset(_G, 'Adonis', nil) rawset(_G, '__Adonis_MODULE_MUTEX', nil) rawset(_G, '__Adonis_MUTEX', nil) diff --git a/MainModule/Server/Shared/FiOne.luau b/MainModule/Server/Shared/FiOne.luau index 8cb0541f7b..34e19467b5 100644 --- a/MainModule/Server/Shared/FiOne.luau +++ b/MainModule/Server/Shared/FiOne.luau @@ -939,14 +939,7 @@ local function run_lua_func(state, env, upvals) -- // ccuser44 added support for generic iteration -- (Please don't use general iteration in vanilla Lua code) if not index and not state and type(func) == "table" then - -- Hacky check to see if __metatable is locked - local canGetMt = pcall(getmetatable, func) - local isMtLocked = canGetMt and not pcall(setmetatable, func, getmetatable(func)) or not canGetMt - local metatable = canGetMt and getmetatable(func) - - if not (table.isfrozen and table.isfrozen(func)) and isMtLocked and not metatable then - warn("[FiOne]: The table has a metatable buts it's hidden, __iter and __call won't work in forloop.") - end + local metatable = pcall(getmetatable, func) and getmetatable(func) if not (type(metatable) == "table" and rawget(metatable, "__call")) then func, state, index = (type(metatable) == "table" and rawget(metatable, "__iter") or next), func, nil From 9ce9741f3077516663e50f2eefdbaa36ff170dc7 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:48:23 +0300 Subject: [PATCH 026/189] Fix leap year handling (#1629) --- MainModule/Client/UI/Default/Profile.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Client/UI/Default/Profile.luau b/MainModule/Client/UI/Default/Profile.luau index c08b8bc5ce..46058fb9f4 100644 --- a/MainModule/Client/UI/Default/Profile.luau +++ b/MainModule/Client/UI/Default/Profile.luau @@ -87,7 +87,7 @@ return function(data, env) {"Display Name", player.DisplayName, "The player's custom display name"}, {"Username", player.Name, "The player's unique Roblox username"}, {"User ID", player.UserId, "The player's unique Roblox user ID"}, - {"Acc. Age", `{player.AccountAge} days ({string.format("%.2f", player.AccountAge/365)} years)`, "How long the player has been registered on Roblox"}, + {"Acc. Age", `{player.AccountAge} days ({string.format("%.2f", player.AccountAge/365.25)} years)`, "How long the player has been registered on Roblox"}, }) do generaltab:Add("TextLabel", { Text = ` {v[1]}: `; From c75fe7c0b48de8eb98f23b89e62af8a1355739f5 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:41:33 +0100 Subject: [PATCH 027/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 55cdfc0460..2f9c0fa2ad 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -23,6 +23,11 @@ return { "(Git/PurpleCreativity) Prevent Anti.RemovePlayer from kicking if in studio (#1605)"; "(Git/ccuser44) Make HTTP constant URLs to Variables (#1618)"; "(Git/ccuser44) Convert README XML to Lua (#1619)"; + "(Git/ccuser44) Remove service.CloneTable (#1628)"; + "(Git/ccuser44) Remove bloat & Fix stuff (#1623)"; + "(Git/ccuser44) Move Trello commands to a plugin (#1624)"; + "(Git/ccuser44) Remove unnecessary table.isfrozen check (#1627)"; + "(Git/ccuser44) Fix leap year handling (#1629)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From a906d3e49e1f9c317f46a3dedbfebd77cbcf90ee Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 19 Oct 2024 18:02:49 +0300 Subject: [PATCH 028/189] Move rank backwards compatibility to plugin and remove junk (#1630) * Remove redundant code and move backwards compatibility * Move legacy rank compatibility to plugin --- MainModule/Server/Core/Admin.luau | 47 -------------------- MainModule/Server/Plugins/Misc_Features.luau | 6 +++ 2 files changed, 6 insertions(+), 47 deletions(-) diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau index fa1050032b..68d173ad5c 100644 --- a/MainModule/Server/Core/Admin.luau +++ b/MainModule/Server/Core/Admin.luau @@ -278,13 +278,6 @@ return function(Vargs, GetEnv) end end - --// Old settings/plugins backwards compatibility - for _, rank in {"Owners", "HeadAdmins", "Admins", "Moderators", "Creators"} do - if Settings[rank] then - Settings.Ranks[if rank == "Owners" then "HeadAdmins" else rank].Users = Settings[rank] - end - end - if Settings.CustomRanks then local Ranks = Settings.Ranks for name, users in Settings.CustomRanks do @@ -317,46 +310,6 @@ return function(Vargs, GetEnv) end end - if Settings.CommandCooldowns then - for cmdName, cooldownData in Settings.CommandCooldowns do - local realCmd = Admin.GetCommand(cmdName) - - if realCmd then - if cooldownData.Player then - realCmd.PlayerCooldown = cooldownData.Player - end - - if cooldownData.Server then - realCmd.ServerCooldown = cooldownData.Server - end - - if cooldownData.Cross then - realCmd.CrossCooldown = cooldownData.Cross - end - end - end - end - - if Settings.CommandCooldowns then - for cmdName, cooldownData in pairs(Settings.CommandCooldowns) do - local realCmd = Admin.GetCommand(cmdName) - - if realCmd then - if cooldownData.Player then - realCmd.PlayerCooldown = cooldownData.Player - end - - if cooldownData.Server then - realCmd.ServerCooldown = cooldownData.Server - end - - if cooldownData.Cross then - realCmd.CrossCooldown = cooldownData.Cross - end - end - end - end - Admin.Init = nil; AddLog("Script", "Admin Module Initialized") end; diff --git a/MainModule/Server/Plugins/Misc_Features.luau b/MainModule/Server/Plugins/Misc_Features.luau index dea7c71543..159d30ed0f 100644 --- a/MainModule/Server/Plugins/Misc_Features.luau +++ b/MainModule/Server/Plugins/Misc_Features.luau @@ -54,6 +54,12 @@ return function(Vargs, GetEnv) if HTTP.Trello.API then HTTP.Trello.API.GenerateRequestID = Functions.GetRandom end + --// Old settings/plugins backwards compatibility + for _, rank in {"Owners", "HeadAdmins", "Admins", "Moderators", "Creators"} do + if Settings[rank] and not Settings.CustomRanks[rank] then + Settings.Ranks[if rank == "Owners" then "HeadAdmins" else rank].Users = Settings[rank] + end + end for k, v in {-- Legacy aliases [":giveppoints "] = ":script local Players = game:GetService(\"Players\") for _, v in ipairs(_G.Adonis.GetPlayers(Players:GetPlayers()[math.random(1, #Players:GetPlayers())], \"\")) do game:GetService(\"PointsService\"):AwardPoints(v.UserId, ) end", [":giveplayerpoints "] = ":script local Players = game:GetService(\"Players\") for _, v in ipairs(_G.Adonis.GetPlayers(Players:GetPlayers()[math.random(1, #Players:GetPlayers())], \"\")) do game:GetService(\"PointsService\"):AwardPoints(v.UserId, ) end", From 577a7e89194214a289d3605f276352a3bbc8f889 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 19 Oct 2024 18:12:59 +0300 Subject: [PATCH 029/189] Lock server on soft shutdown after 1 minute (#1638) * Lock server on soft shutdown * Only serverlock after 1 minute --- MainModule/Server/Plugins/Server-SoftShutdown.luau | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Plugins/Server-SoftShutdown.luau b/MainModule/Server/Plugins/Server-SoftShutdown.luau index d4fb41e545..d04f28ce49 100644 --- a/MainModule/Server/Plugins/Server-SoftShutdown.luau +++ b/MainModule/Server/Plugins/Server-SoftShutdown.luau @@ -84,6 +84,7 @@ return function(Vargs, GetEnv) TeleportService:TeleportToPlaceInstance(game.PlaceId, jobid, player, "", {[PARAMETER_2_NAME] = true}) end end) + for _, player in service.Players:GetPlayers() do teleport(player) end @@ -119,6 +120,9 @@ return function(Vargs, GetEnv) teleportedPlayers[player] = 1 TeleportService:TeleportToPrivateServer(game.PlaceId, newserver, { player }, "", {[PARAMETER_NAME] = true}) end) + task.delay(60, function() + Variables.ServerLock = true + end) while #Players:GetPlayers() > 0 do Players.PlayerRemoving:Wait() @@ -162,7 +166,6 @@ return function(Vargs, GetEnv) end) end - local newserver = TeleportService:ReserveServer(game.PlaceId) Functions.Message("Adonis", "Server Restart", "The server is restarting, please wait...", 'MatIcon://Hourglass empty', service.GetPlayers(), false, 1000) @@ -179,6 +182,9 @@ return function(Vargs, GetEnv) teleportedPlayers[player] = 1 TeleportService:TeleportToPrivateServer(game.PlaceId, newserver, { player }, "", {[PARAMETER_NAME] = true}) end) + task.delay(60, function() + Variables.ServerLock = true + end) while #Players:GetPlayers() > 0 do Players.PlayerRemoving:Wait() From c08f554d9c48b080737a28324a038c54b0f4618f Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 19 Oct 2024 18:14:33 +0300 Subject: [PATCH 030/189] Fix pof handler not understanding all messages (#1636) * Fix pof handler not understanding all messages * Update checkout --- .github/workflows/pof_handler.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pof_handler.yml b/.github/workflows/pof_handler.yml index 08e571da31..5cec0f9aca 100644 --- a/.github/workflows/pof_handler.yml +++ b/.github/workflows/pof_handler.yml @@ -13,14 +13,14 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.2.1 - name: Check comment and image run: | comment_body=$(jq -r '.comment.body' "$GITHUB_EVENT_PATH") comment_body_lowercase=$(echo $comment_body | awk '{print tolower($0)}') - if [[ $comment_body_lowercase =~ "(p\-?o\-?f|proof[-_\s]*of[-_\s]*work)\:?.*\!\[.*\]\(.+\)" ]]; then + if [[ $comment_body_lowercase =~ "(p\-?o\-?f|proof[\-_\s]*of[\-_\s]*work)\:?[\r\n]*.*(\!\[.*\]\(.+\)|\> $GITHUB_OUTPUT else From 4265a4177d0a5cd521efce4434f3a3bd9c83ceed Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 19 Oct 2024 18:17:40 +0300 Subject: [PATCH 031/189] *Finally fixes a very big longstanding issue!* Fix erroneous plugins bricking Adonis (#1635) * Fix erronus userplugins from bricking Adonis * Fix typos * Fix icon URL * Fix Settings.Messages handler * Fix typo * Fix typos * Fix final typo * Update Process.luau * Grrrrrrrrrrrrrrrrrrrr --- Loader/Loader/Loader.server.luau | 2 +- MainModule/Server/Core/Process.luau | 18 ++++++++++++++---- MainModule/Server/Server.luau | 13 +++++++++++-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/Loader/Loader/Loader.server.luau b/Loader/Loader/Loader.server.luau index 20334fb1c2..8a4f952881 100644 --- a/Loader/Loader/Loader.server.luau +++ b/Loader/Loader/Loader.server.luau @@ -125,7 +125,7 @@ else warn("[DEVELOPER ERROR] Settings module errored while loading; Using defaults; Error Message: ", setTab) table.insert(data.Messages, { Title = "Warning!"; - Icon = "rbxassetid://7495468117"; + Icon = "maticon://Dangerous"; Message = "Settings module error detected; using default settings."; Time = 15; }) diff --git a/MainModule/Server/Core/Process.luau b/MainModule/Server/Core/Process.luau index 98b3a9871a..6198243a8e 100644 --- a/MainModule/Server/Core/Process.luau +++ b/MainModule/Server/Core/Process.luau @@ -977,7 +977,6 @@ return function(Vargs, GetEnv) local newVer = (level > 300) and tonumber(string.match(server.Changelog[1], "Version: (.*)")) if Settings.Notification then - task.wait(1) Functions.Notification("Welcome.", `Your rank is {rank} ({level}). Click here for commands.`, {p}, 15, "MatIcon://Verified user", Core.Bytecode(`client.Remote.Send("ProcessCommand","{Settings.Prefix}cmds")`)) @@ -1005,9 +1004,20 @@ return function(Vargs, GetEnv) ]])) end - if level >= 300 and #Settings.Messages > 0 then - for _, Message in Settings.Messages do - task.delay(1, Functions.Notification, "Message", tostring(Message), {p}, math.round((#Message/19)+2.5)) + if level >= 300 and #server.Messages > 0 then + for _, message in server.Messages do + local isString = type(message) == "string" + + task.delay( + 1, + Functions.Notification, + not isString and message.Title or "Message", + isString and message or not isString and message.Message or "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + {p}, + isString and math.round((#message/19)+2.5) or not isString and message.Time or 10, + not isString and message.Icon, + not isString and message.onClick + ) end end end diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index e4835ebb45..5974f47144 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -693,7 +693,16 @@ return service.NewProxy({ end for _, module in ipairs(data.ServerPlugins or {}) do - LoadModule(module, false, {script = module, cPcall = server.cPcall}) + xpcall(LoadModule, function(reason) + warn(`The plugin {type(module) == "string" and string.sub(module, 1, 15) or module} failed to load! Reason: {reason}`) + logError(`The plugin {type(module) == "string" and string.sub(module, 1, 15) or module} failed to load! Reason: {reason}`) + table.insert(server.messages, { + Title = `The plugin {type(module) == "string" and string.sub(module, 1, 15) or module} failed to load!`, + Icon = "maticon://Dangerous", + Message = string.match(reason, "Requested module experienced an error while loading") and "The plugin has invalid code or the code fails before return!" or string.match(reason, "Module code did not return exactly one value") and "The plugin returns an invalid amount of values or returns nothing at all!" or `Reason {reason}`, + Time = 15 + }) + end, module, false, {script = module, cPcall = server.cPcall}) end --// We need to do some stuff *after* plugins are loaded (in case we need to be able to account for stuff they may have changed before doing something, such as determining the max length of remote commands) @@ -738,7 +747,7 @@ return service.NewProxy({ Desc = "Adonis has finished loading"; }) else - warn("SERVER.LOGS TABLE IS MISSING. THIS SHOULDN'T HAPPEN! SOMETHING WENT WRONG WHILE LOADING CORE MODULES(?)"); + warn("CRITICAL ERROR! SERVER.LOGS TABLE IS MISSING. THIS SHOULDN'T HAPPEN! SOMETHING WENT WRONG WHILE LOADING CORE MODULES(?)"); end service.Events.ServerInitialized:Fire(); From 13f4565edf6651b8e1c3b92373bd8342a101a04b Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 19 Oct 2024 18:22:36 +0300 Subject: [PATCH 032/189] Move `DisableRejoinAtMaxPlayers` from Settings to Variables (#1634) * Remove `DisableRejoinAtMaxPlayers` from settings * Remove `DisableRejoinAtMaxPlayers` from settings * Add `Variables.DisableRejoinAtMaxPlayers` * Add Variables option for max players check * Only use Variables * Pool rejoin lock variable from settings --- Loader/Config/Settings.luau | 3 --- MainModule/Server/Commands/Players.luau | 2 +- MainModule/Server/Core/Variables.luau | 2 ++ MainModule/Server/Dependencies/DefaultSettings.luau | 3 --- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Loader/Config/Settings.luau b/Loader/Config/Settings.luau index c5a9b29a98..107103fba2 100644 --- a/Loader/Config/Settings.luau +++ b/Loader/Config/Settings.luau @@ -302,7 +302,6 @@ settings.AutoClean = false -- Will auto clean workspace of things li settings.AutoCleanDelay = 60 -- Time between auto cleans settings.AutoBackup = false -- Run :backupmap automatically when the server starts. To restore the map, run :restoremap settings.ReJail = false -- If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed -settings.DisableRejoinAtMaxPlayers = false -- If true, disables rejoin when max players is reached to avoid an exploit that allows more players than the max amount. settings.Console = true -- Whether the command console is enabled settings.Console_AdminsOnly = false -- If true, only admins will be able to access the console @@ -474,7 +473,6 @@ descs.SongHint = [[ Display a hint with the current song name and ID when a song descs.TopBarShift = [[ By default hints and notifs will appear from the top edge of the window. Set this to true if you don't want hints/notifications to appear in that region. ]] descs.DefaultTheme = [[ Theme to be used as a replacement for "Default". The new replacement theme can still use "Default" as its Base_Theme however any other theme that references "Default" as its redirects to this theme. ]] descs.ReJail = [[ If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed ]] -descs.DisableRejoinAtMaxPlayers = [[ If true, disables rejoin when max players is reached to avoid an exploit that allows more players than the max amount. ]] descs.Messages = [[ A list of notification messages to show HeadAdmins and above on join ]] @@ -592,7 +590,6 @@ order = { "TopBarShift"; "DefaultTheme"; "ReJail"; - "DisableRejoinAtMaxPlayers"; ""; "AutoClean"; "AutoCleanDelay"; diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index d65a042d3d..3f73bf7047 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -434,7 +434,7 @@ return function(Vargs, env) NoStudio = true; -- Commands which cannot be used in Roblox Studio (e.g. commands which use TeleportService) AdminLevel = "Players"; Function = function(plr: Player, args: {string}) - assert(#(service.Players:GetPlayers()) < service.Players.MaxPlayers or not Settings.DisableRejoinAtMaxPlayers, "Cannot rejoin while server is at max capacity.") + assert(#(service.Players:GetPlayers()) < service.Players.MaxPlayers or not Variables.DisableRejoinAtMaxPlayers, "Cannot rejoin while server is at max capacity.") service.TeleportService:TeleportAsync(game.PlaceId, {plr}, service.New("TeleportOptions", { ServerInstanceId = game.JobId })) diff --git a/MainModule/Server/Core/Variables.luau b/MainModule/Server/Core/Variables.luau index f47b73c351..128c5759a3 100644 --- a/MainModule/Server/Core/Variables.luau +++ b/MainModule/Server/Core/Variables.luau @@ -28,6 +28,7 @@ return function(Vargs, GetEnv) Variables.BanMessage = Settings.BanMessage Variables.LockMessage = Settings.LockMessage + Variables.DisableRejoinAtMaxPlayers = Settings.DisableRejoinAtMaxPlayers or Variables.DisableRejoinAtMaxPlayers for _, v in Settings.MusicList or {} do table.insert(Variables.MusicList, v) end for _, v in Settings.InsertList or {} do table.insert(Variables.InsertList, v) end @@ -67,6 +68,7 @@ return function(Vargs, GetEnv) WebPanel_Initiated = false, HTTPCheckUrl = "https://www.google.com/humans.txt", IPInfoUrl = "https://ipinfo.io/json", + DisableRejoinAtMaxPlayers = false, AnimatedFaces = { -- R15 (Hopefully) 14719428401, 12936561806, 12936887700, 12937016609, 12937135097, 12939014597, 12945364777, 12945456452, 14374800823, 14367118483, 13674780763, diff --git a/MainModule/Server/Dependencies/DefaultSettings.luau b/MainModule/Server/Dependencies/DefaultSettings.luau index c2e1409b47..fd4fd162eb 100644 --- a/MainModule/Server/Dependencies/DefaultSettings.luau +++ b/MainModule/Server/Dependencies/DefaultSettings.luau @@ -302,7 +302,6 @@ settings.AutoClean = false -- Will auto clean workspace of things li settings.AutoCleanDelay = 60 -- Time between auto cleans settings.AutoBackup = false -- Run :backupmap automatically when the server starts. To restore the map, run :restoremap settings.ReJail = false -- If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed -settings.DisableRejoinAtMaxPlayers = false -- If true, disables rejoin when max players is reached to avoid an exploit that allows more players than the max amount. settings.Console = true -- Whether the command console is enabled settings.Console_AdminsOnly = false -- If true, only admins will be able to access the console @@ -474,7 +473,6 @@ descs.CodeExecution = [[ Enables the use of code execution in Adonis; Scripting descs.SongHint = [[ Display a hint with the current song name and ID when a song is played via :music ]] descs.TopBarShift = [[ By default hints and notifs will appear from the top edge of the window. Set this to true if you don't want hints/notifications to appear in that region. ]] descs.ReJail = [[ If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed ]] -descs.DisableRejoinAtMaxPlayers = [[ If true, disables rejoin when max players is reached to avoid an exploit that allows more players than the max amount. ]] descs.Messages = [[ A list of notification messages to show HeadAdmins and above on join ]] @@ -592,7 +590,6 @@ order = { "SongHint"; "TopBarShift"; "ReJail"; - "DisableRejoinAtMaxPlayers"; ""; "AutoClean"; "AutoCleanDelay"; From bedaf7e69a60cb8ccbb3a40aa22a2000c90a88df Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 20 Oct 2024 15:44:15 +0100 Subject: [PATCH 033/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 2f9c0fa2ad..2d9d8233d0 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -23,11 +23,15 @@ return { "(Git/PurpleCreativity) Prevent Anti.RemovePlayer from kicking if in studio (#1605)"; "(Git/ccuser44) Make HTTP constant URLs to Variables (#1618)"; "(Git/ccuser44) Convert README XML to Lua (#1619)"; - "(Git/ccuser44) Remove service.CloneTable (#1628)"; "(Git/ccuser44) Remove bloat & Fix stuff (#1623)"; "(Git/ccuser44) Move Trello commands to a plugin (#1624)"; "(Git/ccuser44) Remove unnecessary table.isfrozen check (#1627)"; + "(Git/ccuser44) Remove service.CloneTable (#1628)"; "(Git/ccuser44) Fix leap year handling (#1629)"; + "(Git/ccuser44) Move rank backwards compatibility to plugin and remove junk (#1630)"; + "(Git/ccuser44) Move DisableRejoinAtMaxPlayers from Settings to Variables (#1634)"; + "(Git/ccuser44) Fix erroneous plugins bricking Adonis (#1635)"; + "(Git/ccuser44) Lock server on soft shutdown after 1 minute (#1638)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 0087c053760e6a414ad9b2c0d2268638e72bbd4f Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 26 Oct 2024 19:29:12 +0300 Subject: [PATCH 034/189] Close BTools and/or invalid tickets automatically (#1639) * Fix trello label and mark F3X tickets as invalid * Add BTools to dropdown labels * Add BTools and Trello to dropdown labels * Create close_issues.yml * Remove joke --- .github/ISSUE_TEMPLATE/Bug_Report.yml | 1 + .github/ISSUE_TEMPLATE/Feature_Request.yml | 4 +++- .github/labeler.yml | 4 ++++ .github/workflows/close_issues.yml | 23 ++++++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/close_issues.yml diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.yml b/.github/ISSUE_TEMPLATE/Bug_Report.yml index 7ff67693d8..a751103edc 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.yml +++ b/.github/ISSUE_TEMPLATE/Bug_Report.yml @@ -37,6 +37,7 @@ body: - GitHub Repository - Anti-Exploit - Trello + - F3X/Building Tools - Other validations: required: true diff --git a/.github/ISSUE_TEMPLATE/Feature_Request.yml b/.github/ISSUE_TEMPLATE/Feature_Request.yml index a031f649be..dd373b065a 100644 --- a/.github/ISSUE_TEMPLATE/Feature_Request.yml +++ b/.github/ISSUE_TEMPLATE/Feature_Request.yml @@ -19,6 +19,8 @@ body: - Documentation - GitHub Repository - Anti-Exploit + - Trello + - F3X/Building Tools - Other validations: required: true @@ -29,4 +31,4 @@ body: placeholder: ex. Add a new command that does XYZ validations: required: true - \ No newline at end of file + diff --git a/.github/labeler.yml b/.github/labeler.yml index da6f27169c..bab0f3970c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -10,5 +10,9 @@ - '### What part of Adonis is this related to\?\s+GitHub Repository' '🖇️ loader': - '### What part of Adonis is this related to\?\s+Loader/Settings' +'trello': + - '### What part of Adonis is this related to\?\s+Trello' +'❌ invalid' + - '### What part of Adonis is this related to\?\s+F3X/Building Tools' '🎏 miscellaneous': - '### What part of Adonis is this related to\?\s+Other' diff --git a/.github/workflows/close_issues.yml b/.github/workflows/close_issues.yml new file mode 100644 index 0000000000..461542c629 --- /dev/null +++ b/.github/workflows/close_issues.yml @@ -0,0 +1,23 @@ +name: Close invalid issues + +on: + issues: + types: [labeled] + +jobs: + close-issue: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.2.1 + + - name: Close issue + if: github.event.label.name == '❌ invalid' && !(contains(github.event.issue.body, 'F3X/Building Tools')) && + run: gh issue close --comment "This issue has been closed as invalid. Please look at our [contribution guide](https://github.com/Epix-Incorporated/Adonis/blob/master/CONTRIBUTING.md)" --reason "not planned" "1" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Close BTools issue + if: github.event.label.name == '❌ invalid' && (contains(github.event.issue.body, 'F3X/Building Tools')) && + run: gh issue close --comment "We use F3X for our building tools system. Please [make an issue ticket](https://github.com/F3XTeam/RBX-Building-Tools/issues/new) on the F3X Team BTools repository." --reason "not planned" "1" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 9126f44edd3ef20f4c9e3ee162fde157a555c80c Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 3 Nov 2024 02:33:25 +0200 Subject: [PATCH 035/189] Convert encryption to use buffers (#1652) * Convert encryption to use buffers * Conver encryption to use buffers --- MainModule/Client/Core/Remote.luau | 49 ++++++++++++++---------------- MainModule/Server/Core/Remote.luau | 49 ++++++++++++++---------------- 2 files changed, 44 insertions(+), 54 deletions(-) diff --git a/MainModule/Client/Core/Remote.luau b/MainModule/Client/Core/Remote.luau index 110c08766d..5b37f7dd8d 100644 --- a/MainModule/Client/Core/Remote.luau +++ b/MainModule/Client/Core/Remote.luau @@ -476,56 +476,51 @@ return function(Vargs, GetEnv) Remote.Send("PlayerEvent",event,...) end; - Encrypt = function(str, key, cache) + Encrypt = function(str: string, key: string, cache: {[string]: (buffer|{[string]: string})}?) cache = cache or Remote.EncodeCache or {} + local keyCache = cache[key] or {} if not key or not str then return str - elseif cache[key] and cache[key][str] then - return cache[key][str] + elseif keyCache[str] then + return keyCache[str] else - local byte = string.byte - local sub = string.sub - local char = string.char - - local keyCache = cache[key] or {} - local endStr = {} + local writeu8, readu8 = buffer.writeu8, buffer.readu8 + local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) + local keyLen = #key for i = 1, #str do - local keyPos = (i % #key) + 1 - endStr[i] = char(((byte(sub(str, i, i)) + byte(sub(key, keyPos, keyPos)))%126) + 1) + local keyPos = (i % keyLen) + 1 + writeu8(rawStr, (readu8(rawStr, i) + readu8(rawKey, keyPos)) % 126 + 1) end - endStr = table.concat(endStr) cache[key] = keyCache - keyCache[str] = endStr - return endStr + keyCache[str], keyCache[1] = buffer.tostring(rawStr), rawKey + return keyCache[str] end end; - Decrypt = function(str, key, cache) + Decrypt = function(str: string, key: string, cache: {[string]: (buffer|{[string]: string})}?) cache = cache or Remote.DecodeCache or {} + local keyCache = cache[key] or {} if not key or not str then return str - elseif cache[key] and cache[key][str] then - return cache[key][str] + elseif keyCache[str] then + return keyCache[str] else - local keyCache = cache[key] or {} - local byte = string.byte - local sub = string.sub - local char = string.char - local endStr = {} + local writeu8, readu8 = buffer.writeu8, buffer.readu8 + local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) + local keyLen = #key for i = 1, #str do - local keyPos = (i % #key)+1 - endStr[i] = char(((byte(sub(str, i, i)) - byte(sub(key, keyPos, keyPos)))%126) - 1) + local keyPos = (i % keyLen) + 1 + writeu8(rawStr, (readu8(rawStr, i) - readu8(rawKey, keyPos)) % 126 - 1) end - endStr = table.concat(endStr) cache[key] = keyCache - keyCache[str] = endStr - return endStr + keyCache[str], keyCache[1] = buffer.tostring(rawStr), rawKey + return keyCache[str] end end; } diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index 9319b84eb3..b11065f7b2 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -1347,56 +1347,51 @@ return function(Vargs, GetEnv) end end; - Encrypt = function(str: string?, key: string?, cache: {[string]: any}?) + Encrypt = function(str: string, key: string, cache: {[string]: (buffer|{[string]: string})}?) cache = cache or Remote.EncodeCache or {} + local keyCache = cache[key] or {} if not key or not str then return str - elseif cache[key] and cache[key][str] then - return cache[key][str] + elseif keyCache[str] then + return keyCache[str] else - local byte = string.byte - local sub = string.sub - local char = string.char - - local keyCache = cache[key] or {} - local endStr = {} + local writeu8, readu8 = buffer.writeu8, buffer.readu8 + local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) + local keyLen = #key for i = 1, #str do - local keyPos = (i % #key) + 1 - endStr[i] = char(((byte(sub(str, i, i)) + byte(sub(key, keyPos, keyPos)))%126) + 1) + local keyPos = (i % keyLen) + 1 + writeu8(rawStr, (readu8(rawStr, i) + readu8(rawKey, keyPos)) % 126 + 1) end - endStr = table.concat(endStr) cache[key] = keyCache - keyCache[str] = endStr - return endStr + keyCache[str], keyCache[1] = buffer.tostring(rawStr), rawKey + return keyCache[str] end end; - Decrypt = function(str: string?, key: string?, cache: {[string]: any}?) + Decrypt = function(str: string, key: string, cache: {[string]: (buffer|{[string]: string})}?) cache = cache or Remote.DecodeCache or {} + local keyCache = cache[key] or {} if not key or not str then return str - elseif cache[key] and cache[key][str] then - return cache[key][str] + elseif keyCache[str] then + return keyCache[str] else - local keyCache = cache[key] or {} - local byte = string.byte - local sub = string.sub - local char = string.char - local endStr = {} + local writeu8, readu8 = buffer.writeu8, buffer.readu8 + local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) + local keyLen = #key for i = 1, #str do - local keyPos = (i % #key)+1 - endStr[i] = char(((byte(sub(str, i, i)) - byte(sub(key, keyPos, keyPos)))%126) - 1) + local keyPos = (i % keyLen) + 1 + writeu8(rawStr, (readu8(rawStr, i) - readu8(rawKey, keyPos)) % 126 - 1) end - endStr = table.concat(endStr) cache[key] = keyCache - keyCache[str] = endStr - return endStr + keyCache[str], keyCache[1] = buffer.tostring(rawStr), rawKey + return keyCache[str] end end; }; From 10b41b4751d5039f4b11753de88a301cf61e1c3a Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 3 Nov 2024 02:34:25 +0200 Subject: [PATCH 036/189] Label pull request for PoF (#1645) * Auto tag pull request PoF * Label pull requests for PoF * Fix invalid label lint --- .github/labeler.yml | 5 ++++- .github/workflows/labeling.yml | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index bab0f3970c..1564bff81a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -12,7 +12,10 @@ - '### What part of Adonis is this related to\?\s+Loader/Settings' 'trello': - '### What part of Adonis is this related to\?\s+Trello' -'❌ invalid' +'❌ invalid': - '### What part of Adonis is this related to\?\s+F3X/Building Tools' '🎏 miscellaneous': - '### What part of Adonis is this related to\?\s+Other' +'⌛needs PoF': + - '^(?!.*What part of Adonis is this related to)(?i:(?!.*(p\-?o\-?f|proof[\-_\s]*of[\-_\s]*work)\:?[\r\n]*)).*$' + \ No newline at end of file diff --git a/.github/workflows/labeling.yml b/.github/workflows/labeling.yml index d2fe11da1b..f6764ebc32 100644 --- a/.github/workflows/labeling.yml +++ b/.github/workflows/labeling.yml @@ -7,6 +7,8 @@ permissions: on: issues: types: [opened] + pull_request: + types: [opened] jobs: autotriage: runs-on: ubuntu-latest From 07d823a5db735e1b500859208ec352c4569a290a Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 3 Nov 2024 02:34:58 +0200 Subject: [PATCH 037/189] Use relative markdown links when possible (#1646) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3ceb01c161..fec5e2d35e 100644 --- a/README.md +++ b/README.md @@ -94,11 +94,11 @@ The purpose of this repository is to allow others to contribute and make improve ### 📜 Contributing Guide -Read the [contributing guide](https://github.com/Epix-Incorporated/Adonis/blob/master/CONTRIBUTING.md) to get a better understanding of our development process and workflow, along with answers to common questions related to contributing to Adonis. +Read the [contributing guide](CONTRIBUTING.md) to get a better understanding of our development process and workflow, along with answers to common questions related to contributing to Adonis. ### ⚖️ License -Adonis is available under the terms of [the MIT license](https://github.com/Epix-Incorporated/Adonis/blob/master/LICENSE.md). +Adonis is available under the terms of [the MIT license](LICENSE.md). ### Thank you to our contributors From 3f12491b791b9bf98852a032c48ffa731743d3ee Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 3 Nov 2024 02:37:15 +0200 Subject: [PATCH 038/189] Enforce LF linefeed for .txt files too (#1644) * Enforce LF for .txt * Enforce LF for .txt --- .editorconfig | 3 +++ .gitattributes | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.editorconfig b/.editorconfig index efd3af96da..84ee9a295a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -30,3 +30,6 @@ end_of_line = lf [*.rbxmx] end_of_line = lf + +[*.txt] +end_of_line = lf diff --git a/.gitattributes b/.gitattributes index b6704d9f60..ca5c68a17d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13,3 +13,5 @@ *.toml eol=lf *.yml text=auto *.yml eol=lf +*.txt text=auto +*.txt eol=lf From cc96c9e4bd1d52c08faa9d8279b156dc3507b66b Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 3 Nov 2024 02:37:45 +0200 Subject: [PATCH 039/189] Support named link as PoF (#1643) --- .github/workflows/pof_handler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pof_handler.yml b/.github/workflows/pof_handler.yml index 5cec0f9aca..d6dadc2251 100644 --- a/.github/workflows/pof_handler.yml +++ b/.github/workflows/pof_handler.yml @@ -20,7 +20,7 @@ jobs: comment_body=$(jq -r '.comment.body' "$GITHUB_EVENT_PATH") comment_body_lowercase=$(echo $comment_body | awk '{print tolower($0)}') - if [[ $comment_body_lowercase =~ "(p\-?o\-?f|proof[\-_\s]*of[\-_\s]*work)\:?[\r\n]*.*(\!\[.*\]\(.+\)|\> $GITHUB_OUTPUT else From 2b0a0870b60622b96fc94918b981dca4eec8fd99 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 3 Nov 2024 02:40:43 +0200 Subject: [PATCH 040/189] Move !wait from parser logic to a command (#1631) * Remove wait command from parser logic * Add !wait as a command * Fix typo * Fix typo --- MainModule/Server/Commands/Players.luau | 14 +++++++++++++ MainModule/Server/Core/Process.luau | 27 ++++++------------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index 3f73bf7047..92508c8845 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -1176,6 +1176,7 @@ return function(Vargs, env) service.MarketplaceService:PromptPurchase(plr, assetId, false) end }; + Coordinates = { Prefix = Settings.PlayerPrefix; Commands = {"coordinates", "coords", "position"}; @@ -1210,5 +1211,18 @@ return function(Vargs, env) }) end; }; + + Wait = { + Prefix = Settings.PlayerPrefix; + Commands = {"wait"}; + Args = {"time"}; + Description = "Waits for the desired amount of time in seconds. Only works with batch commands"; + AdminLevel = -math.huge; + Function = function(plr: Player, args: {string}) + task.wait(tonumber(args[1]) or 0) + + return args + end + }; }; end diff --git a/MainModule/Server/Core/Process.luau b/MainModule/Server/Core/Process.luau index 6198243a8e..c8555d14ed 100644 --- a/MainModule/Server/Core/Process.luau +++ b/MainModule/Server/Core/Process.luau @@ -412,29 +412,14 @@ return function(Vargs, GetEnv) for cmd, overrideMap in string.gmatch(msg, `([^{Settings.BatchKey}]+)({Settings.BatchKey}?[%d,>]*)`) do cmd, overrideMap = Functions.Trim(cmd), Process.GetOverrideMap(overrideMap) + local returnArgs = table.pack(Process.Command(p, cmd, opts, false)) + table.clear(overrideArgs) - local waiter = `{Settings.PlayerPrefix}wait` - if string.sub(string.lower(cmd), 1, #waiter) == waiter then - local num = tonumber(overrideArgs[1] or string.sub(cmd, #waiter + 1)) - - if overrideMap[1] then - table.clear(overrideArgs) - overrideArgs[overrideMap[1]] = num - end - - if num then - task.wait(tonumber(num)) - end - else - local returnArgs = table.pack(Process.Command(p, cmd, opts, false)) - table.clear(overrideArgs) - - for i, i2 in overrideMap do - overrideArgs[i2] = returnArgs[i + 1] - end - - opts.OverrideArgs = overrideArgs + for i, i2 in overrideMap do + overrideArgs[i2] = returnArgs[i + 1] end + + opts.OverrideArgs = overrideArgs end else local pData = opts.PlayerData or (p and Core.GetPlayer(p)) From 3c9d0baf06ede8fd182552a7eff58d969e756aae Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:08:32 +0000 Subject: [PATCH 041/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 2d9d8233d0..b3b2d9e3c7 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -32,6 +32,8 @@ return { "(Git/ccuser44) Move DisableRejoinAtMaxPlayers from Settings to Variables (#1634)"; "(Git/ccuser44) Fix erroneous plugins bricking Adonis (#1635)"; "(Git/ccuser44) Lock server on soft shutdown after 1 minute (#1638)"; + "(Git/ccuser44) Convert encryption to use buffers (#1652)"; + "(Git/ccuser44) Move !wait from parser logic to a command (#1631)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From e5043903660b851503bafbe3204732678aca1ef6 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 9 Nov 2024 13:36:39 +0200 Subject: [PATCH 042/189] Turn off nightlymode for release (#1667) --- .github/workflows/publish.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c7aea29937..d91694631e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -55,6 +55,9 @@ jobs: - name: Set DebugMode off run: sed -i "s/DebugMode = true/DebugMode = false/g" Loader/Loader/Loader.server.luau + - name: Set NightlyMode off + run: sed -i "s/NightlyMode = true/NightlyMode = false/g" Loader/Loader/Loader.server.luau + - name: Build Standalone run: rojo build -o ${{ steps.naming.outputs.output_name }}.rbxm .github/build.project.json From 19ddfc7ae614701c0adb4c1c0237e3eeb5c1aab1 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 9 Nov 2024 13:46:13 +0200 Subject: [PATCH 043/189] Fix default settings pooling (#1688) --- MainModule/Server/Core/Remote.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index b11065f7b2..e548b2738e 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -26,7 +26,7 @@ return function(Vargs, GetEnv) Process = server.Process; Variables = server.Variables; Settings = server.Settings; - Defaults = server.Defaults; + Defaults = server.Defaults.Settings; Commands = server.Commands; logError = env.logError; From ee2f0eddf8eccd8db1c485a04833ce7733ba73bf Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 9 Nov 2024 13:47:09 +0200 Subject: [PATCH 044/189] Fix _G API Access write (#1675) --- MainModule/Server/Core/Core.luau | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index 8875a7838b..ce318af411 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -1391,34 +1391,34 @@ return function(Vargs, GetEnv) if Settings.G_Access and key == Settings.G_Access_Key and targ and Settings.Allowed_API_Calls[ind] == true then if type(targ) == "table" then return service.NewProxy { - __index = function(tab,inde) - if targ[inde] ~= nil and API_Special[inde] == nil or API_Special[inde] == true then + __index = function(_, k) + if targ[k] ~= nil and API_Special[k] == nil or API_Special[k] == true then AddLog(Logs.Script, { - Text = `Access to {inde} was granted`; - Desc = `A server script was granted access to {inde}`; + Text = `Access to {k} was granted`; + Desc = `A server script was granted access to {k}`; }) - if targ[inde]~=nil and type(targ[inde]) == "table" and Settings.G_Access_Perms == "Read" then - return service.ReadOnly(targ[inde]) + if targ[k] ~= nil and type(targ[k]) == "table" and Settings.G_Access_Perms == "Read" then + return service.ReadOnly(targ[k]) else - return targ[inde] + return targ[k] end - elseif API_Special[inde] == false then + elseif API_Special[k] == false then AddLog(Logs.Script, { - Text = `Access to {inde} was denied`; - Desc = `A server script attempted to access {inde} via _G.Adonis.Access`; + Text = `Access to {k} was denied`; + Desc = `A server script attempted to access {k} via _G.Adonis.Access`; }) - error(`Access Denied: {inde}`) + error(`Access Denied: {k}`) else - error(`Could not find {inde}`) + error(`Could not find {k}`) end end; - __newindex = function(tabl, inde, valu) + __newindex = function(_, k, v) if Settings.G_Access_Perms == "Read" then error("Read-only") elseif Settings.G_Access_Perms == "Write" then - tabl[inde] = valu + rawset(targ, k, v) end end; __metatable = true; From 6a80ddeb482b9e89eb02ad03cb7785d89c44c936 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 9 Nov 2024 13:49:29 +0200 Subject: [PATCH 045/189] Allow local loading of gerald (#1668) --- MainModule/Server/Commands/Fun.luau | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index 8ce6b8e9b5..b02109a5ca 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -149,14 +149,15 @@ return function(Vargs, env) Fun = true; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) + local gerald = Deps.Assets:FindFirstChild("Gerald") + --// Apparently Rojo doesn't handle mesh parts very well, so I'm loading this remotely (using require to bypass insertservice restrictions) --// The model is free to take so feel free to that 👍 - --// Here's the URL https://www.roblox.com/library/7679952474/AssetModule - - warn("Requiring Assets Module by ID; Expand for module URL > ", {URL = "https://www.roblox.com/library/7679952474/Adonis-Assets-Module"}) - - local rAssets = require(7679952474) --// This apparently caches, so don't delete anything else future usage breaks - local gerald = rAssets.Gerald + --// Here's the URL https://www.roblox.com/library/7679952474/Adonis-Assets-Module + if not gerald then -- TODO: Add gerald to deps and remove require, I think the Rojo plugin (up to date) now supports loading + warn("Requiring Assets Module by ID; Expand for module URL > ", {URL = "https://www.roblox.com/library/7679952474/Adonis-Assets-Module"}) + gerald = require(7679952474).Gerald --// This apparently caches, so don't delete anything else future usage breaks + end for _, v in service.GetPlayers(plr, args[1]) do if v.Character then From 5487d5ad94d432edd78d1ae1bede0bb1abaec3cb Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 9 Nov 2024 19:26:20 +0000 Subject: [PATCH 046/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index b3b2d9e3c7..16ab3d4bb8 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -34,6 +34,9 @@ return { "(Git/ccuser44) Lock server on soft shutdown after 1 minute (#1638)"; "(Git/ccuser44) Convert encryption to use buffers (#1652)"; "(Git/ccuser44) Move !wait from parser logic to a command (#1631)"; + "(Git/ccuser44) Fix default settings pooling (#1688)"; + "(Git/ccuser44) Fix _G API Access write (#1675)"; + "(Git/ccuser44) Allow local loading of gerald (#1668)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From ccb727c800d3c7029a0f569e31c4f453dccc411b Mon Sep 17 00:00:00 2001 From: omwot <140683870+omwot@users.noreply.github.com> Date: Mon, 11 Nov 2024 10:22:43 -0500 Subject: [PATCH 047/189] Remove audit logs (#1698) --- MainModule/Server/Commands/HeadAdmins.luau | 68 +--------------------- MainModule/Server/Commands/Players.luau | 8 +-- MainModule/Server/Core/Functions.luau | 42 +++---------- MainModule/Server/Core/Logs.luau | 1 - 4 files changed, 14 insertions(+), 105 deletions(-) diff --git a/MainModule/Server/Commands/HeadAdmins.luau b/MainModule/Server/Commands/HeadAdmins.luau index af7e8622ed..c09017be13 100644 --- a/MainModule/Server/Commands/HeadAdmins.luau +++ b/MainModule/Server/Commands/HeadAdmins.luau @@ -1,7 +1,6 @@ return function(Vargs, env) local server = Vargs.Server; local service = Vargs.Service; - local AuditLogsDataStore = service.DataStoreService:GetDataStore("AdonisAuditLogsDataStore") local Settings = server.Settings local Functions, Commands, Admin, Anti, Core, HTTP, Logs, Remote, Process, Variables, Deps = server.Functions, server.Commands, server.Admin, server.Anti, server.Core, server.HTTP, server.Logs, server.Remote, server.Process, server.Variables, server.Deps @@ -170,7 +169,7 @@ return function(Vargs, env) Description = "Makes the target player(s) a temporary admin; does not save"; AdminLevel = "HeadAdmins"; Dangerous = true; - Function = function(plr: Player, args: {string}, data: {}) + Function = function(plr: Player, args: {string}, data: any) local senderLevel = data.PlayerData.Level for _, v in service.GetPlayers(plr, assert(args[1], "Missing target player (argument #1)")) do @@ -193,7 +192,7 @@ return function(Vargs, env) Description = "Makes the target player(s) an admin; saves"; AdminLevel = "HeadAdmins"; Dangerous = true; - Function = function(plr: Player, args: {string}, data: {}) + Function = function(plr: Player, args: {string}, data: any) local senderLevel = data.PlayerData.Level for _, v in service.GetPlayers(plr, assert(args[1], "Missing target user (argument #1)"), { @@ -423,7 +422,7 @@ return function(Vargs, env) hide_character=hideCharacter } if hideCharacter then - v.CharacterAdded:Connect(function(character: Model) + v.CharacterAdded:Connect(function(character: Model) for _, otherPlr: Player in service.Players:GetPlayers(v, if hidefromEveryone then "others" else "nonadmins") do if otherPlr == v then continue end Remote.LoadCode(otherPlr, [[ @@ -530,66 +529,5 @@ return function(Vargs, env) end }; - AuditLogs = { - Prefix = Settings.Prefix; - Commands = {"auditlogs", "moderationlogs", "modlogs"}; - Args = {"player"}; - Description = "Fetches the recent moderation activity logs of the specified moderator or admin."; - AdminLevel = "HeadAdmins"; - Function = function(plr: Player, args: {string}) - local targetPlayers = service.GetPlayers(plr, args[1], {NoFakePlayer = true}) - - if #targetPlayers == 0 then - Functions.Hint("No player found with the specified name.", {plr}) - return - end - - for _, targetPlayer in ipairs(targetPlayers) do - local userId = targetPlayer.UserId - local key = "AuditLogs_" .. tostring(userId) - - local success, auditLogs = pcall(function() - return AuditLogsDataStore:GetAsync(key) or {} - end) - - if not success then - warn("Failed to retrieve audit logs for UserId " .. tostring(userId) .. ": " .. auditLogs) - Functions.Hint("Error retrieving logs.", {plr}) - return - end - - local filteredLogs = {} - print("Checking audit logs for:", targetPlayer.Name, "with UserId:", userId) - print(auditLogs) - - for _, log in ipairs(auditLogs) do - local moderatorName = Functions.GetNameFromUserIdAsync(log.ModeratorId) or "Unknown" - local targetUserName = log.TargetPlayer - - if type(targetUserName) == "table" then - targetUserName = targetUserName.Name or "Unknown" - elseif targetUserName == nil then - targetUserName = "Unknown" - end - - local timestamp = os.date("%Y-%m-%d %H:%M:%S", log.Time) - - local logText = string.format("%s | %s | %s", moderatorName, log.Action, timestamp) - local logEntry = { Text = logText .. " | " .. targetUserName, Desc = log.Details } - table.insert(filteredLogs, logEntry) - end - - if #filteredLogs == 0 then - Functions.Hint(`No audit logs found for {targetPlayer.Name}`, {plr}) - else - Remote.MakeGui(plr, "List", { - Title = `Audit Logs for {targetPlayer.Name}`, - Table = filteredLogs, - Update = "filteredLogs" - }) - end - end - end - }; } end diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index 92508c8845..5add1d2537 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -179,7 +179,7 @@ return function(Vargs, env) Args = {"num m", "num n"}; Description = "Generates a number using Lua's math.random"; AdminLevel = "Players"; - Function = function(plr: Player, args: {string}) + Function = function(plr: Player, args: {any}) assert((not args[1]) or tonumber(args[1]), "Argument(s) provided must be numbers") assert((not args[2]) or tonumber(args[2]), "Arguments provided must be numbers") @@ -260,7 +260,7 @@ return function(Vargs, env) "Rock", "Glacier", "Snow", "Sandstone", "Mud", "Basalt", "Ground", "CrackedLava", "Asphalt", "LeafyGrass", "Salt", "Limestone", "Pavement" } for i, mat in mats do - mats[i] = {Text = mat; Desc = `Enum value: {Enum.Material[mat].Value}`} + mats[i] = {Text = mat; Desc = `Enum value: {(Enum.Material[mat]::Enum.Material).Value}`} end Remote.MakeGui(plr, "List", {Title = "Materials"; Tab = mats; TextSelectable = true;}) end @@ -455,12 +455,12 @@ return function(Vargs, env) local UserId = Functions.GetUserIdFromNameAsync(args[1]) if UserId then local success, samePlace, errorMessage, placeId, jobId = pcall(service.TeleportService.GetPlayerPlaceInstanceAsync, service.TeleportService, UserId) - + if success then if samePlace then error("You're already in this server!") end - + if placeId and jobId then service.TeleportService:TeleportAsync(placeId, {plr}, service.New("TeleportOptions", { ServerInstanceId = jobId diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 6e8692fc11..5b782d02d9 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -7,9 +7,6 @@ return function(Vargs, GetEnv) local service = Vargs.Service local logError - local AuditLogsDataStore; pcall(function() - AuditLogsDataStore = service.DataStoreService:GetDataStore("AdonisAuditLogsDataStore") - end) local Functions, Admin, Anti, Core, HTTP, Logs, Remote, Process, Variables, Settings local function Init() Functions = server.Functions; @@ -1048,30 +1045,7 @@ return function(Vargs, GetEnv) end; LogAdminAction = function(plr, action, targetPlayerName, additionalDetails) - local logEntry = { - Timestamp = os.time(), - ModeratorId = plr.UserId, - ModeratorName = plr.Name, - Action = action, - TargetPlayer = targetPlayerName, - AdditionalDetails = additionalDetails or "N/A", - } - - -- Attempt to log the action under the moderator's UserId - local key = "AuditLogs_" .. tostring(plr.UserId) - - local success, errMessage = pcall(function() - -- Get existing logs - local existingLogs = AuditLogsDataStore:GetAsync(key) or {} - table.insert(existingLogs, logEntry) - AuditLogsDataStore:SetAsync(key, existingLogs) - end) - - if not success then - warn("Failed to log audit entry for UserId " .. tostring(plr.UserId) .. ": " .. errMessage) - else - print("Audit log entry saved for:", plr.Name) - end + -- kept function here for potential future reimplementation end; NewParticle = function(target, particleType, props) @@ -1585,7 +1559,7 @@ return function(Vargs, GetEnv) local Humanoid: Humanoid = plr.Character and plr.Character:FindFirstChildOfClass("Humanoid") local HumanoidDescription = Humanoid:GetAppliedDescription() or service.Players:GetHumanoidDescriptionFromUserId(plr.UserId) - local newCharacterModel: Model = service.Players:CreateHumanoidModelFromDescription(HumanoidDescription, rigType, Enum.AssetTypeVerification.Always) + local newCharacterModel: any = service.Players:CreateHumanoidModelFromDescription(HumanoidDescription, rigType, Enum.AssetTypeVerification.Always) local Animate: BaseScript = newCharacterModel.Animate newCharacterModel.Humanoid.DisplayName = Humanoid.DisplayName @@ -1632,7 +1606,7 @@ return function(Vargs, GetEnv) }) end; - ParseColor3 = function(str: string?) + ParseColor3 = function(str: string) if not str then return nil end if str:lower() == "random" then return Color3.fromRGB(math.random(0, 255), math.random(0, 255), math.random(0, 255)) @@ -1644,17 +1618,15 @@ return function(Vargs, GetEnv) end if #color == 3 then - color = Color3.fromRGB(color[1], color[2], color[3]) + return Color3.fromRGB(color[1], color[2], color[3]) else - local brickColor = BrickColor.new(str) + local brickColor = BrickColor.new(str::any); if str == tostring(brickColor) then - color = brickColor.Color + return brickColor.Color else return end end - - return color end; ParseBrickColor = function(str: string, allowNil: boolean?) @@ -1665,7 +1637,7 @@ return function(Vargs, GetEnv) return BrickColor.random() end - local brickColor = BrickColor.new(str) + local brickColor = BrickColor.new(str::any) if str == tostring(brickColor) then return brickColor else diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index 1bee9183fc..2cb2a6436b 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -116,7 +116,6 @@ return function(Vargs, GetEnv) GetAuditLogs = function(playerId) local auditLogs = {} - local logs = Logs.AuditLogs:GetAsTable() or {} for _, log in pairs(Logs.AuditLogs:GetAsTable()) do if log.ModeratorId == playerId then table.insert(auditLogs, log) From ae56d82e4b375848bf9afe784aea937b68883d57 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:23:54 +0000 Subject: [PATCH 048/189] Update Changelog, move from pre-release --- MainModule/Server/Shared/Changelog.luau | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 16ab3d4bb8..ba7acbf28b 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -1,12 +1,11 @@ return { - "Version: 261 [Pre-release – Alpha]"; + "Version: 261"; "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; - "[v261 Pre-release 2024-08-29 14:32 UTC] @Dimenpsyonal"; + "[v261 2024-08-29 14:32 UTC] @Dimenpsyonal"; "(Git/Expertcoderz) Add :ckick command (#1614)"; - "#Not for release until the following issues are resolved:"; - "#Audit logs need be integrated into datastore"; + ""; "(Git/24rr) New System: Audit Logs (#1568)"; "(Git/24rr) New Command: coordinates (#1568)"; "(Git/bsqi) Fix Join command (#1584)"; @@ -37,6 +36,7 @@ return { "(Git/ccuser44) Fix default settings pooling (#1688)"; "(Git/ccuser44) Fix _G API Access write (#1675)"; "(Git/ccuser44) Allow local loading of gerald (#1668)"; + "(Git/omwat) Remove audit logs (#1698)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 7498b2cf26bf97022a8c6d54a7d7596c531cf36f Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:51:05 +0000 Subject: [PATCH 049/189] Remove audit logs (2) --- MainModule/Server/Core/Logs.luau | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index 2cb2a6436b..966e9b3e94 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -47,7 +47,6 @@ return function(Vargs, GetEnv) Exploit = if UseDLL then DLL.new() else {}; Errors = if UseDLL then DLL.new() else {}; DateTime = if UseDLL then DLL.new() else {}; - AuditLogs = if UseDLL then DLL.new() else {}; TempUpdaters = {}; OldCommandLogsLimit = 1000; --// Maximum number of command logs to save to the datastore (the higher the number, the longer the server will take to close) @@ -103,27 +102,6 @@ return function(Vargs, GetEnv) service.Events.LogAdded:Fire(Logs.TabToType(tab), log, tab) end; - LogAudit = function(moderatorId, action, targetId, details) - local logEntry = { - ModeratorId = moderatorId; - Action = action; - TargetId = targetId; - Details = details; - Time = os.time(); - } - Logs:AddLog(Logs.AuditLogs, logEntry); - end; - - GetAuditLogs = function(playerId) - local auditLogs = {} - for _, log in pairs(Logs.AuditLogs:GetAsTable()) do - if log.ModeratorId == playerId then - table.insert(auditLogs, log) - end - end - return auditLogs - end; - SaveCommandLogs = function() --// Disable saving command logs in Studio; not required. if service.RunService:IsStudio() or service.RunService:IsRunMode() then From 1ef2821d3c5c13bf3f22ccdebd136198ee9c8bd3 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:32:56 +0200 Subject: [PATCH 050/189] Remove incompatibility (#1670) * Remove incompatibility * Remove unnecessary patterns --- .github/labeler.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 1564bff81a..ef05e22fa8 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -17,5 +17,5 @@ '🎏 miscellaneous': - '### What part of Adonis is this related to\?\s+Other' '⌛needs PoF': - - '^(?!.*What part of Adonis is this related to)(?i:(?!.*(p\-?o\-?f|proof[\-_\s]*of[\-_\s]*work)\:?[\r\n]*)).*$' - \ No newline at end of file + - '^(?!.*What part of Adonis is this related to)(?!.*([Pp]\-?[Oo]\-?[Ff]|[Pp][Rr][Oo]+[Ff][\-_\s]*[Oo][Ff][\-_\s]*[Ww][Oo][Rr][Kk])).*$' + From 08860da588900fd4bd5110036c2d4b165782c508 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:37:36 +0200 Subject: [PATCH 051/189] Fix client side warn handling (#1683) * Fix client side warn handling * Set warn globally --- MainModule/Client/Client.luau | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/MainModule/Client/Client.luau b/MainModule/Client/Client.luau index 8c2d7705c1..91ef1e8165 100644 --- a/MainModule/Client/Client.luau +++ b/MainModule/Client/Client.luau @@ -115,13 +115,23 @@ local SERVICES_WE_USE = table.freeze({ "NetworkClient", }) +local oldPrint = print +print = function(...) + oldPrint(":: Adonis ::", ...) +end + +local oldWarn = warn +warn = function(...) + oldWarn(":: Adonis ::", ...) +end + --// Logging local clientLog = {} local dumplog = function() - warn(":: Adonis :: Dumping client log...") + warn("Dumping client log...") for _, v in clientLog do - warn(":: Adonis ::", v) + warn(v) end end local log = function(...) @@ -141,7 +151,6 @@ local unique = {} local origEnv = getfenv() local Folder = script.Parent setfenv(1, setmetatable({}, { __metatable = unique })) ---local origWarn = warn local startTime = time() local oldInstNew = Instance.new local oldReq = require @@ -167,17 +176,6 @@ local function logError(...) end end -local oldPrint = print -print = function(...) - oldPrint(":: Adonis ::", ...) -end - ---[[ -local warn = function(...) - warn(...) -end -]] - local Pcall = function(func, ...) local ran, err = pcall(func, ...) @@ -694,7 +692,7 @@ return service.NewProxy({ --// Finished loading log("Finish loading") client.Finish_Loading = function() end - client.LoadingTime() --origWarn(tostring(time()-(client.TrueStart or startTime))) + client.LoadingTime() --warn(tostring(time()-(client.TrueStart or startTime))) service.Events.FinishedLoading:Fire(os.time()) log("~! FINISHED LOADING!") From 610876781ebf66c89e7c6550c0f90cc112e6e35f Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Tue, 12 Nov 2024 20:38:07 +0000 Subject: [PATCH 052/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index ba7acbf28b..8ac9c9cb24 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -37,6 +37,7 @@ return { "(Git/ccuser44) Fix _G API Access write (#1675)"; "(Git/ccuser44) Allow local loading of gerald (#1668)"; "(Git/omwat) Remove audit logs (#1698)"; + "(Git/ccuser44) Fix client side warn handling (#1683)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From e6dd986e7922217f87db08afd3055c075d7d58b0 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:47:15 +0200 Subject: [PATCH 053/189] Add new encryption function (#1704) * Add new encryption function * Add new encryption function * Use new encryption algorithm * Use new encryption algorithm * Use new encryption algorithm * Use new encryption algorithm * Fix typo regarding index arg * Fix typo regarding index arg --- MainModule/Client/Core/Process.luau | 2 +- MainModule/Client/Core/Remote.luau | 32 ++++++++++++++++++++++++++-- MainModule/Server/Core/Process.luau | 4 ++-- MainModule/Server/Core/Remote.luau | 33 ++++++++++++++++++++++++++--- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/MainModule/Client/Core/Process.luau b/MainModule/Client/Core/Process.luau index e9b303049c..30a8a7d11c 100644 --- a/MainModule/Client/Core/Process.luau +++ b/MainModule/Client/Core/Process.luau @@ -97,7 +97,7 @@ return function(Vargs, GetEnv) client.Finish_Loading() end elseif Core.Key then - local comString = Remote.Decrypt(com,Core.Key) + local comString = Remote.NewDecrypt(com,Core.Key) local command = (data.Mode == "Get" and Remote.Returnables[comString]) or Remote.Commands[comString] if command then local rets = {service.TrackTask(`Remote: {comString}`, command, false, args)} diff --git a/MainModule/Client/Core/Remote.luau b/MainModule/Client/Core/Remote.luau index 5b37f7dd8d..4cc4ce4008 100644 --- a/MainModule/Client/Core/Remote.luau +++ b/MainModule/Client/Core/Remote.luau @@ -45,6 +45,9 @@ return function(Vargs, GetEnv) Functions = client.Functions; Process = client.Process; Remote = client.Remote; + Remote.NewDecrypt = function(str, key, cache) -- Bxor works both ways. May want to make a seperate function tho + return Remote.NewEncrypt(str, key, cache or Remote.NewDecodeCache) + end; Remote.Init = nil; end @@ -92,6 +95,8 @@ return function(Vargs, GetEnv) PendingReturns = {}; EncodeCache = {}; DecodeCache = {}; + NewEncodeCache = {}; + NewDecodeCache = {}; Received = 0; Sent = 0; @@ -374,7 +379,7 @@ return function(Vargs, GetEnv) Send = function(com,...) Core.LastUpdate = os.time() - Remote.Fire(Remote.Encrypt(com,Core.Key),...) + Remote.Fire(Remote.NewEncrypt(com,Core.Key),...) end; GetFire = function(...) @@ -429,7 +434,7 @@ return function(Vargs, GetEnv) Get = function(com,...) Core.LastUpdate = os.time() - local ret = Remote.GetFire(Remote.Encrypt(com,Core.Key),...) + local ret = Remote.GetFire(Remote.NewEncrypt(com,Core.Key),...) if type(ret) == "table" then return unpack(ret); else @@ -523,5 +528,28 @@ return function(Vargs, GetEnv) return keyCache[str] end end; + + NewEncrypt = function(str: string, key: string, cache: {[string]: (buffer|{[string]: string})}?) + cache = cache or Remote.NewEncodeCache or {} + local keyCache = cache[key] or {} + + if not key or not str then + return str + elseif keyCache[str] then + return keyCache[str] + else + local writeu8, readu8, bxor = buffer.writeu8, buffer.readu8, bit32.bxor + local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) + local keyLen = #key + + for i = 0, #str - 1 do + writeu8(rawStr, i, bxor(readu8(rawStr, i), readu8(rawKey, i % keyLen))) + end + + cache[key] = keyCache + keyCache[str], keyCache[1] = buffer.tostring(rawStr), rawKey + return keyCache[str] + end + end; } end diff --git a/MainModule/Server/Core/Process.luau b/MainModule/Server/Core/Process.luau index c8555d14ed..5cb1abbc75 100644 --- a/MainModule/Server/Core/Process.luau +++ b/MainModule/Server/Core/Process.luau @@ -26,8 +26,8 @@ return function(Vargs, GetEnv) logError = logError or env.logError; Routine = Routine or env.Routine; Commands = Remote.Commands - Decrypt = Remote.Decrypt - Encrypt = Remote.Encrypt + Decrypt = Remote.NewDecrypt + Encrypt = Remote.NewEncrypt AddLog = Logs.AddLog TrackTask = service.TrackTask Pcall = server.Pcall diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index e548b2738e..576c7db2e4 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -28,8 +28,10 @@ return function(Vargs, GetEnv) Settings = server.Settings; Defaults = server.Defaults.Settings; Commands = server.Commands; - logError = env.logError; + Remote.NewDecrypt = function(str, key, cache) -- Bxor works both ways. May want to make a seperate function tho + return Remote.NewEncrypt(str, key, cache or Remote.NewDecodeCache) + end; Remote.Init = nil; Logs:AddLog("Script", "Remote Module Initialized") @@ -60,6 +62,8 @@ return function(Vargs, GetEnv) PendingReturns = {}; EncodeCache = {}; DecodeCache = {}; + NewEncodeCache = {}; + NewDecodeCache = {}; RemoteExecutionConfirmed = {}; TimeUntilKeyDestroyed = 60 * 5; --// How long until a player's key data should be completely removed? @@ -1140,7 +1144,7 @@ return function(Vargs, GetEnv) assert(p and p:IsA("Player"), `Remote.Send: {p.Name} is not a valid Player`) local keys = Remote.Clients[tostring(p.UserId)] if keys and keys.RemoteReady == true then - Remote.Fire(p, Remote.Encrypt(com, keys.Key, keys.Cache), ...) + Remote.Fire(p, Remote.NewEncrypt(com, keys.Key, keys.Cache), ...) end end; @@ -1156,7 +1160,7 @@ return function(Vargs, GetEnv) Get = function(p: Player, com: string, ...) local keys = Remote.Clients[tostring(p.UserId)] if keys and keys.RemoteReady == true then - local ret = Remote.GetFire(p, Remote.Encrypt(com, keys.Key, keys.Cache), ...) + local ret = Remote.GetFire(p, Remote.NewEncrypt(com, keys.Key, keys.Cache), ...) if type(ret) == "table" then return unpack(ret) else @@ -1394,5 +1398,28 @@ return function(Vargs, GetEnv) return keyCache[str] end end; + + NewEncrypt = function(str: string, key: string, cache: {[string]: (buffer|{[string]: string})}?) + cache = cache or Remote.NewEncodeCache or {} + local keyCache = cache[key] or {} + + if not key or not str then + return str + elseif keyCache[str] then + return keyCache[str] + else + local writeu8, readu8, bxor = buffer.writeu8, buffer.readu8, bit32.bxor + local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) + local keyLen = #key + + for i = 0, #str - 1 do + writeu8(rawStr, i, bxor(readu8(rawStr, i), readu8(rawKey, i % keyLen))) + end + + cache[key] = keyCache + keyCache[str], keyCache[1] = buffer.tostring(rawStr), rawKey + return keyCache[str] + end + end; }; end From d78c41ae4d151612cc88c3b3dfb63ec4b83eb658 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:47:53 +0200 Subject: [PATCH 054/189] Fix Adonis cleanup not being editable (#1703) --- MainModule/Server/Server.luau | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index 5974f47144..996c09897b 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -245,8 +245,8 @@ local function LoadPackage(package, folder, runNow) unpackFolder(package, folder) end; -local function CleanUp() - print("Beginning Adonis cleanup & shutdown process...") +local function CleanUp(reason) + print(`Beginning Adonis cleanup & shutdown process due to {reason}...`) local data = service.UnWrap(server.Data) if type(data) == "table" and typeof(service.UnWrap(data.Config)) == "Instance" then local Settings: ModuleScript = service.UnWrap(data.Config):FindFirstChild("Settings") @@ -582,8 +582,10 @@ return service.NewProxy({ end --// Bind cleanup - service.DataModel:BindToClose(CleanUp) - --server.CleanUp = CleanUp; + service.DataModel:BindToClose(function(...) + server.CleanUp(...) + end) + server.CleanUp = CleanUp --// Require some dependencies server.Typechecker = require(server.Shared.Typechecker) From 20f164ac5ef34ac3cb89de331b4e8901e0e446cb Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:49:28 +0200 Subject: [PATCH 055/189] Fix extremely unfortunate and unlikely error with encryption in nightly (#1702) * Fix index for encryption functions * Fix index for encryption functions --- MainModule/Client/Core/Remote.luau | 11 +++++------ MainModule/Server/Core/Remote.luau | 10 ++++------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/MainModule/Client/Core/Remote.luau b/MainModule/Client/Core/Remote.luau index 4cc4ce4008..b9bb79def8 100644 --- a/MainModule/Client/Core/Remote.luau +++ b/MainModule/Client/Core/Remote.luau @@ -481,6 +481,7 @@ return function(Vargs, GetEnv) Remote.Send("PlayerEvent",event,...) end; + Encrypt = function(str: string, key: string, cache: {[string]: (buffer|{[string]: string})}?) cache = cache or Remote.EncodeCache or {} local keyCache = cache[key] or {} @@ -494,9 +495,8 @@ return function(Vargs, GetEnv) local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) local keyLen = #key - for i = 1, #str do - local keyPos = (i % keyLen) + 1 - writeu8(rawStr, (readu8(rawStr, i) + readu8(rawKey, keyPos)) % 126 + 1) + for i = 0, #str - 1 do + writeu8(rawStr, i, (readu8(rawStr, i) + readu8(rawKey, (i + 1) % keyLen)) % 126 + 1) end cache[key] = keyCache @@ -518,9 +518,8 @@ return function(Vargs, GetEnv) local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) local keyLen = #key - for i = 1, #str do - local keyPos = (i % keyLen) + 1 - writeu8(rawStr, (readu8(rawStr, i) - readu8(rawKey, keyPos)) % 126 - 1) + for i = 0, #str - 1 do + writeu8(rawStr, i, (readu8(rawStr, i) - readu8(rawKey, (i + 1) % keyLen)) % 126 - 1) end cache[key] = keyCache diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index 576c7db2e4..127d6dfd82 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -1364,9 +1364,8 @@ return function(Vargs, GetEnv) local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) local keyLen = #key - for i = 1, #str do - local keyPos = (i % keyLen) + 1 - writeu8(rawStr, (readu8(rawStr, i) + readu8(rawKey, keyPos)) % 126 + 1) + for i = 0, #str - 1 do + writeu8(rawStr, i, (readu8(rawStr, i) + readu8(rawKey, (i + 1) % keyLen)) % 126 + 1) end cache[key] = keyCache @@ -1388,9 +1387,8 @@ return function(Vargs, GetEnv) local rawStr, rawKey = buffer.fromstring(str), keyCache[1] or buffer.fromstring(key) local keyLen = #key - for i = 1, #str do - local keyPos = (i % keyLen) + 1 - writeu8(rawStr, (readu8(rawStr, i) - readu8(rawKey, keyPos)) % 126 - 1) + for i = 0, #str - 1 do + writeu8(rawStr, i, (readu8(rawStr, i) - readu8(rawKey, (i + 1) % keyLen)) % 126 - 1) end cache[key] = keyCache From 3bcf80dcbdf036744d6c5b2a4a9c24b9a346989f Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:53:28 +0200 Subject: [PATCH 056/189] Make ClientMover respect debugmode (#1680) * Make ClientMover respect debugmode * Make ClientLoader respect debugmode * Fix invalid debug outputs * Use recursive findfirstchild * Use recursive FindFirstChild * Fix debug flag check * Fix debug flag check * Fix log type * Improve code style --- .../Dependencies/ClientLoader.client.luau | 134 +++++++++--------- .../Dependencies/ClientMover.client.luau | 108 +++++++------- 2 files changed, 119 insertions(+), 123 deletions(-) diff --git a/MainModule/Server/Dependencies/ClientLoader.client.luau b/MainModule/Server/Dependencies/ClientLoader.client.luau index e11fac7d56..4790e2dff6 100644 --- a/MainModule/Server/Dependencies/ClientLoader.client.luau +++ b/MainModule/Server/Dependencies/ClientLoader.client.luau @@ -2,7 +2,7 @@ --// ACLI - Adonis Client Loading Initializer if true then return end --// #DISABLED -local DebugMode = false +local DebugMode = script.Parent:FindFirstChild("ADONIS_DEBUGMODE_ENABLED") ~= nil local otime = os.time local time = time local game = game @@ -21,11 +21,11 @@ local coroutine = coroutine local Instance = Instance local script = script local select = select -local unpack = unpack -local spawn = spawn +local unpack = table.unpack +local spawn = task.spawn local debug = debug local pairs = pairs -local wait = wait +local wait = task.wait local next = next local time = time local finderEvent @@ -58,15 +58,15 @@ local services = { } local function print(...) - --realPrint(...) -end - -local function warn(str) if DebugMode or player.UserId == 1237666 then - realWarn(`ACLI: {str}`) + realPrint("ACLI:", ...) end end +local function warn(...) + realWarn("ACLI:", ...) +end + local function Kill(info) if DebugMode then warn(info) return end pcall(function() Kick(player, info) end) @@ -75,16 +75,16 @@ local function Kill(info) end local function Locked(obj) - return (not obj and true) or not pcall(function() return obj.GetFullName(obj) end) + return not obj and true or not pcall(function() return obj.GetFullName(obj) end) end local function callCheck(child) - warn(`CallCheck: {child}`) + print(`CallCheck: {child}`) if Locked(child) then warn("Child locked?") Kill("ACLI: Locked") else - warn("Child not locked") + print("Child not locked") xpcall(function() return child[{}] end, function() @@ -96,35 +96,34 @@ local function callCheck(child) end local function doPcall(func, ...) - local ran,ret = pcall(func, ...) + local ran, ret = pcall(func, ...) if ran then - return ran,ret + return ran, ret else warn(tostring(ret)) Kill(`ACLI: Error\n{ret}`) - return ran,ret + return ran, ret end end local function lockCheck(obj) callCheck(obj) obj.Changed:Connect(function(p) - warn("Child changed; Checking...") + print("Child changed; Checking...") callCheck(obj) end) end local function loadingTime() - warn("LoadingTime Called") - setfenv(1,{}) - warn(tostring(time() - start)) + setfenv(1, {}) + print("LoadingTime Called:", tostring(time() - start)) end local function checkChild(child) - warn(`Checking child: child and child.ClassName} : {child and child:GetFullName()}`) + print(`Checking child: child and child.ClassName} : {child and child:GetFullName()}`) callCheck(child) if child and not foundClient and not checkedChildren[child] and child:IsA("Folder") and child.Name == "Adonis_Client" then - warn("Loading Folder...") + print("Loading Folder...") local nameVal local origName local depsFolder @@ -132,38 +131,38 @@ local function checkChild(child) local oldChild = child local container = child.Parent - warn("Adding child to checked list & setting parent...") + print("Adding child to checked list & setting parent...") checkedChildren[child] = true - warn("Waiting for Client & Special") + print("Waiting for Client & Special") nameVal = child:WaitForChild("Special", 30) clientModule = child:WaitForChild("Client", 30) - warn("Checking Client & Special") + print("Checking Client & Special") callCheck(nameVal) callCheck(clientModule) - warn("Getting origName") - origName = (nameVal and nameVal.Value) or child.Name - warn(`Got name: {origName}`) + print("Getting origName") + origName = nameVal and nameVal.Value or child.Name + prit(`Got name: {origName}`) - warn("Changing child parent...") + print("Changing child parent...") child.Parent = nil - warn("Destroying parent...") + print("Destroying parent...") if container and container:IsA("ScreenGui") and container.Name == "Adonis_Container" then spawn(function() - wait(0.5); - container:Destroy(); + wait(0.5) + container:Destroy() end) end if clientModule and clientModule:IsA("ModuleScript") then print("Debug: Loading the client?") local meta = require(clientModule) - warn(`Got metatable: {meta}`) + print(`Got metatable: {meta}`) if meta and type(meta) == "userdata" and tostring(meta) == "Adonis" then - local ran,ret = pcall(meta,{ + local ran, ret = pcall(meta, { Module = clientModule, Start = start, Loader = script, @@ -173,9 +172,9 @@ local function checkChild(child) Kill = Kill }) - warn(`Got return: {ret}`) + print(`Got return: {ret}`) if ret ~= "SUCCESS" then - warn(ret) + warn("Loading failed! Reason", ret) Kill("ACLI: Loading Error [Bad Module Return]") else print("Debug: The client was found and loaded?") @@ -188,6 +187,8 @@ local function checkChild(child) finderEvent = nil end end + else + warn(`Invalid metatable: {meta}!`) end end end @@ -198,21 +199,21 @@ local function scan(folder) if not doPcall(function() for i,child in folder:GetChildren() do if child.Name == "Adonis_Container" then - local client = child:FindFirstChildOfClass("Folder") or child:WaitForChild("Adonis_Client", 5); + local client = child:FindFirstChildOfClass("Folder") or child:WaitForChild("Adonis_Client", 5) if client then - doPcall(checkChild, client); + doPcall(checkChild, client) end end end - end) then warn("Scan failed?") Kick(player, "ACLI: Loading Error [Scan failed]"); end + end) then warn("Scan failed?") Kick(player, "ACLI: Loading Error [Scan failed]") end end --// Load client if _G.__CLIENTLOADER then - warn("ClientLoader already running;"); + warn("ClientLoader already running;") else - _G.__CLIENTLOADER = true; + _G.__CLIENTLOADER = true print("Debug: ACLI Loading?") setfenv(1, {}) @@ -221,64 +222,61 @@ else --lockCheck(script) --lockCheck(game) - warn("Checking CoreGui") + print("Checking CoreGui") if not Locked(game:GetService("CoreGui")) then warn("CoreGui not locked?") Kill("ACLI: Error") else - warn(`CoreGui Locked: {Locked(game:GetService("CoreGui"))}`) + print(`CoreGui Locked: {Locked(game:GetService("CoreGui"))}`) end - warn("Checking Services") + --print("Checking Services") --[[for i,service in next,services do doPcall(lockCheck, game:GetService(service)) end--]] - warn("Waiting for PlayerGui..."); - local playerGui = player:FindFirstChildOfClass("PlayerGui") or player:WaitForChild("PlayerGui", 600); + print("Waiting for PlayerGui...") + local playerGui = player:FindFirstChildOfClass("PlayerGui") or player:WaitForChild("PlayerGui", 600) if not playerGui then - warn("PlayerGui not found after 10 minutes"); - Kick(player, "ACLI: PlayerGui Never Appeared (Waited 10 Minutes)"); + warn("PlayerGui not found after 10 minutes") + Kick(player, "ACLI: PlayerGui Never Appeared (Waited 10 Minutes)") else - playerGui.Changed:Connect(function() - if playerGui.Name ~= "PlayerGui" then - playerGui.Name = "PlayerGui"; - end - end) + --playerGui.Changed:Connect(function() -- How about no + -- if playerGui.Name ~= "PlayerGui" then + -- playerGui.Name = "PlayerGui" + -- end + --end) end finderEvent = playerGui.ChildAdded:Connect(function(child) - warn("Child Added") + print("Child Added") if not foundClient and child.Name == "Adonis_Container" then - local client = child:FindFirstChildOfClass("Folder"); - doPcall(checkChild, client); + local client = child:FindFirstChildOfClass("Folder") + doPcall(checkChild, client) end end) - warn("Waiting and scanning (incase event fails)...") + print("Waiting and scanning (incase event fails)...") repeat - scan(playerGui); - wait(5); + scan(playerGui) + wait(5) until (time() - start > 600) or foundClient - warn(`Elapsed: {time() - start}`); - warn(`Timeout: {time() - start > 600}`); - warn(`Found Client: {foundClient}`); + print(`Elapsed: {time() - start}`) + print(`Timeout: {time() - start > 600}`) + print(`Found Client: {foundClient}`) - warn("Disconnecting finder event..."); + print("Disconnecting finder event...") if finderEvent then - finderEvent:Disconnect(); + finderEvent:Disconnect() end - warn("Checking if client found...") + print("Checking if client found...") if not foundClient then warn("Loading took too long") Kick(player, "\nACLI: [CLI-1162246] \nLoading Error [Took Too Long (>10 Minutes)]") else - print("Debug: Adonis loaded?") - warn("Client found") - warn("Finished") - warn(time()) + print("Debug: Adonis loaded? Took:", time()) end end diff --git a/MainModule/Server/Dependencies/ClientMover.client.luau b/MainModule/Server/Dependencies/ClientMover.client.luau index 4763b678b4..c8785865d8 100644 --- a/MainModule/Server/Dependencies/ClientMover.client.luau +++ b/MainModule/Server/Dependencies/ClientMover.client.luau @@ -1,14 +1,14 @@ --# selene: allow(empty_loop) --// Adonis Client Loader (Non-ReplicatedFirst Version) -local DebugMode = false; +local DebugMode = script.Parent:FindFirstChild("ADONIS_DEBUGMODE_ENABLED") ~= nil -local wait = wait; -local time = time; -local pcall = pcall; -local xpcall = xpcall; -local setfenv = setfenv; -local tostring = tostring; +local wait = task.wait +local time = time +local pcall = pcall +local xpcall = xpcall +local setfenv = setfenv +local tostring = tostring -- This stops all of the public Adonis bypasses. Though they would still be detected in time but it may be better to kick them before load?? do @@ -128,27 +128,28 @@ do end, function(err) task_spawn(loadingDetected, err) while true do end end) end -local players = game:GetService("Players"); -local player = players.LocalPlayer; -local folder = script.Parent; -local container = folder.Parent; -local Kick = player.Kick; -local module = folder:WaitForChild("Client"); -local target = player; -local realPrint = print; -local realWarn = warn; -local start = time(); +-- ccuser44 was here ^_^ +local players = game:GetService("Players") +local player = players.LocalPlayer +local folder = script.Parent +local container = folder.Parent +local Kick = player.Kick +local module = folder:WaitForChild("Client") +local target = player +local realPrint = print +local realWarn = warn +local start = time() local function print(...) - --realPrint(...) -end - -local function warn(str) if DebugMode or player.UserId == 1237666 then - realWarn(`ACLI: {str}`) + realPrint("ACLI:", ...) end end +local function warn(...) + realWarn("ACLI:", ...) +end + local function Kill(info) if DebugMode then warn(info) return end pcall(function() Kick(player, info) end) @@ -157,22 +158,21 @@ local function Kill(info) end local function Locked(obj) - return (not obj and true) or not pcall(function() return obj.GetFullName(obj) end) + return not obj and true or not pcall(function() return obj.GetFullName(obj) end) end local function loadingTime() - warn("LoadingTime Called") - setfenv(1,{}) - warn(tostring(time() - start)) + setfenv(1, {}) + print("LoadingTime Called:", tostring(time() - start)) end local function callCheck(child) - warn(`CallCheck: {child}`) + print(`CallCheck: {child}`) if Locked(child) then warn("Child locked?") Kill("ACLI: Locked") else - warn("Child not locked") + print("Child not locked") xpcall(function() return child[{}] end, function() @@ -195,46 +195,44 @@ local function doPcall(func, ...) end if module and module:IsA("ModuleScript") then - warn("Loading Folder...") + print("Loading Folder...") local nameVal local origName local depsFolder local clientModule - warn("Waiting for Client & Special") + print("Waiting for Client & Special") nameVal = folder:WaitForChild("Special", 30) - warn("Checking Client & Special") + print("Checking Client & Special") --callCheck(nameVal) --callCheck(clientModule) - warn("Getting origName") - origName = (nameVal and nameVal.Value) or folder.Name - warn(`Got name: {origName}`) + print("Getting origName") + origName = nameVal and nameVal.Value or folder.Name + print(`Got name: {origName}`) - warn("Removing old client folder...") - local starterPlayer = game:GetService("StarterPlayer"); - local playerScripts = starterPlayer:FindFirstChildOfClass("StarterPlayerScripts"); - local found = playerScripts:FindFirstChild(folder.Name); - warn(`FOUND?! {found}`); - warn(`LOOKED FOR : {folder.Name}`) + print("Removing old client folder...") + local starterPlayer = game:GetService("StarterPlayer") + local playerScripts = starterPlayer:FindFirstChildOfClass("StarterPlayerScripts") + local found = playerScripts:FindFirstChild(folder.Name) + print(`FOUND?! {found}`) + print(`LOOKED FOR : {folder.Name}`) if found then - print("REMOVED!") - found.Parent = nil --found:Destroy(); + warn("REMOVED!") + found.Parent = nil --found:Destroy() end --// Sometimes we load a little too fast and generate a warning from Roblox so we need to introduce some (minor) artificial loading lag... - warn("Changing child parent...") - folder.Name = ""; - wait(0.01); - folder.Parent = nil; --// We cannot do this assynchronously or it will disconnect events that manage to connect before it changes parent to nil... - - warn("Destroying parent...") + print("Changing child parent...") + folder.Name = "" + wait(0.01) + folder.Parent = nil --// We cannot do this assynchronously or it will disconnect events that manage to connect before it changes parent to nil... print("Debug: Loading the client?") local meta = require(module) - warn(`Got metatable: {meta}`) + print(`Got metatable: {meta}`) if meta and type(meta) == "userdata" and tostring(meta) == "Adonis" then - local ran,ret = pcall(meta,{ + local ran,ret = pcall(meta, { Module = module, Start = start, Loader = script, @@ -245,17 +243,17 @@ if module and module:IsA("ModuleScript") then Kill = Kill }) - warn(`Got return: {ret}`) + print(`Got return: {ret}`) if ret ~= "SUCCESS" then - realWarn(ret) + warn("Loading failed! Reason", ret) Kill("ACLI: Loading Error [Bad Module Return]") else print("Debug: The client was found and loaded?") - warn("Client Loaded") - if container and container:IsA("ScreenGui") then - container.Parent = nil --container:Destroy(); + container.Parent = nil --container:Destroy() end end + else + warn(`Invalid metatable: {meta}!`) end end From e87874b92bfa8f22f5930a7a58b20fed093e7eec Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:56:11 +0200 Subject: [PATCH 057/189] Add multithreading to FiOne (#1545) * Add multithreading handler * Rename MainModule/Server/Shared/FiOne.lua to MainModule/Server/Shared/FiOne/init.lua * Create Runner.lua * Fix typo * Add todo * Update and rename Runner.lua to Runner.server.lua * Create Runner.meta.json * Fix disabling * Fix runner naming * Fix typo * Finally fix multithreading * Create LocalRunner.meta.json * Create LocalRunner.server.lua * Use more AST optimisations * Use more AST optimisations * Fix typo * Fix typo --- .../Server/Shared/FiOne/LocalRunner.meta.json | 6 + .../Shared/FiOne/LocalRunner.server.lua | 21 + .../Server/Shared/FiOne/Runner.meta.json | 5 + .../Server/Shared/FiOne/Runner.server.lua | 21 + MainModule/Server/Shared/FiOne/init.lua | 1073 +++++++++++++++++ 5 files changed, 1126 insertions(+) create mode 100644 MainModule/Server/Shared/FiOne/LocalRunner.meta.json create mode 100644 MainModule/Server/Shared/FiOne/LocalRunner.server.lua create mode 100644 MainModule/Server/Shared/FiOne/Runner.meta.json create mode 100644 MainModule/Server/Shared/FiOne/Runner.server.lua create mode 100644 MainModule/Server/Shared/FiOne/init.lua diff --git a/MainModule/Server/Shared/FiOne/LocalRunner.meta.json b/MainModule/Server/Shared/FiOne/LocalRunner.meta.json new file mode 100644 index 0000000000..6233c02da7 --- /dev/null +++ b/MainModule/Server/Shared/FiOne/LocalRunner.meta.json @@ -0,0 +1,6 @@ +{ + "properties": { + "RunContext": "Client", + "Disabled": true + } +} diff --git a/MainModule/Server/Shared/FiOne/LocalRunner.server.lua b/MainModule/Server/Shared/FiOne/LocalRunner.server.lua new file mode 100644 index 0000000000..cef01f0fc7 --- /dev/null +++ b/MainModule/Server/Shared/FiOne/LocalRunner.server.lua @@ -0,0 +1,21 @@ +--!native +--!optimize 2 +--[[ + Description: Wrapper for FiOne multithread closures + Author: github@ccuser44 + Date: 2024 + License: CC0 +]] + +local fiOne = require(script.FiOne) +local actor = script.Parent +local event = script.ReturnPass +local callback = function(...) return ... end + +actor:BindToMessage("wrap_state", function(proto, env, upval) + callback = fiOne.wrap_state(proto, env, upval) +end) + +actor:BindToMessageParallel("run_callback", function(tag, ...) + event:Fire(tag, pcall(callback, ...)) +end) diff --git a/MainModule/Server/Shared/FiOne/Runner.meta.json b/MainModule/Server/Shared/FiOne/Runner.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Shared/FiOne/Runner.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Shared/FiOne/Runner.server.lua b/MainModule/Server/Shared/FiOne/Runner.server.lua new file mode 100644 index 0000000000..cef01f0fc7 --- /dev/null +++ b/MainModule/Server/Shared/FiOne/Runner.server.lua @@ -0,0 +1,21 @@ +--!native +--!optimize 2 +--[[ + Description: Wrapper for FiOne multithread closures + Author: github@ccuser44 + Date: 2024 + License: CC0 +]] + +local fiOne = require(script.FiOne) +local actor = script.Parent +local event = script.ReturnPass +local callback = function(...) return ... end + +actor:BindToMessage("wrap_state", function(proto, env, upval) + callback = fiOne.wrap_state(proto, env, upval) +end) + +actor:BindToMessageParallel("run_callback", function(tag, ...) + event:Fire(tag, pcall(callback, ...)) +end) diff --git a/MainModule/Server/Shared/FiOne/init.lua b/MainModule/Server/Shared/FiOne/init.lua new file mode 100644 index 0000000000..b01882a2e1 --- /dev/null +++ b/MainModule/Server/Shared/FiOne/init.lua @@ -0,0 +1,1073 @@ +--!native +--!nolint TableOperations +--# selene: allow(divide_by_zero, multiple_statements, mixed_table) +--[[ +FiOne +Copyright (C) 2021 Rerumu + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +]] -- + +local lua_wrap_state +local stm_lua_func + +-- SETLIST config +local FIELDS_PER_FLUSH = 50 + +-- remap for better lookup +local OPCODE_RM = { + -- level 1 + [22] = 18, -- JMP + [31] = 8, -- FORLOOP + [33] = 28, -- TFORLOOP + -- level 2 + [0] = 3, -- MOVE + [1] = 13, -- LOADK + [2] = 23, -- LOADBOOL + [26] = 33, -- TEST + -- level 3 + [12] = 1, -- ADD + [13] = 6, -- SUB + [14] = 10, -- MUL + [15] = 16, -- DIV + [16] = 20, -- MOD + [17] = 26, -- POW + [18] = 30, -- UNM + [19] = 36, -- NOT + -- level 4 + [3] = 0, -- LOADNIL + [4] = 2, -- GETUPVAL + [5] = 4, -- GETGLOBAL + [6] = 7, -- GETTABLE + [7] = 9, -- SETGLOBAL + [8] = 12, -- SETUPVAL + [9] = 14, -- SETTABLE + [10] = 17, -- NEWTABLE + [20] = 19, -- LEN + [21] = 22, -- CONCAT + [23] = 24, -- EQ + [24] = 27, -- LT + [25] = 29, -- LE + [27] = 32, -- TESTSET + [32] = 34, -- FORPREP + [34] = 37, -- SETLIST + -- level 5 + [11] = 5, -- SELF + [28] = 11, -- CALL + [29] = 15, -- TAILCALL + [30] = 21, -- RETURN + [35] = 25, -- CLOSE + [36] = 31, -- CLOSURE + [37] = 35, -- VARARG +} + +-- opcode types for getting values +local OPCODE_T = { + [0] = "ABC", + "ABx", + "ABC", + "ABC", + "ABC", + "ABx", + "ABC", + "ABx", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "AsBx", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "ABC", + "AsBx", + "AsBx", + "ABC", + "ABC", + "ABC", + "ABx", + "ABC", +} + +local OPCODE_M = { + [0] = {b = "OpArgR", c = "OpArgN"}, + {b = "OpArgK", c = "OpArgN"}, + {b = "OpArgU", c = "OpArgU"}, + {b = "OpArgR", c = "OpArgN"}, + {b = "OpArgU", c = "OpArgN"}, + {b = "OpArgK", c = "OpArgN"}, + {b = "OpArgR", c = "OpArgK"}, + {b = "OpArgK", c = "OpArgN"}, + {b = "OpArgU", c = "OpArgN"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgU", c = "OpArgU"}, + {b = "OpArgR", c = "OpArgK"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgR", c = "OpArgN"}, + {b = "OpArgR", c = "OpArgN"}, + {b = "OpArgR", c = "OpArgN"}, + {b = "OpArgR", c = "OpArgR"}, + {b = "OpArgR", c = "OpArgN"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgK", c = "OpArgK"}, + {b = "OpArgR", c = "OpArgU"}, + {b = "OpArgR", c = "OpArgU"}, + {b = "OpArgU", c = "OpArgU"}, + {b = "OpArgU", c = "OpArgU"}, + {b = "OpArgU", c = "OpArgN"}, + {b = "OpArgR", c = "OpArgN"}, + {b = "OpArgR", c = "OpArgN"}, + {b = "OpArgN", c = "OpArgU"}, + {b = "OpArgU", c = "OpArgU"}, + {b = "OpArgN", c = "OpArgN"}, + {b = "OpArgU", c = "OpArgN"}, + {b = "OpArgU", c = "OpArgN"}, +} + +local intiger_types = { + [1] = buffer.readu8, + [2] = buffer.readu16, + [4] = buffer.readu32, +} + +local intiger_write_type = { + [1] = buffer.writeu8, + [2] = buffer.writeu16, + [4] = buffer.writeu32, +} + +-- int rd_int(string src, int s, int e) +-- @src - Source binary string +-- @s - Start index of a little endian integer +-- @e - End index of the integer +local function rd_int(src, s, e) + return intiger_types[e - s](src, s) +end + +-- number big_endian(string src, int s) +-- @callback - Function to be called after bitswap +-- @byte_count - Lenght of the number +local function big_endian(callback, byte_count) + return function(src, s, e) + local e, write = (e or byte_count) * 8, intiger_write_type[e] + write(src, s, bit32.rshift(bit32.byteswap(rd_int(src, s, e)), 32 - e)) + local n2 = callback(src, s) + write(src, s, bit32.rshift(bit32.byteswap(rd_int(src, s, e)), 32 - e)) + + return n2 + end +end + +-- to avoid nested ifs in deserializing +local float_types = { + [4] = {little = buffer.readf32, big = big_endian(buffer.readf32)}, + [8] = {little = buffer.readf64, big = big_endian(buffer.readf64)}, +} + +-- byte stm_byte(Stream S) +-- @S - Stream object to read from +local function stm_byte(S) + local idx = S.index + local bt = buffer.readu8(S.source, idx) + + S.index = idx + 1 + return bt +end + +-- string stm_string(Stream S, int len) +-- @S - Stream object to read from +-- @len - Length of string being read +local function stm_string(S, len) + local str = buffer.readstring(S.source, S.index, len) + + S.index += len + return str +end + +-- string stm_lstring(Stream S) +-- @S - Stream object to read from +local function stm_lstring(S) + local len = S:s_szt() + local str + + if len ~= 0 then str = string.sub(stm_string(S, len), 1, -2) end + + return str +end + +-- fn cst_int_rdr(string src, int len, fn func) +-- @len - Length of type for reader +-- @func - Reader callback +local function cst_int_rdr(len, func) + return function(S) + local pos = S.index + len + local int = func(S.source, S.index, pos) + S.index = pos + + return int + end +end + +-- fn cst_flt_rdr(string src, int len, fn func) +-- @len - Length of type for reader +-- @func - Reader callback +local function cst_flt_rdr(len, func) + return function(S) + local flt = func(S.source, S.index) + S.index = S.index + len + + return flt + end +end + +local function stm_inst_list(S) + local len = S:s_int() + local list = table.create(len) + + for i = 1, len do + local ins = S:s_ins() + local op = bit32.band(ins, 0x3F) + local args = OPCODE_T[op] + local mode = OPCODE_M[op] + local data = {value = ins, op = OPCODE_RM[op], A = bit32.band(bit32.rshift(ins, 6), 0xFF)} + + if args == "ABC" then + data.B = bit32.band(bit32.rshift(ins, 23), 0x1FF) + data.C = bit32.band(bit32.rshift(ins, 14), 0x1FF) + data.is_KB = mode.b == "OpArgK" and data.B > 0xFF -- post process optimization + data.is_KC = mode.c == "OpArgK" and data.C > 0xFF + + if op == 10 then -- decode NEWTABLE array size, store it as constant value + local e = bit32.band(bit32.rshift(data.B, 3), 31) + if e == 0 then + data.const = data.B + else + data.const = bit32.lshift(bit32.band(data.B, 7) + 8, e - 1) + end + end + elseif args == "ABx" then + data.Bx = bit32.band(bit32.rshift(ins, 14), 0x3FFFF) + data.is_K = mode.b == "OpArgK" + elseif args == "AsBx" then + data.sBx = bit32.band(bit32.rshift(ins, 14), 0x3FFFF) - 131071 + end + + list[i] = data + end + + return list +end + +local function stm_const_list(S) + local len = S:s_int() + local list = table.create(len) + + for i = 1, len do + local tt = stm_byte(S) + local k + + if tt == 1 then + k = stm_byte(S) ~= 0 + elseif tt == 3 then + k = S:s_num() + elseif tt == 4 then + k = stm_lstring(S) + end + + list[i] = k -- offset +1 during instruction decode + end + + return list +end + +local function stm_sub_list(S, src) + local len = S:s_int() + local list = table.create(len) + + for i = 1, len do + list[i] = stm_lua_func(S, src) -- offset +1 in CLOSURE + end + + return list +end + +local function stm_line_list(S) + local len = S:s_int() + local list = table.create(len) + + for i = 1, len do list[i] = S:s_int() end + + return list +end + +local function stm_loc_list(S) + local len = S:s_int() + local list = table.create(len) + + for i = 1, len do list[i] = {varname = stm_lstring(S), startpc = S:s_int(), endpc = S:s_int()} end + + return list +end + +local function stm_upval_list(S) + local len = S:s_int() + local list = table.create(len) + + for i = 1, len do list[i] = stm_lstring(S) end + + return list +end + +function stm_lua_func(S, psrc) + local proto = {} + local src = stm_lstring(S) or psrc -- source is propagated + + proto.source = src -- source name + + S:s_int() -- line defined + S:s_int() -- last line defined + + proto.num_upval = stm_byte(S) -- num upvalues + proto.num_param = stm_byte(S) -- num params + + stm_byte(S) -- vararg flag + proto.max_stack = stm_byte(S) -- max stack size + + proto.code = stm_inst_list(S) + proto.const = stm_const_list(S) + proto.subs = stm_sub_list(S, src) + proto.lines = stm_line_list(S) + + stm_loc_list(S) + stm_upval_list(S) + + -- post process optimization + for _, v in ipairs(proto.code) do + if v.is_K then + v.const = proto.const[v.Bx + 1] -- offset for 1 based index + else + if v.is_KB then v.const_B = proto.const[v.B - 0xFF] end + + if v.is_KC then v.const_C = proto.const[v.C - 0xFF] end + end + end + + return proto +end + +local function lua_bc_to_state(src) + -- func reader + local rdr_func + + -- header flags + local little + local size_int + local size_szt + local size_ins + local size_num + local flag_int + + -- stream object + local stream = { + -- data + index = 0, + source = typeof(src) == "buffer" and src or buffer.fromstring(src), + } + + assert(stm_string(stream, 4) == "\27Lua", "invalid Lua signature") + assert(stm_byte(stream) == 0x51, "invalid Lua version") + assert(stm_byte(stream) == 0, "invalid Lua format") + + little = stm_byte(stream) ~= 0 + size_int = stm_byte(stream) + size_szt = stm_byte(stream) + size_ins = stm_byte(stream) + size_num = stm_byte(stream) + flag_int = stm_byte(stream) ~= 0 + + rdr_func = little and rd_int or big_endian(rd_int) + stream.s_int = cst_int_rdr(size_int, rdr_func) + stream.s_szt = cst_int_rdr(size_szt, rdr_func) + stream.s_ins = cst_int_rdr(size_ins, rdr_func) + + if flag_int then + stream.s_num = cst_int_rdr(size_num, rdr_func) + elseif float_types[size_num] then + stream.s_num = cst_flt_rdr(size_num, float_types[size_num][little and "little" or "big"]) + else + error("unsupported float size") + end + + return stm_lua_func(stream, "@virtual") +end + +local function close_lua_upvalues(list, index) + for i, uv in pairs(list) do + if uv.index >= index then + uv.value = uv.store[uv.index] -- store value + uv.store = uv + uv.index = "value" -- self reference + list[i] = nil + end + end +end + +local function open_lua_upvalue(list, index, memory) + local prev = list[index] + + if not prev then + prev = {index = index, store = memory} + list[index] = prev + end + + return prev +end + +local function on_lua_error(failed, err) + local src = failed.source + local line = failed.lines[failed.pc - 1] + + error(string.format("%s:%i: %s", src, line, err), 0) +end + +-- ccuser44 added multithreading support +-- TODO: Create multiple threads for closure and use a module and/or round robin load balancer to distribute usage +local isClient, actorContainer +local function new_threaded_closure(proto, env, upval) + isClient = isClient or game:GetService("RunService"):IsClient() + actorContainer = actorContainer or script + local actor = Instance.new("Actor") + local clone = script:Clone() + local runner = script[isClient and "LocalRunner" or "Runner"]:Clone() + local event = Instance.new("BindableEvent") + local tag = 0 + + for _, v in clone:GetChildren() do + if v:IsA("Actor") then + v:Destroy() + end + end + + event.Name = "ReturnPass" + event.Parent = runner + clone.Parent = runner + runner.Disabled = false + runner.Parent = actor + actor.Name = "MultithreadRunner_"..tostring(math.random()) + actor.Parent = actorContainer + + task.defer(actor.SendMessage, actor, "wrap_state", proto, env, upval) + + task.wait() + + return function(...) + tag = tag + 1 + local currentTag = tag + local routine = coroutine.running() + local connection = event.Event:Connect(function(eventTag, ...) + if eventTag == currentTag then + coroutine.resume(routine, ...) + end + end) + + task.defer(actor.SendMessage, actor, "run_callback", currentTag, ...) + + local args = table.pack(coroutine.yield()) + connection:Disconnect() + + if not args[1] then + error(args[2], 2) + end + + return table.unpack(args, 2) + end +end + +local function run_lua_func(state, env, upvals) + local code = state.code + local subs = state.subs + local vararg = state.vararg + + local top_index = -1 + local open_list = {} + local memory = state.memory + local pc = state.pc + + while true do + local inst = code[pc] + local op = inst.op + pc = pc + 1 + + if op < 18 then + if op < 8 then + if op < 3 then + if op < 1 then + --[[LOADNIL]] + for i = inst.A, inst.B do memory[i] = nil end + elseif op > 1 then + --[[GETUPVAL]] + local uv = upvals[inst.B] + + memory[inst.A] = uv.store[uv.index] + else + --[[ADD]] + local lhs, rhs + + if inst.is_KB then + lhs = inst.const_B + else + lhs = memory[inst.B] + end + + if inst.is_KC then + rhs = inst.const_C + else + rhs = memory[inst.C] + end + + memory[inst.A] = lhs + rhs + end + elseif op > 3 then + if op < 6 then + if op > 4 then + --[[SELF]] + local A = inst.A + local B = inst.B + local index + + if inst.is_KC then + index = inst.const_C + else + index = memory[inst.C] + end + + memory[A + 1] = memory[B] + memory[A] = memory[B][index] + else + --[[GETGLOBAL]] + memory[inst.A] = env[inst.const] + end + elseif op > 6 then + --[[GETTABLE]] + local index + + if inst.is_KC then + index = inst.const_C + else + index = memory[inst.C] + end + + memory[inst.A] = memory[inst.B][index] + else + --[[SUB]] + local lhs, rhs + + if inst.is_KB then + lhs = inst.const_B + else + lhs = memory[inst.B] + end + + if inst.is_KC then + rhs = inst.const_C + else + rhs = memory[inst.C] + end + + memory[inst.A] = lhs - rhs + end + else --[[MOVE]] + memory[inst.A] = memory[inst.B] + end + elseif op > 8 then + if op < 13 then + if op < 10 then + --[[SETGLOBAL]] + env[inst.const] = memory[inst.A] + elseif op > 10 then + if op < 12 then + --[[CALL]] + local A = inst.A + local B = inst.B + local C = inst.C + local params + + if B == 0 then + params = top_index - A + else + params = B - 1 + end + + local ret_list = table.pack(memory[A](table.unpack(memory, A + 1, A + params))) + local ret_num = ret_list.n + + if C == 0 then + top_index = A + ret_num - 1 + else + ret_num = C - 1 + end + + table.move(ret_list, 1, ret_num, A, memory) + else + --[[SETUPVAL]] + local uv = upvals[inst.B] + + uv.store[uv.index] = memory[inst.A] + end + else + --[[MUL]] + local lhs, rhs + + if inst.is_KB then + lhs = inst.const_B + else + lhs = memory[inst.B] + end + + if inst.is_KC then + rhs = inst.const_C + else + rhs = memory[inst.C] + end + + memory[inst.A] = lhs * rhs + end + elseif op > 13 then + if op < 16 then + if op > 14 then + --[[TAILCALL]] + local A = inst.A + local B = inst.B + local params + + if B == 0 then + params = top_index - A + else + params = B - 1 + end + + close_lua_upvalues(open_list, 0) + + return memory[A](table.unpack(memory, A + 1, A + params)) + else + --[[SETTABLE]] + local index, value + + if inst.is_KB then + index = inst.const_B + else + index = memory[inst.B] + end + + if inst.is_KC then + value = inst.const_C + else + value = memory[inst.C] + end + + memory[inst.A][index] = value + end + elseif op > 16 then + --[[NEWTABLE]] + memory[inst.A] = table.create(inst.const) -- inst.const contains array size + else + --[[DIV]] + local lhs, rhs + + if inst.is_KB then + lhs = inst.const_B + else + lhs = memory[inst.B] + end + + if inst.is_KC then + rhs = inst.const_C + else + rhs = memory[inst.C] + end + + memory[inst.A] = lhs / rhs + end + else + --[[LOADK]] + memory[inst.A] = inst.const + end + else + --[[FORLOOP]] + local A = inst.A + local step = memory[A + 2] + local index = memory[A] + step + local limit = memory[A + 1] + local loops + + if step == math.abs(step) then + loops = index <= limit + else + loops = index >= limit + end + + if loops then + memory[A] = index + memory[A + 3] = index + pc = pc + inst.sBx + end + end + elseif op > 18 then + if op < 28 then + if op < 23 then + if op < 20 then + --[[LEN]] + memory[inst.A] = #memory[inst.B] + elseif op > 20 then + if op < 22 then + --[[RETURN]] + local A = inst.A + local B = inst.B + local len + + if B == 0 then + len = top_index - A + 1 + else + len = B - 1 + end + + close_lua_upvalues(open_list, 0) + + return table.unpack(memory, A, A + len - 1) + else + --[[CONCAT]] + local B, C = inst.B, inst.C + local success, str = pcall(table.concat, memory, "", B, C) + + if not success then + str = memory[B] + + for i = B + 1, C do str = str .. memory[i] end + end + + memory[inst.A] = str + end + else + --[[MOD]] + local lhs, rhs + + if inst.is_KB then + lhs = inst.const_B + else + lhs = memory[inst.B] + end + + if inst.is_KC then + rhs = inst.const_C + else + rhs = memory[inst.C] + end + + memory[inst.A] = lhs % rhs + end + elseif op > 23 then + if op < 26 then + if op > 24 then + --[[CLOSE]] + close_lua_upvalues(open_list, inst.A) + else + --[[EQ]] + local lhs, rhs + + if inst.is_KB then + lhs = inst.const_B + else + lhs = memory[inst.B] + end + + if inst.is_KC then + rhs = inst.const_C + else + rhs = memory[inst.C] + end + + if (lhs == rhs) == (inst.A ~= 0) then pc = pc + code[pc].sBx end + + pc = pc + 1 + end + elseif op > 26 then + --[[LT]] + local lhs, rhs + + if inst.is_KB then + lhs = inst.const_B + else + lhs = memory[inst.B] + end + + if inst.is_KC then + rhs = inst.const_C + else + rhs = memory[inst.C] + end + + if (lhs < rhs) == (inst.A ~= 0) then pc = pc + code[pc].sBx end + + pc = pc + 1 + else + --[[POW]] + local lhs, rhs + + if inst.is_KB then + lhs = inst.const_B + else + lhs = memory[inst.B] + end + + if inst.is_KC then + rhs = inst.const_C + else + rhs = memory[inst.C] + end + + memory[inst.A] = lhs ^ rhs + end + else + --[[LOADBOOL]] + memory[inst.A] = inst.B ~= 0 + + if inst.C ~= 0 then pc = pc + 1 end + end + elseif op > 28 then + if op < 33 then + if op < 30 then + --[[LE]] + local lhs, rhs + + if inst.is_KB then + lhs = inst.const_B + else + lhs = memory[inst.B] + end + + if inst.is_KC then + rhs = inst.const_C + else + rhs = memory[inst.C] + end + + if (lhs <= rhs) == (inst.A ~= 0) then pc = pc + code[pc].sBx end + + pc = pc + 1 + elseif op > 30 then + if op < 32 then + --[[CLOSURE]] + local sub = subs[inst.Bx + 1] -- offset for 1 based index + local nups = sub.num_upval + local uvlist + + if nups ~= 0 then + uvlist = table.create(nups - 1) + + for i = 1, nups do + local pseudo = code[pc + i - 1] + + if pseudo.op == OPCODE_RM[0] then -- @MOVE + uvlist[i - 1] = open_lua_upvalue(open_list, pseudo.B, memory) + elseif pseudo.op == OPCODE_RM[4] then -- @GETUPVAL + uvlist[i - 1] = upvals[pseudo.B] + end + end + + pc = pc + nups + end + + memory[inst.A] = (sub.source and string.sub(sub.source, 1, 39) == "SUPER_SECRET_ADONIS_MULTITHREAD_PREFIX_") and new_threaded_closure(sub, env, uvlist) or lua_wrap_state(sub, env, uvlist) + else + --[[TESTSET]] + local A = inst.A + local B = inst.B + + if (not memory[B]) ~= (inst.C ~= 0) then + memory[A] = memory[B] + pc = pc + code[pc].sBx + end + pc = pc + 1 + end + else + --[[UNM]] + memory[inst.A] = -memory[inst.B] + end + elseif op > 33 then + if op < 36 then + if op > 34 then + --[[VARARG]] + local A = inst.A + local len = inst.B + + if len == 0 then + len = vararg.len + top_index = A + len - 1 + end + + table.move(vararg.list, 1, len, A, memory) + else + --[[FORPREP]] + local A = inst.A + local init, limit, step + + init = assert(tonumber(memory[A]), "`for` initial value must be a number") + limit = assert(tonumber(memory[A + 1]), "`for` limit must be a number") + step = assert(tonumber(memory[A + 2]), "`for` step must be a number") + + memory[A] = init - step + memory[A + 1] = limit + memory[A + 2] = step + + pc = pc + inst.sBx + end + elseif op > 36 then + --[[SETLIST]] + local A = inst.A + local C = inst.C + local len = inst.B + local tab = memory[A] + local offset + + if len == 0 then len = top_index - A end + + if C == 0 then + C = inst[pc].value + pc = pc + 1 + end + + offset = (C - 1) * FIELDS_PER_FLUSH + + table.move(memory, A + 1, A + len, offset + 1, tab) + else + --[[NOT]] + memory[inst.A] = not memory[inst.B] + end + else + --[[TEST]] + if (not memory[inst.A]) ~= (inst.C ~= 0) then pc = pc + code[pc].sBx end + pc = pc + 1 + end + else + --[[TFORLOOP]] + local A = inst.A + local func = memory[A] + local state = memory[A + 1] + local index = memory[A + 2] + local base = A + 3 + local vals + + -- === Luau compatibility - General iteration begin === + -- // ccuser44 added support for generic iteration + -- (Please don't use general iteration in vanilla Lua code) + if not index and not state and type(func) == "table" then + -- Hacky check to see if __metatable is locked + local canGetMt = pcall(getmetatable, func) + local isMtLocked = canGetMt and not pcall(setmetatable, func, getmetatable(func)) or not canGetMt + local metatable = canGetMt and getmetatable(func) + + if not (table.isfrozen and table.isfrozen(func)) and isMtLocked and not metatable then + warn("[FiOne]: The table has a metatable buts it's hidden, __iter and __call won't work in forloop.") + end + + if not (type(metatable) == "table" and rawget(metatable, "__call")) then + func, state, index = (type(metatable) == "table" and rawget(metatable, "__iter") or next), func, nil + memory[A], memory[A + 1], memory[A + 2] = func, state, index + end + end + -- === Luau compatibility - General iteration end === + + vals = {func(state, index)} + + table.move(vals, 1, inst.C, base, memory) + + if memory[base] ~= nil then + memory[A + 2] = memory[base] + pc = pc + code[pc].sBx + end + + pc = pc + 1 + end + else + --[[JMP]] + pc = pc + inst.sBx + end + + state.pc = pc + end +end + +function lua_wrap_state(proto, env, upval) + local function wrapped(...) + local passed = table.pack(...) + local memory = table.create(proto.max_stack) + local vararg = {len = 0, list = {}} + + table.move(passed, 1, proto.num_param, 0, memory) + + if proto.num_param < passed.n then + local start = proto.num_param + 1 + local len = passed.n - proto.num_param + + vararg.len = len + table.move(passed, start, start + len - 1, 1, vararg.list) + end + + local state = {vararg = vararg, memory = memory, code = proto.code, subs = proto.subs, pc = 1} + + local result = table.pack(pcall(run_lua_func, state, env, upval)) + + if result[1] then + return table.unpack(result, 2, result.n) + else + local failed = {pc = state.pc, source = proto.source, lines = proto.lines} + + on_lua_error(failed, result[2]) + + return + end + end + + return wrapped +end + +return setmetatable({ + bc_to_state = lua_bc_to_state, + wrap_state = lua_wrap_state, + OPCODE_RM = OPCODE_RM, + OPCODE_T = OPCODE_T, + OPCODE_M = OPCODE_M, +}, {__call = function(_, BCode, Env) -- Backwards compatibility for legacy rerubi usage + return lua_wrap_state(lua_bc_to_state(BCode), Env or {}) +end}) From 84c26661585f7f2c3020b89a953471bd52d7d66a Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Tue, 12 Nov 2024 20:57:37 +0000 Subject: [PATCH 058/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 8ac9c9cb24..0d44fde72c 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -38,6 +38,12 @@ return { "(Git/ccuser44) Allow local loading of gerald (#1668)"; "(Git/omwat) Remove audit logs (#1698)"; "(Git/ccuser44) Fix client side warn handling (#1683)"; + "(Git/ccuser44) Add new encryption function (#1704)"; + "(Git/ccuser44) Fix Adonis cleanup not being editable (#1703)"; + "(Git/ccuser44) Fix error with encryption in nightly (#1702)"; + "(Git/ccuser44) Make ClientMover respect debugmode (#1680)"; + "(Git/ccuser44) Add multithreading to FiOne (#1545)"; + "(Git/ccuser44) Convert test case to nightly mode (#1669)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 2012c366b5135f7f6bb4189328b2f67b213ca7c5 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 23:08:22 +0200 Subject: [PATCH 059/189] Optimize linkedlists (#1695) --- .../Server/Shared/DoubleLinkedList.luau | 142 +++++++++--------- 1 file changed, 67 insertions(+), 75 deletions(-) diff --git a/MainModule/Server/Shared/DoubleLinkedList.luau b/MainModule/Server/Shared/DoubleLinkedList.luau index 3f74cfac80..4b6301730a 100644 --- a/MainModule/Server/Shared/DoubleLinkedList.luau +++ b/MainModule/Server/Shared/DoubleLinkedList.luau @@ -34,27 +34,26 @@ function LinkNode:Destroy() end --[==[ - LinkedNode end + LinkedNode end ]==] function LinkedList.new() local self = setmetatable({}, LinkedList) - + self.snode = nil self.enode = nil - + self.count = 0 - + return self end function LinkedList:IsReal() - --// this is a ghost function - --// don't remove it + --// this is a ghost function + --// don't remove it end function LinkedList:AddStart(data) - local old = self.snode local newNode = LinkNode.new(data) newNode:setprev(nil) @@ -65,13 +64,11 @@ function LinkedList:AddStart(data) end newNode:setnext(old) self.snode = newNode - + self.count += 1 - end function LinkedList:AddEnd(data) - local old = self.enode local newNode = LinkNode.new(data) newNode:setnext(nil) @@ -82,9 +79,8 @@ function LinkedList:AddEnd(data) end newNode:setprev(old) self.enode = newNode - + self.count += 1 - end function LinkedList:AddToStartAndRemoveEndIfEnd(data, limit) @@ -95,79 +91,75 @@ function LinkedList:AddToStartAndRemoveEndIfEnd(data, limit) end function LinkedList:AddBetweenNodes(data, left, right) - if not left or not right then return false end - + local newNode = LinkNode.new(data) newNode:setnext() newNode:setprev() - + left:setnext(newNode) right:setprev(newNode) - + self.count += 1 - end function LinkedList:RemoveNode(node) - local prev = node.prev local nextN = node.next if self.snode == node then self.snode = nextN end - + if self.enode == node then self.enode = prev end - + if nextN then nextN:setprev(prev) end if prev then prev:setnext(nextN) end - + node:setnext(nil) node:setprev(nil) - + node:Destroy() - + self.count -= 1 - end -function LinkedList:Get(val : any) - local nodes = {} +function LinkedList:Get(val: any) + local nodes = table.create(self.count) local curr = self.snode - local tinsert = table.insert + while curr and type(curr) == "table" do if val then - --// Pass a function and Adonis will pass through the current node into it - --// Return true to add it to the "list" - --// Final list will be returned after the call - --// Passed value: - --[==[ - Node: - .data: The data inside of the node - .next: The next node in the list - .prev: The previous node in the list - ]==] - if type(val) == "function" then - local success, found = pcall(val, curr) - if success and found then - tinsert(nodes, curr) - end - else - if curr.data == val then - tinsert(nodes, curr) - end - end + --// Pass a function and Adonis will pass through the current node into it + --// Return true to add it to the "list" + --// Final list will be returned after the call + --// Passed value: + --[==[ + Node: + .data: The data inside of the node + .next: The next node in the list + .prev: The previous node in the list + ]==] + if type(val) == "function" then + local success, found = pcall(val, curr) + if success and found then + table.insert(nodes, curr) + end + else + if curr.data == val then + table.insert(nodes, curr) + end + end else - tinsert(nodes, curr) + table.insert(nodes, curr) end curr = curr.next end @@ -175,42 +167,42 @@ function LinkedList:Get(val : any) end --// Returns a list of all passing notes with data -function LinkedList:GetAsTable(val : any) - local nodes = {} +function LinkedList:GetAsTable(val: any) + local nodes = table.create(self.count) local curr = self.snode - local tinsert = table.insert + while curr and type(curr) == "table" do - --// Pass a function and Adonis will pass through the current node into it - --// Return true to add it to the "list" - --// Final list will be returned after the call - --// Passed value: - --[==[ - Node: - .data: The data inside of the node - .next: The next node in the list - .prev: The previous node in the list - ]==] + --// Pass a function and Adonis will pass through the current node into it + --// Return true to add it to the "list" + --// Final list will be returned after the call + --// Passed value: + --[==[ + Node: + .data: The data inside of the node + .next: The next node in the list + .prev: The previous node in the list + ]==] if val then - if type(val) == "function" then - local success, found = pcall(val, curr) - if success and found then - tinsert(nodes, curr.data) - end - else - if curr.data == val then - tinsert(nodes, curr.data) - end - end - else - tinsert(nodes, curr.data) - end + if type(val) == "function" then + local success, found = pcall(val, curr) + if success and found then + table.insert(nodes, curr.data) + end + else + if curr.data == val then + table.insert(nodes, curr.data) + end + end + else + table.insert(nodes, curr.data) + end curr = curr.next end return nodes end function LinkedList:Destroy() - for i,_ in self do + for i, _ in self do self[i] = nil end setmetatable(self, nil) From 9104fde0047d1de81613d3a9db33bff25d8b35bb Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 23:10:45 +0200 Subject: [PATCH 060/189] Show profile picture for private message notifications (#1691) --- MainModule/Client/UI/Default/PrivateMessage.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Client/UI/Default/PrivateMessage.luau b/MainModule/Client/UI/Default/PrivateMessage.luau index 1b3ec270dd..8e34b6e8df 100644 --- a/MainModule/Client/UI/Default/PrivateMessage.luau +++ b/MainModule/Client/UI/Default/PrivateMessage.luau @@ -79,7 +79,7 @@ return function(data, env) UI.Make("Notification",{ Title = "New Message"; Message = string.format("Message from %s (@%s)", player.DisplayName, player.Name); - Icon = "rbxassetid://7501175708"; + Icon = `rbxthumb://type=AvatarHeadShot&id={player.UserId}&w=48&h=48`;--"rbxassetid://7501175708"; Time = false; OnClick = function() window:Ready() end; OnClose = function() window:Destroy() end; From bd4ed695bdf016d0ad8d823691f03dbda9ac4b6e Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 12 Nov 2024 23:13:51 +0200 Subject: [PATCH 061/189] Small misc fixes and improvements (#1672) * Optimise assert * Remove unused vars * Convert scel check constant to use a variable * Add bones * Improve readability * Load nuclear function at a more appropriate place * Fix blank prefix location * Optimise extractlines * Remove altunpack * Update Misc_Features.luau * Update Misc_Features.luau * Dumb and cringe nitpick --- MainModule/Client/Plugins/Misc_Features.luau | 3 ++ MainModule/Client/UI/Default/Profile.luau | 2 +- MainModule/Server/Core/Admin.luau | 8 ++-- MainModule/Server/Core/Core.luau | 2 - MainModule/Server/Core/Functions.luau | 7 +--- MainModule/Server/Core/Variables.luau | 1 + MainModule/Server/Plugins/Debug_Specific.luau | 21 +++-------- MainModule/Server/Plugins/Misc_Features.luau | 3 ++ MainModule/Server/Shared/Service.luau | 37 +++++-------------- 9 files changed, 28 insertions(+), 56 deletions(-) diff --git a/MainModule/Client/Plugins/Misc_Features.luau b/MainModule/Client/Plugins/Misc_Features.luau index d8d972356d..d6d868c074 100644 --- a/MainModule/Client/Plugins/Misc_Features.luau +++ b/MainModule/Client/Plugins/Misc_Features.luau @@ -15,6 +15,9 @@ return function(Vargs, GetEnv) end, ...) end client.cPcall, service.cPcall = cPcall, cPcall + service.AltUnpack = function(args, shift) -- TODO: Remove. This is not used in Adonis at all and is easily replicatable so you can safely remove it withour fear + return table.unpack(args, 1 + (shift and shift - 1 or 0), 10 + (shift and shift - 1 or 0)) + end; Remote.UnEncrypted = setmetatable({}, { __newindex = function(_, ind, val) warn("Unencrypted remote commands are deprecated; moving", ind, "to Remote.Commands. Replace `Remote.Unencrypted` with `Remote.Commands`!") diff --git a/MainModule/Client/UI/Default/Profile.luau b/MainModule/Client/UI/Default/Profile.luau index 46058fb9f4..7cb030f6d8 100644 --- a/MainModule/Client/UI/Default/Profile.luau +++ b/MainModule/Client/UI/Default/Profile.luau @@ -87,7 +87,7 @@ return function(data, env) {"Display Name", player.DisplayName, "The player's custom display name"}, {"Username", player.Name, "The player's unique Roblox username"}, {"User ID", player.UserId, "The player's unique Roblox user ID"}, - {"Acc. Age", `{player.AccountAge} days ({string.format("%.2f", player.AccountAge/365.25)} years)`, "How long the player has been registered on Roblox"}, + {"Acc. Age", `{player.AccountAge} days ({string.format("%.2f", player.AccountAge/365.2425)} years)`, "How long the player has been registered on Roblox"}, }) do generaltab:Add("TextLabel", { Text = ` {v[1]}: `; diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau index 68d173ad5c..300e59ab2b 100644 --- a/MainModule/Server/Core/Admin.luau +++ b/MainModule/Server/Core/Admin.luau @@ -424,7 +424,7 @@ return function(Vargs, GetEnv) DoHideChatCmd = function(p: Player, message: string, data: {[string]: any}?) local pData = data or Core.GetPlayer(p) if pData.Client.HideChatCommands then - if Variables.BlankPrefix and + if Admin.BlankPrefix and (string.sub(message,1,1) ~= Settings.Prefix or string.sub(message,1,1) ~= Settings.PlayerPrefix) then local isCMD = Admin.GetCommand(message) if isCMD then @@ -780,7 +780,7 @@ return function(Vargs, GetEnv) if type(p) == "userdata" and p:IsA("Player") then --// These are my accounts; Lately I've been using my game dev account(698712377) more so I'm adding it so I can debug without having to sign out and back in (it's really a pain) --// Disable CreatorPowers in settings if you don't trust me. It's not like I lose or gain anything either way. Just re-enable it BEFORE telling me there's an issue with the script so I can go to your place and test it. - if Settings.CreatorPowers and table.find({1237666, 76328606, 698712377}, p.UserId) then + if Settings.CreatorPowers and table.find(Variables.DeveloperWhitelist, p.UserId) then return true end @@ -1193,7 +1193,7 @@ return function(Vargs, GetEnv) for ind, data in Commands do if type(data) == "table" then for i,cmd in data.Commands do - if data.Prefix == "" then Variables.BlankPrefix = true end + if data.Prefix == "" then Admin.BlankPrefix = true end tempPrefix[data.Prefix] = true tempTable[string.lower(data.Prefix..cmd)] = ind end @@ -1263,7 +1263,7 @@ return function(Vargs, GetEnv) end; GetCommand = function(Command) - if Admin.PrefixCache[string.sub(Command, 1, 1)] or Variables.BlankPrefix then + if Admin.PrefixCache[string.sub(Command, 1, 1)] or Admin.BlankPrefix then local matched matched = if string.find(Command, Settings.SplitKey) then string.match(Command, `^(%S+){Settings.SplitKey}`) diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index ce318af411..d6fdea3bd8 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -108,7 +108,6 @@ return function(Vargs, GetEnv) server.Core = { Init = Init; RunAfterPlugins = RunAfterPlugins; - DataQueue = {}; DataCache = {}; PlayerData = {}; CrossServerCommands = {}; @@ -119,7 +118,6 @@ return function(Vargs, GetEnv) ScriptCache = {}; Connections = {}; BytecodeCache = {}; - LastEventValue = 1; SavedPlayerData = {}; Variables = { diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 5b782d02d9..820f5c6c14 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -20,6 +20,7 @@ return function(Vargs, GetEnv) Variables = server.Variables; Settings = server.Settings; logError = server.logError; + Functions.NuclearExplode = select(2, xpcall(require, warn, server.Dependencies.FastNuke)); Functions.Init = nil Logs:AddLog("Script", "Functions Module Initialized") @@ -1650,8 +1651,4 @@ return function(Vargs, GetEnv) return if allowNil then nil else BrickColor.random() end; }; - - task.spawn(xpcall, function() - server.Functions.NuclearExplode = require(server.Dependencies.FastNuke); - end, warn) -end \ No newline at end of file +end diff --git a/MainModule/Server/Core/Variables.luau b/MainModule/Server/Core/Variables.luau index 128c5759a3..113dc29461 100644 --- a/MainModule/Server/Core/Variables.luau +++ b/MainModule/Server/Core/Variables.luau @@ -66,6 +66,7 @@ return function(Vargs, GetEnv) LockMessage = "Not Whitelisted", DonorPass = {1348327, 1990427, 1911740, 167686, 98593, "6878510605", 5212082, 5212081}, --// Strings are items; numbers are gamepasses WebPanel_Initiated = false, + DeveloperWhitelist = {1237666, 76328606, 698712377}, HTTPCheckUrl = "https://www.google.com/humans.txt", IPInfoUrl = "https://ipinfo.io/json", DisableRejoinAtMaxPlayers = false, diff --git a/MainModule/Server/Plugins/Debug_Specific.luau b/MainModule/Server/Plugins/Debug_Specific.luau index 9337518eef..4dae032adc 100644 --- a/MainModule/Server/Plugins/Debug_Specific.luau +++ b/MainModule/Server/Plugins/Debug_Specific.luau @@ -1,4 +1,3 @@ - --// This module is for stuff specific to debugging --// Most of this only runs when DebugMode is enabled --// NOTE: THIS IS NOT A *CONFIG/USER* PLUGIN! ANYTHING IN THE MAINMODULE PLUGIN FOLDERS IS ALREADY PART OF/LOADED BY THE SCRIPT! DO NOT ADD THEM TO YOUR CONFIG>PLUGINS FOLDER! @@ -15,7 +14,6 @@ return function(Vargs, GetEnv) return end - --[[ --// Unfortunately not viable --// TODO: Make this viable perhaps? If done so, expose as a :terminal command @@ -126,25 +124,18 @@ return function(Vargs, GetEnv) local ScriptSrcTxt = "" Remote.MakeGui(plr, "Notepad", { Text = [[-- Made by your friendly moo1210, to make debugging the adonis env not a pain. :) - -local IsRunningInSameScriptIdentity = false -- If you're running as a normal user-space script (aka the script identity is 2 when you use printidentity), you may toggle this to true, to prevent needing to wrap instances. This may prevent any minor incompatiblies caused by the wrapping logic, if any. This will not work in the command bar, run script button, or plugins. +local IS_RUNNING_IN_SAME_SCRIPT_IDENTITY = false -- If you're running as a normal user-space script (aka the script identity is 2 when you use printidentity), you may toggle this to true, to prevent needing to wrap instances. This may prevent any minor incompatiblies caused by the wrapping logic, if any. This will not work in the command bar, run script button, or plugins. ---- -local DebugApiBindable = IsRunningInSameScriptIdentity and nil or game:GetService("ReplicatedStorage"):WaitForChild("Adonis_Debug_API", 15) -if not DebugApiBindable then - error("Adonis Debug API not found within 15 seconds! Is DebugMode enabled?") -end +local DebugApiBindable = assert(IS_RUNNING_IN_SAME_SCRIPT_IDENTITY and nil or game:GetService("ReplicatedStorage"):WaitForChild("Adonis_Debug_API", 15), "Adonis Debug API not found within 15 seconds! Is DebugMode enabled?") local DebugApi -if IsRunningInSameScriptIdentity then +if IS_RUNNING_IN_SAME_SCRIPT_IDENTITY then pcall(function() DebugApi = _G.Adonis.Debug end) if not DebugApi then - warn("The IsRunningInSameScriptIdentity option is enabled, however _G.Adonis.Debug was unable to be accessed. Is DebugMode and the _G API enabled? Falling back to BindableEvent") - DebugApiBindable = game:GetService("ReplicatedStorage"):WaitForChild("Adonis_Debug_API", 15) - if not DebugApiBindable then - error("Adonis Debug API not found within 15 seconds! Is DebugMode enabled?") - end + warn("The IS_RUNNING_IN_SAME_SCRIPT_IDENTITY option is enabled, however _G.Adonis.Debug was unable to be accessed. Is DebugMode and the _G API enabled? Falling back to BindableEvent") + DebugApiBindable = assert(game:GetService("ReplicatedStorage"):WaitForChild("Adonis_Debug_API", 15), "Adonis Debug API not found within 15 seconds! Is DebugMode enabled?") DebugApi = DebugApiBindable:Invoke("GetApi") end else @@ -295,7 +286,6 @@ local service = wrappedEnv.Service Debug = true; AdminLevel = "Creators"; Function = function(plr: Player, args: {string}) - print(Remote.Get(plr,"Test")) local tab = { @@ -347,7 +337,6 @@ local service = wrappedEnv.Service Remote.Send(plr, "TestEvent", "TestEvent", "hi mom I went thru the interwebs") print("RemoteEvent Fired successfully") - end; }; diff --git a/MainModule/Server/Plugins/Misc_Features.luau b/MainModule/Server/Plugins/Misc_Features.luau index 159d30ed0f..de6845ad7c 100644 --- a/MainModule/Server/Plugins/Misc_Features.luau +++ b/MainModule/Server/Plugins/Misc_Features.luau @@ -30,6 +30,9 @@ return function(Vargs, GetEnv) end, ...) end server.cPcall, service.cPcall = cPcall, cPcall + service.AltUnpack = function(args, shift) -- TODO: Remove. This is not used in Adonis at all and is easily replicatable so you can safely remove it withour fear + return table.unpack(args, 1 + (shift and shift - 1 or 0), 10 + (shift and shift - 1 or 0)) + end; service.CloneTable = function(tbl) return getmetatable(tbl) and setmetatable(table.clone(tbl), {__index = function(_, k) return tbl[k] end}) or table.clone(tbl) end diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index b85ea9b9a7..6747b10c6d 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -557,7 +557,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end })) or {} for i,v in tab do - if typeof(v) == 'table' then + if type(v) == "table" then new[i] = service.DeepCopy(v) else new[i] = v @@ -571,34 +571,15 @@ return function(errorHandler, eventChecker, fenceSpecific, env) Timer = function(t,func,check) local start = time() local event; event = service.RunService.RenderStepped:Connect(function() - if time()-start>t or (check and check()) then + if time() - start > t or check and check() then func() event:Disconnect() end end) end; - AltUnpack = function(args,shift) - if shift then shift = shift-1 end - return args[1+(shift or 0)],args[2+(shift or 0)],args[3+(shift or 0)],args[4+(shift or 0)],args[5+(shift or 0)],args[6+(shift or 0)],args[7+(shift or 0)],args[8+(shift or 0)],args[9+(shift or 0)],args[10+(shift or 0)] - end; - ExtractLines = function(str) - local strs = table.create(#str+1) - local new = "" - for i=1,#str+1 do - if string.byte(string.sub(str, i,i)) == 10 or i == #str+1 then - table.insert(strs,new) - new = "" - else - local char = string.sub(str,i,i) - if string.byte(char) < 32 then - char = "" - end - new = new..char - end - end - return strs + return string.split(string.gsub(str, "[%z\1-\9\11-\31]", ""), "") end; Filter = function(str, from, to) @@ -651,7 +632,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) local lines = service.ExtractLines(str) for i = 1,#lines do local ran,newl = pcall(function() return service.TextService:FilterStringAsync(lines[i],from.UserId):GetNonChatStringForBroadcastAsync() end) - newl = (ran and newl) or lines[i] or "" + newl = ran and newl or lines[i] or "" if i > 1 then new = `{new}\n{newl}` else @@ -663,7 +644,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) RecursiveMtSearch = function(tab) for index, val in tab do - if typeof(val) == "table" or typeof(val) == "userdata" then + if type(val) == "table" or typeof(val) == "userdata" then if getmetatable(val) ~= nil or service.RecursiveMtSearch(val) then return true end @@ -732,10 +713,10 @@ return function(errorHandler, eventChecker, fenceSpecific, env) Debounce = function(key,func) local env = getfenv(2) - local Debounces = (env and env._ADONIS_DEBOUNCES) or Debounces or {} + local Debounces = env and env._ADONIS_DEBOUNCES or Debounces or {} if env then - env._ADONIS_DEBOUNCES = (env and env._ADONIS_DEBOUNCES) or {} + env._ADONIS_DEBOUNCES = env and env._ADONIS_DEBOUNCES or {} end if Debounces[key] then @@ -973,7 +954,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) local formatString = options.FormatString if not formatString then - formatString = options.WithWrittenDate and "LL HH:mm:ss" or (options.WithDate and "L HH:mm:ss" or "HH:mm:ss") + formatString = options.WithWrittenDate and "LL HH:mm:ss" or options.WithDate and "L HH:mm:ss" or "HH:mm:ss" end local timeObj = DateTime.fromUnixTimestamp(optTime or service.GetTime()) @@ -988,7 +969,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end local str = if plr.DisplayName == plr.Name then `@{plr.Name}` else string.format("%s (@%s)", plr.DisplayName or "???", plr.Name or "???") if withUserId then - str ..= string.format(" [%s]", if plr.UserId and plr.UserId ~= -1 then plr.UserId else "?") + str ..= `[{if plr.UserId and plr.UserId ~= -1 then plr.UserId else "?"}]` end return str end; From 1763f478cc291f78a9200ad593cea5cf2369f52f Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Tue, 12 Nov 2024 21:14:06 +0000 Subject: [PATCH 062/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 0d44fde72c..401a8db6f3 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -44,6 +44,9 @@ return { "(Git/ccuser44) Make ClientMover respect debugmode (#1680)"; "(Git/ccuser44) Add multithreading to FiOne (#1545)"; "(Git/ccuser44) Convert test case to nightly mode (#1669)"; + "(Git/ccuser44) Optimize linkedlists (#1695)"; + "(Git/ccuser44) Show profile picture for private message notifications (#1691)"; + "(Git/ccuser44) Small misc fixes and improvements (#1672)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 25aba6dc833256b5b8ad81a18825aef79e52b6a7 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:52:04 +0200 Subject: [PATCH 063/189] Fix lint error in nightly (#1705) --- MainModule/Server/Dependencies/ClientLoader.client.luau | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Dependencies/ClientLoader.client.luau b/MainModule/Server/Dependencies/ClientLoader.client.luau index 4790e2dff6..f328868f82 100644 --- a/MainModule/Server/Dependencies/ClientLoader.client.luau +++ b/MainModule/Server/Dependencies/ClientLoader.client.luau @@ -144,7 +144,7 @@ local function checkChild(child) print("Getting origName") origName = nameVal and nameVal.Value or child.Name - prit(`Got name: {origName}`) + print(`Got name: {origName}`) print("Changing child parent...") child.Parent = nil @@ -241,7 +241,7 @@ else if not playerGui then warn("PlayerGui not found after 10 minutes") Kick(player, "ACLI: PlayerGui Never Appeared (Waited 10 Minutes)") - else + --else --playerGui.Changed:Connect(function() -- How about no -- if playerGui.Name ~= "PlayerGui" then -- playerGui.Name = "PlayerGui" From f9965db1d7c56afba600b493d6792d1c31c5f3fe Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:36:12 +0200 Subject: [PATCH 064/189] Fix `:fly` being broken (#1692) --- .../Server/Dependencies/Assets/Fly.client.luau | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/MainModule/Server/Dependencies/Assets/Fly.client.luau b/MainModule/Server/Dependencies/Assets/Fly.client.luau index 2315183ab0..5ca19bc08d 100644 --- a/MainModule/Server/Dependencies/Assets/Fly.client.luau +++ b/MainModule/Server/Dependencies/Assets/Fly.client.luau @@ -42,10 +42,6 @@ function Check() end end -function tranVec(num) - return Vector3.new(num, num, num) -end - function getCF(part, isFor) local cframe = part.CFrame local noRot = CFrame.new(cframe.p) @@ -67,10 +63,10 @@ function Start() end) bPos.Position = part.Position - bPos.MaxForce = tranVec(math.huge) + bPos.MaxForce = math.huge bGyro.CFrame = part.CFrame - bGyro.MaxTorque = tranVec(9e9) + bGyro.MaxTorque = 9e9 antiLoop = antiReLoop @@ -150,11 +146,11 @@ function Stop() human.PlatformStand = false if bPos then - bPos.MaxForce = tranVec(0) + bPos.MaxForce = 0 end if bGyro then - bGyro.MaxTorque = tranVec(0) + bGyro.MaxTorque = 0 end if conn then From 30b2fbf6aee52c4f5a1c38922e592e10416041a5 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:39:26 +0200 Subject: [PATCH 065/189] Fix terminal error hadling (#1685) * Fix terminal error handling * Optimise pcall and fix --- MainModule/Server/Core/Remote.luau | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index 127d6dfd82..689c03c86f 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -612,11 +612,13 @@ return function(Vargs, GetEnv) end end - local func,err = Core.Loadstring(args[1], newenv) + local func, err = Core.Loadstring(args[1], newenv) if func then - func() + xpcall(func, function(reason) + Remote.Terminal.LiveOutput(p,`LUA_ERROR: {string.match(reason, ":(.*)") or reason}`) + end) else - Remote.Terminal.LiveOutput(p,`ERROR: {string.match(err, ":(.*)") or err}`) + Remote.Terminal.LiveOutput(p,`SYNTAX_ERROR: {string.match(err, ":(.*)") or err}`) end end }; @@ -1018,16 +1020,14 @@ return function(Vargs, GetEnv) }) -- TODO: Maybe make it not work with the server Env? - service.TrackTask(`Thread: ScriptEditor: {p.UserId}: {Name}`,function() - local func,err = Core.Loadstring(Variable["Script"], newenv) + service.TrackTask(`Thread: ScriptEditor: {p.UserId}: {Name}`, function() + local func, err = Core.Loadstring(Variable["Script"], newenv) if func then - local Succ,Err = pcall(function() - func() + xpcall(func, function(reason) + Remote.MakeGui(p, "Output", {Title = "LUA_ERROR"; Message = reason}) end) - - Remote.MakeGui(p, "Output", {Title = "Error"; Message = Err}) else - Remote.MakeGui(p, "Output", {Title = "Error"; Message = err}) + Remote.MakeGui(p, "Output", {Title = "SYNTAX_ERROR"; Message = err}) end end) end From 45f3baea960d6287c7bdc4acb14e80b6eb1b2825 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:40:58 +0200 Subject: [PATCH 066/189] Optimise enum handling (#1684) * Remote `GetEnumValue` * Fix typo * Optimise material pooling * Optimise enum handling * Optimise KeyCode name function * Fix typo --- MainModule/Client/Core/Functions.luau | 26 ++++++++++------------ MainModule/Server/Commands/Moderators.luau | 16 ++----------- MainModule/Server/Commands/Players.luau | 8 ++----- MainModule/Server/Core/Functions.luau | 25 +++++---------------- 4 files changed, 21 insertions(+), 54 deletions(-) diff --git a/MainModule/Client/Core/Functions.luau b/MainModule/Client/Core/Functions.luau index e298cc0800..5a0279f5d4 100644 --- a/MainModule/Client/Core/Functions.luau +++ b/MainModule/Client/Core/Functions.luau @@ -1197,21 +1197,19 @@ return function(Vargs, GetEnv) end; KeyCodeToName = function(keyVal) - local keyVal = tonumber(keyVal); - if keyVal then - for _, e in Enum.KeyCode:GetEnumItems() do - if e.Value == keyVal then - local name = service.UserInputService:GetStringForKeyCode(e) - - if service.Trim(name) == "" or Variables.KeycodeNames[e] == name then - return e.Name - else - return name - end - end + local keyCode = Enum.KeyCode:FromValue(tonumber(keyVal)) + + if keyCode then + local name = service.UserInputService:GetStringForKeyCode(keyCode) + + if service.Trim(name) == "" or Variables.KeycodeNames[keyCode] == name then + return keyCode.Name + else + return name end + else + return "UNKNOWN" end - return "UNKNOWN"; end; KeyBindListener = function(keybinds) @@ -1219,7 +1217,7 @@ return function(Vargs, GetEnv) local timer = 0 local data = (not keybinds) and Remote.Get("PlayerData"); - Variables.KeyBinds = keybinds or (data and data.Keybinds) or {} + Variables.KeyBinds = keybinds or data and data.Keybinds or {} service.UserInputService.InputBegan:Connect(function(input) local key = tostring(input.KeyCode.Value) diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index d62a1eed11..6b50b777f0 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -559,10 +559,7 @@ return function(Vargs, env) if data.Options.Chat ~= true then TextToUse = service.SanitizeXML(args[2] or "Hello world!") end - Remote.Send( - v, "Function", "DisplaySystemMessageInTextChat", nil, `{ - service.Filter(TextToUse, plr, v) - }`) + Remote.Send(v, "Function", "DisplaySystemMessageInTextChat", nil, `{service.Filter(TextToUse, plr, v)}`) else Remote.Send(v, "Function", "ChatMessage", service.Filter(args[2], plr, v), Color3.fromRGB(255, 64, 77)) end @@ -5441,16 +5438,7 @@ return function(Vargs, env) local AssetTypeNameDescriptionOverides = { DynamicHead = "Head" } - - local typeId = productInfo.AssetTypeId - local typeEnum - - for _, enum in pairs(Enum.AvatarAssetType:GetEnumItems()) do - if enum.Value == typeId then - typeEnum = enum - break - end - end + local typeEnum = Enum.AvatarAssetType:FromValue(productInfo.AssetTypeId) for _, v: Player in service.GetPlayers(plr, args[1]) do local humanoid: Humanoid? = v.Character and v.Character:FindFirstChildOfClass("Humanoid") diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index 5add1d2537..0273a06e4d 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -254,13 +254,9 @@ return function(Vargs, env) Description = "Shows you a list of Roblox materials for reference"; AdminLevel = "Players"; Function = function(plr: Player, args: {string}) - local mats = { - "Brick", "Cobblestone", "Concrete", "CorrodedMetal", "DiamondPlate", "Fabric", "Foil", "ForceField", "Glass", "Granite", - "Grass", "Ice", "Marble", "Metal", "Neon", "Pebble", "Plastic", "Slate", "Sand", "SmoothPlastic", "Wood", "WoodPlanks", - "Rock", "Glacier", "Snow", "Sandstone", "Mud", "Basalt", "Ground", "CrackedLava", "Asphalt", "LeafyGrass", "Salt", "Limestone", "Pavement" - } + local mats = Enum.Material:GetEnumItems() for i, mat in mats do - mats[i] = {Text = mat; Desc = `Enum value: {(Enum.Material[mat]::Enum.Material).Value}`} + mats[i] = {Text = mat.Name; Desc = `Enum value: {mat.Value}`} end Remote.MakeGui(plr, "List", {Title = "Materials"; Tab = mats; TextSelectable = true;}) end diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 820f5c6c14..df3bbca9a4 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1084,14 +1084,11 @@ return function(Vargs, GetEnv) end end; - Cape = function(player,isdon,material,color,decal,reflect) - material = material or "Neon" - if not Functions.GetEnumValue(Enum.Material, material) then - error("Invalid material value") - end - + Cape = function(player, isdon, material, color, decal, reflect) + material = assert(Enum.Material:FromName(material or "Neon"), "Invalid material value") Functions.UnCape(player) local torso = player.Character:FindFirstChild("HumanoidRootPart") + if torso then if type(color) == "table" then color = Color3.new(unpack(color)) @@ -1142,23 +1139,11 @@ return function(Vargs, GetEnv) end end; - GetEnumValue = function(enum, item) - local valid = false - for _,v in enum:GetEnumItems() do - if v.Name == item then - valid = v.Value - break - end - end - return valid - end; - ApplyBodyPart = function(character, model) -- NOTE: Use HumanoidDescriptions to apply body parts where possible, unless applying custom parts - local humanoid = character:FindFirstChildOfClass("Humanoid") if humanoid then - local rigType = humanoid.RigType == Enum.HumanoidRigType.R6 and "R6" or "R15" + local rigType = humanoid.RigType.Name local part = model:FindFirstChild(rigType) if not part and rigType == "R15" then @@ -1178,7 +1163,7 @@ return function(Vargs, GetEnv) end elseif rigType == "R15" then for _,v in part:GetChildren() do - local value = Functions.GetEnumValue(Enum.BodyPartR15, v.Name) + local value = Enum.BodyPartR15:FromName(v.Name) if value then humanoid:ReplaceBodyPartR15(value, v:Clone()) end From 3f5589a20e03aaa63af8bfa2a43fefde31f6ff6c Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:41:54 +0200 Subject: [PATCH 067/189] Fix issue of debuggers, pentesting tools, script analysers and exploit simulators kicking people in Studio. (#1617) * Fix studio dumb Sceleratis * Fix typo * Fix conditions * Remove unnecessary warning * Remove unnecessary warn --- MainModule/Client/Core/Anti.luau | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/MainModule/Client/Core/Anti.luau b/MainModule/Client/Core/Anti.luau index 13aa692def..3c2aaf9519 100644 --- a/MainModule/Client/Core/Anti.luau +++ b/MainModule/Client/Core/Anti.luau @@ -82,15 +82,13 @@ return function(Vargs, GetEnv) if NetworkClient and action ~= "_" then pcall(Send, "D".."e".."t".."e".."c".."t".."e".."d", action, tostring(info)..(isXbox and " - On Xbox" or isMobile and " - On mobile" or "")) task.wait(0.5) - if action == "k".."i".."c".."k" then - if not isStudio then - if nocrash then - Player:Kick(":"..":".." ".."A".."d".."o".."n".."i".."s".." ".."A".."n".."t".."i".." ".."C".."h".."e".."a".."t"..":"..":".."\n".. tostring(info)); -- service.Players.LocalPlayer - else - Disconnect(info) - end + if action == "k".."i".."c".."k" and not isStudio then + if nocrash then + Player:Kick(":"..":".." ".."A".."d".."o".."n".."i".."s".." ".."A".."n".."t".."i".." ".."C".."h".."e".."a".."t"..":"..":".."\n".. tostring(info)); -- service.Players.LocalPlayer + else + Disconnect(info) end - elseif action == "c".."r".."a".."s".."h" then + elseif action == "c".."r".."a".."s".."h" and not isStudio then Kill(info) end end @@ -329,12 +327,12 @@ return function(Vargs, GetEnv) pcall(metamethod, rawGame, proxyDetector) if callstackInvalid or success or success2 or success3 then - return true + return not isStudio elseif not errorMessages["namecallInstance"] then errorMessages["namecallInstance"] = {err, err2, err3} end - return not compareTables(errorMessages["namecallInstance"], {err, err2, err3}) + return not compareTables(errorMessages["namecallInstance"], {err, err2, err3}) and not isStudio end}, indexEnum = table.freeze{"kick", function() local callstackInvalid = false From 241cf5917112a9234b072681923c8b022a0d42f4 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:43:55 +0200 Subject: [PATCH 068/189] Fix trello api output functions (#1673) --- MainModule/Server/Dependencies/TrelloAPI.luau | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/MainModule/Server/Dependencies/TrelloAPI.luau b/MainModule/Server/Dependencies/TrelloAPI.luau index 7a28d309fe..7d9721993d 100644 --- a/MainModule/Server/Dependencies/TrelloAPI.luau +++ b/MainModule/Server/Dependencies/TrelloAPI.luau @@ -1,17 +1,17 @@ ------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Trello API Documentation: -- --- -- --- App Key Link: /app-key -- --- -- --- Token Link: /1/connect?name=Trello_API_Module&response_type=token&expires=never&scope=read,write&key=YOUR_APP_KEY_HERE -- --- Replace "YOUR_APP_KEY_HERE" with the App Key from /app-key -- --- Trello API Remade by imskyyc for Kronos and Adonis - original by Sceleratis / Davey_Bones for Adonis. -- +-- Trello API Documentation: -- +-- -- +-- App Key Link: /app-key -- +-- -- +-- Token Link: /1/connect?name=Trello_API_Module&response_type=token&expires=never&scope=read,write&key=YOUR_APP_KEY_HERE -- +-- Replace "YOUR_APP_KEY_HERE" with the App Key from /app-key -- +-- Trello API Remade by imskyyc for Kronos and Adonis - original by Sceleratis / Davey_Bones for Adonis. -- -- It is requested that existing credits remain here. -- ------------------------------------------------------------------------------------------------------------------------------------------------------------------- -local print = function(...) for i,v in {...} do warn(`[Adonis TrelloAPI]: INFO: {v}`) end end -local error = function(...) for i,v in {...} do warn(`[Adonis TrelloAPI]: ERROR: {v}`) end end -local warn = function(...) for i,v in {...} do warn(`[Adonis TrelloAPI]: WARN: {v}`) end end +local print = function(...) warn("[Adonis TrelloAPI]: INFO:", ...) end +local warn = function(...) warn("[Adonis TrelloAPI]: WARN:", ...) end +local error = function(message, level) warn("[Adonis TrelloAPI]: ERROR:", message) return error("[Adonis TrelloAPI]: ERROR:"..message, level == 0 and 0 or 1 + (level or 1)) end local HttpService = game:GetService("HttpService") local Weeks = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} From d306d8fd96d98251017c255a4e43d92c90dead73 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:13:34 +0000 Subject: [PATCH 069/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 401a8db6f3..0abd08ee99 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -3,6 +3,7 @@ return { "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; + "[Version – Date & Time released] @Maintainer"; "[v261 2024-08-29 14:32 UTC] @Dimenpsyonal"; "(Git/Expertcoderz) Add :ckick command (#1614)"; ""; @@ -47,6 +48,11 @@ return { "(Git/ccuser44) Optimize linkedlists (#1695)"; "(Git/ccuser44) Show profile picture for private message notifications (#1691)"; "(Git/ccuser44) Small misc fixes and improvements (#1672)"; + "(Git/ccuser44) Fix :fly being broken (#1692)"; + "(Git/ccuser44) Fix terminal error hadling (#1685)"; + "(Git/ccuser44) Optimise enum handling (#1684)"; + "(Git/ccuser44) Fix kick for use of studio tools (#1617)"; + "(Git/ccuser44) Fix trello api output functions (#1673)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 7fe57d7d6a668167be841ea9d77c0ff7fe17ae99 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:42:45 +0200 Subject: [PATCH 070/189] Remove legacy note from settings (#1712) * Remove legacy note * Remove legacy note --- Loader/Config/Settings.luau | 1 - MainModule/Server/Dependencies/DefaultSettings.luau | 1 - 2 files changed, 2 deletions(-) diff --git a/Loader/Config/Settings.luau b/Loader/Config/Settings.luau index 107103fba2..4ec74667a7 100644 --- a/Loader/Config/Settings.luau +++ b/Loader/Config/Settings.luau @@ -375,7 +375,6 @@ settings.AntiNoclip = false -- (Default: false) Attempts to detect noclippin settings.AntiRootJointDeletion = false -- (Default: false) Attempts to detect paranoid and kills the player if found. settings.AntiMultiTool = false -- (Default: false) Prevents multitool and because of that many other exploits. settings.AntiGod = false -- (Default: false) If a player does not respawn when they should have they get respawned. --- settings.AntiHumanoidDeletion and settings.ProtectHats have been superseded by Workspace.RejectCharacterDeletions. settings.AntiSpeed = false -- (Default: false) (Client-Sided) Attempts to detect speed exploits. settings.AntiBuildingTools = false -- (Default: false) (Client-Sided) Attempts to detect any HopperBin(s)/Building Tools added to the client. diff --git a/MainModule/Server/Dependencies/DefaultSettings.luau b/MainModule/Server/Dependencies/DefaultSettings.luau index fd4fd162eb..f4aeef0e63 100644 --- a/MainModule/Server/Dependencies/DefaultSettings.luau +++ b/MainModule/Server/Dependencies/DefaultSettings.luau @@ -375,7 +375,6 @@ settings.AntiNoclip = false -- (Default: false) Attempts to detect noclippin settings.AntiRootJointDeletion = false -- (Default: false) Attempts to detect paranoid and kills the player if found. settings.AntiMultiTool = false -- (Default: false) Prevents multitool and because of that many other exploits. settings.AntiGod = false -- (Default: false) If a player does not respawn when they should have they get respawned. --- settings.AntiHumanoidDeletion and settings.ProtectHats have been superseded by Workspace.RejectCharacterDeletions. settings.AntiSpeed = false -- (Default: false) (Client-Sided) Attempts to detect speed exploits. settings.AntiBuildingTools = false -- (Default: false) (Client-Sided) Attempts to detect any HopperBin(s)/Building Tools added to the client. From a53727b6ec8fb3f7806e2c5c3aae60494618904e Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:26:51 +0200 Subject: [PATCH 071/189] Add people missing from credits (#1731) * Add more people to credits * Capitalise --- MainModule/Server/Shared/Credits.luau | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Shared/Credits.luau b/MainModule/Server/Shared/Credits.luau index e207dd3aa2..e38134a0e3 100644 --- a/MainModule/Server/Shared/Credits.luau +++ b/MainModule/Server/Shared/Credits.luau @@ -32,7 +32,7 @@ return { {Text = "@policetonyR", Desc = "Open Source Contributor"}; {Text = "@enescglyn", Desc = "Open Source Contributor"}; {Text = "@EpicFazbear", Desc = "Open Source Contributor"}; - {Text = "@p3tray", Desc = "Open Source Contributor"}; + {Text = "@P3tray", Desc = "Open Source Contributor"}; {Text = "@okgabe", Desc = "Open Source Contributor"}; {Text = "@fxeP1", Desc = "Open Source Contributor"}; {Text = "@optimisticside", Desc = "Open Source Contributor"}; @@ -102,7 +102,7 @@ return { Misc = { {Text = "Kein-Hong Man", Desc = "Creator of the Yueliang (Lua bytecode compiler in loadstring module). Also created LuLu VM, the first Lua bytecode interpreter used in Adonis (no longer used)"}; - {Text = "Stravant/JustAPerson", Desc = "Wrote LBI (no longer used)"}; + {Text = "Stravant/JustAPerson", Desc = "Wrote LBI (no longer used) and GoodSignal"}; {Text = "darkelementallord", Desc = "Updated some guis"}; {Text = "TheFurryFish", Desc = "Gave me some dank ideas like local particles and some loading related things; and helped debug"}; {Text = "Moistality", Desc = "Helped with finding and patching vulns"}; @@ -117,6 +117,9 @@ return { {Text = "Osyris", Desc = "Wrote 't', an open-source typechecking library"}; {Text = "buildthomas", Desc = "Wrote 'MockDataStoreService', an open-source mock DataStoreService replacement library"}; {Text = "Tiffany352", Desc = "Wrote an improved base64 implementation"}; + {Text = "Merely", Desc = "Wrote the original SoftShutdown"}; + {Text = "Irreflexive", Desc = "Edited SoftShutdown"}; + {Text = "Krypt", Desc = "Wrote Slider module used for AudioPlayer"}; {Text = "",}; {Text = "~ :) ~",}; {Text = "Donors", Desc = "Donors keep the wheels turning ;)"}; From 5dcd2f392426dfbca9e95d2a58d83a63fe699389 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:28:15 +0200 Subject: [PATCH 072/189] Only show profile picture for non-temporary users (#1728) --- MainModule/Client/UI/Default/PrivateMessage.luau | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MainModule/Client/UI/Default/PrivateMessage.luau b/MainModule/Client/UI/Default/PrivateMessage.luau index 8e34b6e8df..aacab2174b 100644 --- a/MainModule/Client/UI/Default/PrivateMessage.luau +++ b/MainModule/Client/UI/Default/PrivateMessage.luau @@ -17,7 +17,7 @@ return function(data, env) local window = UI.Make("Window",{ Name = "PrivateMessage"; Title = tostring(player); - Size = {300,150}; + Size = {300, 150}; }) local label = window:Add("TextLabel",{ @@ -54,7 +54,7 @@ return function(data, env) end window:Close() - Remote.Send('PrivateMessage', replyTicket, player, reply.Text) + Remote.Send("PrivateMessage", replyTicket, player, reply.Text) UI.Make("Hint", { Message = "Reply sent" }) @@ -76,10 +76,10 @@ return function(data, env) reply.FocusLost:Connect(sendIt) gTable = window.gTable - UI.Make("Notification",{ + UI.Make("Notification", { Title = "New Message"; - Message = string.format("Message from %s (@%s)", player.DisplayName, player.Name); - Icon = `rbxthumb://type=AvatarHeadShot&id={player.UserId}&w=48&h=48`;--"rbxassetid://7501175708"; + Message = `Message from {player.DisplayName} ({player.Name})`; + Icon = player.UserId > 0 and `rbxthumb://type=AvatarHeadShot&id={player.UserId}&w=48&h=48` or client.MatIcons.Mail; Time = false; OnClick = function() window:Ready() end; OnClose = function() window:Destroy() end; From 33223803d4961349188abe9644d3e74daa13c153 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:29:53 +0200 Subject: [PATCH 073/189] Remove `service.Yield` and replace with Goodsignal (#1725) * Remove `service.Yield` * Add backwards compatibility for `service.Yield` * Add backwards compatibility for `service.Yield` * Replace usage of `service.Yield` * Replace usage of `service.Yield` * Replace usage of `service.Yield` * Fix typo --- MainModule/Client/Core/Remote.luau | 4 ++-- MainModule/Client/Plugins/Misc_Features.luau | 14 ++++++++++-- MainModule/Server/Core/Remote.luau | 4 ++-- MainModule/Server/Plugins/Misc_Features.luau | 14 ++++++++++-- MainModule/Server/Shared/Service.luau | 24 ++++++-------------- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/MainModule/Client/Core/Remote.luau b/MainModule/Client/Core/Remote.luau index b9bb79def8..f4a8531d79 100644 --- a/MainModule/Client/Core/Remote.luau +++ b/MainModule/Client/Core/Remote.luau @@ -390,7 +390,7 @@ return function(Vargs, GetEnv) local returns; if RemoteEvent and RemoteEvent.Function then - local Yield = service.Yield(); + local Yield = service.Signal.new(); service.Queue("REMOTE_SEND", function() Remote.Sent = Remote.Sent+1; @@ -405,7 +405,7 @@ return function(Vargs, GetEnv) }, unpack(extra)) } - Yield:Release(returns); + Yield:Fire(returns); end) task.wait(limit) diff --git a/MainModule/Client/Plugins/Misc_Features.luau b/MainModule/Client/Plugins/Misc_Features.luau index d6d868c074..d79d2791da 100644 --- a/MainModule/Client/Plugins/Misc_Features.luau +++ b/MainModule/Client/Plugins/Misc_Features.luau @@ -17,7 +17,17 @@ return function(Vargs, GetEnv) client.cPcall, service.cPcall = cPcall, cPcall service.AltUnpack = function(args, shift) -- TODO: Remove. This is not used in Adonis at all and is easily replicatable so you can safely remove it withour fear return table.unpack(args, 1 + (shift and shift - 1 or 0), 10 + (shift and shift - 1 or 0)) - end; + end + service.GoodSignal = service.Signal + service.Yield = function() + local event = service.Signal.new() + return { + Release = function(...) event:Fire(...) end; + Wait = function(...) return event:Wait(...) end; + Destroy = function() event:Destroy() end; + Event = event; + } + end Remote.UnEncrypted = setmetatable({}, { __newindex = function(_, ind, val) warn("Unencrypted remote commands are deprecated; moving", ind, "to Remote.Commands. Replace `Remote.Unencrypted` with `Remote.Commands`!") @@ -32,7 +42,7 @@ return function(Vargs, GetEnv) local Len = (type(pLen) == "number" and pLen) or random(5,10) --// reru local Res = {} for Idx = 1, Len do - Res[Idx] = format('%02x', random(255)) + Res[Idx] = format("%02x", random(255)) end return table.concat(Res) end diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index 689c03c86f..a77f12d675 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -1174,8 +1174,8 @@ return function(Vargs, GetEnv) if keys and keys.RemoteReady == true then local returns, finished local key = service.HttpService:GenerateGUID(false) - local Yield = service.Yield(); - local event = service.Events[key]:Connect(function(...) print("WE ARE GETTING A RETURN!") finished = true returns = {...} Yield:Release() end) + local Yield = service.Signal.new(); + local event = service.Events[key]:Connect(function(...) print("WE ARE GETTING A RETURN!") finished = true returns = {...} Yield:Fire() end) Remote.PendingReturns[key] = true Remote.Send(p,"GetReturn",com,key,...) diff --git a/MainModule/Server/Plugins/Misc_Features.luau b/MainModule/Server/Plugins/Misc_Features.luau index de6845ad7c..336c4fc587 100644 --- a/MainModule/Server/Plugins/Misc_Features.luau +++ b/MainModule/Server/Plugins/Misc_Features.luau @@ -32,10 +32,20 @@ return function(Vargs, GetEnv) server.cPcall, service.cPcall = cPcall, cPcall service.AltUnpack = function(args, shift) -- TODO: Remove. This is not used in Adonis at all and is easily replicatable so you can safely remove it withour fear return table.unpack(args, 1 + (shift and shift - 1 or 0), 10 + (shift and shift - 1 or 0)) - end; + end service.CloneTable = function(tbl) return getmetatable(tbl) and setmetatable(table.clone(tbl), {__index = function(_, k) return tbl[k] end}) or table.clone(tbl) end + service.GoodSignal = service.Signal + service.Yield = function() + local event = service.Signal.new() + return { + Release = function(...) event:Fire(...) end; + Wait = function(...) return event:Wait(...) end; + Destroy = function() event:Destroy() end; + Event = event; + } + end Remote.UnEncrypted = setmetatable({}, { __newindex = function(_, ind, val) warn("Unencrypted remote commands are deprecated; moving", ind, "to Remote.Commands. Replace `Remote.Unencrypted` with `Remote.Commands`!") @@ -57,7 +67,7 @@ return function(Vargs, GetEnv) if HTTP.Trello.API then HTTP.Trello.API.GenerateRequestID = Functions.GetRandom end - --// Old settings/plugins backwards compatibility + --// Old settings/plugins backwards compatibility. Do not remove this because many games use old loader ranks! for _, rank in {"Owners", "HeadAdmins", "Admins", "Moderators", "Creators"} do if Settings[rank] and not Settings.CustomRanks[rank] then Settings.Ranks[if rank == "Owners" then "HeadAdmins" else rank].Users = Settings[rank] diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index 6747b10c6d..b7875f46a6 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -747,7 +747,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) Timeout = timeout; Finished = false; - Yield = doYield and service.Yield(); + Yield = doYield and service.Signal.new(); } table.insert(queue.Functions, tab); @@ -767,7 +767,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) return "Processing" else local funcs = queue.Functions; - local Yield = service.Yield(); + local Yield = service.Signal.new(); local function pop() local n = funcs[1] table.remove(funcs, 1) @@ -783,11 +783,11 @@ return function(errorHandler, eventChecker, fenceSpecific, env) if func.Timeout then delay(func.Timeout, function() if not func.Finished then - Yield:Release(); + Yield:Fire(); warn(`Queue Timeout Reached for {key or "Unknown"}`) if func.Yield then - func.Yield:Release(false, "Timeout Reached"); + func.Yield:Fire(false, "Timeout Reached"); end end end) @@ -803,10 +803,10 @@ return function(errorHandler, eventChecker, fenceSpecific, env) func.Finished = true if func.Yield then - func.Yield:Release(r, e) + func.Yield:Fire(r, e) end - Yield:Release(); + Yield:Fire(); end,false) if func.Running then @@ -1190,16 +1190,6 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end end; - Yield = function() - local event = service.New("BindableEvent"); - return { - Release = function(...) event:Fire(...) end; - Wait = function(...) return event.Event:Wait(...) end; - Destroy = function() event:Destroy() end; - Event = event; - } - end; - StartLoop = function(name,delay,func,noYield) local tab = { Name = name; @@ -1496,7 +1486,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) service.HelperService = HelperService service.ThreadService = ThreadService service.EventService = EventService - service.GoodSignal = require(script.Parent.Shared.GoodSignal) + service.Signal = require(script.Parent.Shared.GoodSignal) if client ~= nil then for i,val in service do From abb33f9a515d84221440155177b2aafed36bee32 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:30:59 +0200 Subject: [PATCH 074/189] Fix string clamping for unicode characters (#1724) --- MainModule/Server/Shared/Service.luau | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index b7875f46a6..714abc46f5 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -1183,8 +1183,11 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end, MaxLen = function(message, length) - if string.len(message) > length then - return `{string.sub(message, 1, length)}...` + local rawLength = string.len(message) + local utf8Length = rawLength <= length * 6 and utf8.len(message) + if rawLength > length and not (utf8Length and utf8Length <= length) then + local clamped = string.sub(message, 1, utf8Length and utf8.offset(message, length + 1) - 1 or length) + return `{not utf8.len(clamped) and string.sub(clamped, 1, select(2, utf8.len(clamped)) - 1) or clamped}...` else return message end From f9e8f4d0b6ccddafdf4425f0acdec4aecebcda3a Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:32:04 +0200 Subject: [PATCH 075/189] Move :guiview to a window (#1722) * Move GUIView to a window * Fix ZIndex handling --- MainModule/Client/Core/Functions.luau | 103 +++++++++++++++++--------- 1 file changed, 70 insertions(+), 33 deletions(-) diff --git a/MainModule/Client/Core/Functions.luau b/MainModule/Client/Core/Functions.luau index 5a0279f5d4..15afb358a2 100644 --- a/MainModule/Client/Core/Functions.luau +++ b/MainModule/Client/Core/Functions.luau @@ -196,7 +196,7 @@ return function(Vargs, GetEnv) SetView = function(ob) local CurrentCamera = workspace.CurrentCamera - if ob=='reset' then + if ob == "reset" then CurrentCamera.CameraType = Enum.CameraType.Custom CurrentCamera.CameraSubject = service.Player.Character:FindFirstChildOfClass("Humanoid") CurrentCamera.FieldOfView = 70 @@ -415,6 +415,7 @@ return function(Vargs, GetEnv) "Name"; "Parent"; "Archivable"; + "DisplayOrder"; "SelectionImageObject"; "Active"; "BackgroundColor3"; @@ -597,57 +598,93 @@ return function(Vargs, GetEnv) end; LoadGuiData = function(data) - local make; make = function(dat) - local props = dat.Properties - local children = dat.Children - local gui = service.New(props.ClassName) + local zIndex = -2^31 -- Signed 32 bit intiger + local make; make = function(data, parent) + local props = data.Properties + local gui = props.ClassName ~= "ScreenGui" and service.New(props.ClassName) - for i,v in props do - pcall(function() - gui[i] = v - end) + if gui then + for k, v in props do + pcall(function() + gui[k] = v + end) + end end - for i,v in children do + for _, v in data.Children do pcall(function() - local g = make(v) + local g = make(v, gui or parent) if g then - g.Parent = gui + g.Parent = gui or parent end end) end + return gui end - local temp = Instance.new("Folder") - for _, v in service.PlayerGui:GetChildren() do - if not UI.Get(v) then - v.Parent = temp + local function normaliseIndex(gui) + local remap, order = {}, {} + local mapIndex; mapIndex = function(object) + local index = object.Properties.ZIndex + + if type(index) == "number" then + if not remap[index] then + remap[index] = {object.Properties} + table.insert(order, index) + else + table.insert(remap[index], object.Properties) + end + end + + for _, v in object.Children do + pcall(mapIndex, v) + end end - end - Variables.GuiViewFolder = temp - local folder = service.New("Folder",{Parent = service.PlayerGui; Name = "LoadedGuis"}) - for _, v in data.Children do - pcall(function() - local g = make(v) - if g then - g.Parent = folder + + pcall(mapIndex, gui) + table.sort(order) + + for _, index in order do + zIndex += 1 + + for _, v in remap[index] do + v.ZIndex = zIndex end - end) + end + + return gui end - end; - UnLoadGuiData = function() - for _, v in service.PlayerGui:GetChildren() do - if v.Name == "LoadedGuis" then - v:Destroy() + local GuiViewContainer = UI.Make("Window", { + Name = "Player GUI View"; + Title = "Player GUI View"; + Icon = client.MatIcons["Grid view"]; + AllowMultiple = true; + SizeLocked = false + }) + + table.sort(data.Children, function(t1, t2) + local o1, o2 = t1.Properties.DisplayOrder, t2.Properties.DisplayOrder + if o1 and o2 then + return o1 < o2 end + + return false + end) + + Variables.GuiViewFolder = GuiViewContainer + zIndex = GuiViewContainer.ZIndex or zIndex + + for _, v in data.Children do + pcall(make, normaliseIndex(v), GuiViewContainer) end + GuiViewContainer:Ready() + end; + + UnLoadGuiData = function() if Variables.GuiViewFolder then - for _, v in Variables.GuiViewFolder:GetChildren() do - v.Parent = service.PlayerGui - end Variables.GuiViewFolder:Destroy() Variables.GuiViewFolder = nil end From d3f6e81bacee90eda3d9eec39afb734aaad6e488 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:32:45 +0200 Subject: [PATCH 076/189] Allow loglimits to be edited by plugins (#1721) * Update Admins.luau * Use logs limit variable * Move maxlogs to logs from local variable * Update Logs.luau --- MainModule/Server/Commands/Admins.luau | 2 +- MainModule/Server/Core/Logs.luau | 9 ++++----- MainModule/Server/Plugins/Server-SoftShutdown.luau | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index dd12dd9099..7fa610adf2 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -1328,7 +1328,7 @@ return function(Vargs, env) }) local nlogs = #logs - if nlogs > 1000 then + if nlogs > Logs.OldCommandLogsLimit then table.remove(logs, nlogs) end diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index 966e9b3e94..91b571690e 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -14,7 +14,6 @@ return function(Vargs, GetEnv) local service = Vargs.Service; local DLL = server.DLL; - local MaxLogs = 1000 local Functions, Admin, Anti, Core, HTTP, Logs, Remote, Process, Variables, Settings local function Init() Functions = server.Functions; @@ -27,8 +26,7 @@ return function(Vargs, GetEnv) Process = server.Process; Variables = server.Variables; Settings = server.Settings; - - MaxLogs = Settings.MaxLogs; + Logs.MaxLogs = Settings.MaxLogs; Logs.Init = nil; Logs:AddLog("Script", "Logging Module Initialized"); @@ -47,6 +45,7 @@ return function(Vargs, GetEnv) Exploit = if UseDLL then DLL.new() else {}; Errors = if UseDLL then DLL.new() else {}; DateTime = if UseDLL then DLL.new() else {}; + MaxLogs = 1000; TempUpdaters = {}; OldCommandLogsLimit = 1000; --// Maximum number of command logs to save to the datastore (the higher the number, the longer the server will take to close) @@ -91,10 +90,10 @@ return function(Vargs, GetEnv) end if tab.__meta == "DLL" then - tab:AddToStartAndRemoveEndIfEnd(log, MaxLogs) + tab:AddToStartAndRemoveEndIfEnd(log, Logs.MaxLogs) else table.insert(tab, 1, log) - if #tab > tonumber(MaxLogs) then + if #tab > tonumber(Logs.MaxLogs) then table.remove(tab, #tab) end end diff --git a/MainModule/Server/Plugins/Server-SoftShutdown.luau b/MainModule/Server/Plugins/Server-SoftShutdown.luau index d04f28ce49..4c5cc16f3d 100644 --- a/MainModule/Server/Plugins/Server-SoftShutdown.luau +++ b/MainModule/Server/Plugins/Server-SoftShutdown.luau @@ -158,7 +158,7 @@ return function(Vargs, GetEnv) }) end - if #logs > 1000 then + if #logs > Logs.OldCommandLogsLimit then table.remove(logs, #logs) end From 53abae1b8dcbc533a90d0893763b769c7c22d974 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:33:26 +0200 Subject: [PATCH 077/189] Allow tabtotype to be updated (#1720) --- MainModule/Server/Core/Logs.luau | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index 91b571690e..e970ed4cf7 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -47,24 +47,23 @@ return function(Vargs, GetEnv) DateTime = if UseDLL then DLL.new() else {}; MaxLogs = 1000; TempUpdaters = {}; + IndToName = { + Chats = "Chat"; + Joins = "Join"; + Leaves = "Leave"; + Script = "Script"; + RemoteFires = "RemoteFire"; + Commands = "Command"; + Exploit = "Exploit"; + Errors = "Error"; + DateTime = "DateTime"; + }; OldCommandLogsLimit = 1000; --// Maximum number of command logs to save to the datastore (the higher the number, the longer the server will take to close) TabToType = function(tab) - local indToName = { - Chats = "Chat"; - Joins = "Join"; - Leaves = "Leave"; - Script = "Script"; - RemoteFires = "RemoteFire"; - Commands = "Command"; - Exploit = "Exploit"; - Errors = "Error"; - DateTime = "DateTime"; - } - for ind, t in server.Logs do if t == tab then - return indToName[ind] or ind + return server.Logs.IndToName[ind] or ind end end end; From 05719a0b6358ab529ed73ff80c892ef85cb34557 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:34:14 +0200 Subject: [PATCH 078/189] Fix leader stat handling (#1719) --- MainModule/Server/Commands/Moderators.luau | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index 6b50b777f0..c82d42a9f0 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -4948,13 +4948,13 @@ return function(Vargs, env) for _, v in service.GetPlayers(plr, args[1], { NoFakePlayer = true }) do local leaderstats = v:FindFirstChild("leaderstats") if leaderstats then - local absoluteMatch = leaderstats:FindFirstChild(statName) - if absoluteMatch and absoluteMatch:IsA("ValueBase") then - absoluteMatch.Value = args[3] + local absolute = leaderstats:FindFirstChild(statName) + if absolute and absolute:IsA("ValueBase") then + absolute.Value = (absolute:IsA("IntValue") or absolute:IsA("NumberValue")) and tonumber(args[3]) or args[3] else for _, st in leaderstats:GetChildren() do - if st:IsA("ValueBase") and string.match(st.Name:lower(), `^{statName:lower()}`) then - st.Value = args[3] + if st:IsA("ValueBase") and string.match(st.Name:lower(), `^{service.SanitizePattern(statName:lower())}`) then + st.Value = (st:IsA("IntValue") or st:IsA("NumberValue")) and tonumber(args[3]) or args[3] end end end @@ -4983,7 +4983,7 @@ return function(Vargs, env) absoluteMatch:Destroy() else for _, st in leaderstats:GetChildren() do - if (st:IsA("IntValue") or st:IsA("NumberValue")) and string.match(st.Name:lower(), `^{statName:lower()}`) then + if (st:IsA("IntValue") or st:IsA("NumberValue")) and string.match(st.Name:lower(), `^{service.SanitizePattern(statName:lower())}`) then st:Destroy() end end @@ -5052,7 +5052,7 @@ return function(Vargs, env) absoluteMatch.Value += valueToAdd else for _, st in leaderstats:GetChildren() do - if (st:IsA("IntValue") or st:IsA("NumberValue")) and string.match(st.Name:lower(), `^{statName:lower()}`) then + if (st:IsA("IntValue") or st:IsA("NumberValue")) and string.match(st.Name:lower(), `^{service.SanitizePattern(statName:lower())}`) then st.Value += valueToAdd end end @@ -5081,7 +5081,7 @@ return function(Vargs, env) absoluteMatch.Value -= valueToSubtract else for _, st in leaderstats:GetChildren() do - if (st:IsA("IntValue") or st:IsA("NumberValue")) and string.match(st.Name:lower(), `^{statName:lower()}`) then + if (st:IsA("IntValue") or st:IsA("NumberValue")) and string.match(st.Name:lower(), `^{service.SanitizePattern(statName:lower())}`) then st.Value -= valueToSubtract end end From 644c3e81783221b86791ffadf2f92cc7c996b1d0 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:34:57 +0200 Subject: [PATCH 079/189] Add better aliases for `:localaudio` (#1718) --- MainModule/Server/Commands/Moderators.luau | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index c82d42a9f0..b446afb79a 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -5552,12 +5552,11 @@ return function(Vargs, env) TargetAudio = { Prefix = Settings.Prefix; - Commands = {"taudio", "localsound", "localaudio", "lsound", "laudio"}; + Commands = {"taudio", "localsound", "localaudio", "localsong", "localmusic", "lsound", "laudio", "lsong", "lmusic"}; Args = {"player", "audioId", "noLoop", "pitch", "volume"}; Description = "Plays an audio on the specified player's client"; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}, data: {}) - assert(args[1], "Missing player name") assert(args[2] and tonumber(args[2]), "Missing or invalid AudioId") From a39306c160771c72c9bca2ce1a266570fccc000d Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:35:19 +0200 Subject: [PATCH 080/189] Fix fake player properties (#1716) --- MainModule/Server/Core/Functions.luau | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index df3bbca9a4..aa0ab05f47 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -401,6 +401,7 @@ return function(Vargs, GetEnv) GetFakePlayer = function(options) local fakePlayer = service.Wrap(service.New("Folder", { Name = options.Name or "Fake_Player"; + Archivable = false; })) local data = { @@ -410,12 +411,12 @@ return function(Vargs, GetEnv) UserId = 0; AccountAge = 0; MembershipType = Enum.MembershipType.None; - CharacterAppearanceId = if options.UserId then tostring(options.UserId) else "0"; + CharacterAppearanceId = options.UserId or 0; FollowUserId = 0; GameplayPaused = false; Parent = service.Players; Character = service.New("Model", {Name = options.Name or "Fake_Player"}); - Backpack = service.New("Folder", {Name = "FakeBackpack"}); + Backpack = service.New("Backpack", {Name = "FakeBackpack"}); PlayerGui = service.New("Folder", {Name = "FakePlayerGui"}); PlayerScripts = service.New("Folder", {Name = "FakePlayerScripts"}); GetJoinData = function() return {} end; @@ -423,15 +424,15 @@ return function(Vargs, GetEnv) GetRankInGroup = function() return 0 end; GetRoleInGroup = function() return "Guest" end; IsFriendsWith = function() return false end; - Kick = function() fakePlayer:Destroy() fakePlayer:SetSpecial("Parent", nil) end; - IsA = function(_, className) return className == "Player" end; + Kick = function() fakePlayer:SetSpecial("Parent", nil) fakePlayer:Destroy() end; + IsA = function(_, className) return className == "Player" or className == "Instance" end; } - for i, v in options do - data[i] = v + for k, v in options do + data[k] = v end - if data.UserId ~= -1 then + if data.UserId > 0 then local success, actualName = pcall(service.Players.GetNameFromUserIdAsync, service.Players, data.UserId) if success then data.Name = actualName @@ -441,8 +442,8 @@ return function(Vargs, GetEnv) data.userId = data.UserId data.ToString = data.Name - for i, v in data do - fakePlayer:SetSpecial(i, v) + for k, v in data do + fakePlayer:SetSpecial(k, v) end return fakePlayer From b1bebfc80e37f17ead1c0d6025cfb9a85536db1d Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:35:55 +0200 Subject: [PATCH 081/189] Allow giving input text to notepad (#1715) --- MainModule/Server/Commands/Players.luau | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index 0273a06e4d..c322464500 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -113,11 +113,11 @@ return function(Vargs, env) Notepad = { Prefix = Settings.PlayerPrefix; Commands = {"notepad", "stickynote"}; - Args = {}; + Args = {"text (optional)"}; Description = "Opens a textbox window for you to type into"; AdminLevel = "Players"; Function = function(plr: Player, args: {string}) - Remote.MakeGui(plr, "Notepad", {}) + Remote.MakeGui(plr, "Notepad", {Text = args[1]}) end }; From 4b02d85877845bb3943b2ff859c75b605673977e Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:36:48 +0200 Subject: [PATCH 082/189] Make cleanup and oldlogs saving respect silentstartup (#1714) * Make cleanup respect silentstartup * Make oldlogs saving respect silentload --- MainModule/Server/Core/Logs.luau | 13 +++++++++---- MainModule/Server/Server.luau | 9 +++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index e970ed4cf7..8d87dba5c7 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -104,12 +104,15 @@ return function(Vargs, GetEnv) --// Disable saving command logs in Studio; not required. if service.RunService:IsStudio() or service.RunService:IsRunMode() then return + elseif not server.Data or not server.Data.SilentStartup then + print("Saving command logs...") end - print("Saving command logs...") - if Settings.SaveCommandLogs ~= true or Settings.DataStoreEnabled ~= true then - print("Skipped saving command logs.") + if not server.Data or not server.Data.SilentStartup then + print("Skipped saving command logs.") + end + return end @@ -173,7 +176,9 @@ return function(Vargs, GetEnv) return service.HttpService:JSONEncode(temp) end) - print("Command logs saved!") + if not server.Data or not server.Data.SilentStartup then + print("Command logs saved!") + end end; ListUpdaters = { diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index 996c09897b..bbdddc9129 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -246,7 +246,10 @@ local function LoadPackage(package, folder, runNow) end; local function CleanUp(reason) - print(`Beginning Adonis cleanup & shutdown process due to {reason}...`) + if not server.Data or not server.Data.SilentStartup then + print(`Beginning Adonis cleanup & shutdown process due to {reason}...`) + end + local data = service.UnWrap(server.Data) if type(data) == "table" and typeof(service.UnWrap(data.Config)) == "Instance" then local Settings: ModuleScript = service.UnWrap(data.Config):FindFirstChild("Settings") @@ -277,7 +280,9 @@ local function CleanUp(reason) pcall(server.Core.DisconnectEvent) end - print("Unloading complete") + if not server.Data or not server.Data.SilentStartup then + print("Unloading complete") + end end; server = { From bf69952b10dba9b95626bf0cde0325e94562e646 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:37:25 +0200 Subject: [PATCH 083/189] Fix bug report version help image (#1709) * Fix version help image link * Add files via upload --- .github/ISSUE_TEMPLATE/Bug_Report.yml | 2 +- .github/ISSUE_TEMPLATE/loader_version.png | Bin 0 -> 44739 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/loader_version.png diff --git a/.github/ISSUE_TEMPLATE/Bug_Report.yml b/.github/ISSUE_TEMPLATE/Bug_Report.yml index a751103edc..d120a8dba7 100644 --- a/.github/ISSUE_TEMPLATE/Bug_Report.yml +++ b/.github/ISSUE_TEMPLATE/Bug_Report.yml @@ -23,7 +23,7 @@ body: id: loader-version attributes: label: Loader version - description: If your issue is related to loader/settings and you do not provide this we may not be able to solve your issue. Paste the value from `Adonis_Loader > Version > .Value` ![Version VALUE](https://media.discordapp.net/attachments/834826232565727282/1194191940640587836/image.png) + description: If your issue is related to loader/settings and you do not provide this we may not be able to solve your issue. Paste the value from `Adonis_Loader > Version > .Value` ![Version VALUE](loader_version.png) placeholder: Value of the version variable. "Latest" is invalid as unbeknownst you may not be using the latest loader for many reasons - type: dropdown id: segment diff --git a/.github/ISSUE_TEMPLATE/loader_version.png b/.github/ISSUE_TEMPLATE/loader_version.png new file mode 100644 index 0000000000000000000000000000000000000000..5ce0eff6001b18686581ca98202656f51bfdab54 GIT binary patch literal 44739 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 Date: Sun, 17 Nov 2024 23:38:14 +0200 Subject: [PATCH 084/189] Remove unnecessary cruft from server (#1682) --- MainModule/Server/Server.luau | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index bbdddc9129..7a639e4cbd 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -285,6 +285,7 @@ local function CleanUp(reason) end end; +-- TODO: Re-add codename to server but remove it from Variables and directly bake it in to the client too without a remote server = { Running = true; Modules = {}; @@ -293,12 +294,10 @@ server = { LogError = logError; ErrorLogs = ErrorLogs; ServerStartTime = os.time(); - CommandCache = {}; }; locals = { server = server; - CodeName = ""; Settings = server.Settings; HookedEvents = HookedEvents; ErrorLogs = ErrorLogs; @@ -529,7 +528,6 @@ return service.NewProxy({ server.Client = Folder.Parent.Client locals.Settings = server.Settings - locals.CodeName = server.CodeName --// THIS NEEDS TO BE DONE **BEFORE** ANY EVENTS ARE CONNECTED if server.Settings.HideScript and data.Model then From c1c6a5b991ac7afa3516a436ffb2cebeb20abc78 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 17 Nov 2024 21:38:59 +0000 Subject: [PATCH 085/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 0abd08ee99..3c6a26240e 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -53,6 +53,19 @@ return { "(Git/ccuser44) Optimise enum handling (#1684)"; "(Git/ccuser44) Fix kick for use of studio tools (#1617)"; "(Git/ccuser44) Fix trello api output functions (#1673)"; + "(Git/ccuser44) Only show profile picture for non-temporary users (#1728)"; + "(Git/ccuser44) Remove service.Yield and replace with Goodsignal (#1725)"; + "(Git/ccuser44) Fix string clamping for unicode characters (#1724)"; + "(Git/ccuser44) Move :guiview to a window (#1722)"; + "(Git/ccuser44) Allow loglimits to be edited by plugins (#1721)"; + "(Git/ccuser44) Allow tabtotype to be updated (#1720)"; + "(Git/ccuser44) Fix leader stat handling (#1719)"; + "(Git/ccuser44) Add better aliases for :localaudio (#1718)"; + "(Git/ccuser44) Fix fake player properties (#1716)"; + "(Git/ccuser44) Allow giving input text to notepad (#1715)"; + "(Git/ccuser44) Make cleanup and oldlogs saving respect silentstartup (#1714)"; + "(Git/ccuser44) Fix bug report version help image (#1709)"; + "(Git/ccuser44) Remove unnecessary cruft from server (#1682)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 89b966c0678b255a7a6d3d5977e763731d921755 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:20:14 +0000 Subject: [PATCH 086/189] Move README to luau --- Loader/Config/Themes/{README.lua => README.luau} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Loader/Config/Themes/{README.lua => README.luau} (100%) diff --git a/Loader/Config/Themes/README.lua b/Loader/Config/Themes/README.luau similarity index 100% rename from Loader/Config/Themes/README.lua rename to Loader/Config/Themes/README.luau From 4d646cfe73f5b74097f1eaa016da7e21280c9056 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:21:45 +0000 Subject: [PATCH 087/189] Rename Runner.server.lua to Runner.server.luau --- .../Server/Shared/FiOne/{Runner.server.lua => Runner.server.luau} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename MainModule/Server/Shared/FiOne/{Runner.server.lua => Runner.server.luau} (100%) diff --git a/MainModule/Server/Shared/FiOne/Runner.server.lua b/MainModule/Server/Shared/FiOne/Runner.server.luau similarity index 100% rename from MainModule/Server/Shared/FiOne/Runner.server.lua rename to MainModule/Server/Shared/FiOne/Runner.server.luau From b92e42a59b883ccebed766fc2ca61afe0bd3ed15 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:22:06 +0000 Subject: [PATCH 088/189] Rename init.lua to init.luau --- MainModule/Server/Shared/FiOne/{init.lua => init.luau} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename MainModule/Server/Shared/FiOne/{init.lua => init.luau} (100%) diff --git a/MainModule/Server/Shared/FiOne/init.lua b/MainModule/Server/Shared/FiOne/init.luau similarity index 100% rename from MainModule/Server/Shared/FiOne/init.lua rename to MainModule/Server/Shared/FiOne/init.luau From 19897aabb63808cb91c53562934dc4cf160eb798 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:31:45 +0200 Subject: [PATCH 089/189] [Big bugfix&improvement pack]: Fixes many annoying bugs (#1647) * Fix elevated info now showing for self Fixes #1578 * Add Variables.CanUseEditableImages * Make RakPeer logs more descriptive * Remove `service.GetUserType` * Fix clone command streaming behavior and archivable * Fix streaming behavior for `:bot` * Make AudioLib archivable false * Fix AudioLib archivable * Remove client.TestEvent * Update Server.luau * Fix Sfling archivable * Fix indentation * Fix TextChatCommands archivable * Fix stupid atmosphere code that doesnt work * Fix atmosphere variables * Fix PerfStats updating too slow * Improve jail commands * Optimise Functions.ArgsToString * Fix poison only working once * Optimise command formatting * Imporve Service.luau * Fix invalid string pattern * Fix invalid `table.insert` arguments * Add `Variables.SizeLimit` * Use `Variables.SizeLimit` * Optimise tabToString * Remove legacy `Anti.GetClassName` * Add `:unzawarudo` * Remove unused `CharacterMesh` check * Remove cruft * Remove unused `doPcall` * Fix Dex disappearing after respawn * Fix streaming enabled for `:nuke` * Fix Aero notification icon * Fix icon missing for notification * Fix `functionify` capitalisation * Fix indentation * Add better security levels for debug commands * Move `TestFilter` to a plugin * Move TestFilter to a plugin * Remove Dex on `:clearguis` * Add `AdminLevel` attribute for TextChat commands * Remove `ChatCreateRobloxCommands` from settings * Remove `ChatCreateRobloxCommands` from settings * Add `Variables.ChatCreateRobloxCommands` * Fixed TextChatCommand suggestions not respecting rank perms * Pass online friends to profile gui * Delete MainModule/Client/UI/Unity/TopBar.rbxmx * Make unity hint respect `Settings.TopBarShift` * Make Aero hint respect `Settings.TopBarShift` * Remove accidental addition * Remove cruft * Fix topbar support * Fix topbar support * Fix topbar support * Fix topbar support * Fix topbar support * Fix TopBarShift support * Create init.luau * Create Visualizer.luau * Create Slider.luau * Create Signal.luau * Delete MainModule/Client/UI/Default/Music.rbxmx * Fix some stuff * Set OriginalGravity on server start * Made `!paint` use `EditableImage` * Turn off EditableImages They are not enabled yet unless you turn them on in studio * Remove unnecessary variables check * `:restoremap` fixes gravity and lighting * `:backup` saves gravity and lighting * Fix atmosphere handling * Dont set current settings * Add atmosphere support * Fix client side atmosphere * Fix atmosphere handling * Fix asset links * Fix serverspeed handling * Fix ServerSpeed handling * Make loader a lot better * Make Server.luau a lot better * Pool loader version * Fix typo * Fix some stuff * Better message handling * Fix typo * Fix sounds for `:zawarudo` * Fix typo * Add showlogs aliases * Fix `:showlogs` * Fix topbar size for console * Fix topbar size for console * Fix topbar size for console * Fix topbar size * Get friend info from client * Add `Functions.GetFriendsOnline` * Fix typo * Fix typo * Show online status on profile * Uploading for paint * Fix typo * Fix * Fix invalid cache timestamp for `service.GetProductInfo` * Delete MainModule/Client/UI/Unity/Music.rbxmx * Redo AudioLib from the ground up Now the AudioLib finally properly works. * Make remote support new AudioLib * Replace outdated signal library with GoodSignal * Update Slider to newer version * Update Music player to new AudioLib and fix many bugs * Use GUID * Fix tween not loading before crash * Use GUID * Use GUID * Remove cruft * Remove cruft * Remove cruft * Use GUID * Use GUID * Use GUID * Fix typo * Fix typo * Fix typo * Fix typo * Fix selene warning * Fix selene lint * Fix typo * Fix typo * Fix typo * Fix typo * Update rojo version * Fix typo * Fix typo * Fix selene warning * Fix typo * Allow clients to see server musiclist * Fix bug from past pull request * Fix serverdetails for studio * Failsafe for musiclist * Remove invalid property * Remove invalid property * Remove invalid property * Remove invalid property * Fix jail * Fix ZaWarudo * Fix HTTP module not loading * Fix aliases * Add GetAliases function * Fix Console * Fix Console * Fix Dex removal * Fix Dex disappearing * Fix typo * Small fix with HttpEnabled * Fix HTTP Checking * Fix HttpEnabled * Add files via upload * Delete MainModule/Server/Plugins/ServerNewDex.rbxm * Add files via upload * Fix typo * Remove logError * Fix decimal handling * Remove cruft * Fix invalid capitalisation for name * Rename Singer.client.luau to Singer.server.luau * Fix award points notification * Remove `Functions.CatchError` * Update Misc_Features.luau * Update Misc_Features.luau * Fix typo * Fix small nitpick * Already fixed * Fix rojo build flag * Fix rojo build flag * Convert Dex names to variable * Move Dex names to variables * Update AudioLib.luau * Show version in server startup logs * Better UX --- .github/loader.deploy.project.json | 1 + .github/module.deploy.project.json | 3 +- Loader/Config/Settings.luau | 3 - Loader/Loader/Loader.server.luau | 107 +- MainModule/Client/Client.luau | 3 +- MainModule/Client/Core/Core.luau | 2 +- MainModule/Client/Core/Functions.luau | 35 +- MainModule/Client/Core/Process.luau | 40 +- MainModule/Client/Core/UI.luau | 26 +- MainModule/Client/Core/Variables.luau | 12 + MainModule/Client/Plugins/Misc_Features.luau | 6 + MainModule/Client/UI/Aero/Console.rbxmx | 5 +- MainModule/Client/UI/Aero/Hint.rbxmx | 5 +- MainModule/Client/UI/Aero/Notif.rbxmx | 2 + MainModule/Client/UI/Aero/Notification.rbxmx | 1 + MainModule/Client/UI/BasicAdmin/Hint.rbxmx | 4 +- MainModule/Client/UI/Default/Console.rbxmx | 5 +- MainModule/Client/UI/Default/Hint.rbxmx | 4 - MainModule/Client/UI/Default/Music.rbxmx | 1684 ----------------- .../Client/UI/Default/Music/Signal.luau | 243 +++ .../Client/UI/Default/Music/Slider.luau | 389 ++++ .../Client/UI/Default/Music/Visualizer.luau | 198 ++ MainModule/Client/UI/Default/Music/init.luau | 907 +++++++++ MainModule/Client/UI/Default/Notif.rbxmx | 14 +- MainModule/Client/UI/Default/Paint.luau | 87 +- MainModule/Client/UI/Default/PerfStats.luau | 4 +- MainModule/Client/UI/Default/Profile.luau | 55 +- .../Client/UI/Default/ServerDetails.luau | 10 +- MainModule/Client/UI/Default/UserPanel.luau | 12 +- MainModule/Client/UI/Steampunk/Console.rbxmx | 7 +- MainModule/Client/UI/Steampunk/Notif.rbxmx | 7 +- MainModule/Client/UI/TransBlack/Console.rbxmx | 8 +- MainModule/Client/UI/Unity/Hint.rbxmx | 5 +- MainModule/Client/UI/Unity/Music.rbxmx | 874 --------- MainModule/Client/UI/Unity/Notif.rbxmx | 4 +- MainModule/Client/UI/Unity/TopBar.rbxmx | 296 --- MainModule/Client/UI/Unity/Window.rbxmx | 1 + MainModule/Client/UI/Windows XP/Hint.rbxmx | 5 +- .../Client/UI/Windows XP/Notification.rbxmx | 1 + MainModule/Server/Commands/Admins.luau | 16 +- MainModule/Server/Commands/Fun.luau | 111 +- MainModule/Server/Commands/HeadAdmins.luau | 31 + MainModule/Server/Commands/Moderators.luau | 93 +- MainModule/Server/Commands/Players.luau | 4 + MainModule/Server/Core/Admin.luau | 55 +- MainModule/Server/Core/Core.luau | 2 +- MainModule/Server/Core/Functions.luau | 37 +- MainModule/Server/Core/HTTP.luau | 25 +- MainModule/Server/Core/Process.luau | 116 +- MainModule/Server/Core/Remote.luau | 32 +- MainModule/Server/Core/Variables.luau | 85 +- .../Server/Dependencies/Assets/Sfling.rbxmx | 1 + ...{Singer.client.luau => Singer.server.luau} | 0 .../Dependencies/ClientMover.client.luau | 11 - .../Server/Dependencies/DefaultSettings.luau | 3 - MainModule/Server/Dependencies/FastNuke.luau | 15 +- MainModule/Server/Plugins/Anti_Cheat.luau | 2 - MainModule/Server/Plugins/Cross_Server.luau | 7 +- MainModule/Server/Plugins/Debug_Specific.luau | 34 +- MainModule/Server/Plugins/Misc_Features.luau | 23 +- MainModule/Server/Plugins/ServerNewDex.rbxmx | 99 +- MainModule/Server/Server.luau | 48 +- MainModule/Server/Shared/AudioLib.luau | 260 ++- MainModule/Server/Shared/Changelog.luau | 24 +- MainModule/Server/Shared/Service.luau | 34 +- aftman.toml | 2 +- 66 files changed, 2821 insertions(+), 3424 deletions(-) delete mode 100644 MainModule/Client/UI/Default/Music.rbxmx create mode 100644 MainModule/Client/UI/Default/Music/Signal.luau create mode 100644 MainModule/Client/UI/Default/Music/Slider.luau create mode 100644 MainModule/Client/UI/Default/Music/Visualizer.luau create mode 100644 MainModule/Client/UI/Default/Music/init.luau delete mode 100644 MainModule/Client/UI/Unity/Music.rbxmx delete mode 100644 MainModule/Client/UI/Unity/TopBar.rbxmx rename MainModule/Server/Dependencies/Assets/{Singer.client.luau => Singer.server.luau} (100%) diff --git a/.github/loader.deploy.project.json b/.github/loader.deploy.project.json index 1520f473bd..bf45779ead 100644 --- a/.github/loader.deploy.project.json +++ b/.github/loader.deploy.project.json @@ -1,5 +1,6 @@ { "name": "Adonis_Loader", + "emitLegacyScripts": true, "tree": { "$className": "Model", "$path": "../Loader" diff --git a/.github/module.deploy.project.json b/.github/module.deploy.project.json index 585b5fee87..d799d12cc7 100644 --- a/.github/module.deploy.project.json +++ b/.github/module.deploy.project.json @@ -1,6 +1,7 @@ { "name": "MainModule", + "emitLegacyScripts": true, "tree": { "$path": "../MainModule" } -} \ No newline at end of file +} diff --git a/Loader/Config/Settings.luau b/Loader/Config/Settings.luau index 4ec74667a7..3d91cb17cb 100644 --- a/Loader/Config/Settings.luau +++ b/Loader/Config/Settings.luau @@ -284,7 +284,6 @@ settings.CreatorPowers = true -- Gives me creator-level admin; This is strictl settings.CodeExecution = true -- Enables the use of code execution in Adonis; Scripting related (such as :s) and a few other commands require this settings.SilentCommandDenials = false -- If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command settings.OverrideChatCallbacks = true -- If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for slowmode. Mutes use a CanSend method to mute when this is set to false. -settings.ChatCreateRobloxCommands = true -- Whether "/" commands for Roblox should get created in new Chat settings.BanMessage = "Banned" -- Message shown to banned users upon kick settings.LockMessage = "Not Whitelisted" -- Message shown to people when they are kicked while the game is :slocked @@ -457,7 +456,6 @@ descs.CrossServerCommands = [[ Are commands which affect more than one server en descs.ChatCommands = [[ If false you will not be able to run commands via the chat; Instead, you MUST use the console or you will be unable to run commands ]] descs.SilentCommandDenials = [[ If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command ]] descs.OverrideChatCallbacks = [[ If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for muting ]] -descs.ChatCreateRobloxCommands = [[ Whether "/" commands for Roblox should get created in new Chat ]] descs.BanMessage = [[ Message shown to banned users ]] descs.LockMessage = [[ Message shown to people when they are kicked while the game is :slocked ]] @@ -576,7 +574,6 @@ order = { ""; "SilentCommandDenials"; "OverrideChatCallbacks"; - "ChatCreateRobloxCommands"; " "; "BanMessage"; "LockMessage"; diff --git a/Loader/Loader/Loader.server.luau b/Loader/Loader/Loader.server.luau index 8a4f952881..951eb4b03c 100644 --- a/Loader/Loader/Loader.server.luau +++ b/Loader/Loader/Loader.server.luau @@ -34,6 +34,37 @@ local ServerScriptService = game:GetService("ServerScriptService") local RunService = game:GetService("RunService") local InsertService = game:GetService("InsertService") +-- Support yieldable xpcall +local function yxpcall(f, callback, ...) + local args = table.pack(pcall(f, ...)) + + if not args[1] then + callback(args[2]) + else + return table.unpack(args, 2) + end +end + +local function loadModuleAsset(moduleId: number) + local asset = InsertService:LoadAsset(moduleId) + + if asset.Name == "MainModule" then + return assert(require(asset), ":LoadAsset() module returned invalid values!") + elseif asset:FindFirstChild("MainModule") then + return assert(require(asset.MainModule), ":LoadAsset() module returned invalid values!") + elseif asset:IsA("ModuleScript") then + return assert(require(asset), ":LoadAsset() module returned invalid values!") + end + + for _, v in asset:GetChildren() do + if v:IsA("ModuleScript") then + return assert(require(v), ":LoadAsset() module returned invalid values!") + end + end + + error(`Failed to find any matching ModuleScripts for {moduleId}.`) +end + local mutex = RunService:FindFirstChild("__Adonis_MUTEX") if mutex then if mutex:IsA("StringValue") then @@ -77,44 +108,49 @@ else Loader = loader; Runner = runner; + LoaderVersion = (model and model:FindFirstChild("Version")) and tonumber(model.Version.Value); ModuleID = 7510592873; --// https://www.roblox.com/library/7510592873/Adonis-MainModule LoaderID = 7510622625; --// https://www.roblox.com/library/7510622625/Adonis-Loader-Sceleratis-Davey-Bones-Epix --// Note: The nightly module is updated frequently with every commit merged to the master branch on the Adonis repo. --// It is prone to breaking, unstable, untested, and should not be used for anything other than testing/feature preview. - NightlyMode = false; --// If true, uses the nightly module instead of the current release module. + NightlyMode = true; --// If true, uses the nightly module instead of the current release module. NightlyModuleID = 8612978896; --// https://www.roblox.com/library/8612978896/Nightlies-Adonis-MainModule --// Module used in case MainModule is unavailable, containing only essential commands Backup = 17438792001; --// https://create.roblox.com/store/asset/17438792001/ DebugMode = true; - SilentStartup = false + SilentStartup = false; } - - if not data.SilentStartup then print("Loading...") end --// Init + if not data.SilentStartup then + print("Loading...") + end + -- selene: allow(incorrect_standard_library_use) - script.Parent = nil --script:Destroy() + script.Parent = nil if not data.DebugMode then model.Name = math.random() end local moduleId = if data.NightlyMode then data.NightlyModuleID else data.ModuleID - + if data.DebugMode then + local found = false for _, v in model.Parent:GetChildren() do if v.Name == "MainModule" and v:IsA("ModuleScript") then - moduleId = v + moduleId, found = v, true break end end - if not moduleId and not data.NightlyMode then - error(`Adonis DebugMode is enabled but no ModuleScript named 'MainModule' is found in {model.Parent:GetFullName()}`) + + if not found and not data.NightlyMode then + warn(`Adonis DebugMode is enabled but no ModuleScript named 'MainModule' is found in {model.Parent and model.Parent:GetFullName()}`) end end @@ -138,18 +174,15 @@ else for _, module in pluginsFolder:GetChildren() do local name = string.lower(module.Name) - + if module:IsA("Folder") then table.insert(data.Packages, module) - elseif string.match(name, "^client[%-:]") then table.insert(data.ClientPlugins, module) - elseif string.match(name, "^server[%-:]") then table.insert(data.ServerPlugins, module) - else - warn(`[DEVELOPER ERROR] Unknown Plugin Type for {module}; Plugin name should either start with 'Server:', 'Server-', 'Client:', or 'Client-'`) + warn(`[DEVELOPER ERROR] Unknown Plugin Type for {module:GetFullName()}; Plugin name should either start with 'Server:', 'Server-', 'Client:' or 'Client-'`) end end @@ -161,28 +194,42 @@ else print(`Requiring Adonis MainModule; Model URL: https://www.roblox.com/library/{moduleId}`) end - local success, module = xpcall(require, warn, moduleId) - if not success and type(moduleId) == "number" then -- Backup method for loading - warn(`Failed to require Adonis mainmodule {moduleId} due to {module}. If this does not work please purchase the Adonis mainmodule in your inventory. Using backup method...`) - local assets = InsertService:LoadAsset(moduleId) - - for _, v in assets do - if v:IsA("ModuleScript") then - module = require(v) - break - end - end - - assert(type(module) ~= "string", module) + local success, module = pcall(require, moduleId) + + --// Backup method for loading Adonis + if not success and type(moduleId) == "number" then -- ccuser44 was here + warn(`Failed to load Adonis MainModule {moduleId} due to {module}! If this does not work please purchase the Adonis MainModule to your inventory. Using backup method...`) + yxpcall(function() + module = loadModuleAsset(moduleId) + end, function(reason) + warn(`Failed to load Adonis mainmodule {moduleId} via :LoadAsset() method due to {reason}! Loading the backup MainModule...`) + yxpcall(function() + module = assert(require(data.Backup), "Backup module returned invalid values!") + end, function(reason) + warn(`Failed to load Adonis backup MainModule {data.Backup} due to {reason}! If this does not work please purchase the Adonis backup MainModule to your inventory. Using backup method...`) + yxpcall(function() + module = loadModuleAsset(data.Backup) + end, function(reason) + module = nil + warn(`FATAL ERROR! Failed to load Adonis backup MainModule {moduleId} via :LoadAsset() method due to {reason}! Adonis can't be booted up! Please contact the Adonis helpers immediately and add both the regular MainModule and the backup MainModule to your user&group inventory!`) + end) + end) + end) end - local response = module(data) + + local response = assert(module, "FATAL ERROR! Adonis bootstrap function is missing!")(data) if response == "SUCCESS" then - if (data.Settings and data.Settings.HideScript) and not data.DebugMode and not RunService:IsStudio() then + if data.Settings and data.Settings.HideScript and not data.DebugMode and not RunService:IsStudio() then model.Parent = nil game:BindToClose(function() - model.Parent = ServerScriptService + local oldArchivable = script.Archivable + script.Archivable = true + local clone = script:Clone() + clone.Archivable = oldArchivable + clone.Parent = loaderFolder model.Name = "Adonis_Loader" + model.Parent = ServerScriptService end) end diff --git a/MainModule/Client/Client.luau b/MainModule/Client/Client.luau index 91ef1e8165..4d6133487c 100644 --- a/MainModule/Client/Client.luau +++ b/MainModule/Client/Client.luau @@ -317,7 +317,6 @@ client = setmetatable({ Routine = Routine, OldPrint = oldPrint, LogError = logError, - TestEvent = Instance.new("RemoteEvent"), Disconnect = function(info) service.Player:Kick(info or "Disconnected from server") @@ -648,7 +647,7 @@ return service.NewProxy({ if not (Variables.LocalContainer and Variables.LocalContainer.Parent) then Variables.LocalContainer = service.New("Folder", { Parent = workspace, - Archivable = false, + Archivable = false, Name = `__ADONIS_LOCALCONTAINER_{service.HttpService:GenerateGUID(false)}`, }) end diff --git a/MainModule/Client/Core/Core.luau b/MainModule/Client/Core/Core.luau index e20b40b8e3..bf4ea09769 100644 --- a/MainModule/Client/Core/Core.luau +++ b/MainModule/Client/Core/Core.luau @@ -343,7 +343,7 @@ return function(Vargs, GetEnv) local realEnvResult, isResultPointer = getRealEnvResult(TableInEnvPath) local metaTableInEnv = getmetatable(realEnvResult) local result = metaTableInEnv[FuncToRun](realEnvResult,table.unpack(args,3,#args)) - local resultPointer = tostring(math.random()) + local resultPointer = service.HttpService:GenerateGUID(false) pointers[resultPointer] = result return UnWrap(result), resultPointer diff --git a/MainModule/Client/Core/Functions.luau b/MainModule/Client/Core/Functions.luau index 15afb358a2..8c2c4bfc86 100644 --- a/MainModule/Client/Core/Functions.luau +++ b/MainModule/Client/Core/Functions.luau @@ -1027,13 +1027,36 @@ return function(Vargs, GetEnv) end end; - SetLighting = function(prop,value) - if service.Lighting[prop]~=nil then + SetLighting = function(prop, value) + if service.Lighting[prop] ~= nil then service.Lighting[prop] = value Variables.LightingSettings[prop] = value end end; + SetAtmosphere = function(prop, value) + local atmosphere = service.Lighting:FindFirstChildWhichIsA("Atmosphere") + + if atmosphere then + if value == nil and atmosphere[prop] and typeof(atmosphere[prop]) ~= "Instance" then + atmosphere:Destroy() + table.clear(Variables.AtmosphereSettings) + else + atmosphere[prop] = value + Variables.AtmosphereSettings[prop] = value + end + elseif value ~= nil then + atmosphere = Instance.new("Atmosphere") + Variables.AtmosphereSettings[prop] = value + + for k, v in Variables.AtmosphereSettings do + atmosphere[k] = v + end + + atmosphere.Parent = service.Lighting + end + end; + ChatMessage = function(msg,color,font,size) local tab = {} @@ -1225,7 +1248,7 @@ return function(Vargs, GetEnv) end end - task.wait(0.5) + task.wait(0.6) Functions.HardCrash() end; @@ -1888,6 +1911,10 @@ return function(Vargs, GetEnv) end end; + GetFriendsOnline = function(maxFriends) + return service.Players.LocalPlayer:GetFriendsOnline(maxFriends) + end; + GetUserInputServiceData = function(args) local data = {} local props = { @@ -1904,7 +1931,7 @@ return function(Vargs, GetEnv) for _, p in props do data[p] = service.UserInputService[p] end - data["Resolution"] = workspace.CurrentCamera.ViewportSize.X.." x "..workspace.CurrentCamera.ViewportSize.Y + data["Resolution"] = math.floor(workspace.CurrentCamera.ViewportSize.X).." x "..math.floor(workspace.CurrentCamera.ViewportSize.Y) return data end; }; diff --git a/MainModule/Client/Core/Process.luau b/MainModule/Client/Core/Process.luau index 30a8a7d11c..30301a207a 100644 --- a/MainModule/Client/Core/Process.luau +++ b/MainModule/Client/Core/Process.luau @@ -50,7 +50,7 @@ return function(Vargs, GetEnv) end local function RunLast() - Process.RunLast = nil; + Process.RunLast = nil; end local function RunAfterLoaded(data) @@ -66,6 +66,9 @@ return function(Vargs, GetEnv) --// Get RateLimits Process.RateLimits = Remote.Get("RateLimits") or Process.RateLimits; + --// Hide TextChatComands + Process.HandleTextChatCommands() + Process.RunAfterLoaded = nil; end @@ -77,6 +80,7 @@ return function(Vargs, GetEnv) Init = Init; RunLast = RunLast; RunAfterLoaded = RunAfterLoaded; + TextChatCommands = {}; RateLimits = { --// Defaults; Will be updated with server data at client run Remote = 0.02; Command = 0.1; @@ -170,6 +174,38 @@ return function(Vargs, GetEnv) end service.Events.CharacterRemoving:Fire() - end + end; + + HandleTextChatCommands = function() + local data = Remote.Get("PlayerData") + local adminLevel, isDonor = data.AdminLevel, data.isDonor + + if service.TextChatService and service.TextChatService.ChatVersion == Enum.ChatVersion.TextChatService then + local function onCommandAdded(command) + if not command:IsA("TextChatCommand") then + return + elseif string.sub(command.Name, 1, 7) ~= "Adonis_" then + return + elseif not Process.TextChatCommands[command.Name] then + Process.TextChatCommands[command.Name] = command + elseif Process.TextChatCommands[command.Name] ~= command then + Process.TextChatCommands[command.Name]:Destroy() + Process.TextChatCommands[command.Name] = command + end + + local commandLevel = command:GetAttribute("AdminLevel") + + if type(commandLevel) == "number" and commandLevel > adminLevel or commandLevel == "Donors" and not isDonor then + command.Parent = nil + end + end + + for _, v in service.TextChatService:GetDescendants() do + onCommandAdded(v) + end + + service.TextChatService.DescendantAdded:Connect(onCommandAdded) + end + end; } end diff --git a/MainModule/Client/Core/UI.luau b/MainModule/Client/Core/UI.luau index 46c11e93f7..2434e1a735 100644 --- a/MainModule/Client/Core/UI.luau +++ b/MainModule/Client/Core/UI.luau @@ -114,21 +114,35 @@ return function(Vargs, GetEnv) LoadModule = function(module, data, env) data = data or {} + local function safeTableClone(t) -- TODO: Make RFC on Luau repo to allow table.clone to work with closed metatables + local success, result = pcall(table.clone, t) + if success then + return result + else + local newT = setmetatable({}, {__index = function(_, k) return t[k] end}) + + for k, v in t do + newT[k] = v + end + + return newT + end + end local ran, func = pcall(require, module) - local newEnv = GetEnv(env, { -- // Is this really necessary? + local newEnv = GetEnv(env, { script = module, - client = setmetatable(table.clone(client), {__index = function(_, k) return client[k] end}), - service = setmetatable(table.clone(service), {__index = function(_, k) return service[k] end}) + client = safeTableClone(client), + service = safeTableClone(service) }) if newEnv.service.Threads then newEnv.service.Threads = table.clone(service.Threads) end - for i,v in newEnv.client do -- // Is this really necessary? + for i,v in newEnv.client do if type(v) == "table" and i ~= "Variables" and i ~= "Handlers" then - newEnv.client[i] = setmetatable(table.clone(v), {__index = function(_, k) return v[k] end}) + newEnv.client[i] = safeTableClone(v) end end @@ -317,7 +331,7 @@ return function(Vargs, GetEnv) local ran, ret = rets[1], rets[2] if ret ~= nil then - if type(ret) == "userdata" and Anti.GetClassName(ret) == "ScreenGui" then + if type(ret) == "userdata" and ret:IsA("ScreenGui") then code = (ret:FindFirstChild("Config") and (ret.Config:FindFirstChild("Code") or ret.Config:FindFirstChild("NoEnv-Code"))) or code if not data.NoEnv and code then diff --git a/MainModule/Client/Core/Variables.luau b/MainModule/Client/Core/Variables.luau index 002bb7c238..84c9ae870c 100644 --- a/MainModule/Client/Core/Variables.luau +++ b/MainModule/Client/Core/Variables.luau @@ -62,6 +62,8 @@ return function(Vargs, GetEnv) getfenv().service = nil getfenv().script = nil + local atmosphere = service.Lighting:FindFirstChildWhichIsA("Atmosphere") + client.GUIs = {} client.GUIHolder = service.New("Folder") client.Variables = { @@ -74,6 +76,7 @@ return function(Vargs, GetEnv) ParticlesEnabled = true; CapesEnabled = true; HideChatCommands = false; + CanUseEditableImages = false; -- TODO: Pool from FFlag Particles = {}; KeyBinds = {}; Aliases = {}; @@ -98,6 +101,15 @@ return function(Vargs, GetEnv) FogEnd = service.Lighting.FogEnd; FogStart = service.Lighting.FogStart; }; + AtmosphereSettings = { + Name = atmosphere and atmosphere.Name, + Density = atmosphere and atmosphere.Density, + Offset = atmosphere and atmosphere.Offset, + Color = atmosphere and atmosphere.Color, + Decay = atmosphere and atmosphere.Decay, + Glare = atmosphere and atmosphere.Glare, + Haze = atmosphere and atmosphere.Haze, + }; KeycodeNames = require(client.Shared.KeycodeNames); }; end diff --git a/MainModule/Client/Plugins/Misc_Features.luau b/MainModule/Client/Plugins/Misc_Features.luau index d79d2791da..0ae630fbb0 100644 --- a/MainModule/Client/Plugins/Misc_Features.luau +++ b/MainModule/Client/Plugins/Misc_Features.luau @@ -15,6 +15,9 @@ return function(Vargs, GetEnv) end, ...) end client.cPcall, service.cPcall = cPcall, cPcall + service.CloneTable = function(tbl) + return (getmetatable(tbl) and not pcall(setmetatable(tbl, getmetatable(tbl)))) and setmetatable({}, {__index = function(_, k) return tbl[k] end}) or table.clone(tbl) + end service.AltUnpack = function(args, shift) -- TODO: Remove. This is not used in Adonis at all and is easily replicatable so you can safely remove it withour fear return table.unpack(args, 1 + (shift and shift - 1 or 0), 10 + (shift and shift - 1 or 0)) end @@ -46,6 +49,9 @@ return function(Vargs, GetEnv) end return table.concat(Res) end + -- TODO: Remove \\/ + service.OwnsAsset = service.CheckAssetOwnership + Functions.CatchError = client.Pcall Logs:AddLog("Script", "Misc Features Module Loaded") end diff --git a/MainModule/Client/UI/Aero/Console.rbxmx b/MainModule/Client/UI/Aero/Console.rbxmx index e2dfb8b68a..f48e5e8a4a 100644 --- a/MainModule/Client/UI/Aero/Console.rbxmx +++ b/MainModule/Client/UI/Aero/Console.rbxmx @@ -287,7 +287,7 @@ false 0 - 0 + 1 false @@ -320,7 +320,7 @@ 0 0 0 - -40 + 0 null 0 @@ -712,6 +712,7 @@ return function(data, env) Position = UDim2.new(0, 0, 0, -200); }) + frame.TopBar.Size = UDim2.new(1, 0, 0, service.GuiService:GetGuiInset().Y) frame.Position = UDim2.new(0,0,0,-200) frame.Visible = false frame.Size = UDim2.new(1,0,0,40) diff --git a/MainModule/Client/UI/Aero/Hint.rbxmx b/MainModule/Client/UI/Aero/Hint.rbxmx index 3408ef34dd..693cd20f38 100644 --- a/MainModule/Client/UI/Aero/Hint.rbxmx +++ b/MainModule/Client/UI/Aero/Hint.rbxmx @@ -457,6 +457,8 @@ return function(data, env) local container = client.UI.Get("HintHolder",nil,true) if not container then local holder = service.New("ScreenGui") + holder.IgnoreGuiInset = not client.Variables.TopBarShift + holder.ClipToDeviceSafeArea = true local hTable = client.UI.Register(holder) local frame = service.New("ScrollingFrame", holder) client.UI.Prepare(holder) @@ -488,9 +490,8 @@ return function(data, env) --// First things first account for notif :) local notif = client.UI.Get("Notif") - local topbar = client.UI.Get("TopBar") - container.Position = UDim2.new(0,0,0,((notif and 30) or 0) + ((topbar and 40) or 0) - 35) + container.Position = UDim2.new(0, 0, 0, (notif and 30 or 0)) local children = container:GetChildren() diff --git a/MainModule/Client/UI/Aero/Notif.rbxmx b/MainModule/Client/UI/Aero/Notif.rbxmx index 866e283cca..0d46a3cc64 100644 --- a/MainModule/Client/UI/Aero/Notif.rbxmx +++ b/MainModule/Client/UI/Aero/Notif.rbxmx @@ -59,6 +59,8 @@ return function(data, env) local gui = client.UI.Prepare(script.Parent.Parent) local label = gui.LABEL local str = data.Message + gui.IgnoreGuiInset = not client.Variables.TopBarShift + gui.ClipToDeviceSafeArea = true client.UI.Remove("Notif",script.Parent.Parent) local log = { diff --git a/MainModule/Client/UI/Aero/Notification.rbxmx b/MainModule/Client/UI/Aero/Notification.rbxmx index 81cbf3b193..2400509eb3 100644 --- a/MainModule/Client/UI/Aero/Notification.rbxmx +++ b/MainModule/Client/UI/Aero/Notification.rbxmx @@ -113,6 +113,7 @@ return function(data, env) local name = data.Title local text = data.Message or data.Text or "" local time = data.Time + local icon = data.Icon local returner = nil diff --git a/MainModule/Client/UI/BasicAdmin/Hint.rbxmx b/MainModule/Client/UI/BasicAdmin/Hint.rbxmx index b157330c01..b09c68c906 100644 --- a/MainModule/Client/UI/BasicAdmin/Hint.rbxmx +++ b/MainModule/Client/UI/BasicAdmin/Hint.rbxmx @@ -68,6 +68,8 @@ return function(data, env) local hintBody = hintClone:WaitForChild('Body') local hintTitleText = hintTop:WaitForChild('Title') local hintBodyText = hintBody:WaitForChild('To Name Later') + baseClip.Parent.IgnoreGuiInset = not client.Variables.TopBarShift + baseClip.Parent.ClipToDeviceSafeArea = true gTable.BindEvent(hintButton.MouseButton1Click, function() hintClone:TweenPosition(UDim2.new(0,0,0,-hintClone.AbsoluteSize.Y),'Out','Quint',0.3,true,function(Stat) @@ -705,4 +707,4 @@ end]]> - \ No newline at end of file + diff --git a/MainModule/Client/UI/Default/Console.rbxmx b/MainModule/Client/UI/Default/Console.rbxmx index d678e403a2..570265d9dc 100644 --- a/MainModule/Client/UI/Default/Console.rbxmx +++ b/MainModule/Client/UI/Default/Console.rbxmx @@ -274,7 +274,7 @@ false 0 - 0 + 1 false @@ -304,7 +304,7 @@ 0 0 0 - -40 + 0 null 0 @@ -588,6 +588,7 @@ return function(data, env) local consoleCloseTween = service.TweenService:Create(frame, tweenInfo, { Position = UDim2.new(0, 0, 0, -200); }) + frame.TopBar.Size = UDim2.new(1, 0, 0, service.GuiService:GetGuiInset().Y) local function showGuis() if UI.Get("Notif") then diff --git a/MainModule/Client/UI/Default/Hint.rbxmx b/MainModule/Client/UI/Default/Hint.rbxmx index b2b9945e67..e41d216e52 100644 --- a/MainModule/Client/UI/Default/Hint.rbxmx +++ b/MainModule/Client/UI/Default/Hint.rbxmx @@ -295,10 +295,6 @@ return function(data, env) --// First things first account for notif :) local notif = client.UI.Get("Notif") - if (container:IsA("ScreenGui")) then - container.IgnoreGuiInset, container.ClipToDeviceSafeArea = not client.Variables.TopBarShift, true - end - container.Position = UDim2.new(0, 0, 0, (notif and 30 or 0)) local children = container:GetChildren() diff --git a/MainModule/Client/UI/Default/Music.rbxmx b/MainModule/Client/UI/Default/Music.rbxmx deleted file mode 100644 index c6f9601764..0000000000 --- a/MainModule/Client/UI/Default/Music.rbxmx +++ /dev/null @@ -1,1684 +0,0 @@ - - true - null - nil - - - - - Music - {C3964A12-AC9F-4411-87D7-F7B291A534D7} - = 1 then - wait(1) --4 - end - - success, product_info = pcall(service.MarketplaceService.GetProductInfo, service.MarketplaceService, toPlay.ID, Enum.InfoType.Asset) --5 - count = count + 1 --6 - end - - --local success, product_info = nil, nil - --repeat pcall(function() - -- success, product_info = service.MarketplaceService:GetProductInfo(toPlay.ID, Enum.InfoType.Asset) - -- return success, product_info - --end) until success == true - heading.Text = success and product_info.Name or `[ERROR] {toPlay.Name}` - selected = { - ID = toPlay.ID, - Name = toPlay.Name, - Button = nil, - Index = selected.Index +1 - } - end - end - end - end) - end - loading:Destroy() - end - - -- Tabs for different playlists - - local tabFrame = window:Add("TabFrame",{ - Size = UDim2.new(1, 0, 1, -165); - Position = UDim2.new(0, 0, 0, 90); - }) - - local personalTab = tabFrame:NewTab("Personal",{ - Text = "Personal"; - OnFocus = function() - activeSongList = availableSongLists["Personal"] or {} - end; - }) - local gameTab = tabFrame:NewTab("Game",{ - Text = "Game"; - OnFocus = function() - activeSongList = availableSongLists["Game"] or {} - end; - }) - local adonisTab = tabFrame:NewTab("Adonis", { - Text = "Adonis"; - OnFocus = function() - activeSongList = availableSongLists["Adonis"] or {} - end; - }) - local customTab = tabFrame:NewTab("Custom", { - Text = "Custom"; - OnFocus = function() - activeSongList = availableSongLists["Custom"] or {} - end; - }) - - - -- The Custom Playlists editor window - - local binderBox; binderBox = tabFrame:Add("Frame", { - Visible = false; - Size = UDim2.new(1,0,1,0); - Position = UDim2.new(0,0,0,0); - BackgroundTransparency = 0; - ZIndex = 10000; - Children = { - { - Class = "TextLabel"; - Text = "New Custom Playlist string:"; - Position = UDim2.new(0, 5, 0, 5); - Size = UDim2.new(1, -10, 0, 30); - BackgroundTransparency = 0; - ZIndex = 10001; - }; - { - Class = "TextButton"; - Text = "Add"; - Position = UDim2.new(0.5, 5, 1, -35); - Size = UDim2.new(0.5, -10, 0, 30); - BackgroundTransparency = 0; - ZIndex = 10002; - OnClicked = function() - end - }; - { - Class = "TextButton"; - Text = "Cancel"; - Position = UDim2.new(0, 5, 1, -35); - Size = UDim2.new(0.5, -5, 0, 30); - BackgroundTransparency = 0; - ZIndex = 10003; - OnClicked = function() - binderBox.Visible = false - end - }; - } - }) - - local PlaylistBox = binderBox:Add("TextBox", { - Position = UDim2.new(0, 5, 0, 40); - Size = UDim2.new(1, -10, 1, -80); - TextWrapped = true; - --TextXAlignment = "Left"; - --TextYAlignment = "Top"; - ClearTextOnFocus = false; - PlaceholderText = "NAME:ID, SECOND:12398801, HeavyIsDead:4881542521"; - ZIndex = 10004; - TextChanged = function(newText, enter, box) - client.Variables.Playlist = {Playlist = {}} - for v in pairs(client.Variables.Playlist.Playlist) do - client.Variables.Playlist.Playlist[v] = nil - end - for i,v in next,(string.split(string.gsub(newText, " ", ""), ",")) do - local split = string.split(v, ":") - table.insert(client.Variables.Playlist.Playlist, (#client.Variables.Playlist.Playlist + 1), { - Name = tostring(split[1]), - ID = tonumber(split[2]) - }) - end - binderBox.Visible = false - getSongs(customTab, (client.Variables.Playlist.Playlist or {})) - activeSongList = availableSongLists["Custom"] or {} - end - }) - - PlaylistBox.BackgroundColor3 = PlaylistBox.BackgroundColor3:lerp(Color3.new(1, 1, 1), 0.1) - binderBox.BackgroundColor3 = binderBox.BackgroundColor3:lerp(Color3.new(1, 1, 1), 0.05) - - --[[ - - ======================================================== - | | - | Top control buttons (Save and load custom playlist) | - | | - ======================================================== - - ]]-- - - -- Create playlist button - local playlistLoad = controls:Add("TextButton", { - Text = "⏫"; - TextSize = 15; - ToolTip = "Create playlist: Create a new custom playlist from a string."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 30, 0, 30); - Position = UDim2.new(0, 5, 0, 5); - TextXAlignment = "Center"; - OnClicked = function() - PlaylistBox.Text = "" - binderBox.Visible = true - customTab:FocusTab(); - activeSongList = availableSongLists["Custom"] or {} - end - }) - - -- Save cutom playlist - - local playlistSave = controls:Add("TextButton", { - Text = "⬆️"; - TextSize = 15; - ToolTip = "Upload playlist: Saves your custom playlist to the games datastore."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 30, 0, 30); - Position = UDim2.new(0, 40, 0, 5); - TextXAlignment = "Center"; - OnClicked = function() - personalTab:FocusTab(); - local Playlist = type(client.Variables.Playlist) == "table" and client.Variables.Playlist.Playlist - if Playlist and next(Playlist) then - client.Functions.UpdatePlaylist(client.Variables.Playlist) - getSongs(personalTab, ((client.Functions.Playlist()).Playlist or {})) - else - warn("[ERROR] Cannot update empty Playlist") - end - - activeSongList = availableSongLists["Personal"] or {} - end - }) - - -- Stop button - local controlStop = controls:Add("TextButton", { - Text = "⏹"; - TextSize = 15; - ToolTip = "Stop: Pauses the track and sets the position to 0."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 30, 0, 30); - Position = UDim2.new(0, 75, 0, 5); - TextXAlignment = "Center"; - OnClick = function() - audioLib("UpdateSound", { - Playing = false; - TimePosition = 0; - }) - end - }) - - -- Back button - local controlBack = controls:Add("TextButton", { - Text = "◀️"; - TextSize = 15; - ToolTip = "Back: Go back to the last played track."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 30, 0, 30); - Position = UDim2.new(0, 110, 0, 5); - TextXAlignment = "Center"; - OnClick = function() - - end - }) - - -- Pause/Play button - local controlPausePlay = controls:Add("TextButton", { - Text = "⏯️"; - TextSize = 15; - ToolTip = "Pause/Play: Control the tracks playing state."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 30, 0, 30); - Position = UDim2.new(0, 145, 0, 5); - TextXAlignment = "Center"; - OnClick = function() - if audioLib("GetSound") then - audioLib("UpdateSound", { - Playing = not audioLib("GetSound").Playing - }) - end - end - }) - - -- Forward button - local controlForward = controls:Add("TextButton", { - Text = "▶️"; - TextSize = 15; - ToolTip = "Forward: Skip to the next track."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 30, 0, 30); - Position = UDim2.new(0, 180, 0, 5); - TextXAlignment = "Center"; - OnClick = function() - - end - }) - - -- Forward button - - local controlShuffle = nil - local controlShuffleBackgroundColor3 = nil - local function changeShuffleColor() - if shuffle then - controlShuffle.BackgroundColor3 = Color3.new(0, 1, 0.6) - else - controlShuffle.BackgroundColor3 = controlShuffleBackgroundColor3 - end - end - controlShuffle = controls:Add("TextButton", { - Text = "🔀"; - TextSize = 15; - ToolTip = "Shuffle: Randomly pick between."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 30, 0, 30); - Position = UDim2.new(0, 215, 0, 5); - TextXAlignment = "Center"; - OnClick = function() - shuffle = not shuffle - changeShuffleColor() - end - }) - - controlShuffleBackgroundColor3 = controlShuffle.BackgroundColor3 - - -- Loop button - - local controlLoop = nil - local controlLoopBackgroundColor3 = nil - local function changeLoopColor() - if loop then - controlLoop.BackgroundColor3 = Color3.new(0, 1, 0.6) - else - controlLoop.BackgroundColor3 = controlLoopBackgroundColor3 - end - end - controlLoop = controls:Add("TextButton", { - Text = "🔁"; - TextSize = 15; - ToolTip = "Loop: Loops the song continuously."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 30, 0, 30); - Position = UDim2.new(0, 250, 0, 5); - TextXAlignment = "Center"; - OnClick = function() - loop = not loop - changeLoopColor() - audioLib("UpdateSound", { - Looped = loop; - }) - end - }) - controlLoopBackgroundColor3 = controlLoop.BackgroundColor3 - - -- Bottom control buttons - - -- Custom Sound ID - - local controlID = controls:Add("TextLabel", { - Text = " ID: "; - ToolTip = "ID: The Sound ID from the roblox catalogue."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 120, 0, 30); - Position = UDim2.new(1, -125, 0, 5); - TextXAlignment = "Left"; - Children = { - TextBox = { - Text = ""; - PlaceholderText = "4881542521"; - Size = UDim2.new(0, 80, 1, 0); - Position = UDim2.new(1, -90, 0, 0); - BackgroundTransparency = 1; - TextXAlignment = "Right"; - TextChanged = function(text, enter, new) - if enter then - audioLib("UpdateSound", { - SoundId = `rbxassetid://{text}`; - Playing = true; - TimePosition = 0; - }) - end - end - } - } - }) - - -- Position - --local controlPosition = controls:Add("TextLabel", { - -- Text = " Pos: "; - -- ToolTip = "Position: Set the audio's position (In seconds)."; - -- BackgroundTransparency = 0; - -- Size = UDim2.new(0, 60, 0, 30); - -- Position = UDim2.new(1, -205, 1, -35); - -- TextXAlignment = "Left"; - -- Children = { - -- TextBox = { - -- Text = ""; - -- PlaceholderText = "0"; - -- Size = UDim2.new(0, 40, 1, 0); - -- Position = UDim2.new(1, -50, 0, 0); - -- BackgroundTransparency = 1; - -- TextXAlignment = "Right"; - -- TextChanged = function(text, enter, new) - -- if enter then - -- audioLib("UpdateSound", { - -- TimePosition = text - -- }) - -- end - -- end - -- } - -- } - --}) - - --[[ - - ======================================================== - | | - | Bottom control buttons (Position and volume slider) | - | | - ======================================================== - - ]]-- - - -- Volume - local controlVolume = controls:Add("TextLabel", { - Text = " "; - ToolTip = "Volume: How loud the audio will play (0 to 10)."; - BackgroundTransparency = 0; - Size = UDim2.new(0, 120, 0, 30); - Position = UDim2.new(1, -125, 1, -35); - TextXAlignment = "Left"; - }) - - controlVolume:Add("ImageLabel", { - Image = "rbxassetid://7541896266"; - Size = UDim2.new(0, 20, 0, 20); - Position = UDim2.new(0, 5, 0, 5); - BackgroundTransparency = 1; - }) - - local controlVolumeSliderContainer = controlVolume:Add("Frame", { - Image = "rbxassetid://7541896266"; - Size = UDim2.new(1, -45, 0, 2); - Position = UDim2.new(0, 30, 0, 14); - BackgroundColor3 = Color3.new(0.454902, 0.454902, 0.454902); - BackgroundTransparency = 0; - }) - - local controlVolumeSliderInstance = controlVolumeSliderContainer:Add("ImageButton", { - Name = "Slider"; - --Text = ""; - Size = UDim2.new(0, 10, 0, 10); - Position = UDim2.new(0, 0, 0, -4); - BackgroundColor3 = Color3.new(1,1,1); - BackgroundTransparency = 0; - TextXAlignment = "Right"; - Children = { - UICorner = { - CornerRadius = UDim.new(1, 0); - } - } - }) - - local controlVolumeSlider = sliderModule.new(service.UnWrap(controlVolumeSliderContainer), {Start = 0, End = 1000, Increment = 1, DefaultValue = 0.5}, TweenInfo.new(0.1, Enum.EasingStyle.Quad), "X", 0) - controlVolumeSlider:Track() - - controlVolumeSlider.Changed:Connect(function(value) - audioLib("UpdateSound", { - Volume = value / 100; - }) - end) - - -- Track position - local controlPosition = controls:Add("TextLabel", { - Text = " "; - ToolTip = "Position: Control where the song is playing from."; - BackgroundTransparency = 0; - Size = UDim2.new(1, -135, 0, 30); - Position = UDim2.new(0, 5, 1, -35); - TextXAlignment = "Left"; - }) - - local controlPositionSliderContainer = controlPosition:Add("Frame", { - Image = "rbxassetid://7541896266"; - Size = UDim2.new(1, -30, 0, 2); - Position = UDim2.new(0, 14, 0, 14); - BackgroundColor3 = Color3.new(0.454902, 0.454902, 0.454902); - BackgroundTransparency = 0; - }) - - local controlPositionSliderInstance = controlPositionSliderContainer:Add("ImageButton", { - Name = "Slider"; - Size = UDim2.new(0, 10, 0, 10); - Position = UDim2.new(0, 0, 0, -4); - BackgroundColor3 = Color3.new(1,1,1); - BackgroundTransparency = 0; - TextXAlignment = "Right"; - Children = { - UICorner = { - CornerRadius = UDim.new(1, 0); - } - } - }) - - local controlPositionSlider = sliderModule.new(service.UnWrap(controlPositionSliderContainer), {Start = 0, End = 10000, Increment = 1, DefaultValue = 0.5}, TweenInfo.new(0.1, Enum.EasingStyle.Quad), "X", 0) - controlPositionSlider:Track() - - controlPositionSlider.Changed:Connect(function(value) - local length = audioLib("GetSound").TimeLength - audioLib("UpdateSound", { - TimePosition = value / 10000 * length; - }) - end) - - -- Used to play a sound on window open. 4881542521. - - -- Create OnClose event after everything has been initialised - - -- Load in track lists - - local loadingMessage = function(tab) - tab:Add("TextLabel", { - Text = "Waiting in queue to load tracks..."; - ToolTip = "Never gonna give you up, Never gonna let you down..."; - BackgroundTransparency = 0; - Size = UDim2.new(1,0,1,0); - Position = UDim2.new(0,0,0,0); - ZIndex = 69420 - --TextXAlignment = "Left"; - }) - end - - loadingMessage(personalTab) - loadingMessage(gameTab) - loadingMessage(adonisTab) - getSongs(personalTab, ((client.Functions.Playlist()).Playlist or {})) - getSongs(gameTab, (client.Remote.Get("Variable", "MusicList") or {})) - getSongs(adonisTab, (client.Remote.Get("Variable", "MusicList") or {})) - activeSongList = availableSongLists["Personal"] or {} - - task.spawn(function() - local tempsound = audioLib("GetSound") - while task.wait(progressupdatewait) do - tempsound = audioLib("GetSound") - if tempsound and tempsound.TimeLength ~= 0 then - controlPositionSlider:OverrideVisualValue(tempsound.TimePosition / tempsound.TimeLength * 10000) - end - end - end) -end]]> - -1 - - - - - - - Visualizer - {0087460F-28F3-4168-B330-7401BCFC92E4} - = Alpha then - EndKeypoint = Keypoint - StartKeypoint = Keypoints[math.max(1, i-1)] - break - end - end - - local StartTime, EndTime = StartKeypoint.Time, EndKeypoint.Time - local StartValue, EndValue = StartKeypoint.Value, EndKeypoint.Value - - local KeyframeAlpha = (Alpha - StartTime) / (EndTime - StartTime) - - return StartValue:Lerp(EndValue, KeyframeAlpha) -end - -function module.new(Frame, BarCount) - - -- Determine settings - local BAR_COUNT = math.clamp(type(BarCount) == "number" and BarCount or 41, 11,601) - local SAMPLE_HZ = math.clamp(BAR_COUNT/2,10,500) - - if BAR_COUNT%2==0 then - BAR_COUNT += 1 - end - - local BAR_SIZE = 1/BAR_COUNT - local BUFFER_COUNT = math.ceil(BAR_COUNT/2) - local BAR_TO_BUFFER = table.create(BAR_COUNT) - local BAR_TO_MULTIPLIER = table.create(BAR_COUNT) - - for i=1, BAR_COUNT do - BAR_TO_BUFFER[i] = math.abs(BUFFER_COUNT- (i+ (i<=BUFFER_COUNT and -1 or 1) )) - BAR_TO_MULTIPLIER[i] = 1-(math.clamp(math.abs(BUFFER_COUNT- (i+ (i<=BUFFER_COUNT and -1 or 1) ))/BUFFER_COUNT, 0.01,1)^2) - end - - local UPDATE_WAIT = 1/SAMPLE_HZ - - -- Setup visualizer - - local Visualizer = { - Frame = Frame; - VolumeBuffer = table.create(BUFFER_COUNT+1); - Bars = {}; - BufferConnection = nil; - PlayingConnection = nil; - Sound = nil; - } - - -- Create the bar guis - for i=1, BAR_COUNT do - - local Bar = Frame:Add("Frame", { - BorderSizePixel = 0; - BackgroundColor3 = Color3.new(0.98,0.98,0.99); - AnchorPoint = Vector2.new(0,0.5); - Size = UDim2.new(BAR_SIZE,0,0.02,0); - Position = UDim2.new(BAR_SIZE* (i-1), 0,0.5,0); - }) - - Visualizer.Bars[i] = Bar - end - - local function HandlePlaying() - if Visualizer.BufferConnection then - Visualizer.BufferConnection:Disconnect() - Visualizer.BufferConnection = nil - end - - local Sound = Visualizer.Sound - if not Sound then return end - - if Sound.Playing then - local LastStored = os.clock() - Visualizer.BufferConnection = RunService.Heartbeat:Connect(function() - local success, void = pcall(function() - Visualizer.VolumeBuffer[1] = Sound.PlaybackLoudness - Visualizer.Bars[BUFFER_COUNT]:TweenSize( - UDim2.new( - BAR_SIZE,0, - math.clamp((Sound.PlaybackLoudness/400), 0.02,1),0 - ), - Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.014, true - ) - - if os.clock()-LastStored > UPDATE_WAIT then - LastStored = os.clock() - - table.insert(Visualizer.VolumeBuffer,1,Sound.PlaybackLoudness) - local Length = #Visualizer.VolumeBuffer - if Length > BUFFER_COUNT then - Visualizer.VolumeBuffer[#Visualizer.VolumeBuffer] = nil - end - - local Color = Visualizer.Color - local ColorType = typeof(Color) - - for i,Bar in ipairs(Visualizer.Bars) do - - local Alpha = math.clamp( - ((Visualizer.VolumeBuffer[BAR_TO_BUFFER[i]] or 0)/400), - 0.02, 1 - ) - - Bar:TweenSize( - UDim2.new( - BAR_SIZE,0, - Alpha,0 - ), - Enum.EasingDirection.Out, Enum.EasingStyle.Linear, UPDATE_WAIT, true - ) - - if Color then - if ColorType == "Color3" then - Bar.BackgroundColor3 = Color - elseif ColorType == "ColorSequence" then - Bar.BackgroundColor3 = AlphaColorSequence(Color, Alpha) - end - end - - end - end - end) - if not success then Visualizer:UnlinkFromSound() end - end) - else - table.clear(Visualizer.VolumeBuffer) - for i,Bar in ipairs(Visualizer.Bars) do - Bar:TweenSize( - UDim2.new(BAR_SIZE,0,0.02,0), - Enum.EasingDirection.Out, Enum.EasingStyle.Linear, UPDATE_WAIT, true - ) - end - end - end - - function Visualizer:LinkToSound(Sound) - - Visualizer:UnlinkFromSound() - - table.clear(Visualizer.VolumeBuffer) - - Visualizer.Sound = Sound - - HandlePlaying() - Visualizer.PlayingConnection = Sound:GetPropertyChangedSignal("Playing"):Connect(HandlePlaying) - end - - function Visualizer:UnlinkFromSound() - - if Visualizer.PlayingConnection then - Visualizer.PlayingConnection:Disconnect() - Visualizer.PlayingConnection = nil - end - if Visualizer.BufferConnection then - Visualizer.BufferConnection:Disconnect() - Visualizer.BufferConnection = nil - end - - Visualizer.Sound = nil - - for i,Bar in ipairs(Visualizer.Bars) do - Bar:TweenSize( - UDim2.new(BAR_SIZE,0,0.02,0), - Enum.EasingDirection.Out, Enum.EasingStyle.Linear, UPDATE_WAIT, true - ) - end - - end - - function Visualizer:Destroy() - if Visualizer.PlayingConnection then - Visualizer.PlayingConnection:Disconnect() - Visualizer.PlayingConnection = nil - end - if Visualizer.BufferConnection then - Visualizer.BufferConnection:Disconnect() - Visualizer.BufferConnection = nil - end - for i,Bar in ipairs(Visualizer.Bars) do - Bar:Destroy() - end - table.clear(Visualizer.VolumeBuffer) - end - - - return Visualizer -end - -return module -]]> - 6360148029 - - - - - - - - Slider - {8AD85B7A-B61C-4D68-9106-50EA59AAF9B7} - 0, "Increment must be greater than 0") - assert(configuration.End > configuration.Start, `Config.End must be greater than Config.Start ({configuration.End} <= {configuration.Start})`) - - axis = axis or "x" - axis = Lower(axis) - assert(axis == "x" or axis == "y", "Axis must be X or Y!") - - assert(typeof(moveTweenInfo) == "TweenInfo", "MoveTweenInfo must be a TweenInfo object!") - - padding = padding or 5 - assert(type(padding) == "number", "Padding variable must be a number!") - - local self = setmetatable({}, Slider) - - self._holder = holder - self._button = sliderBtn - self._config = configuration - self._axis = Upper(axis) - self._padding = padding - - self.IsHeld = false - self._mainConnection = nil - self._buttonConnections = {} - self._inputPos = nil - - self._percent = 0 - if configuration.DefaultValue then - configuration.DefaultValue = Clamp(configuration.DefaultValue, configuration.Start, configuration.End) - self._percent = getAlphaBetween(configuration.Start, configuration.End, configuration.DefaultValue) - end - self._percent = Clamp(self._percent, 0, 1) - - self._value = getNewValue(self) - self._scaleIncrement = getScaleIncrement(self) - - self._currentTween = nil - self._tweenInfo = moveTweenInfo or TweenInfo.new(1) - - self.Changed = Signal.new() - self.Dragged = Signal.new() - self.Released = Signal.new() - - self:Move() - table.insert(Slider.Sliders, self) - - return self -end - -function Slider:Track() - for _, connection in ipairs(self._buttonConnections) do - connection:Disconnect() - end - - table.insert(self._buttonConnections, self._button.MouseButton1Down:Connect(function() - self.IsHeld = true - end)) - - table.insert(self._buttonConnections, self._button.MouseButton1Up:Connect(function() - if self.IsHeld then - self.Released:Fire(self._value) - end - self.IsHeld = false - end)) - - if self.Changed then - self.Changed:Fire(self._value) - end - - if self._mainConnection then - self._mainConnection:Disconnect() - end - - self._mainConnection = UserInputService.InputChanged:Connect(function(inputObject, gameProcessed) - if inputObject.UserInputType == Enum.UserInputType.MouseMovement or inputObject.UserInputType == Enum.UserInputType.Touch then - self._inputPos = inputObject.Position - self:Update() - end - end) -end - -function Slider:Update() - if self.IsHeld and self._inputPos then - local mousePos = self._inputPos[self._axis] - - local sliderSize = self._holder.AbsoluteSize[self._axis] - local sliderPos = self._holder.AbsolutePosition[self._axis] - local newPos = snapToScale((mousePos - sliderPos) / sliderSize, self._scaleIncrement) - - local percent = Clamp(newPos, 0, 1) - self._percent = percent - self:Move() - self.Dragged:Fire(self._value) - end -end - -function Slider:Untrack() - for _, connection in ipairs(self._buttonConnections) do - connection:Disconnect() - end - if self._mainConnection then - self._mainConnection:Disconnect() - end - self.IsHeld = false -end - -function Slider:Reset() - for _, connection in ipairs(self._buttonConnections) do - connection:Disconnect() - end - if self._mainConnection then - self._mainConnection:Disconnect() - end - - self.IsHeld = false - - self._percent = 0 - if self._config.DefaultValue then - self._percent = getAlphaBetween(self._config.Start, self._config.End, self._config.DefaultValue) - end - self._percent = Clamp(self._percent, 0, 1) - self:Move() -end - -function Slider:OverrideValue(newValue: number) - self.IsHeld = false - self._percent = getAlphaBetween(self._config.Start, self._config.End, newValue) - self._percent = Clamp(self._percent, 0, 1) - self._percent = snapToScale(self._percent, self._scaleIncrement) - self:Move() -end - -function Slider:Move() - self._value = getNewValue(self) - - if self._currentTween then - self._currentTween:Cancel() - end - self._currentTween = TweenService:Create(self._button, self._tweenInfo, { - Position = getNewPosition(self) - }) - - self._currentTween:Play() - self.Changed:Fire(self._value) -end - -function Slider:OverrideVisualValue(newValue: number) - if self.IsHeld then - return false - end - - local percent = getAlphaBetween(self._config.Start, self._config.End, newValue) - percent = Clamp(percent, 0, 1) - percent = snapToScale(percent, self._scaleIncrement) - - if self._currentTween then - self._currentTween:Cancel() - end - self._currentTween = TweenService:Create(self._button, self._tweenInfo, { - Position = getNewPosition(self, percent) - }) - - self._currentTween:Play() -end - -function Slider:OverrideIncrement(newIncrement: number) - self._config.Increment = newIncrement - self._scaleIncrement = getScaleIncrement(self) - self._percent = Clamp(self._percent, 0, 1) - self._percent = snapToScale(self._percent, self._scaleIncrement) - self:Move() -end - -function Slider:GetValue() - return self._value -end - -function Slider:GetIncrement() - return self._increment -end - -function Slider:Destroy() - for _, connection in ipairs(self._buttonConnections) do - connection:Disconnect() - end - if self._mainConnection then - self._mainConnection:Disconnect() - end - self.Changed:Destroy() - self.Dragged:Destroy() - self.Released:Destroy() - - for index = 1, #Slider.Sliders do - if Slider.Sliders[index] == self then - table.remove(Slider.Sliders, index) - end - end - - setmetatable(self, nil) - self = nil -end - -UserInputService.InputEnded:Connect(function(inputObject, internallyProcessed) - if inputObject.UserInputType == Enum.UserInputType.MouseButton1 or inputObject.UserInputType == Enum.UserInputType.Touch then - for _, slider in ipairs(Slider.Sliders) do - if slider.IsHeld then - slider.Released:Fire(slider._value) - end - slider.IsHeld = false - end - end -end) - -return Slider - ------------------------------------------------------------------------------------------]]> - 8314798830 - - - - - - - - Signal - {9ACE78A1-7123-447F-B11E-921DE1E2E90F} - Used to create, connect, wait and destroy signals. --- > Created by Quenty ------------------------------------------------------------------------------------------ - ---- Lua-side duplication of the API of events on Roblox objects. --- Signals are needed for to ensure that for local events objects are passed by --- reference rather than by value where possible, as the BindableEvent objects --- always pass signal arguments by value, meaning tables will be deep copied. --- Roblox's deep copy method parses to a non-lua table compatable format. --- @classmod Signal - -local Signal = {} -Signal.__index = Signal -Signal.ClassName = "Signal" - ---- Constructs a new signal. --- @constructor Signal.new() --- @treturn Signal -function Signal.new() - local self = setmetatable({}, Signal) - - self._bindableEvent = Instance.new("BindableEvent") - self._argData = nil - self._argCount = nil -- Prevent edge case of :Fire("A", nil) --> "A" instead of "A", nil - - return self -end - ---- Fire the event with the given arguments. All handlers will be invoked. Handlers follow --- Roblox signal conventions. --- @param ... Variable arguments to pass to handler --- @treturn nil -function Signal:Fire(...) - self._argData = {...} - self._argCount = select("#", ...) - self._bindableEvent:Fire() - self._argData = nil - self._argCount = nil -end - ---- Connect a new handler to the event. Returns a connection object that can be disconnected. --- @tparam function handler Function handler called with arguments passed when `:Fire(...)` is called --- @treturn Connection Connection object that can be disconnected -function Signal:Connect(handler) - if not (type(handler) == "function") then - error(("connect(%s)"):format(typeof(handler)), 2) - end - - return self._bindableEvent.Event:Connect(function() - handler(unpack(self._argData, 1, self._argCount)) - end) -end - ---- Wait for fire to be called, and return the arguments it was given. --- @treturn ... Variable arguments from connection -function Signal:Wait() - self._bindableEvent.Event:Wait() - assert(self._argData, "Missing arg data, likely due to :TweenSize/Position corrupting threadrefs.") - return unpack(self._argData, 1, self._argCount) -end - ---- Disconnects all connected events to the signal. Voids the signal as unusable. --- @treturn nil -function Signal:Destroy() - if self._bindableEvent then - self._bindableEvent:Destroy() - self._bindableEvent = nil - end - - self._argData = nil - self._argCount = nil -end - -return Signal]]> - -1 - - - - - - false - - 0 - 0 - - - true - 0 - - 1 - 1 - 1 - - 0 - - 0.105882362 - 0.164705887 - 0.207843155 - - 0 - 1 - false - false - rbxasset://textures/ui/GuiImagePlaceholder.png - - 1 - 1 - 1 - - - 0 - 0 - - - 0 - 0 - - 0 - 0 - ImageLabel - null - null - null - null - - 0 - 0 - 0 - 0 - - 0 - null - 0 - 0 - false - 0 - 0 - 0 - 0 - false - null - 0 - - 0 - 100 - 0 - 100 - - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - -1 - - - 1 - 0 - 1 - 0 - - true - 1 - - - - diff --git a/MainModule/Client/UI/Default/Music/Signal.luau b/MainModule/Client/UI/Default/Music/Signal.luau new file mode 100644 index 0000000000..6c1ddda242 --- /dev/null +++ b/MainModule/Client/UI/Default/Music/Signal.luau @@ -0,0 +1,243 @@ +-------------------------------------------------------------------------------- +-- Batched Yield-Safe Signal Implementation -- +-- This is a Signal class which has effectively identical behavior to a -- +-- normal RBXScriptSignal, with the only difference being a couple extra -- +-- stack frames at the bottom of the stack trace when an error is thrown. -- +-- This implementation caches runner coroutines, so the ability to yield in -- +-- the signal handlers comes at minimal extra cost over a naive signal -- +-- implementation that either always or never spawns a thread. -- +-- -- +-- API: -- +-- local Signal = require(THIS MODULE) -- +-- local sig = Signal.new() -- +-- local connection = sig:Connect(function(arg1, arg2, ...) ... end) -- +-- sig:Fire(arg1, arg2, ...) -- +-- connection:Disconnect() -- +-- sig:DisconnectAll() -- +-- local arg1, arg2, ... = sig:Wait() -- +-- -- +-- Licence: -- +-- Licenced under the MIT licence. -- +-- -- +-- Authors: -- +-- stravant - July 31st, 2021 - Created the file. -- +-------------------------------------------------------------------------------- + +--[[ +MIT License + +Copyright (c) 2021 Mark Langen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]] + +-- The currently idle thread to run the next handler on +local freeRunnerThread = nil + +-- Function which acquires the currently idle handler runner thread, runs the +-- function fn on it, and then releases the thread, returning it to being the +-- currently idle one. +-- If there was a currently idle runner thread already, that's okay, that old +-- one will just get thrown and eventually GCed. +local function acquireRunnerThreadAndCallEventHandler(fn, ...) + local acquiredRunnerThread = freeRunnerThread + freeRunnerThread = nil + fn(...) + -- The handler finished running, this runner thread is free again. + freeRunnerThread = acquiredRunnerThread +end + +-- Coroutine runner that we create coroutines of. The coroutine can be +-- repeatedly resumed with functions to run followed by the argument to run +-- them with. +local function runEventHandlerInFreeThread() + -- Note: We cannot use the initial set of arguments passed to + -- runEventHandlerInFreeThread for a call to the handler, because those + -- arguments would stay on the stack for the duration of the thread's + -- existence, temporarily leaking references. Without access to raw bytecode + -- there's no way for us to clear the "..." references from the stack. + while true do + acquireRunnerThreadAndCallEventHandler(coroutine.yield()) + end +end + +-- Connection class +local Connection = {} +Connection.__index = Connection + +function Connection.new(signal, fn) + return setmetatable({ + _connected = true, + _signal = signal, + _fn = fn, + _next = false, + }, Connection) +end + +function Connection:Disconnect() + self._connected = false + + -- Unhook the node, but DON'T clear it. That way any fire calls that are + -- currently sitting on this node will be able to iterate forwards off of + -- it, but any subsequent fire calls will not hit it, and it will be GCed + -- when no more fire calls are sitting on it. + if self._signal._handlerListHead == self then + self._signal._handlerListHead = self._next + else + local prev = self._signal._handlerListHead + while prev and prev._next ~= self do + prev = prev._next + end + if prev then + prev._next = self._next + end + end +end + +-- Make Connection strict +setmetatable(Connection, { + __index = function(tb, key) + error(("Attempt to get Connection::%s (not a valid member)"):format(tostring(key)), 2) + end, + __newindex = function(tb, key, value) + error(("Attempt to set Connection::%s (not a valid member)"):format(tostring(key)), 2) + end +}) + +-- Signal class +local Signal = {} +Signal.__index = Signal + +function Signal.new() + return setmetatable({ + _handlerListHead = false, + Event = {}, + }, Signal) +end + +function Signal:Connect(fn) + local connection = Connection.new(self, fn) + if self._handlerListHead then + connection._next = self._handlerListHead + self._handlerListHead = connection + else + self._handlerListHead = connection + end + local signalSelf = self + function connection:Fire(...) + signalSelf:Fire(fn) + end + function connection:fire(...) + signalSelf:Fire(fn) + end + function connection:disconnect() + self:Disconnect() + end + function connection:wait() + return signalSelf:Wait() + end + return connection +end + +function Signal:connect(fn) + return self:Connect(fn) +end + +-- Disconnect all handlers. Since we use a linked list it suffices to clear the +-- reference to the head handler. +function Signal:DisconnectAll() + self._handlerListHead = false +end + +-- Signal:Fire(...) implemented by running the handler functions on the +-- coRunnerThread, and any time the resulting thread yielded without returning +-- to us, that means that it yielded to the Roblox scheduler and has been taken +-- over by Roblox scheduling, meaning we have to make a new coroutine runner. +function Signal:Fire(...) + local item = self._handlerListHead + while item do + if item._connected then + if not freeRunnerThread then + freeRunnerThread = coroutine.create(runEventHandlerInFreeThread) + -- Get the freeRunnerThread to the first yield + coroutine.resume(freeRunnerThread) + end + task.spawn(freeRunnerThread, item._fn, ...) + end + item = item._next + end +end + +function Signal:fire(...) + self:Fire(...) +end + +-- Implement Signal:Wait() in terms of a temporary connection using +-- a Signal:Connect() which disconnects itself. +function Signal:Wait() + local waitingCoroutine = coroutine.running() + local cn; + cn = self:Connect(function(...) + cn:Disconnect() + task.spawn(waitingCoroutine, ...) + end) + return coroutine.yield() +end + +function Signal:wait() + return self:Wait() +end + +-- Implement Signal:Once() in terms of a connection which disconnects +-- itself before running the handler. +function Signal:Once(fn) + local cn; + cn = self:Connect(function(...) + if cn._connected then + cn:Disconnect() + end + fn(...) + end) + return cn +end + +function Signal:ConnectOnce(fn) + return self:Once(fn) +end + +function Signal:connectOnce(fn) + return self:Once(fn) +end + +function Signal:Destroy() + self:DisconnectAll() + setmetatable(self, nil) +end + +-- Make signal strict +setmetatable(Signal, { + __index = function(tb, key) + error(("Attempt to get Signal::%s (not a valid member)"):format(tostring(key)), 2) + end, + __newindex = function(tb, key, value) + error(("Attempt to set Signal::%s (not a valid member)"):format(tostring(key)), 2) + end +}) + +return Signal diff --git a/MainModule/Client/UI/Default/Music/Slider.luau b/MainModule/Client/UI/Default/Music/Slider.luau new file mode 100644 index 0000000000..f24cc2065b --- /dev/null +++ b/MainModule/Client/UI/Default/Music/Slider.luau @@ -0,0 +1,389 @@ +-------------------------------------------------------------------------------------------- +-------------------------------------- Slider Module --------------------------------------- +-- [Adonis Maintainer]: P3tray +-- [Author]: Krypt +-- [Description]: Creates a slider based on a start, end and incremental value. Allows ... +-- ... sliders to be moved, tracked/untracked, reset, and have specific properties such ... +-- ... as their current value and increment to be overriden. + +-- [Version]: 2.1.1 +-- [Created]: 22/12/2021 +-- [Updated]: 23/11/2022 +-- [Dev Forum Link]: https://devforum.roblox.com/t/1597785/ +-------------------------------------------------------------------------------------------- + +--!nonstrict +local Slider = {Sliders = {}} + +local RunService = game:GetService("RunService") +local UserInputService = game:GetService("UserInputService") +local TweenService = game:GetService("TweenService") + +assert(RunService:IsClient(), "Slider module can only be used on the Client!") + +local SliderFuncs = {} +do + function SliderFuncs.snapToScale(val: number, step: number): number + return math.clamp(math.round(val / step) * step, 0, 1) + end + + function lerp(start: number, finish: number, percent: number): number + return (1 - percent) * start + percent * finish + end + + function SliderFuncs.map(value: number, start: number, stop: number, newStart: number, newEnd: number, constrain: boolean): number + local newVal = lerp(newStart, newEnd, SliderFuncs.getAlphaBetween(start, stop, value)) + if not constrain then + return newVal + end + + if newStart < newEnd then + newStart, newEnd = newEnd, newStart + end + + return math.max(math.min(newVal, newStart), newEnd) + end + + function SliderFuncs.getNewPosition(self): UDim2 + local absoluteSize = self._data.Button.AbsoluteSize[self._config.Axis] + local holderSize = self._holder.AbsoluteSize[self._config.Axis] + + local anchorPoint = self._data.Button.AnchorPoint[self._config.Axis] + + local paddingScale = (self._config.Padding / holderSize) + + local minScale = ((anchorPoint * absoluteSize) / holderSize + paddingScale) + local decrement = ((2 * absoluteSize) * anchorPoint) - absoluteSize + local maxScale = (1 - minScale) + (decrement / holderSize) + + local newPercent = SliderFuncs.map(self._data._percent, 0, 1, minScale, maxScale, true) + + return + if self._config.Axis == "X" then UDim2.fromScale(newPercent, self._data.Button.Position.Y.Scale) + else UDim2.fromScale(self._data.Button.Position.X.Scale, newPercent) + end + + function SliderFuncs.getScaleIncrement(self) + return 1 / ((self._config.SliderData.End - self._config.SliderData.Start) / self._config.SliderData.Increment) + end + + function SliderFuncs.getAlphaBetween(a: number, b: number, c: number): number + return (c - a) / (b - a) + end + + function SliderFuncs.getNewValue(self) + local newValue = lerp(self._config.SliderData.Start, self._config.SliderData.End, self._data._percent) + local incrementScale = (1 / self._config.SliderData.Increment) + + newValue = math.round(newValue * incrementScale) / incrementScale + return newValue + end +end + +local Signal = require(script.Parent.Signal) + +Slider.__index = function(object, indexed) + local deprecated = { + {".OnChange", ".Changed", rawget(object, "Changed")} + } + + for _, tbl in ipairs(deprecated) do + local deprecatedStr = string.sub(tbl[1], 2) + + if deprecatedStr == indexed then + warn(string.format("%s is deprecated, please use %s instead", tbl[1], tbl[2])) + return tbl[3] + end + end + + return Slider[indexed] +end + +export type configDictionary = { + SliderData: {Start: number, End: number, Increment: number, DefaultValue: number | nil}, + MoveType: "Tween" | "Instant" | nil, + MoveInfo: TweenInfo | nil, + Axis: string | nil, + Padding: number | nil, + AllowBackgroundClick: boolean +} + +function Slider.new(holder: GuiBase2d, config: configDictionary) + assert(pcall(function() + return holder.AbsoluteSize, holder.AbsolutePosition + end), "Holder argument does not have an AbsoluteSize/AbsolutePosition") + + local duplicate = false + for _, slider in ipairs(Slider.Sliders) do + if slider._holder == holder then + duplicate = true + break + end + end + + assert(not duplicate, "Cannot set two sliders with same frame!") + assert(config.SliderData.Increment ~= nil, "Failed to find Increment in SliderData table") + assert(config.SliderData.Start ~= nil, "Failed to find Start in SliderData table") + assert(config.SliderData.End ~= nil, "Failed to find End in SliderData table") + assert(config.SliderData.Increment > 0, "SliderData.Increment must be greater than 0") + assert(config.SliderData.End > config.SliderData.Start, string.format("Slider end value must be greater than its start value! (%.1f <= %.1f)", config.SliderData.End, config.SliderData.Start)) + + local self = setmetatable({}, Slider) + self._holder = holder + self._data = { + -- Buttons + Button = nil, + HolderButton = nil, + + -- Clicking + _clickOverride = false, + + _mainConnection = nil, + _clickConnections = {}, + _otherConnections = {}, + + _inputPos = nil, + + -- Internal + _percent = 0, + _value = 0, + _scaleIncrement = 0, + _currentTween = nil, + _allowBackgroundClick = if config.AllowBackgroundClick == false then false else true + } + + self._config = config + self._config.Axis = string.upper(config.Axis or "X") + self._config.Padding = config.Padding or 5 + self._config.MoveInfo = config.MoveInfo or TweenInfo.new(0.2) + self._config.MoveType = config.MoveType or "Tween" + self.IsHeld = false + + local sliderBtn = holder:FindFirstChild("Slider") + assert(sliderBtn ~= nil, "Failed to find slider button.") + assert(sliderBtn:IsA("GuiButton"), "Slider is not a GuiButton") + + self._data.Button = sliderBtn + + -- Holder button -- + if self._data._allowBackgroundClick then + local holderClickButton = Instance.new("TextButton") + holderClickButton.BackgroundTransparency = 1 + holderClickButton.Text = "" + holderClickButton.Name = "HolderClickButton" + holderClickButton.Size = UDim2.fromScale(1, 1) + holderClickButton.ZIndex = -1 + holderClickButton.Parent = self._holder + self._data.HolderButton = holderClickButton + end + + -- Finalise -- + + self._data._percent = 0 + if config.SliderData.DefaultValue then + config.SliderData.DefaultValue = math.clamp(config.SliderData.DefaultValue, config.SliderData.Start, config.SliderData.End) + self._data._percent = SliderFuncs.getAlphaBetween(config.SliderData.Start, config.SliderData.End, config.SliderData.DefaultValue) + end + + self._data._percent = math.clamp(self._data._percent, 0, 1) + + self._data._value = SliderFuncs.getNewValue(self) + self._data._increment = config.SliderData.Increment + self._data._scaleIncrement = SliderFuncs.getScaleIncrement(self) + + self.Changed = Signal.new() + self.Dragged = Signal.new() + self.Released = Signal.new() + + self._data._percent = SliderFuncs.snapToScale(self._data._percent, self._data._scaleIncrement) + self:Move() + + table.insert(self._data._otherConnections, sliderBtn:GetPropertyChangedSignal("AbsoluteSize"):Connect(function() + self:Move("Instant") + end)) + + table.insert(Slider.Sliders, self) + + return self +end + +function Slider:Track() + for _, connection in ipairs(self._data._clickConnections) do + connection:Disconnect() + end + + table.insert(self._data._clickConnections, self._data.Button.MouseButton1Down:Connect(function() + self.IsHeld = true + end)) + + table.insert(self._data._clickConnections, self._data.Button.MouseButton1Up:Connect(function() + if self.IsHeld then + self.Released:Fire(self._data._value) + end + self.IsHeld = false + end)) + + if self._data._allowBackgroundClick then + table.insert(self._data._clickConnections, self._data.HolderButton.Activated:Connect(function(inputObject: InputObject) + if inputObject.UserInputType == Enum.UserInputType.MouseButton1 or inputObject.UserInputType == Enum.UserInputType.Touch then + self._data._inputPos = inputObject.Position + self._data._clickOverride = true + self:Update() + self._data._clickOverride = false + end + end)) + end + + if self.Changed then + self.Changed:Fire(self._data._value) + end + + if self._data._mainConnection then + self._data._mainConnection:Disconnect() + end + + self._data._mainConnection = UserInputService.InputChanged:Connect(function(inputObject, gameProcessed) + if inputObject.UserInputType == Enum.UserInputType.MouseMovement or inputObject.UserInputType == Enum.UserInputType.Touch then + self._data._inputPos = inputObject.Position + self:Update() + end + end) +end + +function Slider:Update() + if (self.IsHeld or self._data._clickOverride) and self._data._inputPos then + local sliderSize = self._holder.AbsoluteSize[self._config.Axis] + local sliderPos = self._holder.AbsolutePosition[self._config.Axis] + + local mousePos = self._data._inputPos[self._config.Axis] + + if mousePos then + local relativePos = (mousePos - sliderPos) + local newPos = SliderFuncs.snapToScale(relativePos / sliderSize, self._data._scaleIncrement) + + local percent = math.clamp(newPos, 0, 1) + self._data._percent = percent + self.Dragged:Fire(self._data._value) + self:Move() + end + end +end + +function Slider:Untrack() + for _, connection in ipairs(self._data._clickConnections) do + connection:Disconnect() + end + if self._data._mainConnection then + self._data._mainConnection:Disconnect() + end + self.IsHeld = false +end + +function Slider:Reset() + for _, connection in ipairs(self._data._clickConnections) do + connection:Disconnect() + end + if self._data._mainConnection then + self._data._mainConnection:Disconnect() + end + + self.IsHeld = false + + self._data._percent = 0 + if self._config.SliderData.DefaultValue then + self._data._percent = SliderFuncs.getAlphaBetween(self._config.SliderData.Start, self._config.SliderData.End, self._config.SliderData.DefaultValue) + end + self._data._percent = math.clamp(self._data._percent, 0, 1) + self:Move() +end + +function Slider:OverrideValue(newValue: number, supressEvent: boolean?) -- Patch by ccuser44 to prevent music glitching + self.IsHeld = false + self._data._percent = SliderFuncs.getAlphaBetween(self._config.SliderData.Start, self._config.SliderData.End, newValue) + self._data._percent = math.clamp(self._data._percent, 0, 1) + self._data._percent = SliderFuncs.snapToScale(self._data._percent, self._data._scaleIncrement) + self:Move(nil, supressEvent) +end + +function Slider:Move(override: string, supressEvent: boolean?) + self._data._value = SliderFuncs.getNewValue(self) + + local moveType = if override ~= nil then override else self._config.MoveType + if moveType == "Tween" or moveType == nil then + if self._data._currentTween then + self._data._currentTween:Cancel() + end + self._data._currentTween = TweenService:Create(self._data.Button, self._config.MoveInfo, { + Position = SliderFuncs.getNewPosition(self) + }) + self._data._currentTween:Play() + elseif moveType == "Instant" then + self._data.Button.Position = SliderFuncs.getNewPosition(self) + end + + if not supressEvent then + self.Changed:Fire(self._data._value) + end +end + +function Slider:OverrideIncrement(newIncrement: number) + self._config.SliderData.Increment = newIncrement + self._data._increment = newIncrement + self._data._scaleIncrement = SliderFuncs.getScaleIncrement(self) + self._data._percent = math.clamp(self._data._percent, 0, 1) + self._data._percent = SliderFuncs.snapToScale(self._data._percent, self._data._scaleIncrement) + self:Move() +end + +function Slider:GetValue() + return self._data._value +end + +function Slider:GetIncrement() + return self._data._increment +end + +function Slider:Destroy() + for _, connection in ipairs(self._data._clickConnections) do + connection:Disconnect() + end + for _, connection in ipairs(self._data._otherConnections) do + connection:Disconnect() + end + + if self._data._mainConnection then + self._data._mainConnection:Disconnect() + end + + if self._data.HolderButton then + self._data.HolderButton:Destroy() + self._data.HolderButton = nil + end + + self.Changed:Destroy() + self.Dragged:Destroy() + self.Released:Destroy() + + for index = 1, #Slider.Sliders do + if Slider.Sliders[index] == self then + table.remove(Slider.Sliders, index) + end + end + + setmetatable(self, nil) + self = nil +end + +UserInputService.InputEnded:Connect(function(inputObject: InputObject, internallyProcessed: boolean) + if inputObject.UserInputType == Enum.UserInputType.MouseButton1 or inputObject.UserInputType == Enum.UserInputType.Touch then + for _, slider in ipairs(Slider.Sliders) do + if slider.IsHeld then + slider.Released:Fire(slider._data._value) + end + slider.IsHeld = false + end + end +end) + +return Slider +----------------------------------------------------------------------------------------- diff --git a/MainModule/Client/UI/Default/Music/Visualizer.luau b/MainModule/Client/UI/Default/Music/Visualizer.luau new file mode 100644 index 0000000000..6772f56c24 --- /dev/null +++ b/MainModule/Client/UI/Default/Music/Visualizer.luau @@ -0,0 +1,198 @@ +local RunService = game:GetService("RunService") + +local module = {} + +local function AlphaColorSequence(Sequence, Alpha) + local Keypoints = Sequence.Keypoints + local StartKeypoint, EndKeypoint = 1, #Keypoints + + for i, Keypoint in ipairs(Keypoints) do + if Keypoint.Time >= Alpha then + EndKeypoint = Keypoint + StartKeypoint = Keypoints[math.max(1, i-1)] + break + end + end + + local StartTime, EndTime = StartKeypoint.Time, EndKeypoint.Time + local StartValue, EndValue = StartKeypoint.Value, EndKeypoint.Value + + local KeyframeAlpha = (Alpha - StartTime) / (EndTime - StartTime) + + return StartValue:Lerp(EndValue, KeyframeAlpha) +end + +function module.new(Frame, BarCount) + + -- Determine settings + local BAR_COUNT = math.clamp(type(BarCount) == "number" and BarCount or 41, 11,601) + local SAMPLE_HZ = math.clamp(BAR_COUNT/2,10,500) + + if BAR_COUNT%2==0 then + BAR_COUNT += 1 + end + + local BAR_SIZE = 1/BAR_COUNT + local BUFFER_COUNT = math.ceil(BAR_COUNT/2) + local BAR_TO_BUFFER = table.create(BAR_COUNT) + local BAR_TO_MULTIPLIER = table.create(BAR_COUNT) + + for i=1, BAR_COUNT do + BAR_TO_BUFFER[i] = math.abs(BUFFER_COUNT- (i+ (i<=BUFFER_COUNT and -1 or 1) )) + BAR_TO_MULTIPLIER[i] = 1-(math.clamp(math.abs(BUFFER_COUNT- (i+ (i<=BUFFER_COUNT and -1 or 1) ))/BUFFER_COUNT, 0.01,1)^2) + end + + local UPDATE_WAIT = 1/SAMPLE_HZ + + -- Setup visualizer + + local Visualizer = { + Frame = Frame; + VolumeBuffer = table.create(BUFFER_COUNT+1); + Bars = {}; + BufferConnection = nil; + PlayingConnection = nil; + Sound = nil; + } + + -- Create the bar guis + for i=1, BAR_COUNT do + + local Bar = Frame:Add("Frame", { + BorderSizePixel = 0; + BackgroundColor3 = Color3.new(0.98,0.98,0.99); + AnchorPoint = Vector2.new(0,0.5); + Size = UDim2.new(BAR_SIZE,0,0.02,0); + Position = UDim2.new(BAR_SIZE* (i-1), 0,0.5,0); + }) + + Visualizer.Bars[i] = Bar + end + + local function HandlePlaying() + if Visualizer.BufferConnection then + Visualizer.BufferConnection:Disconnect() + Visualizer.BufferConnection = nil + end + + local Sound = Visualizer.Sound + if not Sound then return end + + if Sound.Playing then + local LastStored = os.clock() + Visualizer.BufferConnection = RunService.Heartbeat:Connect(function() + local success, void = pcall(function() + Visualizer.VolumeBuffer[1] = Sound.PlaybackLoudness + Visualizer.Bars[BUFFER_COUNT]:TweenSize( + UDim2.new( + BAR_SIZE,0, + math.clamp((Sound.PlaybackLoudness/400), 0.02,1),0 + ), + Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.014, true + ) + + if os.clock()-LastStored > UPDATE_WAIT then + LastStored = os.clock() + + table.insert(Visualizer.VolumeBuffer,1,Sound.PlaybackLoudness) + local Length = #Visualizer.VolumeBuffer + if Length > BUFFER_COUNT then + Visualizer.VolumeBuffer[#Visualizer.VolumeBuffer] = nil + end + + local Color = Visualizer.Color + local ColorType = typeof(Color) + + for i,Bar in ipairs(Visualizer.Bars) do + + local Alpha = math.clamp( + ((Visualizer.VolumeBuffer[BAR_TO_BUFFER[i]] or 0)/400), + 0.02, 1 + ) + + Bar:TweenSize( + UDim2.new( + BAR_SIZE,0, + Alpha,0 + ), + Enum.EasingDirection.Out, Enum.EasingStyle.Linear, UPDATE_WAIT, true + ) + + if Color then + if ColorType == "Color3" then + Bar.BackgroundColor3 = Color + elseif ColorType == "ColorSequence" then + Bar.BackgroundColor3 = AlphaColorSequence(Color, Alpha) + end + end + + end + end + end) + if not success then Visualizer:UnlinkFromSound() end + end) + else + table.clear(Visualizer.VolumeBuffer) + for i,Bar in ipairs(Visualizer.Bars) do + Bar:TweenSize( + UDim2.new(BAR_SIZE,0,0.02,0), + Enum.EasingDirection.Out, Enum.EasingStyle.Linear, UPDATE_WAIT, true + ) + end + end + end + + function Visualizer:LinkToSound(Sound) + + Visualizer:UnlinkFromSound() + + table.clear(Visualizer.VolumeBuffer) + + Visualizer.Sound = Sound + + HandlePlaying() + Visualizer.PlayingConnection = Sound:GetPropertyChangedSignal("Playing"):Connect(HandlePlaying) + end + + function Visualizer:UnlinkFromSound() + + if Visualizer.PlayingConnection then + Visualizer.PlayingConnection:Disconnect() + Visualizer.PlayingConnection = nil + end + if Visualizer.BufferConnection then + Visualizer.BufferConnection:Disconnect() + Visualizer.BufferConnection = nil + end + + Visualizer.Sound = nil + + for i,Bar in ipairs(Visualizer.Bars) do + Bar:TweenSize( + UDim2.new(BAR_SIZE,0,0.02,0), + Enum.EasingDirection.Out, Enum.EasingStyle.Linear, UPDATE_WAIT, true + ) + end + + end + + function Visualizer:Destroy() + if Visualizer.PlayingConnection then + Visualizer.PlayingConnection:Disconnect() + Visualizer.PlayingConnection = nil + end + if Visualizer.BufferConnection then + Visualizer.BufferConnection:Disconnect() + Visualizer.BufferConnection = nil + end + for i,Bar in ipairs(Visualizer.Bars) do + Bar:Destroy() + end + table.clear(Visualizer.VolumeBuffer) + end + + + return Visualizer +end + +return module diff --git a/MainModule/Client/UI/Default/Music/init.luau b/MainModule/Client/UI/Default/Music/init.luau new file mode 100644 index 0000000000..8ed9af3ec1 --- /dev/null +++ b/MainModule/Client/UI/Default/Music/init.luau @@ -0,0 +1,907 @@ +client, service = nil, nil + +return function(data, env) + if env then + setfenv(1, env) + end + + + -- Saving those microseconds from using the dot operator + local Variables = client.Variables + local Functions = client.Functions + + -- Some pre-defined "global" variables + local gTable + local sImg + local gImg + local visualiser = nil + local isMuted = false + local isGlobal = false + local shuffle = false + local loop = false + local activeSongList = nil + local availableSongLists = {} + local activeSoundIdCache = {} + local selected = nil + local persistVolume = 0.25 + local audioLib = nil + local controlPositionSlider = nil + local controlVolumeSlider = nil + local lastSoundIdEvent = nil + local posTrackSound = nil + local progressupdatewait = 0.05 + local canUseGlobal = data.GlobalPerms + + -- The audio visulaiser at the top of the menu. + local visualiserModule = require(script:FindFirstChild("Visualizer")) + local sliderModule = require(script:FindFirstChild("Slider")) + local audioLibModule = Functions.AudioLib or require(client.Shared:FindFirstChild("AudioLib")) + Functions.AudioLib = audioLibModule + local localAudioLib = audioLibModule.new(service.UnWrap(service.LocalContainer())) + + local INDEX_LOCALISE = { + "IsLoaded", + "IsPaused", + "IsPlaying", + "PlaybackLoudness", + "TimeLength", + "TimePosition", + "DidLoop", + "Ended", + "Loaded", + "Paused", + "Played", + "Playing" + } + -- ========= UGLY HACK to bypass metatable yield restrictions because Roblox is big dumb ========= + -- TODO: Make an RFC on the Luau repo to add yieldable metamethods and xpcall (like Lua 5.2+ has!) + local defaultValues = localAudioLib._defaultProperties + local propertyCache = { + Looped = defaultValues.Looped, + PlaybackSpeed = defaultValues.PlaybackSpeed, + Volume = defaultValues.Volume, + Shuffle = false, + Autoplay = false + } + local fakePlaylist = {Position = 0} + local getRequestMade = service.GoodSignal.new() + + if canUseGlobal then + task.spawn(client.Remote.Get, "AudioLib", {"call", "GetSound"}) -- Create default container + end + + local function compatibilityGet(_, args) + if args[1] == "index" then + if propertyCache[args[2]] ~= nil then + return propertyCache[args[2]] + elseif args[2] == "Playlist" then + return fakePlaylist + else + error(`The index {args[2]} is not supported with compatibility get!`, 2) + end + elseif args[1] == "newindex" then + propertyCache[args[2]] = args[3] + getRequestMade:Fire("AudioLib", args) + elseif args[1] == "call" then + table.move(args, 4, math.max(4, args.n or #args), 3) -- Get rid of self arg + + if args[2] == "GetContainer" then + return service.UnWrap(service.SoundService:FindFirstChild("ADONIS_AUDIOLIB")) + elseif args[2] == "GetSound" then + return service.UnWrap( + assert( + assert( + service.SoundService:FindFirstChild("ADONIS_AUDIOLIB"), + "No server AudioLib folder found!" + ):FindFirstChild(localAudioLib._defaultSoundName), + "No server AudioLib sound object found!" + ) + ) + elseif args[2] == "GetTrack" then + assert(args[3] <= #fakePlaylist, "Track position outside of playlist size") + return fakePlaylist[args[3]] + elseif args[2] == "SetTrack" then + assert(args[3] <= #fakePlaylist, "Track position outside of playlist size") + fakePlaylist.Position = args[3] + elseif args[2] == "AddTrack" then + assert(not args[4] or args[4] <= #fakePlaylist, "Track position outside of playlist size") + + if args[3] then + table.insert(fakePlaylist, args[4], args[3]) + + if args[3] <= fakePlaylist.Position then + fakePlaylist.Position += 1 + end + else + table.insert(fakePlaylist, args[3]) + end + elseif args[2] == "RemoveTrack" then + assert(not args[3] or args[3] <= #fakePlaylist, "Track position outside of playlist size") + args[3] = args[3] or #fakePlaylist + + table.remove(fakePlaylist, args[3]) + + if args[3] <= fakePlaylist.Position then + fakePlaylist.Position -= 1 + end + elseif args[2] == "SetPlaylist" then + table.clear(fakePlaylist) + fakePlaylist.Position = 0 + table.move(args[3], 1, #args[3], 1, fakePlaylist) + end + + getRequestMade:Fire("AudioLib", args) + end + end + + getRequestMade:Connect(client.Remote.Get) + -- =============================================================================================== + local globalAudioLib = setmetatable({}, { + __index = function(_, k) + if type(rawget(audioLibModule, k)) == "function" then + return function(...) + return --[[client.Remote.Get]]compatibilityGet("AudioLib", table.pack("call", k, ...)) + end + elseif table.find(INDEX_LOCALISE, k) then + return service.UnWrap( + assert( + assert( + service.SoundService:FindFirstChild("ADONIS_AUDIOLIB"), + "No server AudioLib folder found!" + ):FindFirstChild(localAudioLib._defaultSoundName), + "No server AudioLib sound object found!" + ) + )[k] + else + return --[[client.Remote.Get]]compatibilityGet("AudioLib", {"index", k}) + end + end, + __newindex = function(_, k, v) + --[[client.Remote.Get]]compatibilityGet("AudioLib", {"newindex", k, v}) + end, + __tostring = function() + return "AudioLib" + end + }) + audioLib = localAudioLib + + -- Function to run when we close the window + local function doOnClose() + audioLib:Stop() + if visualiser then + --pcall(visualiser.UnlinkFromSound, visualiser) + visualiser:Destroy() + visualiser = nil + end + if controlPositionSlider then + controlPositionSlider:Destroy() + end + if controlVolumeSlider then + controlVolumeSlider:Destroy() + end + if visualiserModule then + visualiserModule = nil + end + if sliderModule then + sliderModule = nil + end + if getRequestMade then + getRequestMade:Destroy() + end + end + + -- The when the who the when the window + local window = client.UI.Make("Window", { + Name = "Audio Player"; + Title = "Audio Player"; + Size = {420, 400}; + MinSize = {420, 245}; + icon = "http://www.roblox.com/asset/?id=7032721624"; + Position = UDim2.new(0, 10, 1, -410); + OnClose = function() + doOnClose() + end + }) + + -- The controls frame at the bottom of the window + local controls = window:Add("Frame", { + Size = UDim2.new(1, 0, 0, 75); + Position = UDim2.new(0, 0, 1, -75); + BackgroundColor3 = Color3.new(0.235294, 0.235294, 0.235294); + BackgroundTransparency = 0; + }) + + -- Make the window ready before completing any code - Used to allow for delays in loading caused by MarketplaceService. + gTable = window.gTable + gTable:Ready() + + -- Song title and Audio Visaliser Frame. + local heading = window:Add("TextLabel", { + Text = "Music Player"; + Size = UDim2.new(1,0,0,20); + BackgroundTransparency = 1; + TextScaled = true; + ToolTip = "Music Player"; + }) + + local visualiserFrame = window:Add("Frame", { + Size = UDim2.new(1,0,0,50); + Position = UDim2.new(0, 0, 0, 30); + BackgroundTransparency = 1; + TextScaled = true; + }) + + -- Create audio visualiser + local visualiser = visualiserModule.new(visualiserFrame, 400) + visualiser:LinkToSound(audioLib:GetSound()) + + -- Play input audio + if data.Song then + audioLib.AutoPlay = false + audioLib:SetPlaylist({}) + audioLib:Play(tonumber(data.Song) and `rbxassetid://{data.Song}` or data.Song) + end + + -- Mute button + local muteButton = window:AddTitleButton({ + Text = ""; + OnClick = function() + if isMuted then + audioLib.Volume = persistVolume + sImg.Image = "rbxassetid://1638551696" + isMuted = false + else + persistVolume = audioLib.Volume + audioLib.Volume = 0 + sImg.Image = "rbxassetid://1638584675"; + isMuted = true + end + end + }) + + local function registerSoundIdEvent() + local rawSound = audioLib:GetSound() + posTrackSound = rawSound + + if lastSoundIdEvent then + local button = selected and selected.Button + if button then + button.Text = string.gsub(button.Text, "^🔊\u{202F}", "") + end + + lastSoundIdEvent:Disconnect() + end + + lastSoundIdEvent = rawSound:GetPropertyChangedSignal("SoundId"):Connect(function() + local soundId = rawSound.SoundId + local newSelected = activeSoundIdCache[soundId] + local numericId = tonumber(string.match(soundId, "(%d+)")) + local oldButton = selected and selected.Button + local newButton = newSelected and newSelected.Button + + if oldButton then + oldButton.Text = string.gsub(oldButton.Text, "^🔊\u{202F}", "") + end + + if service.Trim(soundId) == "" then + selected, heading.Text = nil, "Music Player - None" + return + elseif selected and selected.ID ~= numericId or not selected then + heading.Text = `{newSelected and newSelected.Name.." - " or ""}Loading...` + end + + if newButton then -- Add "Narrow NonBreaking space" to prevent conflicts with speaker emojis in name + newButton.Text = "🔊\u{202F}" .. string.gsub(newButton.Text, "^🔊\u{202F}", "") + end + + local productInfo = numericId and service.GetProductInfo(numericId, Enum.InfoType.Asset) + local text = productInfo and productInfo.Name or numericId and `[ERROR] {soundId}` or heading.Text + heading.Text = text + selected = newSelected or { + ID = numericId or 0, + Name = text + } + + if not audioLib.IsLoaded then + heading.Text = `({string.sub(text, 1, 10)}...) Loading...` + + audioLib.Loaded:Once(function() + if rawSound.SoundId == soundId then + heading.Text = text + end + end) + end + end) + end + + local globalButton = nil + + if canUseGlobal then + globalButton = window:AddTitleButton({ + Text = ""; + OnClick = function() + audioLib:Stop() + isGlobal = not isGlobal + gImg.Image = isGlobal and "rbxassetid://8318257291" or "rbxassetid://8318256297" + task.spawn(client.UI.Make, "Notification",{ + Title = "Global Audio"; + Icon = "rbxassetid://7541916144"; + Message = isGlobal and "Everyone can hear your music" or "Only you can hear your music"; + Time = 3; + }) + audioLib = isGlobal and globalAudioLib or localAudioLib + audioLib:Stop() + visualiser:LinkToSound(audioLib:GetSound()) + registerSoundIdEvent() + end + }) + gImg = globalButton:Add("ImageLabel", { + Size = UDim2.new(1, 0, 1 ,0); + Position = UDim2.new(0, 0, 0, 0); + Image = "rbxassetid://8318256297"; + BackgroundTransparency = 1; + }) + end + + sImg = muteButton:Add("ImageLabel", { + Size = UDim2.new(1, 0, 1 ,0); + Position = UDim2.new(0, 0, 0, 0); + Image = "rbxassetid://1638551696"; + BackgroundTransparency = 1; + }) + + local function getRawPlaylist(playlist) + local rawPlaylist = table.create(#playlist) + + for i, v in ipairs(playlist) do + rawPlaylist[i] = `rbxassetid://{v.ID}` + end + + return rawPlaylist + end + + local function fillSoundIdCache(playlist) + for _, v in playlist do + activeSoundIdCache[`rbxassetid://{v.ID}`] = v + end + end + + -- Function that makes the song list. + local function getSongs(tab, list) + local num = 0 + selected = nil + availableSongLists[tab.Name] = {} + tab:ClearAllChildren() + + local frame = tab:Add("ScrollingFrame", { + Size = UDim2.new(1, 0, 1, 1); + Position = UDim2.new(0, 0, 0, 0); + BackgroundColor3 = Color3.new(0.235294, 0.235294, 0.235294); + BackgroundTransparency = 1; + }) + + local loading = frame:Add("TextLabel", { + Text = "Loading nothing yet!"; + ToolTip = "Never gonna give you up, Never gonna let you down..."; + BackgroundTransparency = 0; + Size = UDim2.new(1,0,1,0); + Position = UDim2.new(0,0,0,0); + ZIndex = 69420 + --TextXAlignment = "Left"; + }) + + local function loop(i, v) + if type(v) == "table" then + local productInfo = service.GetProductInfo(v.ID, Enum.InfoType.Asset) + loading.Text = `Loading tracks ({i}/{#list})`; + + if productInfo.AssetTypeId == 3 then + local trackPos = num + 1 + table.insert(availableSongLists[tab.Name], v) + + v.Button = frame:Add("TextButton", { + Text = ` {num + 1}) {productInfo.Name or `[ERROR] {v.Name}`}`; + ToolTip = `Name: {v.Name} | ID: {v.ID}`; + Size = UDim2.new(1, 0, 0, 25); + Position = UDim2.new(0, 0, 0, num*25); + BackgroundTransparency = (num%2 == 0 and 0) or 0.2; + TextXAlignment = "Left"; + OnClicked = function(button) + if activeSoundIdCache.listName ~= tab.Name then + table.clear(activeSoundIdCache) + activeSoundIdCache.listName = tab.Name + fillSoundIdCache(availableSongLists[tab.Name]) + end + + heading.Text = productInfo.Name or v.Name + audioLib.AutoPlay = true + audioLib:SetPlaylist(getRawPlaylist(availableSongLists[tab.Name])) + audioLib:SetTrack(trackPos) + audioLib:Play() + end + }) + num = trackPos + frame:ResizeCanvas(false, true) + end + end + end + + for i, v in ipairs(list or {}) do + task.spawn(xpcall, loop, warn, i, v) + end + + loading:Destroy() + end + + -- Tabs for different playlists + local tabFrame = window:Add("TabFrame",{ + Size = UDim2.new(1, 0, 1, -165); + Position = UDim2.new(0, 0, 0, 90); + }) + + local personalTab = tabFrame:NewTab("Personal",{ + Text = "Personal"; + OnFocus = function() + activeSongList = availableSongLists["Personal"] or {} + end; + }) + local gameTab = tabFrame:NewTab("Game",{ + Text = "Game"; + OnFocus = function() + activeSongList = availableSongLists["Game"] or {} + end; + }) + local adonisTab = tabFrame:NewTab("Adonis", { + Text = "Adonis"; + OnFocus = function() + activeSongList = availableSongLists["Adonis"] or {} + end; + }) + local customTab = tabFrame:NewTab("Custom", { + Text = "Custom"; + OnFocus = function() + activeSongList = availableSongLists["Custom"] or {} + end; + }) + + -- The Custom Playlists editor window + local binderBox, playlistBox; binderBox = tabFrame:Add("Frame", { + Visible = false; + Size = UDim2.new(1,0,1,0); + Position = UDim2.new(0,0,0,0); + BackgroundTransparency = 0; + ZIndex = 10000; + Children = { + { + Class = "TextLabel"; + Text = "New Custom Playlist string:"; + Position = UDim2.new(0, 5, 0, 5); + Size = UDim2.new(1, -10, 0, 30); + BackgroundTransparency = 0; + ZIndex = 10001; + }; + { + Class = "TextButton"; + Text = "Add"; + Position = UDim2.new(0.5, 5, 1, -35); + Size = UDim2.new(0.5, -10, 0, 30); + BackgroundTransparency = 0; + ZIndex = 10002; + OnClicked = function() + client.Variables.Playlist = {Playlist = {}} + table.clear(client.Variables.Playlist.Playlist) + for name, id in string.gmatch(string.gsub(playlistBox.Text, "%s", ""), "([^:,]+):(%d+),?") do + table.insert(client.Variables.Playlist.Playlist, { + Name = name or "UNKNOWN", + ID = tonumber(id) or 0 + }) + end + binderBox.Visible = false + getSongs(customTab, client.Variables.Playlist.Playlist or {}) + activeSongList = availableSongLists["Custom"] or {} + end + }; + { + Class = "TextButton"; + Text = "Cancel"; + Position = UDim2.new(0, 5, 1, -35); + Size = UDim2.new(0.5, -5, 0, 30); + BackgroundTransparency = 0; + ZIndex = 10003; + OnClicked = function() + binderBox.Visible = false + end + }; + } + }) + + playlistBox = binderBox:Add("TextBox", { + Position = UDim2.new(0, 5, 0, 40); + Size = UDim2.new(1, -10, 1, -80); + TextWrapped = true; + --TextXAlignment = "Left"; + --TextYAlignment = "Top"; + ClearTextOnFocus = false; + PlaceholderText = "NAME:ID, SECOND:12398801, HeavyIsDead:4881542521"; + ZIndex = 10004; + }) + + playlistBox.BackgroundColor3 = playlistBox.BackgroundColor3:lerp(Color3.new(1, 1, 1), 0.1) + binderBox.BackgroundColor3 = binderBox.BackgroundColor3:lerp(Color3.new(1, 1, 1), 0.05) + + --[[ + + ======================================================== + | | + | Top control buttons (Save and load custom playlist) | + | | + ======================================================== + + ]]-- + + -- Create playlist button + local playlistLoad = controls:Add("TextButton", { + Text = "⏫"; + TextSize = 15; + ToolTip = "Create playlist: Create a new custom playlist from a string."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 30, 0, 30); + Position = UDim2.new(0, 5, 0, 5); + TextXAlignment = "Center"; + OnClicked = function() + playlistBox.Text = "" + binderBox.Visible = true + customTab:FocusTab(); + activeSongList = availableSongLists["Custom"] or {} + end + }) + + -- Save cutom playlist + local playlistSave = controls:Add("TextButton", { + Text = "⬆️"; + TextSize = 15; + ToolTip = "Upload playlist: Saves your custom playlist to the games datastore."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 30, 0, 30); + Position = UDim2.new(0, 40, 0, 5); + TextXAlignment = "Center"; + OnClicked = function() + personalTab:FocusTab(); + local Playlist = type(client.Variables.Playlist) == "table" and client.Variables.Playlist.Playlist + if Playlist and next(Playlist) then + client.Functions.UpdatePlaylist(client.Variables.Playlist) + getSongs(personalTab, client.Functions.Playlist().Playlist or {}) + else + warn("[ERROR] Cannot update empty Playlist") + end + + activeSongList = availableSongLists["Personal"] or {} + end + }) + + -- Stop button + local controlStop = controls:Add("TextButton", { + Text = "⏹"; + TextSize = 15; + ToolTip = "Stop: Pauses the track and sets the position to 0."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 30, 0, 30); + Position = UDim2.new(0, 75, 0, 5); + TextXAlignment = "Center"; + OnClick = function() + audioLib:Stop() + end + }) + + -- Back button + local controlBack = controls:Add("TextButton", { + Text = "◀️"; + TextSize = 15; + ToolTip = "Back: Go back to the last played track."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 30, 0, 30); + Position = UDim2.new(0, 110, 0, 5); + TextXAlignment = "Center"; + OnClick = function() + local playlist = audioLib.Playlist + audioLib:SetTrack((playlist.Position - 2) % #playlist + 1) + audioLib:Play() + end + }) + + -- Pause/Play button + local controlPausePlay = controls:Add("TextButton", { + Text = "⏯️"; + TextSize = 15; + ToolTip = "Pause/Play: Control the tracks playing state."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 30, 0, 30); + Position = UDim2.new(0, 145, 0, 5); + TextXAlignment = "Center"; + OnClick = function() + if audioLib.Playing then + audioLib:Pause() + else + audioLib:Resume() + end + end + }) + + -- Forward button + local controlForward = controls:Add("TextButton", { + Text = "▶️"; + TextSize = 15; + ToolTip = "Forward: Skip to the next track."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 30, 0, 30); + Position = UDim2.new(0, 180, 0, 5); + TextXAlignment = "Center"; + OnClick = function() + audioLib:PlayNext() + end + }) + + -- Shuffle button + local controlShuffle = nil + local controlShuffleBackgroundColor3 = nil + local function changeShuffleColor() + if shuffle then + controlShuffle.BackgroundColor3 = Color3.new(0, 1, 0.6) + else + controlShuffle.BackgroundColor3 = controlShuffleBackgroundColor3 + end + end + controlShuffle = controls:Add("TextButton", { + Text = "🔀"; + TextSize = 15; + ToolTip = "Shuffle: Randomly pick between."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 30, 0, 30); + Position = UDim2.new(0, 215, 0, 5); + TextXAlignment = "Center"; + OnClick = function() + shuffle = not shuffle + audioLib.Shuffle = shuffle + changeShuffleColor() + end + }) + + controlShuffleBackgroundColor3 = controlShuffle.BackgroundColor3 + + -- Loop button + local controlLoop = nil + local controlLoopBackgroundColor3 = nil + local function changeLoopColor() + if loop then + controlLoop.BackgroundColor3 = Color3.new(0, 1, 0.6) + else + controlLoop.BackgroundColor3 = controlLoopBackgroundColor3 + end + end + controlLoop = controls:Add("TextButton", { + Text = "🔁"; + TextSize = 15; + ToolTip = "Loop: Loops the song continuously."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 30, 0, 30); + Position = UDim2.new(0, 250, 0, 5); + TextXAlignment = "Center"; + OnClick = function() + loop = not loop + changeLoopColor() + audioLib.Looped = loop + end + }) + controlLoopBackgroundColor3 = controlLoop.BackgroundColor3 + + -- Bottom control buttons + + -- Custom Sound ID + local controlID = controls:Add("TextLabel", { + Text = " ID: "; + ToolTip = "ID: The Sound ID from the roblox catalogue."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 120, 0, 30); + Position = UDim2.new(1, -125, 0, 5); + TextXAlignment = "Left"; + Children = { + TextBox = { + Text = ""; + PlaceholderText = "4881542521"; + Size = UDim2.new(0, 80, 1, 0); + Position = UDim2.new(1, -90, 0, 0); + BackgroundTransparency = 1; + TextXAlignment = "Right"; + TextChanged = function(text, enter, new) + text = service.Trim(text) + + if enter then + audioLib.AutoPlay = false + audioLib:SetPlaylist({}) + audioLib:Play(tonumber(text) and `rbxassetid://{text}` or text) + end + end + } + } + }) + + -- Position + --local controlPosition = controls:Add("TextLabel", { + -- Text = " Pos: "; + -- ToolTip = "Position: Set the audio's position (In seconds)."; + -- BackgroundTransparency = 0; + -- Size = UDim2.new(0, 60, 0, 30); + -- Position = UDim2.new(1, -205, 1, -35); + -- TextXAlignment = "Left"; + -- Children = { + -- TextBox = { + -- Text = ""; + -- PlaceholderText = "0"; + -- Size = UDim2.new(0, 40, 1, 0); + -- Position = UDim2.new(1, -50, 0, 0); + -- BackgroundTransparency = 1; + -- TextXAlignment = "Right"; + -- TextChanged = function(text, enter, new) + -- if enter then + -- audioLib("UpdateSound", { + -- TimePosition = text + -- }) + -- end + -- end + -- } + -- } + --}) + + --[[ + + ======================================================== + | | + | Bottom control buttons (Position and volume slider) | + | | + ======================================================== + + ]]-- + + -- Volume + local controlVolume = controls:Add("TextLabel", { + Text = " "; + ToolTip = "Volume: How loud the audio will play (0 to 10)."; + BackgroundTransparency = 0; + Size = UDim2.new(0, 120, 0, 30); + Position = UDim2.new(1, -125, 1, -35); + TextXAlignment = "Left"; + }) + + controlVolume:Add("ImageLabel", { + Image = "rbxassetid://7541896266"; + Size = UDim2.new(0, 20, 0, 20); + Position = UDim2.new(0, 5, 0, 5); + BackgroundTransparency = 1; + }) + + local controlVolumeSliderContainer = controlVolume:Add("Frame", { + Image = "rbxassetid://7541896266"; + Size = UDim2.new(1, -45, 0, 2); + Position = UDim2.new(0, 30, 0, 14); + BackgroundColor3 = Color3.new(0.454902, 0.454902, 0.454902); + BackgroundTransparency = 0; + }) + + local controlVolumeSliderInstance = controlVolumeSliderContainer:Add("ImageButton", { + Name = "Slider"; + AnchorPoint = Vector2.new(0.5, 0.5); + Size = UDim2.new(0, 10, 0, 10); + Position = UDim2.new(0, 0, 0, -4); + BackgroundColor3 = Color3.new(1,1,1); + BackgroundTransparency = 0; + TextXAlignment = "Right"; + Children = { + UICorner = { + CornerRadius = UDim.new(1, 0); + } + } + }) + + controlVolumeSlider = sliderModule.new(service.UnWrap(controlVolumeSliderContainer), { + SliderData = {Start = 0, End = 1000, Increment = 1, DefaultValue = 0.5}, + MoveInfo = TweenInfo.new(0.1, Enum.EasingStyle.Quad), + Axis = "X", + Padding = 0 + }) + controlVolumeSlider:Track() + + do + local lastSliderChange = -math.huge + controlVolumeSlider.Changed:Connect(function(value) + if not isGlobal or os.clock() > lastSliderChange + 0.5 then -- Prevent spamming of remotes with global AudioLib + lastSliderChange = os.clock() + audioLib.Volume = value / 100 + end + end) + end + + -- Track position + local controlPosition = controls:Add("TextLabel", { + Text = " "; + ToolTip = "Position: Control where the song is playing from."; + BackgroundTransparency = 0; + Size = UDim2.new(1, -135, 0, 30); + Position = UDim2.new(0, 5, 1, -35); + TextXAlignment = "Left"; + }) + + local controlPositionSliderContainer = controlPosition:Add("Frame", { + Image = "rbxassetid://7541896266"; + Size = UDim2.new(1, -30, 0, 2); + Position = UDim2.new(0, 14, 0, 14); + BackgroundColor3 = Color3.new(0.454902, 0.454902, 0.454902); + BackgroundTransparency = 0; + }) + + local controlPositionSliderInstance = controlPositionSliderContainer:Add("ImageButton", { + Name = "Slider"; + AnchorPoint = Vector2.new(0.5, 0.5); + Size = UDim2.new(0, 10, 0, 10); + Position = UDim2.new(0, 0, 0, -4); + BackgroundColor3 = Color3.new(1,1,1); + BackgroundTransparency = 0; + TextXAlignment = "Right"; + Children = { + UICorner = { + CornerRadius = UDim.new(1, 0); + } + } + }) + + controlPositionSlider = sliderModule.new(service.UnWrap(controlPositionSliderContainer), { + SliderData = {Start = 0, End = 10000, Increment = 1, DefaultValue = 0.5}, + MoveInfo = TweenInfo.new(0.1, Enum.EasingStyle.Quad), + Axis = "X", + Padding = 0 + }) + controlPositionSlider:Track() + + do + local lastSliderChange = -math.huge + controlPositionSlider.Changed:Connect(function(value) + if not isGlobal or os.clock() > lastSliderChange + 0.5 then -- Prevent spamming of remotes with global AudioLib + local length = audioLib.TimeLength + lastSliderChange = os.clock() + audioLib.TimePosition = value / 10000 * length + end + end) + end + + -- Used to play a sound on window open. 4881542521. + + -- Load in track lists + local loadingMessage = function(tab) + tab:Add("TextLabel", { + Text = "Waiting in queue to load tracks..."; + ToolTip = "Never gonna give you up, Never gonna let you down..."; + BackgroundTransparency = 0; + Size = UDim2.new(1,0,1,0); + Position = UDim2.new(0,0,0,0); + ZIndex = 69420 + --TextXAlignment = "Left"; + }) + end + + loadingMessage(personalTab) + loadingMessage(gameTab) + loadingMessage(adonisTab) + registerSoundIdEvent() + getSongs(personalTab, client.Functions.Playlist().Playlist or {}) + local musicList = client.Remote.Get("Variable", "MusicList") or {} + getSongs(gameTab, musicList) + getSongs(adonisTab, table.move(service.DeepCopy(musicList), 1, #musicList - #(client.Remote.Get("Setting", "MusicList") or {}), 1, {})) + activeSongList = availableSongLists["Personal"] or {} + + task.spawn(function() + while task.wait(progressupdatewait) do + if posTrackSound and posTrackSound.TimeLength ~= 0 and not controlPositionSlider.IsHeld then + controlPositionSlider:OverrideValue(posTrackSound.TimePosition / posTrackSound.TimeLength * 10000, true) + end + end + end) +end diff --git a/MainModule/Client/UI/Default/Notif.rbxmx b/MainModule/Client/UI/Default/Notif.rbxmx index 82513929c1..4f311856c3 100644 --- a/MainModule/Client/UI/Default/Notif.rbxmx +++ b/MainModule/Client/UI/Default/Notif.rbxmx @@ -53,8 +53,8 @@ return function(data, env) local gui = client.UI.Prepare(script.Parent.Parent) local label = gui.LABEL local str = data.Message - local topbar = client.UI.Get("TopBar") - local topshift + gui.IgnoreGuiInset = not client.Variables.TopBarShift + gui.ClipToDeviceSafeArea = true client.UI.Remove("Notif",script.Parent.Parent) @@ -70,16 +70,8 @@ return function(data, env) table.insert(client.Variables.CommunicationsHistory, log) service.Events.CommsPanel:Fire(log) - if client.Variables.TopBarShift == true then - topshift = true - else - topshift = false - end - - if str and type(str)=="string" then label.Text = str - label.Position = UDim2.new(0, 0, 0, ((topshift and 0) or -35)) gTable:Ready() else gui:Destroy() @@ -151,7 +143,7 @@ end]]> 0 0 0 - -35 + 0 false null diff --git a/MainModule/Client/UI/Default/Paint.luau b/MainModule/Client/UI/Default/Paint.luau index ddbea5599a..83f56cc676 100644 --- a/MainModule/Client/UI/Default/Paint.luau +++ b/MainModule/Client/UI/Default/Paint.luau @@ -1,10 +1,12 @@ +local buffer = buffer -- // Adonis doesnt support buffers yet! client, service = nil, nil return function(data, env) if env then setfenv(1, env) end - + + local Variables = client.Variables local mouse = service.Players.LocalPlayer:GetMouse() local hold = false @@ -22,8 +24,8 @@ return function(data, env) local pixelCount = topbar:Add("TextLabel", { Size = UDim2.new(0, 100, 1, -8); - Position = UDim2.new(1, -180, 0, 4); - Text = "Pixels: 0"; + Position = UDim2.new(1, -180 - (Variables.CanUseEditableImages and 75 or 0), 0, 4); + Text = `Pixels: {Variables.CanUseEditableImages and "N/A" or "0"}`; TextXAlignment = "Right"; BackgroundTransparency = 1; }) @@ -34,10 +36,23 @@ return function(data, env) BackgroundColor3 = Color3.new(1, 1, 1); ClipsDescendants = true; }) - + + local rawCanvas = Variables.CanUseEditableImages and canvas:Add("ImageLabel", { + Position = UDim2.new(0, 0, 0, 0); + Size = UDim2. new(1, 0, 1, 0); + Active = false; + BackgroundTransparency = 1; + BorderSizePixel = 0; + Image = "rbxtemp://0"; -- // TODO: Replace when EditableImage:GetContent() becomes available (without FFlag) + }) + local editableImage = Variables.CanUseEditableImages and rawCanvas:Add("EditableImage", { + Size = rawCanvas.AbsoluteSize; + }) + local pointer = canvas:Add("Frame", { Position = UDim2.new(0, 0, 0, 0); Size = UDim2.new(0, 4, 0, 4); + AnchorPoint = Vector2.new(0.5, 0.5); BackgroundColor3 = Color3.new(0, 0, 0); BackgroundTransparency = 0; Visible = false; @@ -52,33 +67,79 @@ return function(data, env) end) canvas.MouseMoved:Connect(function(x, y) - local offset = Vector2.new(math.abs(x - canvas.AbsolutePosition.X), math.abs(y - canvas.AbsolutePosition.Y - 36)) + local offset = Vector2.new(math.abs(x - canvas.AbsolutePosition.X), math.abs(y - canvas.AbsolutePosition.Y)) - service.GuiService:GetGuiInset() pointer.Position = UDim2.new(0, offset.X, 0, offset.Y) if hold == false then return end - local pixel = pointer:Clone() - pixel.Name = "Pixel" - pixel.Parent = canvas - pixelCount.Text = `Pixels: {pixelCount.Text:sub(9) + 1}` + if Variables.CanUseEditableImages then + editableImage:DrawCircle(offset, math.ceil(pointer.Size.X.Offset / 2), pointer.BackgroundColor3, 0, Enum.ImageCombineType.Overwrite) + else + local pixel = pointer:Clone() + pixel.Name = "Pixel" + pixel.Parent = canvas + pixelCount.Text = `Pixels: {pixelCount.Text:sub(9) + 1}` + end end) - local clearButton = topbar:Add("TextButton", { + topbar:Add("TextButton", { Size = UDim2.new(0, 70, 1, -8); Position = UDim2.new(1, -75, 0, 4); Text = "Clear"; TextXAlignment = "Center"; OnClick = function() - local children = canvas:GetChildren() - for i, child in pairs (children) do + for i, child in canvas:GetChildren() do if child.Name == "Pixel" then child:Destroy() end end - pixelCount.Text = "Pixels: 0" + + if Variables.CanUseEditableImages then + local size = editableImage.Size + local newImage = buffer.create(size.X * size.Y * 4) + + buffer.fill(newImage, 0, 255) + editableImage:WritePixelsBuffer(Vector2.new(0, 0), size, buffer.create(size.X * size.Y * 4)) + end + + pixelCount.Text = `Pixels: {Variables.CanUseEditableImages and "N/A" or "0"}` end }) + if Variables.CanUseEditableImages then + local uploadDebounce = -math.huge + + topbar:Add("TextButton", { + Size = UDim2.new(0, 70, 1, -8); + Position = UDim2.new(1, -150, 0, 4); + Text = "Upload"; + ToolTip = "Upload your paint creation as decal on the creator store."; + TextXAlignment = "Center"; + OnClick = function() + if os.clock() > uploadDebounce + 2.5 then + uploadDebounce = os.clock() + local decal = service.New("Decal") + + decal.Name = "Adonis_PaintDecal" + decal.Texture = rawCanvas.Image + editableImage:Clone().Parent = decal + + -- // Prompt user to upload decal + local success, reason = pcall(service.AssetService.PromptCreateAssetAsync, service.AssetService, service.Players.LocalPlayer, decal, Enum.AssetType.Decal) + + if not success then + client.UI.Make("Notification", { + Title = "Uploading decal failed"; + Message = `Uploading decal failed due to: {reason}.`; + Icon = client.MatIcons["Error"]; + Time = 10; + }) + end + end + end + }) + end + topbar:Add("TextLabel", { Text = " Color: "; Size = UDim2.new(0, 90, 1, -8); diff --git a/MainModule/Client/UI/Default/PerfStats.luau b/MainModule/Client/UI/Default/PerfStats.luau index 7ae741d6c1..1a47e70547 100644 --- a/MainModule/Client/UI/Default/PerfStats.luau +++ b/MainModule/Client/UI/Default/PerfStats.luau @@ -8,8 +8,6 @@ return function(data, env) local gfps = true local gTable - --warn(math.floor(1/game:GetService("RunService").RenderStepped:Wait())) - local window = client.UI.Make("Window", { Name = "Performance stats", Title = "Stats", @@ -46,7 +44,7 @@ return function(data, env) workspace:GetRealPhysicsFPS(), service.Players.LocalPlayer:GetNetworkPing() * 1000 ) - task.wait(1) + task.wait(0.5) until not gfps or not gTable.Active end end diff --git a/MainModule/Client/UI/Default/Profile.luau b/MainModule/Client/UI/Default/Profile.luau index 7cb030f6d8..b1105632bf 100644 --- a/MainModule/Client/UI/Default/Profile.luau +++ b/MainModule/Client/UI/Default/Profile.luau @@ -1,3 +1,4 @@ +local DateTime = DateTime client, service, Routine = nil, nil, nil local function boolToStr(bool) @@ -177,22 +178,52 @@ return function(data, env) end) end + local LOCATION_TYPE = {"Mobile Website", "Mobile InGame", "Webpage", "Studio", "InGame", "Xbox", "Team Create"} + local ACTIVITY_COLOR_CODES = { + ["Mobile Website"] = Color3.fromRGB(50, 140, 231); + ["Mobile InGame"] = Color3.fromRGB(55, 200, 55); + ["Webpage"] = Color3.fromRGB(50, 140, 231); + ["Studio"] = Color3.fromRGB(231, 112, 0); + ["InGame"] = Color3.fromRGB(55, 200, 55); + ["Xbox"] = Color3.fromRGB(127, 0, 127); + ["Team Create"] = Color3.fromRGB(231, 112, 0); + } local friendPages = service.Players:GetFriendsAsync(player.UserId) + local onlineFriends = {} local sortedFriends = {} local friendInfoRef = {} local friendCount = 0 local onlineCount = 0 + for _, user in data.OnlineFriends do + onlineFriends[user.VisitorId] = { + lastOnline = DateTime.fromIsoDate(user.LastOnline), + isOnline = user.IsOnline, + lastLocation = user.LastLocation, + placeId = user.PlaceId, + jobId = user.GameId, + locationType = LOCATION_TYPE[user.LocationType and user.LocationType + 1] + } + end + Routine(function() for item, pageNo in iterPageItems(friendPages) do table.insert(sortedFriends, item.Username) + local userId = item.id + local activity = onlineFriends[userId] friendInfoRef[item.Username] = { - id = item.Id; + id = userId; displayName = item.DisplayName; - isOnline = item.IsOnline; + -- // Activity data + isOnline = activity and activity.isOnline; + lastOnline = activity and activity.lastOnline or DateTime.fromUnixTimestamp(0); + lastLocation = activity and activity.lastLocation; + placeId = activity and activity.placeId; + jobId = activity and activity.jobId; + locationType = activity and activity.locationType; } - if item.IsOnline then + if activity and activity.isOnline then onlineCount += 1 end friendCount += 1 @@ -242,15 +273,15 @@ return function(data, env) Position = UDim2.new(0, 0, 0, (30*(i-1))); TextXAlignment = "Left"; }) - if friendInfo.isOnline then - entry:Add("TextLabel", { - Text = "Online"; - BackgroundTransparency = 1; - Size = UDim2.new(0, 120, 1, 0); - Position = UDim2.new(1, -130, 0, 0); - TextXAlignment = "Right"; - }) - end + entry:Add("TextLabel", { -- TODO: Add support for joining + Text = friendInfo.locationType or "Offline"; + ToolTip = friendInfo.placeId and `Playing {friendInfo.placeId} - (friendInfo.lastLocation)` or `Last online {friendInfo.lastOnline:FormatLocalTime("LLLL", service.GetCurrentLocale())}`; + BackgroundTransparency = 1; + TextColor3 = ACTIVITY_COLOR_CODES[friendInfo.locationType] or Color3.fromRGB(127, 127, 127); + Size = UDim2.new(0, 120, 1, 0); + Position = UDim2.new(1, -130, 0, 0); + TextXAlignment = "Right"; + }) Routine(function() entry:Add("ImageLabel", { Image = service.Players:GetUserThumbnailAsync(friendInfo.id, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size48x48); diff --git a/MainModule/Client/UI/Default/ServerDetails.luau b/MainModule/Client/UI/Default/ServerDetails.luau index 84b2960d70..f3fdaa61c2 100644 --- a/MainModule/Client/UI/Default/ServerDetails.luau +++ b/MainModule/Client/UI/Default/ServerDetails.luau @@ -101,11 +101,11 @@ return function(data, env) local entries = { {"Game ID", game.GameId}, - {"Game Creator", `{service.MarketPlace:GetProductInfo(game.PlaceId).Creator.Name} (#{data.CreatorId})`}, + {"Game Creator", `{((service.GetProductInfo(game.PlaceId) or {Creator = {Name = "[Error]"}}).Creator or {Name = "[Error]"}).Name} (#{data.CreatorId})`}, -- selene: allow(incorrect_standard_library_use) {"Creator Type", game.CreatorType.Name}, {"Place ID", game.PlaceId}, - {"Place Name", service.MarketPlace:GetProductInfo(game.PlaceId).Name or "[Error]"}, + {"Place Name", (service.GetProductInfo(game.PlaceId) or {Name = "[Error"}).Name or "[Error]"}, {"Place Version", game.PlaceVersion}, "", {"Server Job ID", game.JobId or "[Error]"}, @@ -157,13 +157,12 @@ return function(data, env) while wait(0.5) do local timeNow = os.time() if not displays["Server Speed"] or not displays["Server Age"] then break end - displays["Server Speed"].Text = math.round(service.Workspace:GetRealPhysicsFPS()) + displays["Server Speed"].Text = math.round(data.ServerSpeed or 0) displays["Server Age"].Text = string.format("%ds (%d min)", string.format(timeNow - data.ServerStartTime, "%.1f"), math.round((timeNow - data.ServerStartTime)/60)) end end) - end - + local success, isAmerica = xpcall(function() return service.LocalizationService:GetCountryRegionForPlayerAsync(service.Players.LocalPlayer) == "US" end, function() return false end) @@ -374,6 +373,7 @@ return function(data, env) local workspaceInfo = data.Refreshables.WorkspaceInfo if workspaceInfo then local i, currentPos = 0, 0 + data.ServerSpeed = workspaceInfo.ServerSpeed or data.ServerSpeed for _, v in ipairs({ {"Streaming Enabled", boolToStr(service.Workspace.StreamingEnabled)}, {"Interpolation Throttling", service.Workspace.InterpolationThrottling.Name}, diff --git a/MainModule/Client/UI/Default/UserPanel.luau b/MainModule/Client/UI/Default/UserPanel.luau index b56aa20aee..7d50c7f385 100644 --- a/MainModule/Client/UI/Default/UserPanel.luau +++ b/MainModule/Client/UI/Default/UserPanel.luau @@ -25,15 +25,11 @@ local canEditTables = { local function tabToString(tab) if type(tab) == "table" then - local str = "" + local str = table.create(#tab) for i, v in tab do - if #str > 0 then - str ..= "; " - end - - str ..= `{i}: {v}` + table.insert(str, `{i}: {v}`) end - return str + return table.concat(str, "; ") else return tostring(tab) end @@ -1785,4 +1781,4 @@ return function(data, env) gTable = window.gTable window:Ready() end -end \ No newline at end of file +end diff --git a/MainModule/Client/UI/Steampunk/Console.rbxmx b/MainModule/Client/UI/Steampunk/Console.rbxmx index 7b93be4eec..132bf1370f 100644 --- a/MainModule/Client/UI/Steampunk/Console.rbxmx +++ b/MainModule/Client/UI/Steampunk/Console.rbxmx @@ -109,6 +109,7 @@ return function(data, env) local consoleCloseTween = service.TweenService:Create(frame, tweenInfo, { Position = UDim2.new(0, 0, 0, -200); }) + frame.TopBar.Size = UDim2.new(1, 0, 0, service.GuiService:GetGuiInset().Y) local function showGuis() if UI.Get("Notif") then @@ -614,7 +615,7 @@ end false 0 - 0 + 1 true @@ -638,7 +639,7 @@ end false true 0 - Frame + TopBar null null null @@ -647,7 +648,7 @@ end 0 0 0 - -40 + 0 null 0 diff --git a/MainModule/Client/UI/Steampunk/Notif.rbxmx b/MainModule/Client/UI/Steampunk/Notif.rbxmx index 50e1c504f5..55044a9ae5 100644 --- a/MainModule/Client/UI/Steampunk/Notif.rbxmx +++ b/MainModule/Client/UI/Steampunk/Notif.rbxmx @@ -59,7 +59,8 @@ return function(data, env) local gui = client.UI.Prepare(script.Parent.Parent) local label = gui.LABEL local str = data.Message - local topbar = client.UI.Get("TopBar") + gui.IgnoreGuiInset = not client.Variables.TopBarShift + gui.ClipToDeviceSafeArea = true client.UI.Remove("Notif",script.Parent.Parent) @@ -75,10 +76,8 @@ return function(data, env) table.insert(client.Variables.CommunicationsHistory, log) service.Events.CommsPanel:Fire(log) - if str and type(str)=="string" then label.Text = str - label.Position = UDim2.new(0, 0, 0, ((topbar and 40) or 0) - 35) gTable:Ready() else gui:Destroy() @@ -157,7 +156,7 @@ end]]> 0 0 0 - -35 + 0 false null diff --git a/MainModule/Client/UI/TransBlack/Console.rbxmx b/MainModule/Client/UI/TransBlack/Console.rbxmx index 6648d6f4ad..e7543cf940 100644 --- a/MainModule/Client/UI/TransBlack/Console.rbxmx +++ b/MainModule/Client/UI/TransBlack/Console.rbxmx @@ -300,7 +300,7 @@ false 0 - 0 + 1 true @@ -324,7 +324,7 @@ false true 0 - Frame + TopBar null null null @@ -333,7 +333,7 @@ 0 0 0 - -40 + 0 null 0 @@ -553,4 +553,4 @@ - \ No newline at end of file + diff --git a/MainModule/Client/UI/Unity/Hint.rbxmx b/MainModule/Client/UI/Unity/Hint.rbxmx index c97065ce14..e6418751c2 100644 --- a/MainModule/Client/UI/Unity/Hint.rbxmx +++ b/MainModule/Client/UI/Unity/Hint.rbxmx @@ -274,6 +274,8 @@ return function(data, env) local container = client.UI.Get("HintHolder",nil,true) if not container then local holder = service.New("ScreenGui") + holder.IgnoreGuiInset = not client.Variables.TopBarShift + holder.ClipToDeviceSafeArea = true local hTable = client.UI.Register(holder) local frame = service.New("ScrollingFrame", holder) client.UI.Prepare(holder) @@ -305,9 +307,8 @@ return function(data, env) --// First things first account for notif :) local notif = client.UI.Get("Notif") - local topbar = client.UI.Get("TopBar") - container.Position = UDim2.new(0,0,0,((notif and 30) or 0) + ((topbar and 40) or 0) - 35) + container.Position = UDim2.new(0, 0, 0, (notif and 30 or 0)) local children = container:GetChildren() diff --git a/MainModule/Client/UI/Unity/Music.rbxmx b/MainModule/Client/UI/Unity/Music.rbxmx deleted file mode 100644 index afe0265ed7..0000000000 --- a/MainModule/Client/UI/Unity/Music.rbxmx +++ /dev/null @@ -1,874 +0,0 @@ - - true - null - nil - - - - 0 - false - - Music - {BC72332A-A8F2-4672-BCED-4768BE760D25} - - -1 - - - - - - 0 - false - - Visualizer - {2C9A3CE4-D0CF-4AB2-B13D-C2304D0B6BBA} - = Alpha then - EndKeypoint = Keypoint - StartKeypoint = Keypoints[math.max(1, i-1)] - break - end - end - - local StartTime, EndTime = StartKeypoint.Time, EndKeypoint.Time - local StartValue, EndValue = StartKeypoint.Value, EndKeypoint.Value - - local KeyframeAlpha = (Alpha - StartTime) / (EndTime - StartTime) - - return StartValue:Lerp(EndValue, KeyframeAlpha) -end - -function module.new(Frame, BarCount) - - -- Determine settings - local BAR_COUNT = math.clamp(type(BarCount) == "number" and BarCount or 41, 11,601) - local SAMPLE_HZ = math.clamp(BAR_COUNT/2,10,500) - - if BAR_COUNT%2==0 then - BAR_COUNT += 1 - end - - local BAR_SIZE = 1/BAR_COUNT - local BUFFER_COUNT = math.ceil(BAR_COUNT/2) - local BAR_TO_BUFFER = table.create(BAR_COUNT) - local BAR_TO_MULTIPLIER = table.create(BAR_COUNT) - - for i=1, BAR_COUNT do - BAR_TO_BUFFER[i] = math.abs(BUFFER_COUNT- (i+ (i<=BUFFER_COUNT and -1 or 1) )) - BAR_TO_MULTIPLIER[i] = 1-(math.clamp(math.abs(BUFFER_COUNT- (i+ (i<=BUFFER_COUNT and -1 or 1) ))/BUFFER_COUNT, 0.01,1)^2) - end - - local UPDATE_WAIT = 1/SAMPLE_HZ - - -- Setup visualizer - - local Visualizer = { - Frame = Frame; - VolumeBuffer = table.create(BUFFER_COUNT+1); - Bars = {}; - BufferConnection = nil; - PlayingConnection = nil; - Sound = nil; - } - - -- Create the bar guis - for i=1, BAR_COUNT do - - local Bar = Frame:Add("Frame", { - BorderSizePixel = 0; - BackgroundColor3 = Color3.new(0.98,0.98,0.99); - AnchorPoint = Vector2.new(0,0.5); - Size = UDim2.new(BAR_SIZE,0,0.02,0); - Position = UDim2.new(BAR_SIZE* (i-1), 0,0.5,0); - }) - - Visualizer.Bars[i] = Bar - end - - local function HandlePlaying() - if Visualizer.BufferConnection then - Visualizer.BufferConnection:Disconnect() - Visualizer.BufferConnection = nil - end - - local Sound = Visualizer.Sound - if not Sound then return end - - if Sound.Playing then - local LastStored = os.clock() - Visualizer.BufferConnection = RunService.Heartbeat:Connect(function() - local success, void = pcall(function() - Visualizer.VolumeBuffer[1] = Sound.PlaybackLoudness - Visualizer.Bars[BUFFER_COUNT]:TweenSize( - UDim2.new( - BAR_SIZE,0, - math.clamp((Sound.PlaybackLoudness/400), 0.02,1),0 - ), - Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.014, true - ) - - if os.clock()-LastStored > UPDATE_WAIT then - LastStored = os.clock() - - table.insert(Visualizer.VolumeBuffer,1,Sound.PlaybackLoudness) - local Length = #Visualizer.VolumeBuffer - if Length > BUFFER_COUNT then - Visualizer.VolumeBuffer[#Visualizer.VolumeBuffer] = nil - end - - local Color = Visualizer.Color - local ColorType = typeof(Color) - - for i,Bar in ipairs(Visualizer.Bars) do - - local Alpha = math.clamp( - ((Visualizer.VolumeBuffer[BAR_TO_BUFFER[i]] or 0)/400), - 0.02, 1 - ) - - Bar:TweenSize( - UDim2.new( - BAR_SIZE,0, - Alpha,0 - ), - Enum.EasingDirection.Out, Enum.EasingStyle.Linear, UPDATE_WAIT, true - ) - - if Color then - if ColorType == "Color3" then - Bar.BackgroundColor3 = Color - elseif ColorType == "ColorSequence" then - Bar.BackgroundColor3 = AlphaColorSequence(Color, Alpha) - end - end - - end - end - end) - if not success then Visualizer:UnlinkFromSound() end - end) - else - table.clear(Visualizer.VolumeBuffer) - for i,Bar in ipairs(Visualizer.Bars) do - Bar:TweenSize( - UDim2.new(BAR_SIZE,0,0.02,0), - Enum.EasingDirection.Out, Enum.EasingStyle.Linear, UPDATE_WAIT, true - ) - end - end - end - - function Visualizer:LinkToSound(Sound) - - Visualizer:UnlinkFromSound() - - table.clear(Visualizer.VolumeBuffer) - - Visualizer.Sound = Sound - - HandlePlaying() - Visualizer.PlayingConnection = Sound:GetPropertyChangedSignal("Playing"):Connect(HandlePlaying) - end - - function Visualizer:UnlinkFromSound() - - if Visualizer.PlayingConnection then - Visualizer.PlayingConnection:Disconnect() - Visualizer.PlayingConnection = nil - end - if Visualizer.BufferConnection then - Visualizer.BufferConnection:Disconnect() - Visualizer.BufferConnection = nil - end - - Visualizer.Sound = nil - - for i,Bar in ipairs(Visualizer.Bars) do - Bar:TweenSize( - UDim2.new(BAR_SIZE,0,0.02,0), - Enum.EasingDirection.Out, Enum.EasingStyle.Linear, UPDATE_WAIT, true - ) - end - - end - - function Visualizer:Destroy() - if Visualizer.PlayingConnection then - Visualizer.PlayingConnection:Disconnect() - Visualizer.PlayingConnection = nil - end - if Visualizer.BufferConnection then - Visualizer.BufferConnection:Disconnect() - Visualizer.BufferConnection = nil - end - for i,Bar in ipairs(Visualizer.Bars) do - Bar:Destroy() - end - table.clear(Visualizer.VolumeBuffer) - end - - - return Visualizer -end - -return module -]]> - -1 - - - - - \ No newline at end of file diff --git a/MainModule/Client/UI/Unity/Notif.rbxmx b/MainModule/Client/UI/Unity/Notif.rbxmx index 3823ba5cc0..221d10f0af 100644 --- a/MainModule/Client/UI/Unity/Notif.rbxmx +++ b/MainModule/Client/UI/Unity/Notif.rbxmx @@ -58,7 +58,8 @@ return function(data, env) local gui = client.UI.Prepare(script.Parent.Parent) local label = gui.LABEL local str = data.Message - local topbar = client.UI.Get("TopBar") + gui.IgnoreGuiInset = not client.Variables.TopBarShift + gui.ClipToDeviceSafeArea = true client.UI.Remove("Notif",script.Parent.Parent) @@ -77,7 +78,6 @@ return function(data, env) if str and type(str)=="string" then label.Text = str - label.Position = UDim2.new(0, 0, 0, ((topbar and 40) or 0) - 35) gTable:Ready() else gui:Destroy() diff --git a/MainModule/Client/UI/Unity/TopBar.rbxmx b/MainModule/Client/UI/Unity/TopBar.rbxmx deleted file mode 100644 index 99a1b0ed70..0000000000 --- a/MainModule/Client/UI/Unity/TopBar.rbxmx +++ /dev/null @@ -1,296 +0,0 @@ - - true - null - nil - - - - false - 0 - true - false - 0 - true - TopBar - true - null - 1 - 2 - 0 - 0 - 0 - 0 - false - -1 - - 0 - - - - false - - 0 - 0 - - - false - 0 - - 0.0431372561 - 0.0431372561 - 0.0431372561 - - 0 - - 0.105882362 - 0.164705887 - 0.207843155 - - 0 - 0 - 0 - false - false - false - - rbxasset://fonts/families/GothamSSm.json - 400 - - rbxasset://fonts/GothamSSm-Book.otf - - true - 0 - 1 - - - -1 - TextLabel - null - null - null - null - - 0 - 0 - 0 - 0 - - false - null - 0 - false - 0 - 0 - 0 - 0 - false - null - 0 - - 1 - 0 - 0 - 40 - - 0 - -1 - - Arigato - - 1 - 1 - 1 - - 0 - false - 24 - - 0 - 0 - 0 - - 0.5 - 0 - 0 - true - 2 - 1 - true - 1 - - - - - 0 - - 0.0599999987 - 0 - - false - UICorner - -1 - - - - - - - false - - 0 - 0 - - - false - 0 - - 0 - 0 - 0 - - 0 - - 0.105882362 - 0.164705887 - 0.207843155 - - 0 - 0 - 0 - false - false - false - true - 0 - Tester - null - null - null - null - - 0 - 0 - 0 - 0 - - null - 0 - false - 0 - 0 - 0 - 0 - false - null - 0 - - 1 - 0 - 0 - 40 - - 0 - -1 - 0 - - false - 3 - - - - - - 0 - false - Config - -1 - - - - - - 0 - false - - Code - {0BF11DA2-74C3-4A97-93C1-FE86AD798952} - 12 or tonumber(hour)<1 then - nt4=`{math.abs(tonumber(hour)-12)}{t4:match(":%d+")} PM` - else - nt4=`{t4} AM` - end - bar.Text=`{t4} / {nt4}` - until not wait(1) - end) - else - bar.Text=TopbarText - end - bar.BackgroundColor3=TopbarColor - bar.BorderSizePixel=0 - bar.BackgroundTransparency=TopbarTransparency - end - --]] - - bar.Position=UDim2.new(0,0,0,-40) - gTable:Ready() -end]]> - -1 - - - - - - - 0 - false - AllowMultiple - -1 - - false - - - - - - 0 - false - CanKeepAlive - -1 - - true - - - - - diff --git a/MainModule/Client/UI/Unity/Window.rbxmx b/MainModule/Client/UI/Unity/Window.rbxmx index fa8bdddd66..7b6b705d01 100644 --- a/MainModule/Client/UI/Unity/Window.rbxmx +++ b/MainModule/Client/UI/Unity/Window.rbxmx @@ -1149,6 +1149,7 @@ return function(data, env) local addTitleButton local LoadChildren local BringToFront + local functionify local Drag = GUI.Drag local Close = Drag.Close diff --git a/MainModule/Client/UI/Windows XP/Hint.rbxmx b/MainModule/Client/UI/Windows XP/Hint.rbxmx index 9d107d174b..672f27ed99 100644 --- a/MainModule/Client/UI/Windows XP/Hint.rbxmx +++ b/MainModule/Client/UI/Windows XP/Hint.rbxmx @@ -360,6 +360,8 @@ return function(data, env) local container = client.UI.Get("HintHolder",nil,true) if not container then local holder = service.New("ScreenGui") + holder.IgnoreGuiInset = not client.Variables.TopBarShift + holder.ClipToDeviceSafeArea = true local hTable = client.UI.Register(holder) local frame = service.New("ScrollingFrame", holder) client.UI.Prepare(holder) @@ -391,9 +393,8 @@ return function(data, env) --// First things first account for notif :) local notif = client.UI.Get("Notif") - local topbar = client.UI.Get("TopBar") - container.Position = UDim2.new(0,0,0,((notif and 30) or 0) + ((topbar and 40) or 0) - 35) + container.Position = UDim2.new(0, 0, 0, (notif and 30 or 0)) local children = container:children() diff --git a/MainModule/Client/UI/Windows XP/Notification.rbxmx b/MainModule/Client/UI/Windows XP/Notification.rbxmx index 1c66fb1548..c632da334a 100644 --- a/MainModule/Client/UI/Windows XP/Notification.rbxmx +++ b/MainModule/Client/UI/Windows XP/Notification.rbxmx @@ -113,6 +113,7 @@ return function(data, env) local name = data.Title local text = data.Message or data.Text or "" local time = data.Time + local icon = data.Icon local returner = nil diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index 7fa610adf2..4e144bdfa0 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -556,12 +556,10 @@ return function(Vargs, env) AdminLevel = "Admins"; Function = function(plr: Player, args: {string}) local F3X = require(580330877)() - do - service.New("StringValue", { - Name = `__ADONIS_VARIABLES_{Variables.CodeName}`, - Parent = F3X - }) - end + service.New("StringValue", { + Name = `__ADONIS_VARIABLES_{Variables.CodeName}`, + Parent = F3X + }) for _, v in service.GetPlayers(plr, args[1]) do local Backpack = v:FindFirstChildOfClass("Backpack") @@ -577,7 +575,7 @@ return function(Vargs, env) Prefix = Settings.Prefix; Commands = {"insert", "ins"}; Args = {"id"}; - Description = "Inserts whatever object belongs to the ID you supply, the object must be in the place owner's or ROBLOX's inventory"; + Description = "Inserts whatever object belongs to the ID you supply, the object must be in the place owner's or Roblox's inventory"; AdminLevel = "Admins"; Function = function(plr: Player, args: {string}) local id = string.lower(args[1]) @@ -713,6 +711,7 @@ return function(Vargs, env) Variables.RestoringMap = true Functions.Hint("Restoring Map...", service.Players:GetPlayers()) + workspace.Gravity = Variables.OriginalGravity for _, obj in workspace:GetChildren() do if obj.ClassName ~= "Terrain" and not service.Players:GetPlayerFromCharacter(obj) then @@ -738,6 +737,7 @@ return function(Vargs, env) task.wait() + Admin.RunCommand(`{Settings.Prefix}fixlighting`) Admin.RunCommand(`{Settings.Prefix}respawn`, "all") Variables.RestoringMap = false Functions.Hint('Map Restore Complete.',service.Players:GetPlayers()) @@ -1020,7 +1020,7 @@ return function(Vargs, env) for _,v : Instance in service.StarterGui:GetChildren() do if v:IsA("LocalScript") and v.Name:find("[Adonis]") then - table.insert(result, v.Name:gsub("%[Adonis%] ", "")) + table.insert(result, (v.Name:gsub("%[Adonis%] ", ""))) end end diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index b02109a5ca..c980a06fa3 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -460,41 +460,15 @@ return function(Vargs, env) end if not Variables.ZaWarudoDebounce then - Variables.ZaWarudoDebounce = true - task.delay(10, function() Variables.ZaWarudoDebounce = false end) if Variables.ZaWarudo then - local audio = service.New("Sound", service.SoundService) - audio.SoundId = "rbxassetid://676242549" - audio.Volume = 0.5 - audio:Play() - task.wait(2) - for i, part in Variables.FrozenObjects do - part.Anchored = false - end - - local old = service.Lighting:FindFirstChild("ADONIS_ZAWARUDO") - if old then - for i = -2, 0, 0.1 do - old.Saturation = i - task.wait(0.01) - end - old:Destroy() - end - - local audio = service.SoundService:FindFirstChild("ADONIS_CLOCK_AUDIO") - if audio then - audio:Stop() - audio:Destroy() - end - - Variables.ZaWarudo:Disconnect() - Variables.FrozenObjects = {} - Variables.ZaWarudo = false - audio:Destroy() + Admin.RunCommandAsPlayer(`{Settings.Prefix}unzawarudo`, plr) else + Variables.ZaWarudoDebounce = true + task.delay(10, function() Variables.ZaWarudoDebounce = false end) local audio = service.New("Sound", service.SoundService) - audio.SoundId = "rbxassetid://274698941" + audio.SoundId = "rbxassetid://8762717966" -- Old audio: "rbxassetid://274698941" audio.Volume = 10 + audio.Name = "ADONIS_ZAWARUDO_AUDIO" audio:Play() task.wait(2.25) doPause(workspace) @@ -512,14 +486,60 @@ return function(Vargs, env) task.wait(0.01) end + task.wait(2.5) audio:Destroy() local clock = service.New("Sound", service.SoundService) clock.Name = "ADONIS_CLOCK_AUDIO" - clock.SoundId = "rbxassetid://160189066" + clock.SoundId = "rbxassetid://9133682204" -- Other new audio: "rbxassetid://850256806" Old audio "rbxassetid://160189066" clock.Looped = true clock.Volume = 1 clock:Play() + Variables.ZaWarudoDebounce = false end + end + end + }; + + UnZaWarudo = { + Prefix = Settings.Prefix; + Commands = {"unzawarudo", "unstoptime"}; + Args = {}; + Fun = true; + Description = "Stops zawarudo"; + AdminLevel = "Admins"; + Function = function(plr: Player, args: {string}) + if not Variables.ZaWarudoDebounce and Variables.ZaWarudo then + Variables.ZaWarudoDebounce = true + task.delay(10, function() Variables.ZaWarudoDebounce = false end) + local audio = service.New("Sound", service.SoundService) + audio.SoundId = "rbxassetid://676242549" + audio.Volume = 0.5 + audio.Name = "ADONIS_ZAWARUDO_AUDIO" + audio:Play() + task.wait(2) + for i, part in Variables.FrozenObjects do + part.Anchored = false + end + + local old = service.Lighting:FindFirstChild("ADONIS_ZAWARUDO") + if old then + for i = -2, 0, 0.1 do + old.Saturation = i + task.wait(0.01) + end + old:Destroy() + end + + local clock = service.SoundService:FindFirstChild("ADONIS_CLOCK_AUDIO") + if clock then + clock:Stop() + clock:Destroy() + end + + audio:Destroy() + Variables.ZaWarudo:Disconnect() + Variables.FrozenObjects = {} + Variables.ZaWarudo = false Variables.ZaWarudoDebounce = false end end @@ -1197,6 +1217,9 @@ return function(Vargs, env) humanoid.WalkSpeed = 0 ufo.Name = "ADONIS_UFO" + ufo.Archivable = false + ufo.ModelStreamingMode = Enum.ModelStreamingMode.PersistentPerPlayer + ufo:AddPersistentPlayer(p) ufo.PrimaryPart = primary ufo:PivotTo(tPos*CFrame.new(0, 500, 0)) @@ -1512,6 +1535,9 @@ return function(Vargs, env) van.PrimaryPart = van.Primary van.Name = "ADONIS_VAN" + van.Archivable = false + van.ModelStreamingMode = Enum.ModelStreamingMode.PersistentPerPlayer + van:AddPersistentPlayer(p) van.Parent = workspace humanoid.Name = "NoResetForYou" humanoid.WalkSpeed = 0 @@ -1626,7 +1652,7 @@ return function(Vargs, env) hat.ChickenSounds.Disabled = true table.insert(hats, hat) table.insert(Variables.Objects, hat) - hat.Parent = workspace + hat.Parent = workspace.Terrain hat.CFrame = plr.Character.Head.CFrame service.StopLoop("ChickenSpam") service.StartLoop("ChickenSpam", 5, function() @@ -1640,7 +1666,7 @@ return function(Vargs, env) table.insert(tempHats, v) table.insert(tempHats, nhat) table.insert(Variables.Objects, nhat) - nhat.Parent = workspace + nhat.Parent = workspace.Terrain nhat.Quacker.Disabled = false nhat.CFrame = v.CFrame*CFrame.new(math.random(-100, 100), math.random(-100, 100), math.random(-100, 100))*CFrame.Angles(math.random(-360, 360), math.random(-360, 360), math.random(-360, 360)) end @@ -1674,6 +1700,7 @@ return function(Vargs, env) p.Anchored = true p.CanCollide = false p.Archivable = false + p.Name = "ADONIS_Tornado" --local tornado = deps.Tornado:Clone() --tornado.Parent = p --tornado.Disabled = false @@ -2131,6 +2158,7 @@ return function(Vargs, env) end task.defer(humanoid.ApplyDescription, humanoid, description, Enum.AssetTypeVerification.Always) + poisoned:Destroy() end end end) @@ -3353,9 +3381,6 @@ return function(Vargs, env) p1.Anchored = true v.Part0 = nil end - elseif v:IsA("CharacterMesh") then - local bp = tostring(v.BodyPart):match("%w+.%w+.(%w+)") - local msh = service.New("SpecialMesh") elseif v:IsA("SpecialMesh") and v.Parent ~= char.Head then v.Scale = Vector3.new(v.Scale.X, v.Scale.Y, num) end @@ -3638,13 +3663,12 @@ return function(Vargs, env) Fun = true; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) - local sizeLimit = Settings.SizeLimit or 20 - local num = math.clamp(tonumber(args[2]) or 1, 0.001, sizeLimit) -- Size limit exceeding over 20 would be unnecessary and may potientially create massive lag !! + local num = math.clamp(tonumber(args[2]) or 1, 0.001, Variables.SizeLimit) -- Size limit exceeding over 20 would be unnecessary and may potientially create massive lag !! if not args[2] or not tonumber(args[2]) then num = 1 Functions.Hint("Size changed to 1 [Argument #2 (size multiplier) wasn't supplied correctly.]", {plr}) - elseif tonumber(args[2]) and tonumber(args[2]) > sizeLimit then + elseif tonumber(args[2]) and tonumber(args[2]) > Variables.SizeLimit then Functions.Hint(`Size changed to the maximum {num} [Argument #2 (size multiplier) went over the size limit]`, {plr}) end @@ -3671,7 +3695,7 @@ return function(Vargs, env) local resizeAttributeValue = char:GetAttribute("Adonis_Resize") if not resizeAttributeValue then char:SetAttribute("Adonis_Resize", num) - elseif resizeAttributeValue * num < sizeLimit then + elseif resizeAttributeValue * num < Variables.SizeLimit then char:SetAttribute("Adonis_Resize", resizeAttributeValue * num) else Functions.Hint(string.format("Cannot resize %s's character by %g%%: size limit exceeded.", service.FormatPlayer(v), num*100), {plr}) @@ -4772,10 +4796,6 @@ return function(Vargs, env) Fun = true; AdminLevel = "Admins"; Function = function(plr: Player, args: {string}) - if not Variables.OriginalGravity then - Variables.OriginalGravity = workspace.Gravity - end - workspace.Gravity = args[1] == "fix" and Variables.OriginalGravity or assert(tonumber(args[1]), "Missing gravity value (or enter 'fix' to reset to normal)'") end }; @@ -4955,6 +4975,7 @@ return function(Vargs, env) local pipe = Deps.Assets.Pipe:Clone() pipe.Name = "Pipe" + pipe.Archivable = false pipe.Parent = workspace pipe:PivotTo(Person:GetPivot() * CFrame.new(0, 50, 0)) diff --git a/MainModule/Server/Commands/HeadAdmins.luau b/MainModule/Server/Commands/HeadAdmins.luau index c09017be13..acddf436f0 100644 --- a/MainModule/Server/Commands/HeadAdmins.luau +++ b/MainModule/Server/Commands/HeadAdmins.luau @@ -285,6 +285,37 @@ return function(Vargs, env) end Variables.BackingupMap = true + Variables.OriginalGravity = workspace.Gravity + + local Lighting = service.Lighting + local atmosphere = Lighting:FindFirstChildWhichIsA("Atmosphere") + + Variables.OriginalLightingSettings = { + Ambient = Lighting.Ambient, + OutdoorAmbient = Lighting.OutdoorAmbient, + Brightness = Lighting.Brightness, + TimeOfDay = Lighting.TimeOfDay, + FogColor = Lighting.FogColor, + FogEnd = Lighting.FogEnd, + FogStart = Lighting.FogStart, + GlobalShadows = Lighting.GlobalShadows, + Outlines = Lighting.Outlines, + ShadowColor = Lighting.ShadowColor, + ColorShift_Bottom = Lighting.ColorShift_Bottom, + ColorShift_Top = Lighting.ColorShift_Top, + GeographicLatitude = Lighting.GeographicLatitude, + Name = Lighting.Name, + Sky = Lighting:FindFirstChildOfClass("Sky") and Lighting:FindFirstChildOfClass("Sky"):Clone(), + } + Variables.OriginalAtmosphereSettings = { + Name = atmosphere and atmosphere.Name, + Density = atmosphere and atmosphere.Density, + Offset = atmosphere and atmosphere.Offset, + Color = atmosphere and atmosphere.Color, + Decay = atmosphere and atmosphere.Decay, + Glare = atmosphere and atmosphere.Glare, + Haze = atmosphere and atmosphere.Haze, + } local tempmodel = service.New("Model", { Name = "BACKUP_MAP_MODEL" diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index b446afb79a..3734df252a 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -1954,7 +1954,7 @@ return function(Vargs, env) local answers = args[2] local anstab = {} local responses = {} - local voteKey = `ADONISVOTE{math.random()}`; + local voteKey = `ADONISVOTE{service.HttpService:GenerateGUID(false)}`; local players = service.GetPlayers(plr, args[1]) local startTime = os.clock(); @@ -2039,7 +2039,7 @@ return function(Vargs, env) local answers = args[2] local anstab = {} local responses = {} - local voteKey = `ADONISVOTE{math.random()}`; + local voteKey = `ADONISVOTE{service.GenerateGUID(false)}`; local players = service.GetPlayers(plr, args[1]) local startTime = os.clock(); @@ -2322,6 +2322,10 @@ return function(Vargs, env) end end) end + -- Remove Dex + for _, name in Variables.DexNames do + task.spawn(Remote.RemoveLocal, v, name, "PlayerGui") + end end end }; @@ -2362,27 +2366,18 @@ return function(Vargs, env) end -- Atmosphere - if service.Lighting:FindFirstChildWhichIsA("Atmosphere") then - Variables.OriginalAtmosphereSettings = { - Name = service.Lighting:FindFirstChildWhichIsA("Atmosphere").Name, - Density = service.Lighting:FindFirstChildWhichIsA("Atmosphere").Density, - Offset = service.Lighting:FindFirstChildWhichIsA("Atmosphere").Offset, - Color = service.Lighting:FindFirstChildWhichIsA("Atmosphere").Color, - Decay = service.Lighting:FindFirstChildWhichIsA("Atmosphere").Decay, - Glare = service.Lighting:FindFirstChildWhichIsA("Atmosphere").Glare, - Haze = service.Lighting:FindFirstChildWhichIsA("Atmosphere").Haze, - } - - if service.Lighting:FindFirstChildWhichIsA("Atmosphere") ~= nil then - local Atmosphere = service.Lighting:FindFirstChildWhichIsA("Atmosphere") - - Atmosphere.Name = Variables.OriginalAtmosphereSettings.Name - Atmosphere.Density = Variables.OriginalAtmosphereSettings.Density - Atmosphere.Offset = Variables.OriginalAtmosphereSettings.Offset - Atmosphere.Color = Variables.OriginalAtmosphereSettings.Color - Atmosphere.Decay = Variables.OriginalAtmosphereSettings.Decay - Atmosphere.Glare = Variables.OriginalAtmosphereSettings.Glare - Atmosphere.Haze = Variables.OriginalAtmosphereSettings.Haze + local atmosphere = service.Lighting:FindFirstChildWhichIsA("Atmosphere") + if atmosphere then + if Variables.OriginalAtmosphereSettings.Name then + atmosphere.Name = Variables.OriginalAtmosphereSettings.Name + atmosphere.Density = Variables.OriginalAtmosphereSettings.Density + atmosphere.Offset = Variables.OriginalAtmosphereSettings.Offset + atmosphere.Color = Variables.OriginalAtmosphereSettings.Color + atmosphere.Decay = Variables.OriginalAtmosphereSettings.Decay + atmosphere.Glare = Variables.OriginalAtmosphereSettings.Glare + atmosphere.Haze = Variables.OriginalAtmosphereSettings.Haze + else + atmosphere:Destroy() end end end @@ -2560,28 +2555,18 @@ return function(Vargs, env) end end - local Color = BrickColor.new("White") - if args[3] then - local R,G,B = string.match(args[3],"(%d+),(%d+),(%d+)") - if R and G and B then - R,G,B = tonumber(R),tonumber(G),tonumber(B); if R>255 then R=255 end; if G>255 then G=255 end;if B>255 then B=255 end; - Color = Color3.fromRGB(R,G,B) - elseif string.lower(args[3]) == "rainbow" then - Color = "rainbow" - else - Color = BrickColor.new(args[3]) or BrickColor.new("White") - end - end + local Color = args[3] and (string.lower(args[3]) == "rainbow" and "rainbow" or string.match(args[3], "%d") and Functions.ParseColor3(args[3]) or Functions.ParseBrickColor(args[3], true)) or BrickColor.new("White") for _, v in service.GetPlayers(plr, args[1]) do local cHumanoidRootPart = v.Character and v.Character.PrimaryPart or v.Character and v.Character:FindFirstChild("HumanoidRootPart") if cHumanoidRootPart then - local CF = CFrame.new(cHumanoidRootPart.CFrame.p + Vector3.new(0, 1, 0)) local OrigPos = cHumanoidRootPart.Position local Model = service.New("Model", { Name = `{v.Name}_ADONISJAIL`, + Archivable = false, + ModelStreamingMode = Enum.ModelStreamingMode.Persistent }) local top = service.New("Part", { Locked = true, @@ -3022,7 +3007,8 @@ return function(Vargs, env) service.Debris:AddItem(clone, service.Players.RespawnTime) end) - clone.Archivable = oldArchivable + clone.Archivable = false + clone.ModelStreamingMode = Enum.ModelStreamingMode.Atomic clone.Parent = workspace if appearenceId and not avatarType then clone.Name = Functions.GetNameFromUserIdAsync(appearenceId) @@ -4029,7 +4015,7 @@ return function(Vargs, env) local color = assert(Functions.ParseColor3(args[1]), "Invalid color provided") if service.Lighting:FindFirstChildWhichIsA("Atmosphere") then - Remote.SetAtmosphere(color) + Functions.SetAtmosphere("Color", color) end if args[2] then for _, v in service.GetPlayers(plr, args[2]) do @@ -6137,31 +6123,6 @@ return function(Vargs, env) end }; - TestFilter = { - Prefix = Settings.Prefix; - Commands = {"testfilter", "filtertest", "tfilter"}; - Args = {"player", "text"}; - NoFilter = true; - Description = "Test out Roblox's text filtering on a player"; - AdminLevel = "Moderators"; - Function = function(plr: Player, args: {string}) - assert(args[1], "Missing player name") - assert(args[2], "Missing text to filter") - local temp = {{Text=`Original: {args[2]}`, Desc = args[2]}} - if service.RunService:IsStudio() then - table.insert(temp, {Text="!! The string has not been filtered !!", Desc="Text filtering does not work in studio"}) - end - for _, v in service.GetPlayers(plr, args[1]) do - table.insert(temp, {Text = `-- {v.DisplayName} --`, Desc = `{v.UserId} ({v.Name})`}) - table.insert(temp, {Text = `ChatForUser: {service.TextService:FilterStringAsync(args[2], v.UserId):GetChatForUserAsync(v.UserId)}`}) - table.insert(temp, {Text = `NonChatForBroadcast: {service.TextService:FilterStringAsync(args[2], v.UserId):GetNonChatStringForBroadcastAsync()}`}) - table.insert(temp, {Text = `NonChatForUser: {service.TextService:FilterStringAsync(args[2], v.UserId):GetNonChatStringForUserAsync(v.UserId)}`}) - - end - Remote.MakeGui(plr, "List", {Title = "Filtering Results", Tab = temp}) - end - }; - DisplayName = { Prefix = Settings.Prefix; Commands = {"displayname", "dname"}; @@ -6691,16 +6652,16 @@ return function(Vargs, env) ShowLogs = { Prefix = Settings.Prefix; Commands = {"showlogs", "showcommandlogs"}; - Args = {"autoupdate? (default: false)", "player"}; + Args = {"player", "autoupdate? (default: false)"}; Description = "Shows the target player(s) the command logs."; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) local autoUpdate = false - if args[1] and table.find({"yes", "true", "1", "autoupdate", "on"}, args[1]:lower()) then + if args[2] and table.find({"yes", "true", "1", "autoupdate", "on"}, args[2]:lower()) then autoUpdate = true end local str = `{Settings.Prefix}logs {tostring(autoUpdate) or ""}` - for _, v in service.GetPlayers(plr, args[2]) do + for _, v in service.GetPlayers(plr, args[1]) do Admin.RunCommandAsPlayer(str, v) end end diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index c322464500..33b54e3335 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -887,6 +887,7 @@ return function(Vargs, env) for _, v: Player in players do task.defer(function() local gameData + local elevated = plr == v or elevated if elevated then local level, rank = Admin.GetLevel(v) @@ -927,6 +928,7 @@ return function(Vargs, env) IsServerOwner = v.UserId == game.PrivateServerOwnerId; CmdPrefix = Settings.Prefix; CmdSplitKey = Settings.SplitKey; + OnlineFriends = Remote.Get(v, "Function", "GetFriendsOnline"); }) end) end @@ -971,6 +973,7 @@ return function(Vargs, env) NilPlayerCount = nilPlayers; HttpEnabled = HTTP.HttpEnabled; LoadstringEnabled = HTTP.LoadstringEnabled; + ServerSpeed = workspace:GetRealPhysicsFPS(); } end @@ -1000,6 +1003,7 @@ return function(Vargs, env) PrivateServerId = game.PrivateServerId; PrivateServerOwnerId = game.PrivateServerOwnerId; ServerStartTime = server.ServerStartTime; + ServerSpeed = workspace:GetRealPhysicsFPS(); ServerAge = service.FormatTime(os.time() - server.ServerStartTime); ServerInternetInfo = serverInfo; Refreshables = Logs.ListUpdaters.ServerDetails(plr); diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau index 300e59ab2b..26bf0fdc12 100644 --- a/MainModule/Server/Core/Admin.luau +++ b/MainModule/Server/Core/Admin.luau @@ -1203,7 +1203,7 @@ return function(Vargs, GetEnv) Admin.PrefixCache = tempPrefix Admin.CommandCache = tempTable - if Settings.ChatCreateRobloxCommands then + if Variables.ChatCreateRobloxCommands then -- // Support for commands to be ran via TextChat task.spawn(function() local container = service.TextChatService.ChatVersion == Enum.ChatVersion.TextChatService and service.TextChatService:WaitForChild("TextChatCommands", 9e9) @@ -1242,11 +1242,13 @@ return function(Vargs, GetEnv) end if command1 then - local command = Instance.new("TextChatCommand") + local command = service.New("TextChatCommand") command.Name = "Adonis_"..name command.PrimaryAlias = command1 command.SecondaryAlias = command2 or "" + command.Archivable = false + command:SetAttribute("AdminLevel", tonumber(data.AdminLevel) or data.AdminLevel or nil) command.Parent = container command.Triggered:Connect(function(textSource, text) local player = service.Players:GetPlayerByUserId(textSource.UserId) @@ -1325,43 +1327,41 @@ return function(Vargs, GetEnv) end; FormatCommandArguments = function(command) - local text = "" + local text = table.create(#command.Args) for i, arg in command.Args do - text ..= `<{arg}>` - if i < #command.Args then - text ..= Settings.SplitKey - end + text[i] = `<{arg}>` end - return text + return table.concat(text, Settings.SplitKey) end; FormatCommand = function(command, cmdn) - local text = (command.Prefix or "")..tostring(command.Commands[cmdn or 1]) - if #command.Args > 0 then - text ..= Settings.SplitKey .. Admin.FormatCommandArguments(command) - end - return text + return table.concat({ + (command.Prefix or ""), + tostring(command.Commands[cmdn or 1]), + #command.Args > 0 and Settings.SplitKey or "", + #command.Args > 0 and Admin.FormatCommandArguments(command) or "" + }) end; FormatCommandAdminLevel = function(command) local levels = if type(command.AdminLevel) == "table" then table.clone(command.AdminLevel) else {command.AdminLevel} - local permissionDesc = "" + local permissionDesc = table.create(#levels) + for i, lvl in levels do if type(lvl) == "number" then local list, name, data = Admin.LevelToList(lvl) - permissionDesc ..= `{name or "No Rank"}; Level {lvl}` + permissionDesc[i] = `{name or "No Rank"}; Level {lvl}` elseif type(lvl) == "string" then local numLvl = Admin.StringToComLevel(lvl) - permissionDesc ..= `{lvl}; Level {numLvl or "Unknown"}` - end - - if i < #levels then - permissionDesc ..= ", " + permissionDesc[i] = `{lvl}; Level {numLvl or "Unknown"}` + else + permissionDesc[i] = "N/A" end end - return permissionDesc + + return table.concat(permissionDesc, ", ") end; CheckTable = function(p, tab) @@ -1680,5 +1680,18 @@ return function(Vargs, GetEnv) Functions.Hint(`You don't have permission to {actionName} {service.FormatPlayer(target)}`, {p}) return false end; + + GetAliases = function(player) + local aliases = table.clone(Variables.Aliases) + local pData = player and Core.GetPlayer(player) + + if pData and pData.Aliases then + for alias, command in pData.Aliases do + aliases[alias] = command + end + end + + return aliases + end; } end diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index d6fdea3bd8..eb08ce669f 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -1549,7 +1549,7 @@ return function(Vargs, GetEnv) local realEnvResult, isResultPointer = getRealEnvResult(TableInEnvPath) local metaTableInEnv = getmetatable(realEnvResult) local result = metaTableInEnv[FuncToRun](realEnvResult,table.unpack(args,3,#args)) - local resultPointer = tostring(math.random()) + local resultPointer = service.HttpService:GenerateGUID(false) pointers[resultPointer] = result return service.UnWrap(result), resultPointer diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index aa0ab05f47..845c114c5b 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -347,7 +347,7 @@ return function(Vargs, GetEnv) ["#number"] = { Match = "#"; Function = function(msg, plr, ...) - local matched = string.match(msg, "%#(.*)") + local matched = string.match(msg, "#(.*)") if matched and tonumber(matched) then local num = tonumber(matched) if not num then @@ -388,16 +388,6 @@ return function(Vargs, GetEnv) }; }; - CatchError = function(func, ...) - local ret = {pcall(func, ...)} - - if not ret[1] then - logError(ret[2] or "Unknown error occurred") - else - return unpack(ret, 2) - end - end; - GetFakePlayer = function(options) local fakePlayer = service.Wrap(service.New("Folder", { Name = options.Name or "Fake_Player"; @@ -463,11 +453,11 @@ return function(Vargs, GetEnv) end; ArgsToString = function(args) - local str = "" + local str = table.create(args.n or #args) for i, arg in args do - str ..= `Arg{i}: {arg}; ` + str[i] = `Arg{i}: {arg}; ` end - return string.sub(str, 1, -3) + return string.sub(table.concat(str), 1, -3) end; GetPlayers = function(plr, argument, options) @@ -1023,9 +1013,17 @@ return function(Vargs, GetEnv) end; SetAtmosphere = function(prop,value) - if service:FindFirstChildWhichIsA("Atmosphere")[prop] ~= nil then - service:FindFirstChildWhichIsA("Atmosphere")[prop] = value - Variables.AtmosphereSettings[prop] = value + local atmosphere = service.Lighting:FindFirstChildWhichIsA("Atmosphere") + + if atmosphere then + if value == nil and atmosphere[prop] and typeof(atmosphere[prop]) ~= "Instance" then + atmosphere:Destroy() + table.clear(Variables.AtmosphereSettings) + else + atmosphere[prop] = value + Variables.AtmosphereSettings[prop] = value + end + for _, p in service.GetPlayers() do Remote.SetAtmosphere(p, prop, value) end @@ -1198,6 +1196,7 @@ return function(Vargs, GetEnv) new.Name = player.Name new.Archivable = false + new.ModelStreamingMode = Enum.ModelStreamingMode.Atomic new:PivotTo(pos * CFrame.Angles(0, math.rad((360/num)*i+90), 0) * CFrame.new((num*0.2)+5, 0, 0) * CFrame.Angles(0, math.pi / 2, 0)) hum.WalkSpeed = speed @@ -1229,7 +1228,7 @@ return function(Vargs, GetEnv) Damage = damage; Health = health; WalkSpeed = speed; - SpecialKey = math.random(); + SpecialKey = service.HttpService:GenerateGUID(false); }) if walk then @@ -1238,6 +1237,8 @@ return function(Vargs, GetEnv) table.insert(Variables.Objects, new) end + + clone:Destroy() end, GetJoints = function(character) diff --git a/MainModule/Server/Core/HTTP.luau b/MainModule/Server/Core/HTTP.luau index 198a90b32b..c027309537 100644 --- a/MainModule/Server/Core/HTTP.luau +++ b/MainModule/Server/Core/HTTP.luau @@ -32,23 +32,24 @@ return function(Vargs, GetEnv) HTTP.Trello.API = require(server.Deps.TrelloAPI)(Settings.Trello_AppKey, Settings.Trello_Token) end + -- Check HTTP asynchronously + task.spawn(function() + if service.RunService:IsStudio() then + server.HTTP.HttpEnabled = service.HttpService.HttpEnabled + else + local success, res = pcall(service.HttpService.GetAsync, service.HttpService, Variables.HTTPCheckUrl) + server.HTTP.HttpEnabled = not (not success and res:find("Http requests are not enabled.")) or true + end + Logs:AddLog("Script", "Successfully pooled HttpEnabled") + end) + HTTP.Init = nil; Logs:AddLog("Script", "HTTP Module Initialized") end; server.HTTP = { Init = Init; - HttpEnabled = (function() - if service.RunService:IsStudio() then - return service.HttpService.HttpEnabled - else - local success, res = pcall(service.HttpService.GetAsync, service.HttpService, Variables.HTTPCheckUrl) - if not success and res:find("Http requests are not enabled.") then - return false - end - return true - end - end)(); + HttpEnabled = service.HttpService.HttpEnabled; LoadstringEnabled = pcall(loadstring, ""); WebPanel = { @@ -81,7 +82,7 @@ return function(Vargs, GetEnv) }) end }, - { -- // Was this really a good idea? Since when should databases run code + { Lists = {"Commands", "Command List"}, Process = function(card) if not HTTP.Trello.PerformedCommands[tostring(card.id)] then diff --git a/MainModule/Server/Core/Process.luau b/MainModule/Server/Core/Process.luau index 5cb1abbc75..b12215611d 100644 --- a/MainModule/Server/Core/Process.luau +++ b/MainModule/Server/Core/Process.luau @@ -92,6 +92,55 @@ return function(Vargs, GetEnv) service.RbxEvent(service.Players.PlayerAdded, service.EventTask("PlayerAdded", Process.PlayerAdded)) service.RbxEvent(service.Players.PlayerRemoving, service.EventTask("PlayerRemoving", Process.PlayerRemoving)) + task.spawn(function() + local oldVer = tonumber(Core.GetData("VersionNumber")) + + if oldVer and server.Version and server.Version > oldVer then + Process.SaveDatastoreVersionDebounce = true + table.insert(server.Messages, { + Level = 1; + Title = "Updated!"; + Message = "Click to view the changelog."; + Time = 10; + Icon = "MatIcon://System upgrade"; + onClick = Core.Bytecode(`client.Remote.Send("ProcessCommand","{Settings.Prefix}changelog")`); + }) + end + end) + + if Core.DebugMode == true then + table.insert(server.Messages, { + Level = 301; + Title = "Debug Mode Enabled"; + Message = "Adonis is currently running in Debug Mode."; + Time = 10; + Icon = "MatIcon://Bug report"; + onClick = Core.Bytecode(`client.Remote.Send("ProcessCommand","{Settings.Prefix}debugcmds")`); + }) + end + + if Settings.DataStoreKey == Defaults.Settings.DataStoreKey and Core.DebugMode == false then + table.insert(server.Messages, { + Level = 301; + Title = "Warning!"; + Message = "Using default datastore key!"; + Time = 15; + Icon = "MatIcon://Description"; + onClick = Core.Bytecode([[ + local window = client.UI.Make("Window", { + Title = "How to change the DataStore key"; + Size = {700,300}; + Icon = "rbxassetid://7510994359"; + }) + + window:Add("ImageLabel", { + Image = "rbxassetid://1059543904"; + }) + + window:Ready() + ]])}) + end + --// Load client onto existing players if existingPlayers then for i, p in existingPlayers do @@ -422,8 +471,7 @@ return function(Vargs, GetEnv) opts.OverrideArgs = overrideArgs end else - local pData = opts.PlayerData or (p and Core.GetPlayer(p)) - msg = (pData and Admin.AliasFormat(pData.Aliases, msg)) or msg + msg = Admin.AliasFormat(Admin.GetAliases(p), msg) or msg if string.match(msg, Settings.BatchKey) then return Process.Command(p, msg, opts, false) @@ -958,57 +1006,33 @@ return function(Vargs, GetEnv) end if level > 0 then - local oldVer = (level > 300) and Core.GetData("VersionNumber") - local newVer = (level > 300) and tonumber(string.match(server.Changelog[1], "Version: (.*)")) - if Settings.Notification then task.wait(1) Functions.Notification("Welcome.", `Your rank is {rank} ({level}). Click here for commands.`, {p}, 15, "MatIcon://Verified user", Core.Bytecode(`client.Remote.Send("ProcessCommand","{Settings.Prefix}cmds")`)) - if oldVer and newVer and newVer > oldVer then - task.delay(1, Functions.Notification, "Updated!", "Click to view the changelog.", {p}, 10, "MatIcon://System upgrade", Core.Bytecode(`client.Remote.Send("ProcessCommand","{Settings.Prefix}changelog")`)) - end - - if level > 300 and Core.DebugMode == true then - task.delay(1, Functions.Notification, "Debug Mode Enabled", "Adonis is currently running in Debug Mode.", {p}, 10, "MatIcon://Bug report", Core.Bytecode(`client.Remote.Send("ProcessCommand","{Settings.Prefix}debugcmds")`)) - end - - if level > 300 and Settings.DataStoreKey == Defaults.Settings.DataStoreKey and Core.DebugMode == false then - task.delay(1, Functions.Notification, "Warning!", "Using default datastore key!", {p}, 15, "MatIcon://Description", Core.Bytecode([[ - local window = client.UI.Make("Window", { - Title = "How to change the DataStore key"; - Size = {700,300}; - Icon = "rbxassetid://7510994359"; - }) - - window:Add("ImageLabel", { - Image = "rbxassetid://1059543904"; - }) - - window:Ready() - ]])) - end - - if level >= 300 and #server.Messages > 0 then + if #server.Messages > 0 then for _, message in server.Messages do local isString = type(message) == "string" - task.delay( - 1, - Functions.Notification, - not isString and message.Title or "Message", - isString and message or not isString and message.Message or "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", - {p}, - isString and math.round((#message/19)+2.5) or not isString and message.Time or 10, - not isString and message.Icon, - not isString and message.onClick - ) + if level >= (not isString and message.Level or 300) then + task.delay( + 1, + Functions.Notification, + not isString and message.Title or "Message", + isString and message or not isString and message.Message or "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + {p}, + isString and math.round((#message/19)+2.5) or not isString and message.Time or 10, + not isString and message.Icon, + not isString and message.onClick + ) + end end end end - if newVer then - Core.SetData("VersionNumber", newVer) + if Process.SaveDatastoreVersionDebounce then + Process.SaveDatastoreVersionDebounce = false + Core.SetData("VersionNumber", server.Version) end end @@ -1140,13 +1164,13 @@ return function(Vargs, GetEnv) AddLog("Script", { Text = `{p.Name} connected`; - Desc = `{p.Name} successfully established a connection with the server`; + Desc = `{p.Name} successfully established a RakPeer network connection with the server (RakNet)`; Player = p; }) else AddLog("Script", { Text = " connected"; - Desc = "An unknown user successfully established a connection with the server"; + Desc = "An unknown user without a player instance successfully established a RakPeer network connection with the server (RakNet)"; }) end @@ -1162,13 +1186,13 @@ return function(Vargs, GetEnv) Anti.KickedPlayers[p] = nil AddLog("Script", { Text = `{p.Name} disconnected`; - Desc = `{p.Name} disconnected from the server`; + Desc = `{p.Name} disconnected from the server (RakNet)`; Player = p; }) else AddLog("Script", { Text = " disconnected"; - Desc = "An unknown user disconnected from the server"; + Desc = "An unknown user without a player instance disconnected from the server (RakNet)"; }) end diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index a77f12d675..33d47f027a 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -83,6 +83,7 @@ return function(Vargs, GetEnv) PlayerPrefix = true; SpecialPrefix = true; ConsoleKeyCode = true; + MusicList = true; }; --// Settings that are never sent to the client @@ -513,21 +514,34 @@ return function(Vargs, GetEnv) end end; - AudioLib = function(p,args) + AudioLib = function(p, args) local AdminLevel = Admin.GetLevel(p) if Commands.Music and Admin.CheckComLevel(AdminLevel, Commands.Music) then - if not server.Functions.AudioLib then + local audioLib = Functions.AudioLib + + if not Functions.AudioLib then local audioLibFolder = service.SoundService:FindFirstChild("ADONIS_AUDIOLIB") if not audioLibFolder then audioLibFolder = service.New("Folder") audioLibFolder.Name = "ADONIS_AUDIOLIB" audioLibFolder.Parent = service.SoundService end - server.Functions.AudioLib = require(server.Shared.AudioLib).new(service.UnWrap(audioLibFolder)) + audioLib = require(server.Shared.AudioLib).new(service.UnWrap(audioLibFolder)) + Functions.AudioLib = audioLib + end + + if type(args[1]) == "table" then + args = service.UnWrap(args[1]) + else + return end - if type(args[1]) == "table" and type(Functions.AudioLib[args[1][1]]) == "function" then - return Functions.AudioLib[args[1][1]](Functions.AudioLib, args[1][2]) + if args[1] == "index" then + return audioLib[args[2]] + elseif args[1] == "newindex" then + audioLib[args[2]] = args[3] + elseif args[1] == "call" then + return audioLib[args[2]](audioLib, table.unpack(args, 3)) end end end; @@ -535,10 +549,10 @@ return function(Vargs, GetEnv) Terminal = { Data = {}; - Format = function(msg,data) (data or {}).Text = msg end; - Output = function(tab,msg,mata) table.insert(tab,Remote.Terminal.Format(msg,mata)) end; - GetCommand = function(cmd) for i,com in Remote.Terminal.Commands do if com.Command:lower() == cmd:lower() then return com end end end; - LiveOutput = function(p,data,type) Remote.FireEvent(p,"TerminalLive",{Data = data; Type = type or "Terminal";}) end; + Format = function(msg, data) (data or {}).Text = msg end; + Output = function(tab, msg, mata) table.insert(tab, Remote.Terminal.Format(msg, mata)) end; + GetCommand = function(cmd) for i, com in Remote.Terminal.Commands do if com.Command:lower() == cmd:lower() then return com end end end; + LiveOutput = function(p, data, type) Remote.FireEvent(p, "TerminalLive", {Data = data; Type = type or "Terminal";}) end; Commands = { Help = { Usage = "help"; diff --git a/MainModule/Server/Core/Variables.luau b/MainModule/Server/Core/Variables.luau index 113dc29461..c4440fc391 100644 --- a/MainModule/Server/Core/Variables.luau +++ b/MainModule/Server/Core/Variables.luau @@ -28,6 +28,8 @@ return function(Vargs, GetEnv) Variables.BanMessage = Settings.BanMessage Variables.LockMessage = Settings.LockMessage + Variables.SizeLimit = Settings.SizeLimit or Variables.SizeLimit + Variables.ChatCreateRobloxCommands = Settings.ChatCreateRobloxCommands == nil and Variables.ChatCreateRobloxCommands or Settings.ChatCreateRobloxCommands Variables.DisableRejoinAtMaxPlayers = Settings.DisableRejoinAtMaxPlayers or Variables.DisableRejoinAtMaxPlayers for _, v in Settings.MusicList or {} do table.insert(Variables.MusicList, v) end @@ -41,19 +43,18 @@ return function(Vargs, GetEnv) end local function AfterInit(data) - server.Variables.CodeName = service.HttpService:GenerateGUID(false) - Variables.RunAfterInit = nil Logs:AddLog("Script", "Finished Variables AfterInit") end local Lighting = service.Lighting + local atmosphere = Lighting:FindFirstChildWhichIsA("Atmosphere") server.Variables = { Init = Init, RunAfterInit = AfterInit, ZaWarudo = false, - CodeName = math.random(), + CodeName = service.HttpService:GenerateGUID(false), IsStudio = service.RunService:IsStudio(), -- Used to check if Adonis is running inside Roblox Studio as things like TeleportService and DataStores (if API Access is disabled) do not work in Studio AuthorizedToReply = {}, FrozenObjects = {}, @@ -69,7 +70,11 @@ return function(Vargs, GetEnv) DeveloperWhitelist = {1237666, 76328606, 698712377}, HTTPCheckUrl = "https://www.google.com/humans.txt", IPInfoUrl = "https://ipinfo.io/json", + SizeLimit = 20, + ChatCreateRobloxCommands = true, + OriginalGravity = workspace.Gravity, DisableRejoinAtMaxPlayers = false, + DexNames = {"Dex_Explorer", "Dex_Client", "Dex_Intro", "Dex_MainMenu", "Dex_ExplorerSelections", "Dex_Context", "Dex_Window", "Dex_SidesGui", "Dex_BrickColor", "Dex_AboutWindow", "Dex_SettingsWindow"}, AnimatedFaces = { -- R15 (Hopefully) 14719428401, 12936561806, 12936887700, 12937016609, 12937135097, 12939014597, 12945364777, 12945456452, 14374800823, 14367118483, 13674780763, @@ -118,9 +123,25 @@ return function(Vargs, GetEnv) Sky = Lighting:FindFirstChildOfClass("Sky") and Lighting:FindFirstChildOfClass("Sky"):Clone(), }, - AtmosphereSettings = {}, + AtmosphereSettings = { + Name = atmosphere and atmosphere.Name, + Density = atmosphere and atmosphere.Density, + Offset = atmosphere and atmosphere.Offset, + Color = atmosphere and atmosphere.Color, + Decay = atmosphere and atmosphere.Decay, + Glare = atmosphere and atmosphere.Glare, + Haze = atmosphere and atmosphere.Haze, + }, - OriginalAtmosphereSettings = {}, + OriginalAtmosphereSettings = { + Name = atmosphere and atmosphere.Name, + Density = atmosphere and atmosphere.Density, + Offset = atmosphere and atmosphere.Offset, + Color = atmosphere and atmosphere.Color, + Decay = atmosphere and atmosphere.Decay, + Glare = atmosphere and atmosphere.Glare, + Haze = atmosphere and atmosphere.Haze, + }, PMtickets = {}; @@ -152,27 +173,27 @@ return function(Vargs, GetEnv) {Name = "crabrave", ID = 5410086218}, {Name = "shiawase", ID = 5409360995}, {Name = "unchartedwaters", ID = 7028907200}, - {Name = "glow", ID = 7028856935}, - {Name = "good4me", ID = 7029051434}, - {Name = "bloom", ID = 7029024726}, + {Name = "glow", ID = 7028856935}, + {Name = "good4me", ID = 7029051434}, + {Name = "bloom", ID = 7029024726}, {Name = "safe&sound", ID = 7024233823}, - {Name = "shaku", ID = 7024332460}, + {Name = "shaku", ID = 7024332460}, {Name = "fromdust&ashes", ID = 7024254685}, - {Name = "loveis", ID = 7029092469}, + {Name = "loveis", ID = 7029092469}, {Name = "playitcool", ID = 7029017448}, - {Name = "still", ID = 7023771708}, - {Name = "sleep", ID = 7023407320}, - {Name = "whatareyouwaitingfor", ID = 7028977687}, - {Name = "balace", ID = 7024183256}, + {Name = "still", ID = 7023771708}, + {Name = "sleep", ID = 7023407320}, + {Name = "whatareyouwaitingfor", ID = 7028977687}, + {Name = "balace", ID = 7024183256}, {Name = "brokenglass", ID = 7028799370}, - {Name = "thelanguageofangels", ID = 7029031068}, + {Name = "thelanguageofangels", ID = 7029031068}, {Name = "imprints", ID = 7023704173}, {Name = "foundareason", ID = 7028919492}, {Name = "newhorizons", ID = 7028518546}, {Name = "whatsitlike", ID = 7028997537}, {Name = "destroyme", ID = 7023617400}, {Name = "consellations", ID = 7023733671}, - {Name = "wish", ID = 7023670701}, + {Name = "wish", ID = 7023670701}, {Name = "samemistake", ID = 7024101188}, {Name = "whereibelong", ID = 7028527348}, {Name = "rainingtacos", ID = 142376088}, @@ -181,30 +202,30 @@ return function(Vargs, GetEnv) InsertList = {}; Capes = { - {Name = "crossota", Material = "Neon", Color = "Cyan", ID = 420260457}, - {Name = "jamiejr99", Material = "Neon", Color = "Cashmere", ID = 429297485}, + {Name = "crossota", Material = "Neon", Color = "Cyan", ID = 420260457}, + {Name = "jamiejr99", Material = "Neon", Color = "Cashmere", ID = 429297485}, {Name = "new yeller", Material = "Fabric", Color = "New Yeller"}, {Name = "pastel blue", Material = "Fabric", Color = "Pastel Blue"}, {Name = "dusty rose", Material = "Fabric", Color = "Dusty Rose"}, {Name = "cga brown", Material = "Fabric", Color = "CGA brown"}, - {Name = "random", Material = "Fabric", Color = (BrickColor.random()).Name}, - {Name = "shiny", Material = "Plastic", Color = "Institutional white", Reflectance = 1}, - {Name = "gold", Material = "Plastic", Color = "Bright yellow", Reflectance = 0.4}, - {Name = "kohl", Material = "Fabric", Color = "Really black", ID = 108597653}, - {Name = "script", Material = "Plastic", Color = "White", ID = 151359194}, - {Name = "batman", Material = "Fabric", Color = "Institutional white", ID = 108597669}, - {Name = "epix", Material = "Plastic", Color = "Really black", ID = 149442745}, + {Name = "random", Material = "Fabric", Color = (BrickColor.random()).Name}, + {Name = "shiny", Material = "Plastic", Color = "Institutional white", Reflectance = 1}, + {Name = "gold", Material = "Plastic", Color = "Bright yellow", Reflectance = 0.4}, + {Name = "kohl", Material = "Fabric", Color = "Really black", ID = 108597653}, + {Name = "script", Material = "Plastic", Color = "White", ID = 151359194}, + {Name = "batman", Material = "Fabric", Color = "Institutional white", ID = 108597669}, + {Name = "epix", Material = "Plastic", Color = "Really black", ID = 149442745}, {Name = "superman", Material = "Fabric", Color = "Bright blue", ID = 108597677}, - {Name = "swag", Material = "Fabric", Color = "Pink", ID = 109301474}, - {Name = "donor", Material = "Plastic", Color = "White", ID = 149009184}, + {Name = "swag", Material = "Fabric", Color = "Pink", ID = 109301474}, + {Name = "donor", Material = "Plastic", Color = "White", ID = 149009184}, {Name = "gomodern", Material = "Plastic", Color = "Really black", ID = 149438175}, - {Name = "admin", Material = "Plastic", Color = "White", ID = 149092195}, + {Name = "admin", Material = "Plastic", Color = "White", ID = 149092195}, {Name = "giovannis", Material = "Plastic", Color = "White", ID = 149808729}, {Name = "godofdonuts", Material = "Plastic", Color = "Institutional white", ID = 151034443}, - {Name = "host", Material = "Plastic", Color = "Really black", ID = 152299000}, - {Name = "cohost", Material = "Plastic", Color = "Really black", ID = 152298950}, - {Name = "trainer", Material = "Plastic", Color = "Really black", ID = 152298976}, - {Name = "ba", Material = "Plastic", Color = "White", ID = 172528001} + {Name = "host", Material = "Plastic", Color = "Really black", ID = 152299000}, + {Name = "cohost", Material = "Plastic", Color = "Really black", ID = 152298950}, + {Name = "trainer", Material = "Plastic", Color = "Really black", ID = 152298976}, + {Name = "ba", Material = "Plastic", Color = "White", ID = 172528001} }; Blacklist = { diff --git a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx b/MainModule/Server/Dependencies/Assets/Sfling.rbxmx index caa6fd505e..c58966959f 100644 --- a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx +++ b/MainModule/Server/Dependencies/Assets/Sfling.rbxmx @@ -24,6 +24,7 @@ for i = 1, 100 do ex.BlastPressure = strength ex.ExplosionType = Enum.ExplosionType.Craters ex.DestroyJointRadiusPercent = 0 + ex.Archivable = false ex.Parent = cam end script:Destroy()]]> diff --git a/MainModule/Server/Dependencies/Assets/Singer.client.luau b/MainModule/Server/Dependencies/Assets/Singer.server.luau similarity index 100% rename from MainModule/Server/Dependencies/Assets/Singer.client.luau rename to MainModule/Server/Dependencies/Assets/Singer.server.luau diff --git a/MainModule/Server/Dependencies/ClientMover.client.luau b/MainModule/Server/Dependencies/ClientMover.client.luau index c8785865d8..37d157cb88 100644 --- a/MainModule/Server/Dependencies/ClientMover.client.luau +++ b/MainModule/Server/Dependencies/ClientMover.client.luau @@ -183,17 +183,6 @@ local function callCheck(child) end end -local function doPcall(func, ...) - local ran,ret = pcall(func, ...) - if ran then - return ran,ret - else - warn(tostring(ret)) - Kill(`ACLI: Error\n{ret}`) - return ran,ret - end -end - if module and module:IsA("ModuleScript") then print("Loading Folder...") local nameVal diff --git a/MainModule/Server/Dependencies/DefaultSettings.luau b/MainModule/Server/Dependencies/DefaultSettings.luau index f4aeef0e63..ac5f5129af 100644 --- a/MainModule/Server/Dependencies/DefaultSettings.luau +++ b/MainModule/Server/Dependencies/DefaultSettings.luau @@ -285,7 +285,6 @@ settings.CreatorPowers = true -- Gives me creator-level admin; This is strictl settings.CodeExecution = true -- Enables the use of code execution in Adonis; Scripting related (such as :s) and a few other commands require this settings.SilentCommandDenials = false -- If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command settings.OverrideChatCallbacks = true -- If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for slowmode. Mutes use a CanSend method to mute when this is set to false. -settings.ChatCreateRobloxCommands = true -- Whether "/" commands for Roblox should get created in new Chat settings.BanMessage = "Banned" -- Message shown to banned users upon kick settings.LockMessage = "Not Whitelisted" -- Message shown to people when they are kicked while the game is :slocked @@ -458,7 +457,6 @@ descs.CrossServerCommands = [[ Are commands which affect more than one server en descs.ChatCommands = [[ If false you will not be able to run commands via the chat; Instead, you MUST use the console or you will be unable to run commands ]] descs.SilentCommandDenials = [[ If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command ]] descs.OverrideChatCallbacks = [[ If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for muting ]] -descs.ChatCreateRobloxCommands = [[ Whether "/" commands for Roblox should get created in new Chat ]] descs.BanMessage = [[ Message shown to banned users ]] descs.LockMessage = [[ Message shown to people when they are kicked while the game is :slocked ]] @@ -577,7 +575,6 @@ order = { ""; "SilentCommandDenials"; "OverrideChatCallbacks"; - "ChatCreateRobloxCommands"; " "; "BanMessage"; "LockMessage"; diff --git a/MainModule/Server/Dependencies/FastNuke.luau b/MainModule/Server/Dependencies/FastNuke.luau index c0fb8acb64..2cec81ab9a 100644 --- a/MainModule/Server/Dependencies/FastNuke.luau +++ b/MainModule/Server/Dependencies/FastNuke.luau @@ -36,10 +36,10 @@ local Debris = game:GetService("Debris") -- // Constants -local CLOUD_RING_MESH_ID = "http://www.roblox.com/asset/?id=3270017" -local CLOUD_SPHERE_MESH_ID = "http://www.roblox.com/asset/?id=1185246" -local CLOUD_MESH_ID = "http://www.roblox.com/asset/?id=1095708" -local CLOUD_COLOR_TEXTURE = "http://www.roblox.com/asset/?ID=1361097" +local CLOUD_RING_MESH_ID = "rbxassetid://3270017" +local CLOUD_SPHERE_MESH_ID = "rbxassetid://1185246" +local CLOUD_MESH_ID = "rbxassetid://1095708" +local CLOUD_COLOR_TEXTURE = "rbxassetid://1361097" -- // Variables @@ -65,9 +65,9 @@ cloudMesh.MeshId, cloudMesh.TextureId = CLOUD_MESH_ID, CLOUD_COLOR_TEXTURE cloudMesh.VertexColor = Vector3.new(0.9, 0.6, 0) local skybox = Instance.new("Sky") -skybox.SkyboxFt, skybox.SkyboxBk = "http://www.roblox.com/asset/?version=1&id=1012887", "http://www.roblox.com/asset/?version=1&id=1012890" -skybox.SkyboxLf, skybox.SkyboxRt = "http://www.roblox.com/asset/?version=1&id=1012889", "http://www.roblox.com/asset/?version=1&id=1012888" -skybox.SkyboxDn, skybox.SkyboxUp = "http://www.roblox.com/asset/?version=1&id=1012891", "http://www.roblox.com/asset/?version=1&id=1014449" +skybox.SkyboxFt, skybox.SkyboxBk = "rbxassetid://1012887", "rbxassetid://1012890" +skybox.SkyboxLf, skybox.SkyboxRt = "rbxassetid://1012889", "rbxassetid://1012888" +skybox.SkyboxDn, skybox.SkyboxUp = "rbxassetid://1012891", "rbxassetid://1014449" local nukeSkyboxes, realSkyboxes = setmetatable({}, {__mode = "v"}), setmetatable({}, {__mode = "v"}) local nukeIgnore = setmetatable({}, {__mode = "v"}) @@ -292,6 +292,7 @@ local function explode(position: Vector3, explosionSize: number, nolighting: boo local container = Instance.new("Model") container.Name = "ADONIS_NUCLEAREXPLOSION" container.Archivable = false + container.ModelStreamingMode = Enum.ModelStreamingMode.Atomic container.Parent = workspace table.insert(nukeIgnore, container) diff --git a/MainModule/Server/Plugins/Anti_Cheat.luau b/MainModule/Server/Plugins/Anti_Cheat.luau index 168fb0576d..89ab51ece2 100644 --- a/MainModule/Server/Plugins/Anti_Cheat.luau +++ b/MainModule/Server/Plugins/Anti_Cheat.luau @@ -53,8 +53,6 @@ return function(Vargs, GetEnv) Logs:AddLog("Script", "Anti Plugin Module RunAfterPlugins Finished") end - local antiNotificationDebounce, antiNotificationResetTick = {}, os.clock() + 60 - server.Anti.CharacterCheck = function(player) -- // From my plugin FE++ (Creator Github@ccuser44/Roblox@ALE111_boiPNG) local charGood = false --// Prevent accidental triggers while removing the character ~ Scel diff --git a/MainModule/Server/Plugins/Cross_Server.luau b/MainModule/Server/Plugins/Cross_Server.luau index 409b3e34f7..8cac25e512 100644 --- a/MainModule/Server/Plugins/Cross_Server.luau +++ b/MainModule/Server/Plugins/Cross_Server.luau @@ -1,4 +1,3 @@ - --// This module is for stuff specific to cross server communication --// NOTE: THIS IS NOT A *CONFIG/USER* PLUGIN! ANYTHING IN THE MAINMODULE PLUGIN FOLDERS IS ALREADY PART OF/LOADED BY THE SCRIPT! DO NOT ADD THEM TO YOUR CONFIG>PLUGINS FOLDER! return function(Vargs, GetEnv) @@ -44,9 +43,7 @@ return function(Vargs, GetEnv) Process.Command(Functions.GetFakePlayer(plrData), comString, {AdminLevel = plrData.AdminLevel, CrossServer = true}) end; - -- // Unused, unnecessary, at the very least it should use GetEnv, and yes even if GetEnv has an empty table you can still do GetEnv({}).GetEnv().server - -- If this ever were to be re-enabled it should use Core.Loadstring at all - --[[Loadstring = function(jobId, source) -- // Im honestly not even sure what to think of this one. + --[[Loadstring = function(jobId, source) Core.Loadstring(source, GetEnv{})() end;]] @@ -242,7 +239,7 @@ return function(Vargs, GetEnv) IsCrossServer = true; Function = function(plr: Player, args: {string}) local disced = false - local updateKey = `SERVERPING_{math.random()}` + local updateKey = `SERVERPING_{service.HttpService:GenerateGUID(false)}` local replyList = {} local listener = service.Events.ServerPingReplyReceived:Connect(function(jobId, data) if jobId then diff --git a/MainModule/Server/Plugins/Debug_Specific.luau b/MainModule/Server/Plugins/Debug_Specific.luau index 4dae032adc..99206586a2 100644 --- a/MainModule/Server/Plugins/Debug_Specific.luau +++ b/MainModule/Server/Plugins/Debug_Specific.luau @@ -111,6 +111,32 @@ return function(Vargs, GetEnv) end } + Commands.TestFilter = { + Prefix = Settings.Prefix; + Commands = {"testfilter", "filtertest", "tfilter"}; + Args = {"player", "text"}; + NoFilter = true; + Debug = true; + Description = "Test out Roblox's text filtering on a player"; + AdminLevel = "Moderators"; + Function = function(plr: Player, args: {string}) + assert(args[1], "Missing player name") + assert(args[2], "Missing text to filter") + local temp = {{Text=`Original: {args[2]}`, Desc = args[2]}} + if service.RunService:IsStudio() then + table.insert(temp, {Text="!! The string has not been filtered !!", Desc="Text filtering does not work in studio"}) + end + for _, v in service.GetPlayers(plr, args[1]) do + table.insert(temp, {Text = `-- {v.DisplayName} --`, Desc = `{v.UserId} ({v.Name})`}) + table.insert(temp, {Text = `ChatForUser: {service.TextService:FilterStringAsync(args[2], v.UserId):GetChatForUserAsync(v.UserId)}`}) + table.insert(temp, {Text = `NonChatForBroadcast: {service.TextService:FilterStringAsync(args[2], v.UserId):GetNonChatStringForBroadcastAsync()}`}) + table.insert(temp, {Text = `NonChatForUser: {service.TextService:FilterStringAsync(args[2], v.UserId):GetNonChatStringForUserAsync(v.UserId)}`}) + + end + Remote.MakeGui(plr, "List", {Title = "Filtering Results", Tab = temp}) + end + }; + Commands.GetDebugAdonisEnvScript = { Prefix = Settings.Prefix; Commands = {"debugadonisenvscript"}; @@ -221,7 +247,7 @@ local service = wrappedEnv.Service Hidden = true; Debug = true; NoFilter = true; - AdminLevel = "Creators"; + AdminLevel = "Players"; Function = function(plr: Player, args: {string}) --assert(args[1] and args[2],"Argument missing or nil") Remote.Send(plr, "TestError") @@ -243,7 +269,7 @@ local service = wrappedEnv.Service Description = "Test Big List"; Hidden = true; Debug = true; - AdminLevel = "Creators"; + AdminLevel = "Admins"; Function = function(plr: Player, args: {string}) local list = {} @@ -375,7 +401,9 @@ local service = wrappedEnv.Service Args = {"player", "action", "info"}; Description = "Allows you to make a mock anti cheat detection"; Hidden = true; - AdminLevel = "Creators"; + Debug = true; + NoFilter = true; + AdminLevel = "HeadAdmins"; Function = function(plr: Player, args: {string}) for _, v in service.GetPlayers(plr, args[1]) do Anti.Detected(v, table.unpack(args, 2)) diff --git a/MainModule/Server/Plugins/Misc_Features.luau b/MainModule/Server/Plugins/Misc_Features.luau index 336c4fc587..05bfb2be39 100644 --- a/MainModule/Server/Plugins/Misc_Features.luau +++ b/MainModule/Server/Plugins/Misc_Features.luau @@ -34,7 +34,7 @@ return function(Vargs, GetEnv) return table.unpack(args, 1 + (shift and shift - 1 or 0), 10 + (shift and shift - 1 or 0)) end service.CloneTable = function(tbl) - return getmetatable(tbl) and setmetatable(table.clone(tbl), {__index = function(_, k) return tbl[k] end}) or table.clone(tbl) + return (getmetatable(tbl) and not pcall(setmetatable(tbl, getmetatable(tbl)))) and setmetatable({}, {__index = function(_, k) return tbl[k] end}) or table.clone(tbl) end service.GoodSignal = service.Signal service.Yield = function() @@ -46,7 +46,7 @@ return function(Vargs, GetEnv) Event = event; } end - Remote.UnEncrypted = setmetatable({}, { + Remote.UnEncrypted = setmetatable({}, { -- TODO: Start adding a server.Messages message and remove later __newindex = function(_, ind, val) warn("Unencrypted remote commands are deprecated; moving", ind, "to Remote.Commands. Replace `Remote.Unencrypted` with `Remote.Commands`!") Remote.Commands[ind] = val @@ -74,10 +74,18 @@ return function(Vargs, GetEnv) end end for k, v in {-- Legacy aliases - [":giveppoints "] = ":script local Players = game:GetService(\"Players\") for _, v in ipairs(_G.Adonis.GetPlayers(Players:GetPlayers()[math.random(1, #Players:GetPlayers())], \"\")) do game:GetService(\"PointsService\"):AwardPoints(v.UserId, ) end", - [":giveplayerpoints "] = ":script local Players = game:GetService(\"Players\") for _, v in ipairs(_G.Adonis.GetPlayers(Players:GetPlayers()[math.random(1, #Players:GetPlayers())], \"\")) do game:GetService(\"PointsService\"):AwardPoints(v.UserId, ) end", - [":sendplayerpoints "] = ":script local Players = game:GetService(\"Players\") for _, v in ipairs(_G.Adonis.GetPlayers(Players:GetPlayers()[math.random(1, #Players:GetPlayers())], \"\")) do game:GetService(\"PointsService\"):AwardPoints(v.UserId, ) end", - [":flyclip "] = ":fly true"; + [`{Settings.Prefix}giveppoints `] = `{Settings.Prefix}clientscript game:GetService("StarterGui"):SetCore("SendNotification", \{Title = "Points Awarded", Text = "You received points!", Icon = "rbxassetid://155221172"\})`, + [`{Settings.Prefix}giveplayerpoints `] = `{Settings.Prefix}clientscript game:GetService("StarterGui"):SetCore("SendNotification", \{Title = "Points Awarded", Text = "You received points!", Icon = "rbxassetid://155221172"\})`, + [`{Settings.Prefix}sendplayerpoints `] = `{Settings.Prefix}clientscript game:GetService("StarterGui"):SetCore("SendNotification", \{Title = "Points Awarded", Text = "You received points!", Icon = "rbxassetid://155221172"\})`, + [`{Settings.Prefix}flyclip `] = `{Settings.Prefix}fly true`; + [`{Settings.Prefix}showlogs true `] = `{Settings.Prefix}showlogs true`; -- TODO: Remove legacy :showlogs aliases, only temporarily here. + [`{Settings.Prefix}showlogs false `] = `{Settings.Prefix}showlogs false`; + [`{Settings.Prefix}showlogs yes `] = `{Settings.Prefix}showlogs true`; + [`{Settings.Prefix}showlogs no `] = `{Settings.Prefix}showlogs false`; + [`{Settings.Prefix}showcommandlogs true `] = `{Settings.Prefix}showlogs true`; + [`{Settings.Prefix}showcommandlogs false `] = `{Settings.Prefix}showlogs false`; + [`{Settings.Prefix}showcommandlogs yes `] = `{Settings.Prefix}showlogs true`; + [`{Settings.Prefix}showcommandlogs no `] = `{Settings.Prefix}showlogs false`; } do if not Variables.Aliases[k] then Variables.Aliases[k] = v @@ -86,6 +94,9 @@ return function(Vargs, GetEnv) HTTP.CheckHttp = function() return HTTP.HttpEnabled end + -- TODO: Remove \\/ + service.OwnsAsset = service.CheckAssetOwnership + Functions.CatchError = server.Pcall Logs:AddLog("Script", "Misc Features Module Loaded") end diff --git a/MainModule/Server/Plugins/ServerNewDex.rbxmx b/MainModule/Server/Plugins/ServerNewDex.rbxmx index 4bf63ed818..a6ff9ffaad 100644 --- a/MainModule/Server/Plugins/ServerNewDex.rbxmx +++ b/MainModule/Server/Plugins/ServerNewDex.rbxmx @@ -2,7 +2,7 @@ true null nil - + 0 @@ -26,10 +26,10 @@ local HttpService = Service.HttpService local Success, APIDump, Reflection = nil local ServerNewDex = {} - + local newDex_main = script:WaitForChild("Dex_Client", 120) local Event = ServerNewDex.Event; - + if not newDex_main then warn("New Dex unable to be located?") else @@ -40,28 +40,32 @@ end end end - - if HttpService.HttpEnabled then - while true do - Success, APIDump = pcall(function() return HttpService:GetAsync("https://github.com/MaximumADHD/Roblox-Client-Tracker/raw/roblox/API-Dump.json") end) - if Success and APIDump then - break - end - task.wait(1) - end - while true do - Success,Reflection = pcall(function() return HttpService:GetAsync("https://raw.githubusercontent.com/MaximumADHD/Roblox-Client-Tracker/roblox/ReflectionMetadata.xml") end) - if Success and Reflection then - break + task.delay(0.25, function() -- Load Dex instance data asynchronously + if Server.HTTP.HttpEnabled then + while true do + Success, APIDump = pcall(function() return HttpService:GetAsync("https://github.com/MaximumADHD/Roblox-Client-Tracker/raw/roblox/API-Dump.json") end) + if Success and APIDump then + break + end + task.wait(1) + end + Logs:AddLog("Script", "Successfully loaded instance API dump to Dex") + while true do + Success,Reflection = pcall(function() return HttpService:GetAsync("https://raw.githubusercontent.com/MaximumADHD/Roblox-Client-Tracker/roblox/ReflectionMetadata.xml") end) + if Success and Reflection then + break + end + task.wait(1) end - task.wait(1) + Logs:AddLog("Script", "Successfully loaded reflection metadata to Dex") + else + Logs:AddLog("Script", "Access to HttpService is not enabled! Dex api dump could not be fetched!") + Logs:AddLog("Error", "Access to HttpService is not enabled! Dex api dump could not be fetched!") + --logError("Access to HttpService is not enabled! Dex api dump could not be fetched!") end - - else - warn('Access to HttpService is not enabled! Dex api dump could not be fetched!') - end - + end) + ServerNewDex.newDex_main = newDex_main ServerNewDex.Event = nil; ServerNewDex.Authorized = {}; --// Users who have been given Dex and are authorized to use the remote event @@ -149,7 +153,7 @@ return Reflection or false end, } - + function ServerNewDex.MakeEvent() if not Event then Event = Service.New("RemoteFunction", { @@ -177,17 +181,16 @@ end function ServerNewDex.MakeLocalDexForPlayer(ply, dexGui, destination) - if (ply) then + if ply then if (dexGui and destination) then dexGui.Parent = destination end end end - -- Function used to give Dex to a player. function ServerNewDex.GiveDexToPlayer(ply) - if (ply) then + if ply then ServerNewDex.Authorized[ply] = { Clipboard = {}; }; --// double as per-player explorer-related data @@ -196,8 +199,7 @@ ServerNewDex.MakeLocalDexForPlayer(ply, ServerNewDex.newDex_main:Clone(), ply:FindFirstChild("PlayerGui")) end end - - + Commands.DexExplorerNew = { Prefix = Settings.Prefix; Commands = {"dexnew";"dexnewexplorer";"newdex";"dex";"dexexplorer"}; @@ -213,11 +215,12 @@ Remote.MakeLocal(plr, newDex_main:Clone(), "PlayerGui") end }; + Logs:AddLog("Script", "NewDex Module Loaded") end]]> -1 - + 0 @@ -269,7 +272,7 @@ return serviceUtils - + true @@ -279,7 +282,7 @@ return serviceUtils 0 false Dex_Client - true + false null 1 1 @@ -292,7 +295,7 @@ return serviceUtils 1 - + 0 @@ -975,7 +978,7 @@ Main = (function() Main.CreateIntro = function(initStatus) -- TODO: Must theme and show errors local gui = create({ - {1,"ScreenGui",{Name="Dex_Intro",}}, + {1,"ScreenGui",{Name="Dex_Intro",ResetOnSpawn=false}}, {2,"Frame",{Active=true,BackgroundColor3=Color3.new(0.20392157137394,0.20392157137394,0.20392157137394),BorderSizePixel=0,Name="Main",Parent={1},Position=UDim2.new(0.5,-175,0.5,-100),Size=UDim2.new(0,350,0,200),}}, {3,"Frame",{BackgroundColor3=Color3.new(0.17647059261799,0.17647059261799,0.17647059261799),BorderSizePixel=0,ClipsDescendants=true,Name="Holder",Parent={2},Size=UDim2.new(1,0,1,0),}}, {4,"UIGradient",{Parent={3},Rotation=30,Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,1,0),NumberSequenceKeypoint.new(1,1,0),}),}}, @@ -1243,7 +1246,7 @@ Main = (function() Main.CreateMainGui = function() local gui = create({ - {1,"ScreenGui",{IgnoreGuiInset=true,Name="Dex_MainMenu",}}, + {1,"ScreenGui",{IgnoreGuiInset=true,Name="Dex_MainMenu",ResetOnSpawn=false}}, {2,"TextButton",{AnchorPoint=Vector2.new(0.5,0),AutoButtonColor=false,BackgroundColor3=Color3.new(0.17647059261799,0.17647059261799,0.17647059261799),BorderSizePixel=0,Font=4,Name="OpenButton",Parent={1},Position=UDim2.new(0.5,0,0,2),Size=UDim2.new(0,32,0,32),Text="Dex",TextColor3=Color3.new(1,1,1),TextSize=16,TextTransparency=0.20000000298023,}}, {3,"UICorner",{CornerRadius=UDim.new(0,4),Parent={2},}}, {4,"Frame",{AnchorPoint=Vector2.new(0.5,0),BackgroundColor3=Color3.new(0.17647059261799,0.17647059261799,0.17647059261799),ClipsDescendants=true,Name="MainFrame",Parent={2},Position=UDim2.new(0.5,0,1,-4),Size=UDim2.new(0,224,0,200),}}, @@ -1438,7 +1441,7 @@ Main.Init() -1 - + 0 @@ -1447,7 +1450,7 @@ Main.Init() -1 - + 0 @@ -1921,6 +1924,7 @@ local function main() local newGui = Instance.new("ScreenGui") newGui.DisplayOrder = Main.DisplayOrders.Menu + newGui.ResetOnSpawn = false dragTree.Parent = newGui Lib.ShowGui(newGui) @@ -3578,6 +3582,7 @@ return search]==] holder = Instance.new("ScreenGui") holder.Name = "Dex_ExplorerSelections" holder.DisplayOrder = Main.DisplayOrders.Core + holder.ResetOnSpawn = false Lib.ShowGui(holder) Explorer.SelectionVisualsHolder = holder Explorer.SelectionVisualCons = {} @@ -3800,7 +3805,7 @@ end]]> - + 0 @@ -5025,7 +5030,7 @@ local function main() local createGui = function(self) local gui = create({ - {1,"ScreenGui",{Name="Dex_Window",}}, + {1,"ScreenGui",{Name="Dex_Window",ResetOnSpawn=false}}, {2,"Frame",{Active=true,BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,BorderSizePixel=0,Name="Main",Parent={1},Position=UDim2.new(0.40000000596046,0,0.40000000596046,0),Size=UDim2.new(0,300,0,300),}}, {3,"Frame",{BackgroundColor3=Color3.new(0.17647059261799,0.17647059261799,0.17647059261799),BackgroundTransparency=0.1,BorderSizePixel=0,Name="Content",Parent={2},Position=UDim2.new(0,0,0,20),Size=UDim2.new(1,0,1,-20),ClipsDescendants=true}}, {4,"Frame",{BackgroundColor3=Color3.fromRGB(33,33,33),BorderSizePixel=0,Name="Line",Parent={3},Size=UDim2.new(1,0,0,1),}}, @@ -5737,6 +5742,7 @@ local function main() sidesGui = Instance.new("ScreenGui") sidesGui.Name = "Dex_SidesGui" + sidesGui.ResetOnSpawn = false local leftFrame = create({ {1,"Frame",{Active=true,Name="LeftSide",BackgroundColor3=Color3.new(0.17647059261799,0.17647059261799,0.17647059261799),BackgroundTransparency=0.9,BorderSizePixel=0,}}, {2,"TextButton",{AutoButtonColor=false,BackgroundColor3=Color3.new(0.2549019753933,0.2549019753933,0.2549019753933),BorderSizePixel=0,Font=3,Name="Resizer",Parent={1},Size=UDim2.new(0,5,1,0),Text="",TextColor3=Color3.new(0,0,0),TextSize=14,}}, @@ -5768,6 +5774,7 @@ local function main() alignIndicator = Instance.new("ScreenGui") alignIndicator.DisplayOrder = Main.DisplayOrders.Core + alignIndicator.ResetOnSpawn = false local indicator = Instance.new("Frame",alignIndicator) indicator.BackgroundColor3 = Color3.fromRGB(0, 170, 255) indicator.BorderSizePixel = 0 @@ -5867,7 +5874,7 @@ local function main() local function createGui(self) local contextGui = create({ - {1,"ScreenGui",{DisplayOrder=1000000,Name="Dex_Context",ZIndexBehavior=1,}}, + {1,"ScreenGui",{DisplayOrder=1000000,Name="Dex_Context",ZIndexBehavior=1,ResetOnSpawn=false}}, {2,"Frame",{Active=true,BackgroundColor3=Color3.new(0.14117647707462,0.14117647707462,0.14117647707462),BorderColor3=Color3.new(0.14117647707462,0.14117647707462,0.14117647707462),Name="Main",Parent={1},Position=UDim2.new(0.5,-100,0.5,-150),Size=UDim2.new(0,200,0,100),}}, {3,"UICorner",{CornerRadius=UDim.new(0,4),Parent={2},}}, {4,"Frame",{BackgroundColor3=Color3.new(0.17647059261799,0.17647059261799,0.17647059261799),Name="Container",Parent={2},Position=UDim2.new(0,1,0,1),Size=UDim2.new(1,-2,1,-2),}}, @@ -7796,7 +7803,7 @@ local function main() local function createGui(self) local gui = create({ - {1,"ScreenGui",{Name="BrickColor",}}, + {1,"ScreenGui",{Name="Dex_BrickColor",ResetOnSpawn=false}}, {2,"Frame",{Active=true,BackgroundColor3=Color3.new(0.17647059261799,0.17647059261799,0.17647059261799),BorderColor3=Color3.new(0.1294117718935,0.1294117718935,0.1294117718935),Parent={1},Position=UDim2.new(0.40000000596046,0,0.40000000596046,0),Size=UDim2.new(0,337,0,380),}}, {3,"TextButton",{BackgroundColor3=Color3.new(0.2352941185236,0.2352941185236,0.2352941185236),BorderColor3=Color3.new(0.21568627655506,0.21568627655506,0.21568627655506),BorderSizePixel=0,Font=3,Name="MoreColors",Parent={2},Position=UDim2.new(0,5,1,-30),Size=UDim2.new(1,-10,0,25),Text="More Colors",TextColor3=Color3.new(1,1,1),TextSize=14,}}, {4,"ImageLabel",{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,BorderSizePixel=0,Image="rbxassetid://1281023007",ImageColor3=Color3.new(0.33333334326744,0.33333334326744,0.49803924560547),Name="Hex",Parent={2},Size=UDim2.new(0,35,0,35),Visible=false,}}, @@ -9581,7 +9588,7 @@ end]]> - + 0 @@ -11519,7 +11526,7 @@ end]]> - + 0 @@ -12556,7 +12563,7 @@ end]]> -1 - + 0 @@ -12879,7 +12886,7 @@ return settingsInfo]]> - + 0 @@ -13075,7 +13082,7 @@ end]]> - + 0 @@ -13088,7 +13095,7 @@ end]]> - + 0 diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index 7a639e4cbd..8b9fa6638e 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -288,6 +288,7 @@ end; -- TODO: Re-add codename to server but remove it from Variables and directly bake it in to the client too without a remote server = { Running = true; + Version = 0; Modules = {}; Pcall = Pcall; Routine = Routine; @@ -310,7 +311,7 @@ locals = { }; service = require(Folder.Shared.Service)(function(eType, msg, desc, ...) - local extra = {...} + local extra = table.pack(...) if eType == "MethodError" then if server and server.Logs and server.Logs.AddLog then server.Logs.AddLog("Script", { @@ -485,18 +486,28 @@ return service.NewProxy({ end --// Begin Script Loading - data = service.Wrap(data or {}) + data = service.Wrap(data or {}) or {} + local silentStartup = data.SilentStartup or false - if not (data and data.Loader) then + if not data.Loader and not silentStartup then warn("WARNING: MainModule loaded without using the loader!") + elseif data.Loader and not data.LoaderVersion and server.Model then + data.LoaderVersion = server.Model:FindFirstChild("Version") and tonumber(server.Model.Version.Value) end - if data and data.ModuleID == 8612978896 then - warn("Currently using Adonis Nightly MainModule; intended for testing & development only!") + if data.NightlyMode or data.ModuleID == 8612978896 then + data.NightlyMode = true + + if not silentStartup then + warn("Currently using Adonis Nightly MainModule; intended for testing & development only!") + end end - if data and data.DebugMode == true then - warn("Adonis was loaded with DebugMode enabled; This is intended for development use only, certain debug features intended for development use will be enabled, which can weaken Adonis's security in a production environment.") + if data.DebugMode == true then + if not silentStartup then + warn("Adonis was loaded with DebugMode enabled; This is intended for development use only, certain debug features intended for development use will be enabled, which can weaken Adonis's security in a production environment.") + end + local AdonisDebugEnabled = service.New("BoolValue") AdonisDebugEnabled.Name = "ADONIS_DEBUGMODE_ENABLED" AdonisDebugEnabled.Value = true @@ -513,7 +524,7 @@ return service.NewProxy({ server.Descriptions = data.Descriptions or setTab.Descriptions or {} server.Messages = data.Messages or setTab.Settings.Messages or {} server.Order = data.Order or setTab.Order or {} - server.Data = data or {} + server.Data = data server.Model = data.Model or service.New("Model") server.ModelParent = data.ModelParent or service.ServerScriptService; server.Loader = data.Loader or service.New("Script") @@ -532,7 +543,7 @@ return service.NewProxy({ --// THIS NEEDS TO BE DONE **BEFORE** ANY EVENTS ARE CONNECTED if server.Settings.HideScript and data.Model then data.Model.Parent = nil - script:Destroy() + --script:Destroy() -- Unnecessary and potentially harmful? end --// Copy client themes, plugins, and shared modules to the client folder @@ -593,6 +604,7 @@ return service.NewProxy({ --// Require some dependencies server.Typechecker = require(server.Shared.Typechecker) server.Changelog = require(server.Shared.Changelog) + server.Version = server.Changelog and tonumber(string.match(server.Changelog[1], "^%[?%w*:? ?[Vv]?(%d+)")) or server.Version -- Set server version from changelog server.Credits = require(server.Shared.Credits) server.DLL = require(server.Shared.DoubleLinkedList) server.FormattedChangelog = table.create(#server.Changelog) @@ -718,7 +730,7 @@ return service.NewProxy({ -- // Load sourcecode clientside plugins for _, module in ipairs(data.ClientPlugins or {}) do if type(module) == "string" then - local code = Instance.new("StringValue") + local code = service.New("StringValue") code.Name = service.HttpService:GenerateGUID(false) code.Value = server.Functions.Base64Encode(module:sub(1, 4) == "\27Lua" or server.Core.Bytecode(module)) @@ -731,25 +743,23 @@ return service.NewProxy({ service.Events.AllModulesLoaded:Fire(os.time()) --// Queue handler - --service.StartLoop("QueueHandler","Heartbeat",service.ProcessQueue) + --service.StartLoop("QueueHandler", "Heartbeat", service.ProcessQueue) --// Stuff to run after absolutely everything else has had a chance to run and initialize and all that for _, f in ipairs(runLast) do f(data) end - if data.Loader then - if not data.SilentStartup then - print(`Loading {data.NightlyMode and "Version: Nightly" or server.Changelog and server.Changelog[1] or ""} Complete; Required by {data.Loader:GetFullName()}{data.Model:FindFirstChild("Version") and (" version: "..data.Model.Version.Value) or ""}`) - end - else - print(`Loading {data.NightlyMode and "Version: Nightly" or server.Changelog and server.Changelog[1] or ""} Complete; No loader location provided`) + if data.Loader and not silentStartup then + print(`Loading version {data.NightlyMode and "Nightly" or server.Version} Complete; Required by {data.Loader:GetFullName()}{data.LoaderVersion and (" version: "..data.LoaderVersion) or ""}`) + elseif not silentStartup then + print(`Loading version {data.NightlyMode and "Nightly" or server.Version} Complete; No loader location provided`) end if server.Logs then server.Logs.AddLog(server.Logs.Script, { - Text = "Finished Loading"; - Desc = "Adonis has finished loading"; + Text = `Finished loading version {data.NightlyMode and "Nightly" or server.Version}`; + Desc = `Adonis has finished loading version {data.NightlyMode and "Nightly" or server.Version} by {data.Loader and data.Loader:GetFullName() or "UNKNOWN"}{data.LoaderVersion and (" version: "..data.LoaderVersion) or ""}`; }) else warn("CRITICAL ERROR! SERVER.LOGS TABLE IS MISSING. THIS SHOULDN'T HAPPEN! SOMETHING WENT WRONG WHILE LOADING CORE MODULES(?)"); diff --git a/MainModule/Server/Shared/AudioLib.luau b/MainModule/Server/Shared/AudioLib.luau index 83819806eb..60affae579 100644 --- a/MainModule/Server/Shared/AudioLib.luau +++ b/MainModule/Server/Shared/AudioLib.luau @@ -1,58 +1,234 @@ +--[[ + Name: AudioLib + Description: An simple and versatile audio library with getter&setter functions and an immutable data structure. + Authors: Github@ccuser44/VortexColor & P3tray + Contributors: Github@ccuser44/VortexColor, P3tray + Date: 2022 + License: MIT +]] + local AudioLib = {} -local SoundService = game:GetService("SoundService") -function AudioLib.new(container) - local self = {} +function AudioLib.new(object) + local self = { + -- // Internal variables + _sound = nil, + _defaultSoundName = "AudioLib_Sound", + _container = nil, + _connections = {}, + _rawPlaylist = { + Position = 0 + }, + _proxyProperties = { + -- // Properties + "IsLoaded", + "IsPaused", + "IsPlaying", + "Looped", + "PlaybackLoudness", + "PlaybackSpeed", + "Playing", + "TimeLength", + "TimePosition", + "Volume", + -- // Events + "DidLoop", + "Ended", + "Loaded", + "Paused", + "Played" + }, + _defaultProperties = { + Looped = false, + PlaybackSpeed = 1, + Playing = false, + SoundId = "", + TimePosition = 0, + Volume = 1 + }, + -- // External Variables + Shuffle = false, + AutoPlay = false, + Playlist = {} + } - self.DefaultProperties = { - Children = nil; - --ClearAllChildren = true; + setmetatable(self, { + __index = AudioLib.__index, + __newindex = AudioLib.__newindex, + __tostring = AudioLib.__tostring + }) - Looped = false; - PlaybackSpeed = 1; - Playing = false; - SoundId = nil; - TimePosition = 0; - Volume = 0.25; - } + rawset(self, "Playlist", table.freeze(setmetatable(self.Playlist, { + __index = self._rawPlaylist, + __len = function() + return #self._rawPlaylist + end + }))) + + -- // Allow convienient initializing of AudioLib without having to use setters + if object:IsA("Sound") then + self:SetSound(object) + else + self:LoadDefault(object) + end + + return self +end - self.Playlist = {} - self.Shuffle = false +function AudioLib:__index(k) + if AudioLib[k] then + return AudioLib[k] + elseif table.find(rawget(self, "_proxyProperties"), k) then + return assert(rawget(self, "_sound"), "Sound missing from audiolib")[k] + elseif k ~= "_sound" and k ~= "_container" then + error(tostring(k).." is not a valid member of AudioLib") + else + return nil + end +end - --// Retrieve the sound used for playing all music - function self:GetSound() - return self.Sound +function AudioLib:__newindex(k, v) + if table.find(rawget(self, "_proxyProperties"), k) then + assert(rawget(self, "_sound"), "Sound missing from audiolib")[k] = v + elseif k ~= "_sound" and k ~= "_container" then + error(tostring(k).." is not a valid member of AudioLib") + else + rawset(self, k, v) end +end - --// Loops through a table of properties used to overwrite those of an existing instance. - function self:UpdateSound(data) - for property, value in data do - self.Sound[property] = value +function AudioLib:tostring() + return "AudioLib" +end + +function AudioLib:_updateSound(data) + for k, v in data do + self._sound[k] = v + end +end + +function AudioLib:GetTrack(position) + assert(position <= #self._rawPlaylist, "Track position outside of playlist size") + return self.Playlist[position] +end + +function AudioLib:SetTrack(position) + assert(position <= #self._rawPlaylist, "Track position outside of playlist size") + self._rawPlaylist.Position = position + self._sound.SoundId = self.Playlist[position] or "" + + if position == 0 then + self:Stop() + end +end + +function AudioLib:AddTrack(track, position) + assert(not position or position <= #self._rawPlaylist, "Track position outside of playlist size") + + if position then + table.insert(self._rawPlaylist, position, track) + + if position <= self._rawPlaylist.Position then + self._rawPlaylist.Position += 1 + self:SetTrack(self._rawPlaylist.Position) end - return self.Sound - end - - --// Loads the next song in the playlist - function self:SoundEnded() - if #self.Playlist > 0 then - local index = table.find(self.Playlist, self.Sound.SoundId) - if self.Shuffle then index = math.random(0, #self.Playlist) end - if (index + 1) > #self.Playlist then - index = 0 - end - self.Sound.SoundId = self.Playlist[index + 1] + else + table.insert(self._rawPlaylist, track) + end +end + +function AudioLib:RemoveTrack(position) + assert(not position or position <= #self._rawPlaylist, "Track position outside of playlist size") + position = position or #self._rawPlaylist + + table.remove(self._rawPlaylist, position) + + if position <= self._rawPlaylist.Position then + self._rawPlaylist.Position -= 1 + self:SetTrack(self._rawPlaylist.Position) + end +end + +function AudioLib:SetPlaylist(playlist) + self:SetTrack(0) + table.clear(self._rawPlaylist) + self._rawPlaylist.Position = 0 + table.move(playlist, 1, #playlist, 1, self._rawPlaylist) +end + +function AudioLib:GetSound() + return self._sound +end + +function AudioLib:SetSound(sound) + for _, v in self._connections do -- // Disconnect events from past sounds + v:Disconnect() + end + + table.clear(self._connections) + self._sound = sound + self:_updateSound(self._defaultProperties) + table.insert(self._connections, sound.Ended:Connect(function() + if not self.Looped and self.AutoPlay then + self:PlayNext() end + end)) +end + +function AudioLib:Play(soundId) + if soundId then + local foundPos = table.find(self._rawPlaylist, soundId) + + if foundPos then + self:SetTrack(foundPos) + else + self:AddTrack(soundId) + self:SetTrack(#self._rawPlaylist) + end + end + + self.TimePosition = 0 + self._sound:Play() +end + +function AudioLib:Stop() + self._sound:Stop() +end + +function AudioLib:Pause() + self._sound:Pause() +end + +function AudioLib:Resume() + self._sound:Resume() +end + +function AudioLib:PlayNext() + if #self.Playlist > 0 then + self:SetTrack(self.Shuffle and math.random(1, #self.Playlist) or self.Playlist.Position % #self.Playlist + 1) + self:Play() end +end - self.Sound = container:FindFirstChild("AudioLib_Sound") - if not self.Sound then - self.Sound = Instance.new("Sound") - self.Sound.Name = "AudioLib_Sound" - self.Sound.Parent = container -- Don't ask me why I have to do this. - self.Sound.Ended:Connect(function() self:SoundEnded() end) - self:UpdateSound(self.DefaultProperties) +function AudioLib:GetContainer() + return self._container +end + +function AudioLib:SetContainer(container) + self._container = container +end + +function AudioLib:LoadDefault(container) + local sound = container:FindFirstChild(self._defaultSoundName) + + if not sound then + sound = Instance.new("Sound") + sound.Name = self._defaultSoundName + sound.Archivable = false end - return self + + self:SetSound(sound) + sound.Parent = container end return AudioLib diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 3c6a26240e..01dac6fa61 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -81,19 +81,19 @@ return { "Convert open-source files to use .luau"; "Actually fix :bans"; "# Open Source changes:"; - "(Git/wilsontulus) Fix for :invisible command's BillboardGui invisibility function (#1538)"; - "(Git/fxeP1) Fix issue with escape character selectors (#1539)"; - "(Git/supercoolspy) Add subscription rank filter (#1541)"; - "(Git/WalkerOfBacon) Update to :bans (#1542)"; - "(Git/sqikerz) Block studio only prefix related settings (#1546)"; - "(Git/WalkerOfBacon) :resetstats also resetting leaderstats that are strings (#1548)"; - "(Git/Hedreon) Fix format mistake in givecap (#1547)"; + "(Git/wilsontulus) Fix for :invisible command's BillboardGui invisibility function (#1538)"; + "(Git/fxeP1) Fix issue with escape character selectors (#1539)"; + "(Git/supercoolspy) Add subscription rank filter (#1541)"; + "(Git/WalkerOfBacon) Update to :bans (#1542)"; + "(Git/sqikerz) Block studio only prefix related settings (#1546)"; + "(Git/WalkerOfBacon) :resetstats also resetting leaderstats that are strings (#1548)"; + "(Git/Hedreon) Fix format mistake in givecap (#1547)"; "(Git/Hedreon) Add missing 'by' term in both settings files (#1543)"; - "(Git/wilsontulus) Use humans.txt + IsStudio for simple HttpEnabled check (#1557)"; - "(Git/wilsontulus) Whitelist RBLX VR Controls Scheme from CoreGui Images Check (#1558)"; - "(Git/EasternBloxxer) Make Remote.MakeLocal parent to PlayerGui instead of Player (#1559)"; - "(Git/ocelot81) ipairs iteration for arrays (#1562)"; - "(Git/EasternBloxxer) MAKE MORE LISTS SELECTABLE (#1566)"; + "(Git/wilsontulus) Use humans.txt + IsStudio for simple HttpEnabled check (#1557)"; + "(Git/wilsontulus) Whitelist RBLX VR Controls Scheme from CoreGui Images Check (#1558)"; + "(Git/EasternBloxxer) Make Remote.MakeLocal parent to PlayerGui instead of Player (#1559)"; + "(Git/ocelot81) ipairs iteration for arrays (#1562)"; + "(Git/EasternBloxxer) MAKE MORE LISTS SELECTABLE (#1566)"; "(Git/EasternBloxxer) Remove CustomChat (#1570)"; ""; "[v259 2024-05-21 19:10 UTC] @Dimenpsyonal"; diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index 714abc46f5..1d90077da3 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -107,7 +107,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) logError(err.."\n"..debug.traceback()) end end - local index = (main and main.Functions and game:GetService("HttpService"):GenerateGUID(false)) or math.random(); + local index = game:GetService("HttpService"):GenerateGUID(false); local isThread = string.sub(name, 1, 7) == "Thread:" local data = { @@ -566,8 +566,6 @@ return function(errorHandler, eventChecker, fenceSpecific, env) return new end, - IsLocked = function(obj) return not pcall(function() obj.Name = obj.Name return obj.Name end) end; - Timer = function(t,func,check) local start = time() local event; event = service.RunService.RenderStepped:Connect(function() @@ -696,15 +694,6 @@ return function(errorHandler, eventChecker, fenceSpecific, env) return newProxy end; - GetUserType = function(obj) - local ran,err = pcall(function() local temp = obj[math.random()] end) - if ran then - return "Unknown" - else - return string.match(err, "%S+$") - end - end; - CountTable = function(tab) local num = 0 for _ in tab do num += 1 end @@ -996,22 +985,15 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end int = int:reverse() - local newInt = "" - local counter = 1 + local newInt = table.create(#int + math.floor((#int - 1) / 3)) for i = 1, #int do - if counter > 3 then - newInt ..= separator - counter = 1 + if i % 3 == 1 and i ~= 1 then + table.insert(newInt, separator) end - newInt ..= int:sub(i, i) - counter += 1 + table.insert(newInt, int:sub(i, i)) end - return `{(if num < 0 then "-" else "")}{newInt:reverse()}{if dec then `.{dec}` else ""}` - end; - - OwnsAsset = function(...) - return service.CheckAssetOwnership(...) + return `{(if num < 0 then "-" else "")}{table.concat(newInt):reverse()}{if dec then `.{dec}` else ""}` end; GetProductInfo = function(assetId, infoType) @@ -1026,7 +1008,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) results = { Created = false; }; - lastUpdated = os.clock(); + lastUpdated = -math.huge; } assetInfoCache[`{assetId}-{infoType}`] = cache end @@ -1453,7 +1435,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) SelfEvent = function(signal, func) local rbxevent = service.RbxEvent(signal, function(...) func(...) end) end; DelRbxEvent = function(signal) for i,v in RbxEvents do if v == signal then v:Disconnect() table.remove(RbxEvents, i) end end end; SanitizeString = function(str) str = service.Trim(str) local new = "" for i = 1,#str do if string.sub(str,i,i) ~= "\n" and string.sub(str,i,i) ~= "\0" then new = new..string.sub(str,i,i) end end return new end; - Trim = function(str) return string.match(str,"^%s*(.-)%s*$") end; + Trim = function(str) return string.match(str,"^%s*(.-)%s*$") end; Localize = function(obj, readOnly) local Localize = service.Localize local ReadOnly = service.ReadOnly if type(obj) == "table" then local newTab = {} for i in obj do newTab[i] = Localize(obj[i], readOnly) end return (readOnly and ReadOnly(newTab)) or newTab else return obj end end; RawEqual = function(obj1, obj2) return service.UnWrap(obj1) == service.UnWrap(obj2) end; CheckProperty = function(obj,prop) return pcall(function() return obj[prop] end) end; diff --git a/aftman.toml b/aftman.toml index 6b8c1dd38c..8927d3f4cc 100644 --- a/aftman.toml +++ b/aftman.toml @@ -3,5 +3,5 @@ # To add a new tool, add an entry to this table. [tools] -rojo = "rojo-rbx/rojo@7.4.1" +rojo = "rojo-rbx/rojo@7.4.4" selene = "Kampfkarren/selene@0.27.1" From 9eb4c395ce17d4782a0bcd6b887edc748892364c Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:33:14 +0000 Subject: [PATCH 090/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 01dac6fa61..19ea7718c1 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -3,8 +3,7 @@ return { "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; - "[Version – Date & Time released] @Maintainer"; - "[v261 2024-08-29 14:32 UTC] @Dimenpsyonal"; + "[v261 2024-11-18 13:35 UTC] @Dimenpsyonal"; "(Git/Expertcoderz) Add :ckick command (#1614)"; ""; "(Git/24rr) New System: Audit Logs (#1568)"; @@ -66,6 +65,7 @@ return { "(Git/ccuser44) Make cleanup and oldlogs saving respect silentstartup (#1714)"; "(Git/ccuser44) Fix bug report version help image (#1709)"; "(Git/ccuser44) Remove unnecessary cruft from server (#1682)"; + "(Git/ccuser44) Fix many annoying bugs (#1647)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 2cb7abd1eb5b2cc6ba17a21775c4d9b875a727bb Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:58:23 +0200 Subject: [PATCH 091/189] Remove FiOne copy artifact and update FiOne (#1736) * Backport: Optimize 2 annotation on FiOne (#1585) * Backport: Remove unnecessary table.isfrozen check (#1627) * Delete MainModule/Server/Shared/FiOne.luau * Pull upstream FiOne changes * Fix publish date --- MainModule/Server/Shared/AudioLib.luau | 2 +- MainModule/Server/Shared/FiOne.luau | 1013 ---------------------- MainModule/Server/Shared/FiOne/init.luau | 14 +- 3 files changed, 5 insertions(+), 1024 deletions(-) delete mode 100644 MainModule/Server/Shared/FiOne.luau diff --git a/MainModule/Server/Shared/AudioLib.luau b/MainModule/Server/Shared/AudioLib.luau index 60affae579..ff3c332626 100644 --- a/MainModule/Server/Shared/AudioLib.luau +++ b/MainModule/Server/Shared/AudioLib.luau @@ -3,7 +3,7 @@ Description: An simple and versatile audio library with getter&setter functions and an immutable data structure. Authors: Github@ccuser44/VortexColor & P3tray Contributors: Github@ccuser44/VortexColor, P3tray - Date: 2022 + Date: 2024 License: MIT ]] diff --git a/MainModule/Server/Shared/FiOne.luau b/MainModule/Server/Shared/FiOne.luau deleted file mode 100644 index 34e19467b5..0000000000 --- a/MainModule/Server/Shared/FiOne.luau +++ /dev/null @@ -1,1013 +0,0 @@ ---!native ---!optimize 2 ---# selene: allow(divide_by_zero, multiple_statements, mixed_table) ---[[ -FiOne -Copyright (C) 2021 Rerumu - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -]] -- - -local lua_wrap_state -local stm_lua_func - --- SETLIST config -local FIELDS_PER_FLUSH = 50 - --- remap for better lookup -local OPCODE_RM = { - -- level 1 - [22] = 18, -- JMP - [31] = 8, -- FORLOOP - [33] = 28, -- TFORLOOP - -- level 2 - [0] = 3, -- MOVE - [1] = 13, -- LOADK - [2] = 23, -- LOADBOOL - [26] = 33, -- TEST - -- level 3 - [12] = 1, -- ADD - [13] = 6, -- SUB - [14] = 10, -- MUL - [15] = 16, -- DIV - [16] = 20, -- MOD - [17] = 26, -- POW - [18] = 30, -- UNM - [19] = 36, -- NOT - -- level 4 - [3] = 0, -- LOADNIL - [4] = 2, -- GETUPVAL - [5] = 4, -- GETGLOBAL - [6] = 7, -- GETTABLE - [7] = 9, -- SETGLOBAL - [8] = 12, -- SETUPVAL - [9] = 14, -- SETTABLE - [10] = 17, -- NEWTABLE - [20] = 19, -- LEN - [21] = 22, -- CONCAT - [23] = 24, -- EQ - [24] = 27, -- LT - [25] = 29, -- LE - [27] = 32, -- TESTSET - [32] = 34, -- FORPREP - [34] = 37, -- SETLIST - -- level 5 - [11] = 5, -- SELF - [28] = 11, -- CALL - [29] = 15, -- TAILCALL - [30] = 21, -- RETURN - [35] = 25, -- CLOSE - [36] = 31, -- CLOSURE - [37] = 35, -- VARARG -} - --- opcode types for getting values -local OPCODE_T = { - [0] = "ABC", - "ABx", - "ABC", - "ABC", - "ABC", - "ABx", - "ABC", - "ABx", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "AsBx", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "ABC", - "AsBx", - "AsBx", - "ABC", - "ABC", - "ABC", - "ABx", - "ABC", -} - -local OPCODE_M = { - [0] = {b = "OpArgR", c = "OpArgN"}, - {b = "OpArgK", c = "OpArgN"}, - {b = "OpArgU", c = "OpArgU"}, - {b = "OpArgR", c = "OpArgN"}, - {b = "OpArgU", c = "OpArgN"}, - {b = "OpArgK", c = "OpArgN"}, - {b = "OpArgR", c = "OpArgK"}, - {b = "OpArgK", c = "OpArgN"}, - {b = "OpArgU", c = "OpArgN"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgU", c = "OpArgU"}, - {b = "OpArgR", c = "OpArgK"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgR", c = "OpArgN"}, - {b = "OpArgR", c = "OpArgN"}, - {b = "OpArgR", c = "OpArgN"}, - {b = "OpArgR", c = "OpArgR"}, - {b = "OpArgR", c = "OpArgN"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgK", c = "OpArgK"}, - {b = "OpArgR", c = "OpArgU"}, - {b = "OpArgR", c = "OpArgU"}, - {b = "OpArgU", c = "OpArgU"}, - {b = "OpArgU", c = "OpArgU"}, - {b = "OpArgU", c = "OpArgN"}, - {b = "OpArgR", c = "OpArgN"}, - {b = "OpArgR", c = "OpArgN"}, - {b = "OpArgN", c = "OpArgU"}, - {b = "OpArgU", c = "OpArgU"}, - {b = "OpArgN", c = "OpArgN"}, - {b = "OpArgU", c = "OpArgN"}, - {b = "OpArgU", c = "OpArgN"}, -} - -local intiger_types = { - [1] = buffer.readu8, - [2] = buffer.readu16, - [4] = buffer.readu32, -} - -local intiger_write_type = { - [1] = buffer.writeu8, - [2] = buffer.writeu16, - [4] = buffer.writeu32, -} - --- int rd_int(string src, int s, int e) --- @src - Source binary string --- @s - Start index of a little endian integer --- @e - End index of the integer -local function rd_int(src, s, e) - return intiger_types[e - s](src, s) -end - --- number big_endian(string src, int s) --- @callback - Function to be called after bitswap --- @byte_count - Lenght of the number -local function big_endian(callback, byte_count) - return function(src, s, e) - local e, write = (e or byte_count) * 8, intiger_write_type[e] - write(src, s, bit32.rshift(bit32.byteswap(rd_int(src, s, e)), 32 - e)) - local n2 = callback(src, s) - write(src, s, bit32.rshift(bit32.byteswap(rd_int(src, s, e)), 32 - e)) - - return n2 - end -end - --- to avoid nested ifs in deserializing -local float_types = { - [4] = {little = buffer.readf32, big = big_endian(buffer.readf32)}, - [8] = {little = buffer.readf64, big = big_endian(buffer.readf64)}, -} - --- byte stm_byte(Stream S) --- @S - Stream object to read from -local function stm_byte(S) - local idx = S.index - local bt = buffer.readu8(S.source, idx) - - S.index = idx + 1 - return bt -end - --- string stm_string(Stream S, int len) --- @S - Stream object to read from --- @len - Length of string being read -local function stm_string(S, len) - local str = buffer.readstring(S.source, S.index, len) - - S.index += len - return str -end - --- string stm_lstring(Stream S) --- @S - Stream object to read from -local function stm_lstring(S) - local len = S:s_szt() - local str - - if len ~= 0 then str = string.sub(stm_string(S, len), 1, -2) end - - return str -end - --- fn cst_int_rdr(string src, int len, fn func) --- @len - Length of type for reader --- @func - Reader callback -local function cst_int_rdr(len, func) - return function(S) - local pos = S.index + len - local int = func(S.source, S.index, pos) - S.index = pos - - return int - end -end - --- fn cst_flt_rdr(string src, int len, fn func) --- @len - Length of type for reader --- @func - Reader callback -local function cst_flt_rdr(len, func) - return function(S) - local flt = func(S.source, S.index) - S.index = S.index + len - - return flt - end -end - -local function stm_inst_list(S) - local len = S:s_int() - local list = table.create(len) - - for i = 1, len do - local ins = S:s_ins() - local op = bit32.band(ins, 0x3F) - local args = OPCODE_T[op] - local mode = OPCODE_M[op] - local data = {value = ins, op = OPCODE_RM[op], A = bit32.band(bit32.rshift(ins, 6), 0xFF)} - - if args == "ABC" then - data.B = bit32.band(bit32.rshift(ins, 23), 0x1FF) - data.C = bit32.band(bit32.rshift(ins, 14), 0x1FF) - data.is_KB = mode.b == "OpArgK" and data.B > 0xFF -- post process optimization - data.is_KC = mode.c == "OpArgK" and data.C > 0xFF - - if op == 10 then -- decode NEWTABLE array size, store it as constant value - local e = bit32.band(bit32.rshift(data.B, 3), 31) - if e == 0 then - data.const = data.B - else - data.const = bit32.lshift(bit32.band(data.B, 7) + 8, e - 1) - end - end - elseif args == "ABx" then - data.Bx = bit32.band(bit32.rshift(ins, 14), 0x3FFFF) - data.is_K = mode.b == "OpArgK" - elseif args == "AsBx" then - data.sBx = bit32.band(bit32.rshift(ins, 14), 0x3FFFF) - 131071 - end - - list[i] = data - end - - return list -end - -local function stm_const_list(S) - local len = S:s_int() - local list = table.create(len) - - for i = 1, len do - local tt = stm_byte(S) - local k - - if tt == 1 then - k = stm_byte(S) ~= 0 - elseif tt == 3 then - k = S:s_num() - elseif tt == 4 then - k = stm_lstring(S) - end - - list[i] = k -- offset +1 during instruction decode - end - - return list -end - -local function stm_sub_list(S, src) - local len = S:s_int() - local list = table.create(len) - - for i = 1, len do - list[i] = stm_lua_func(S, src) -- offset +1 in CLOSURE - end - - return list -end - -local function stm_line_list(S) - local len = S:s_int() - local list = table.create(len) - - for i = 1, len do list[i] = S:s_int() end - - return list -end - -local function stm_loc_list(S) - local len = S:s_int() - local list = table.create(len) - - for i = 1, len do list[i] = {varname = stm_lstring(S), startpc = S:s_int(), endpc = S:s_int()} end - - return list -end - -local function stm_upval_list(S) - local len = S:s_int() - local list = table.create(len) - - for i = 1, len do list[i] = stm_lstring(S) end - - return list -end - -function stm_lua_func(S, psrc) - local proto = {} - local src = stm_lstring(S) or psrc -- source is propagated - - proto.source = src -- source name - - S:s_int() -- line defined - S:s_int() -- last line defined - - proto.num_upval = stm_byte(S) -- num upvalues - proto.num_param = stm_byte(S) -- num params - - stm_byte(S) -- vararg flag - proto.max_stack = stm_byte(S) -- max stack size - - proto.code = stm_inst_list(S) - proto.const = stm_const_list(S) - proto.subs = stm_sub_list(S, src) - proto.lines = stm_line_list(S) - - stm_loc_list(S) - stm_upval_list(S) - - -- post process optimization - for _, v in ipairs(proto.code) do - if v.is_K then - v.const = proto.const[v.Bx + 1] -- offset for 1 based index - else - if v.is_KB then v.const_B = proto.const[v.B - 0xFF] end - - if v.is_KC then v.const_C = proto.const[v.C - 0xFF] end - end - end - - return proto -end - -local function lua_bc_to_state(src) - -- func reader - local rdr_func - - -- header flags - local little - local size_int - local size_szt - local size_ins - local size_num - local flag_int - - -- stream object - local stream = { - -- data - index = 0, - source = typeof(src) == "buffer" and src or buffer.fromstring(src), - } - - assert(stm_string(stream, 4) == "\27Lua", "invalid Lua signature") - assert(stm_byte(stream) == 0x51, "invalid Lua version") - assert(stm_byte(stream) == 0, "invalid Lua format") - - little = stm_byte(stream) ~= 0 - size_int = stm_byte(stream) - size_szt = stm_byte(stream) - size_ins = stm_byte(stream) - size_num = stm_byte(stream) - flag_int = stm_byte(stream) ~= 0 - - rdr_func = little and rd_int or big_endian(rd_int) - stream.s_int = cst_int_rdr(size_int, rdr_func) - stream.s_szt = cst_int_rdr(size_szt, rdr_func) - stream.s_ins = cst_int_rdr(size_ins, rdr_func) - - if flag_int then - stream.s_num = cst_int_rdr(size_num, rdr_func) - elseif float_types[size_num] then - stream.s_num = cst_flt_rdr(size_num, float_types[size_num][little and "little" or "big"]) - else - error("unsupported float size") - end - - return stm_lua_func(stream, "@virtual") -end - -local function close_lua_upvalues(list, index) - for i, uv in pairs(list) do - if uv.index >= index then - uv.value = uv.store[uv.index] -- store value - uv.store = uv - uv.index = "value" -- self reference - list[i] = nil - end - end -end - -local function open_lua_upvalue(list, index, memory) - local prev = list[index] - - if not prev then - prev = {index = index, store = memory} - list[index] = prev - end - - return prev -end - -local function on_lua_error(failed, err) - local src = failed.source - local line = failed.lines[failed.pc - 1] - - error(string.format("%s:%i: %s", src, line, err), 0) -end - -local function run_lua_func(state, env, upvals) - local code = state.code - local subs = state.subs - local vararg = state.vararg - - local top_index = -1 - local open_list = {} - local memory = state.memory - local pc = state.pc - - while true do - local inst = code[pc] - local op = inst.op - pc = pc + 1 - - if op < 18 then - if op < 8 then - if op < 3 then - if op < 1 then - --[[LOADNIL]] - for i = inst.A, inst.B do memory[i] = nil end - elseif op > 1 then - --[[GETUPVAL]] - local uv = upvals[inst.B] - - memory[inst.A] = uv.store[uv.index] - else - --[[ADD]] - local lhs, rhs - - if inst.is_KB then - lhs = inst.const_B - else - lhs = memory[inst.B] - end - - if inst.is_KC then - rhs = inst.const_C - else - rhs = memory[inst.C] - end - - memory[inst.A] = lhs + rhs - end - elseif op > 3 then - if op < 6 then - if op > 4 then - --[[SELF]] - local A = inst.A - local B = inst.B - local index - - if inst.is_KC then - index = inst.const_C - else - index = memory[inst.C] - end - - memory[A + 1] = memory[B] - memory[A] = memory[B][index] - else - --[[GETGLOBAL]] - memory[inst.A] = env[inst.const] - end - elseif op > 6 then - --[[GETTABLE]] - local index - - if inst.is_KC then - index = inst.const_C - else - index = memory[inst.C] - end - - memory[inst.A] = memory[inst.B][index] - else - --[[SUB]] - local lhs, rhs - - if inst.is_KB then - lhs = inst.const_B - else - lhs = memory[inst.B] - end - - if inst.is_KC then - rhs = inst.const_C - else - rhs = memory[inst.C] - end - - memory[inst.A] = lhs - rhs - end - else --[[MOVE]] - memory[inst.A] = memory[inst.B] - end - elseif op > 8 then - if op < 13 then - if op < 10 then - --[[SETGLOBAL]] - env[inst.const] = memory[inst.A] - elseif op > 10 then - if op < 12 then - --[[CALL]] - local A = inst.A - local B = inst.B - local C = inst.C - local params - - if B == 0 then - params = top_index - A - else - params = B - 1 - end - - local ret_list = table.pack(memory[A](table.unpack(memory, A + 1, A + params))) - local ret_num = ret_list.n - - if C == 0 then - top_index = A + ret_num - 1 - else - ret_num = C - 1 - end - - table.move(ret_list, 1, ret_num, A, memory) - else - --[[SETUPVAL]] - local uv = upvals[inst.B] - - uv.store[uv.index] = memory[inst.A] - end - else - --[[MUL]] - local lhs, rhs - - if inst.is_KB then - lhs = inst.const_B - else - lhs = memory[inst.B] - end - - if inst.is_KC then - rhs = inst.const_C - else - rhs = memory[inst.C] - end - - memory[inst.A] = lhs * rhs - end - elseif op > 13 then - if op < 16 then - if op > 14 then - --[[TAILCALL]] - local A = inst.A - local B = inst.B - local params - - if B == 0 then - params = top_index - A - else - params = B - 1 - end - - close_lua_upvalues(open_list, 0) - - return memory[A](table.unpack(memory, A + 1, A + params)) - else - --[[SETTABLE]] - local index, value - - if inst.is_KB then - index = inst.const_B - else - index = memory[inst.B] - end - - if inst.is_KC then - value = inst.const_C - else - value = memory[inst.C] - end - - memory[inst.A][index] = value - end - elseif op > 16 then - --[[NEWTABLE]] - memory[inst.A] = table.create(inst.const) -- inst.const contains array size - else - --[[DIV]] - local lhs, rhs - - if inst.is_KB then - lhs = inst.const_B - else - lhs = memory[inst.B] - end - - if inst.is_KC then - rhs = inst.const_C - else - rhs = memory[inst.C] - end - - memory[inst.A] = lhs / rhs - end - else - --[[LOADK]] - memory[inst.A] = inst.const - end - else - --[[FORLOOP]] - local A = inst.A - local step = memory[A + 2] - local index = memory[A] + step - local limit = memory[A + 1] - local loops - - if step == math.abs(step) then - loops = index <= limit - else - loops = index >= limit - end - - if loops then - memory[A] = index - memory[A + 3] = index - pc = pc + inst.sBx - end - end - elseif op > 18 then - if op < 28 then - if op < 23 then - if op < 20 then - --[[LEN]] - memory[inst.A] = #memory[inst.B] - elseif op > 20 then - if op < 22 then - --[[RETURN]] - local A = inst.A - local B = inst.B - local len - - if B == 0 then - len = top_index - A + 1 - else - len = B - 1 - end - - close_lua_upvalues(open_list, 0) - - return table.unpack(memory, A, A + len - 1) - else - --[[CONCAT]] - local B, C = inst.B, inst.C - local success, str = pcall(table.concat, memory, "", B, C) - - if not success then - str = memory[B] - - for i = B + 1, C do str = str .. memory[i] end - end - - memory[inst.A] = str - end - else - --[[MOD]] - local lhs, rhs - - if inst.is_KB then - lhs = inst.const_B - else - lhs = memory[inst.B] - end - - if inst.is_KC then - rhs = inst.const_C - else - rhs = memory[inst.C] - end - - memory[inst.A] = lhs % rhs - end - elseif op > 23 then - if op < 26 then - if op > 24 then - --[[CLOSE]] - close_lua_upvalues(open_list, inst.A) - else - --[[EQ]] - local lhs, rhs - - if inst.is_KB then - lhs = inst.const_B - else - lhs = memory[inst.B] - end - - if inst.is_KC then - rhs = inst.const_C - else - rhs = memory[inst.C] - end - - if (lhs == rhs) == (inst.A ~= 0) then pc = pc + code[pc].sBx end - - pc = pc + 1 - end - elseif op > 26 then - --[[LT]] - local lhs, rhs - - if inst.is_KB then - lhs = inst.const_B - else - lhs = memory[inst.B] - end - - if inst.is_KC then - rhs = inst.const_C - else - rhs = memory[inst.C] - end - - if (lhs < rhs) == (inst.A ~= 0) then pc = pc + code[pc].sBx end - - pc = pc + 1 - else - --[[POW]] - local lhs, rhs - - if inst.is_KB then - lhs = inst.const_B - else - lhs = memory[inst.B] - end - - if inst.is_KC then - rhs = inst.const_C - else - rhs = memory[inst.C] - end - - memory[inst.A] = lhs ^ rhs - end - else - --[[LOADBOOL]] - memory[inst.A] = inst.B ~= 0 - - if inst.C ~= 0 then pc = pc + 1 end - end - elseif op > 28 then - if op < 33 then - if op < 30 then - --[[LE]] - local lhs, rhs - - if inst.is_KB then - lhs = inst.const_B - else - lhs = memory[inst.B] - end - - if inst.is_KC then - rhs = inst.const_C - else - rhs = memory[inst.C] - end - - if (lhs <= rhs) == (inst.A ~= 0) then pc = pc + code[pc].sBx end - - pc = pc + 1 - elseif op > 30 then - if op < 32 then - --[[CLOSURE]] - local sub = subs[inst.Bx + 1] -- offset for 1 based index - local nups = sub.num_upval - local uvlist - - if nups ~= 0 then - uvlist = table.create(nups - 1) - - for i = 1, nups do - local pseudo = code[pc + i - 1] - - if pseudo.op == OPCODE_RM[0] then -- @MOVE - uvlist[i - 1] = open_lua_upvalue(open_list, pseudo.B, memory) - elseif pseudo.op == OPCODE_RM[4] then -- @GETUPVAL - uvlist[i - 1] = upvals[pseudo.B] - end - end - - pc = pc + nups - end - - memory[inst.A] = lua_wrap_state(sub, env, uvlist) - else - --[[TESTSET]] - local A = inst.A - local B = inst.B - - if (not memory[B]) ~= (inst.C ~= 0) then - memory[A] = memory[B] - pc = pc + code[pc].sBx - end - pc = pc + 1 - end - else - --[[UNM]] - memory[inst.A] = -memory[inst.B] - end - elseif op > 33 then - if op < 36 then - if op > 34 then - --[[VARARG]] - local A = inst.A - local len = inst.B - - if len == 0 then - len = vararg.len - top_index = A + len - 1 - end - - table.move(vararg.list, 1, len, A, memory) - else - --[[FORPREP]] - local A = inst.A - local init, limit, step - - init = assert(tonumber(memory[A]), "`for` initial value must be a number") - limit = assert(tonumber(memory[A + 1]), "`for` limit must be a number") - step = assert(tonumber(memory[A + 2]), "`for` step must be a number") - - memory[A] = init - step - memory[A + 1] = limit - memory[A + 2] = step - - pc = pc + inst.sBx - end - elseif op > 36 then - --[[SETLIST]] - local A = inst.A - local C = inst.C - local len = inst.B - local tab = memory[A] - local offset - - if len == 0 then len = top_index - A end - - if C == 0 then - C = inst[pc].value - pc = pc + 1 - end - - offset = (C - 1) * FIELDS_PER_FLUSH - - table.move(memory, A + 1, A + len, offset + 1, tab) - else - --[[NOT]] - memory[inst.A] = not memory[inst.B] - end - else - --[[TEST]] - if (not memory[inst.A]) ~= (inst.C ~= 0) then pc = pc + code[pc].sBx end - pc = pc + 1 - end - else - --[[TFORLOOP]] - local A = inst.A - local func = memory[A] - local state = memory[A + 1] - local index = memory[A + 2] - local base = A + 3 - local vals - - -- === Luau compatibility - General iteration begin === - -- // ccuser44 added support for generic iteration - -- (Please don't use general iteration in vanilla Lua code) - if not index and not state and type(func) == "table" then - local metatable = pcall(getmetatable, func) and getmetatable(func) - - if not (type(metatable) == "table" and rawget(metatable, "__call")) then - func, state, index = (type(metatable) == "table" and rawget(metatable, "__iter") or next), func, nil - memory[A], memory[A + 1], memory[A + 2] = func, state, index - end - end - -- === Luau compatibility - General iteration end === - - vals = {func(state, index)} - - table.move(vals, 1, inst.C, base, memory) - - if memory[base] ~= nil then - memory[A + 2] = memory[base] - pc = pc + code[pc].sBx - end - - pc = pc + 1 - end - else - --[[JMP]] - pc = pc + inst.sBx - end - - state.pc = pc - end -end - -function lua_wrap_state(proto, env, upval) - local function wrapped(...) - local passed = table.pack(...) - local memory = table.create(proto.max_stack) - local vararg = {len = 0, list = {}} - - table.move(passed, 1, proto.num_param, 0, memory) - - if proto.num_param < passed.n then - local start = proto.num_param + 1 - local len = passed.n - proto.num_param - - vararg.len = len - table.move(passed, start, start + len - 1, 1, vararg.list) - end - - local state = {vararg = vararg, memory = memory, code = proto.code, subs = proto.subs, pc = 1} - - local result = table.pack(pcall(run_lua_func, state, env, upval)) - - if result[1] then - return table.unpack(result, 2, result.n) - else - local failed = {pc = state.pc, source = proto.source, lines = proto.lines} - - on_lua_error(failed, result[2]) - - return - end - end - - return wrapped -end - -return setmetatable({ - bc_to_state = lua_bc_to_state, - wrap_state = lua_wrap_state, - OPCODE_RM = OPCODE_RM, - OPCODE_T = OPCODE_T, - OPCODE_M = OPCODE_M, -}, {__call = function(_, BCode, Env) -- Backwards compatibility for legacy rerubi usage - return lua_wrap_state(lua_bc_to_state(BCode), Env or {}) -end}) diff --git a/MainModule/Server/Shared/FiOne/init.luau b/MainModule/Server/Shared/FiOne/init.luau index b01882a2e1..ced6a41123 100644 --- a/MainModule/Server/Shared/FiOne/init.luau +++ b/MainModule/Server/Shared/FiOne/init.luau @@ -1,6 +1,7 @@ --!native +--!optimize 2 --!nolint TableOperations ---# selene: allow(divide_by_zero, multiple_statements, mixed_table) +--# selene: allow(multiple_statements, mixed_table) --[[ FiOne Copyright (C) 2021 Rerumu @@ -731,7 +732,7 @@ local function run_lua_func(state, env, upvals) local limit = memory[A + 1] local loops - if step == math.abs(step) then + if step >= 0 then loops = index <= limit else loops = index >= limit @@ -992,14 +993,7 @@ local function run_lua_func(state, env, upvals) -- // ccuser44 added support for generic iteration -- (Please don't use general iteration in vanilla Lua code) if not index and not state and type(func) == "table" then - -- Hacky check to see if __metatable is locked - local canGetMt = pcall(getmetatable, func) - local isMtLocked = canGetMt and not pcall(setmetatable, func, getmetatable(func)) or not canGetMt - local metatable = canGetMt and getmetatable(func) - - if not (table.isfrozen and table.isfrozen(func)) and isMtLocked and not metatable then - warn("[FiOne]: The table has a metatable buts it's hidden, __iter and __call won't work in forloop.") - end + local metatable = pcall(getmetatable, func) and getmetatable(func) if not (type(metatable) == "table" and rawget(metatable, "__call")) then func, state, index = (type(metatable) == "table" and rawget(metatable, "__iter") or next), func, nil From dcbf76fdf51d33546ab9f53c806813cdd9a54179 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:59:20 +0000 Subject: [PATCH 092/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 19ea7718c1..420811d83c 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -66,6 +66,7 @@ return { "(Git/ccuser44) Fix bug report version help image (#1709)"; "(Git/ccuser44) Remove unnecessary cruft from server (#1682)"; "(Git/ccuser44) Fix many annoying bugs (#1647)"; + "(Git/ccuser44) Remove FiOne copy artifact and update FiOne (#1736)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 26a86286849716a03c83201c77dcea20d5cc1df0 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:01:13 +0200 Subject: [PATCH 093/189] Fix donor perks not updating live (#1741) --- MainModule/Server/Core/Admin.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau index 26bf0fdc12..8af44c182b 100644 --- a/MainModule/Server/Core/Admin.luau +++ b/MainModule/Server/Core/Admin.luau @@ -340,7 +340,7 @@ return function(Vargs, GetEnv) end service.MarketplaceService.PromptGamePassPurchaseFinished:Connect(function(player, id, purchased) - if Variables and player.Parent and id == 1348327 and purchased then + if Variables and player.Parent and table.find(Variables.DonorPass, id) and purchased then Variables.CachedDonors[tostring(player.UserId)] = os.time() end end) From 8ed31b27351d9845066281212b16006d32f4c2ca Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:02:08 +0200 Subject: [PATCH 094/189] Add more animatedheads (#1740) --- MainModule/Server/Core/Variables.luau | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Core/Variables.luau b/MainModule/Server/Core/Variables.luau index c4440fc391..bfe7910b31 100644 --- a/MainModule/Server/Core/Variables.luau +++ b/MainModule/Server/Core/Variables.luau @@ -83,9 +83,14 @@ return function(Vargs, GetEnv) 14525129330, 13001896404, 14719225657, 14640105786, 13820802344, 14638466361, 13821294344, 14840473015, 13822584343, 14701679873, 13822985393, 13823226706, 14719266373, 14192299483, 14192630651, 14192804513, 14192863652, 14192993380, 14193224583, 14205130925, 14205179825, 13020957350, 13021695400, 12995139274, 12733096025, 12732440273, 14377306239, 12859102530, 14521518488, 14918993907, 14401304993, 12860895688, 10704977958, - 14380344401, + 14380344401, 14366112499, 10725526074, 11402532474, 10725092133, 11445572546, 14192828782, 13702851678, 12929417417, 13675436366, 14755069931, + 14374802942, 14638203853, 12939016971, 11564337259, 13691524922, 14719366846, 12945457988, 14760102190, 13675155984, 14367119766, 14205146154, + 14377320953, 14193020364, 11116786674, 13822986276, 14638467750, 10998132528, 13675472848, 14182904315, 12936914000, 12936596034, 14524488089, + 14478215763, 13684480556, 13822585823, 14754581557, 14401306473, 11821976793, 14193703522, 14760226358, -- R6 - 14366393007 + 14366393007, 18446596298, + -- R15 custom UGC heads are not supported currently! (And probably never will be lol) + -- If there are any heads with baked in faces made by Roblox that are not here tell Adonis maintainers immediatly! }, LightingSettings = { From f0cbee330424ebf087f87992d250ad5bbf79a02c Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:02:32 +0200 Subject: [PATCH 095/189] Fix incompatibility with legacy `service.Yield` (#1739) --- MainModule/Server/Shared/Service.luau | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index 1d90077da3..95eb1615e0 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -257,7 +257,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) GetEvent = function(name) if not HookedEvents[name] then --// GoodSignal has been setup to be fully backwards-compatible with the existing Events system - local event = service.GoodSignal.new() + local event = service.Signal.new() HookedEvents[name] = event return event @@ -746,7 +746,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end if doYield and not tab.Finished then - return select(2, tab.Yield:Wait()); + return tab.Yield:Wait() end end; From a6eb784a9bdc932be302ceb695c2b3c6513311f3 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:05:15 +0200 Subject: [PATCH 096/189] Optimise `service.SanitizeString` and filter functions. (#1738) * Optimise filter functions * Optimise SanitizeString --------- Co-authored-by: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> --- MainModule/Server/Shared/Service.luau | 82 ++++++++++++--------------- 1 file changed, 36 insertions(+), 46 deletions(-) diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index 95eb1615e0..502704193a 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -551,16 +551,16 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end; },{ DeepCopy = function(tab) - local new = (getmetatable(tab) ~= nil and setmetatable({},{ + local new = (getmetatable(tab) ~= nil and setmetatable({}, { __index = function(t, ind) return tab[ind] end })) or {} - for i,v in tab do + for k, v in tab do if type(v) == "table" then - new[i] = service.DeepCopy(v) + new[k] = service.DeepCopy(v) else - new[i] = v + new[k] = v end end return new @@ -577,7 +577,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end; ExtractLines = function(str) - return string.split(string.gsub(str, "[%z\1-\9\11-\31]", ""), "") + return string.split(string.gsub(str, "[%z\1-\9\11-\31]", ""), "\n") end; Filter = function(str, from, to) @@ -585,23 +585,18 @@ return function(errorHandler, eventChecker, fenceSpecific, env) return "Filter Error" end - local new = "" local lines = service.ExtractLines(str) - for i = 1,#lines do - local ran,newl = pcall(function() - return service.TextService:FilterStringAsync(lines[i],from.UserId):GetChatForUserAsync(to.UserId) + local new = table.create(#lines) + for i = 1, #lines do + local ran, newl = pcall(function() + return service.TextService:FilterStringAsync(lines[i], from.UserId):GetChatForUserAsync(to.UserId) end) - newl = (ran and newl) or lines[i] or "" - if i > 1 then - new = `{new}\n{newl}` - else - new = newl - end + new[i] = ran and newl or lines[i] or "" end - return new or "Filter Error" + return new and table.concat(new, "\n") or "Filter Error" end; - LaxFilter = function(str,from,cmd) -- @Roblox; If this function violates the filtering rules please note that this is currently the only way + LaxFilter = function(str, from, cmd) -- @Roblox; If this function violates the filtering rules please note that this is currently the only way if tonumber(str) then -- to avoid major filter related problems (like commands becoming unusable due to numbers or names being filtered) return str -- Please consider dropping the filter rules down a notch or improving on the existing filtering methods elseif type(str) == "string" then -- Also always feel free to message me with any concerns you have :)! @@ -611,7 +606,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) if cmd and #service.GetPlayers(from, str, { DontError = true; - }) > 0 then + }) > 0 then return str else return service.Filter(str, from, from) @@ -626,18 +621,13 @@ return function(errorHandler, eventChecker, fenceSpecific, env) return "Filter Error" end - local new = "" local lines = service.ExtractLines(str) - for i = 1,#lines do - local ran,newl = pcall(function() return service.TextService:FilterStringAsync(lines[i],from.UserId):GetNonChatStringForBroadcastAsync() end) - newl = ran and newl or lines[i] or "" - if i > 1 then - new = `{new}\n{newl}` - else - new = newl - end + local new = table.create(#lines) + for i = 1, #lines do + local ran, newl = pcall(function() return service.TextService:FilterStringAsync(lines[i], from.UserId):GetNonChatStringForBroadcastAsync() end) + new[i] = ran and newl or lines[i] or "" end - return new or "Filter Error" + return new and table.concat(new, "\n") or "Filter Error" end; RecursiveMtSearch = function(tab) @@ -690,7 +680,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) local metatable = getmetatable(newProxy) metatable.__metatable = if main.Core and main.Core.DebugMode then nil else "Adonis_Proxy" metatable.__ADONIS_WRAPPED = true - for i,v in meta do metatable[i] = v end + for k, v in meta do metatable[k] = v end return newProxy end; @@ -739,10 +729,10 @@ return function(errorHandler, eventChecker, fenceSpecific, env) Yield = doYield and service.Signal.new(); } - table.insert(queue.Functions, tab); + table.insert(queue.Functions, tab) if not queue.Processing then - service.TrackTask(`Thread: QueueProcessor_{key}`, service.ProcessQueue, false, queue, key); + service.TrackTask(`Thread: QueueProcessor_{key}`, service.ProcessQueue, false, queue, key) end if doYield and not tab.Finished then @@ -755,24 +745,24 @@ return function(errorHandler, eventChecker, fenceSpecific, env) if queue.Processing then return "Processing" else - local funcs = queue.Functions; - local Yield = service.Signal.new(); + local funcs = queue.Functions + local Yield = service.Signal.new() local function pop() local n = funcs[1] table.remove(funcs, 1) return n - end; + end queue.Processing = true while funcs[1] ~= nil do - local func = pop(); - func.Running = true; + local func = pop() + func.Running = true if func.Timeout then delay(func.Timeout, function() if not func.Finished then - Yield:Fire(); + Yield:Fire() warn(`Queue Timeout Reached for {key or "Unknown"}`) if func.Yield then @@ -783,10 +773,10 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end service.TrackTask(`Thread: {key or "Unknown"}_QueuedFunction`, function() - local r,e = xpcall(func.Function,function(e) + local r, e = xpcall(func.Function, function(e) func.Error = e; warn(`Queue Error: {key}: {e} \n {debug.traceback()}`) - end); + end) func.Running = false; func.Finished = true @@ -803,11 +793,11 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end end - Yield:Destroy(); - queue.Processing = false; + Yield:Destroy() + queue.Processing = false if key then - Queues[key] = nil; + Queues[key] = nil end end end @@ -1430,17 +1420,17 @@ return function(errorHandler, eventChecker, fenceSpecific, env) GamepassService = game:GetService("GamePassService"); ChatService = game:GetService("Chat"); Gamepasses = game:GetService("GamePassService"); - Delete = function(obj,num) game:GetService("Debris"):AddItem(obj,(num or 0)) pcall(obj.Destroy, obj) end; + Delete = function(obj, num) game:GetService("Debris"):AddItem(obj,(num or 0)) pcall(obj.Destroy, obj) end; RbxEvent = function(signal, func) local event = signal:Connect(func) table.insert(RbxEvents, event) return event end; SelfEvent = function(signal, func) local rbxevent = service.RbxEvent(signal, function(...) func(...) end) end; DelRbxEvent = function(signal) for i,v in RbxEvents do if v == signal then v:Disconnect() table.remove(RbxEvents, i) end end end; - SanitizeString = function(str) str = service.Trim(str) local new = "" for i = 1,#str do if string.sub(str,i,i) ~= "\n" and string.sub(str,i,i) ~= "\0" then new = new..string.sub(str,i,i) end end return new end; + SanitizeString = function(str) return string.gsub(service.Trim(str), "[%c%z\n]", "") end; Trim = function(str) return string.match(str,"^%s*(.-)%s*$") end; Localize = function(obj, readOnly) local Localize = service.Localize local ReadOnly = service.ReadOnly if type(obj) == "table" then local newTab = {} for i in obj do newTab[i] = Localize(obj[i], readOnly) end return (readOnly and ReadOnly(newTab)) or newTab else return obj end end; RawEqual = function(obj1, obj2) return service.UnWrap(obj1) == service.UnWrap(obj2) end; - CheckProperty = function(obj,prop) return pcall(function() return obj[prop] end) end; + CheckProperty = function(obj, prop) return pcall(function() return obj[prop] end) end; NewWaiter = function() local event = service.New("BindableEvent") return {Wait = event.wait; Finish = event.Fire} end; - },{ + }, { __index = function(tab, index) local found = (fenceSpecific and fenceSpecific[index]) or Wrapper[index] or Events[index] or Helpers[index] From a7b00a3a3bd9a2d468e706c56a1078dbe2645916 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:06:17 +0200 Subject: [PATCH 097/189] Finally improve service readability (#1737) --- MainModule/Server/Shared/Service.luau | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index 502704193a..6ad48f0d00 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -100,7 +100,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) local EventService = Instance.new("Folder") local Instance = {new = function(obj, parent) local obj = oldInstNew(obj) if parent then obj.Parent = service.UnWrap(parent) end return service and client and service.Wrap(obj, true) or obj end} - local Events, Threads, Wrapper, Helpers = { + local Events = { TrackTask = function(name, func, errHandler, ...) if type(errHandler) ~= "function" or select("#", ...) == 0 and errHandler == nil then errHandler = function(err) @@ -286,7 +286,9 @@ return function(errorHandler, eventChecker, fenceSpecific, env) event:Destroy() end end; - },{ + } + + local Threads = { Tasks = {}; Threads = {}; CheckTasks = function() @@ -395,7 +397,9 @@ return function(errorHandler, eventChecker, fenceSpecific, env) Resume = function(thread,...) if thread and coroutine.status(thread) == "suspended" then return coroutine.resume(thread,...) end end; Remove = function(thread) service.Threads.Stop(thread) for ind,th in service.Threads.Threads do if th == thread then table.remove(service.Threads.Threads,ind) end end end; StopAll = function() for ind,th in service.Threads.Threads do service.Threads.Stop(th) table.remove(service.Threads.Threads,ind) end end; ResumeAll = function() for ind,th in service.Threads.Threads do service.Threads.Resume(th) end end; GetAll = function() return service.Threads.Threads end; - },{ + } + + local Wrapper = { WrapIgnore = function(tab) return setmetatable(tab,{__metatable = if main.Core and main.Core.DebugMode then "Ignore" else nil}) end; -- Unused CheckWrappers = function() for obj,wrap in Wrappers do @@ -549,7 +553,9 @@ return function(errorHandler, eventChecker, fenceSpecific, env) return object end end; - },{ + } + + local Helpers = { DeepCopy = function(tab) local new = (getmetatable(tab) ~= nil and setmetatable({}, { __index = function(t, ind) From dc01978943a4da646f721834ca2d80959b7e9b37 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:08:01 +0200 Subject: [PATCH 098/189] Make AudioPlayer used GoodSignal library inside shared instead of having a local copy of it (#1735) * Clone GoodSignal to AudioPlayer * Delete MainModule/Client/UI/Default/Music/Signal.luau * Fix naming --- .../Client/UI/Default/Music/Signal.luau | 243 ------------------ MainModule/Client/UI/Default/Music/init.luau | 9 +- 2 files changed, 7 insertions(+), 245 deletions(-) delete mode 100644 MainModule/Client/UI/Default/Music/Signal.luau diff --git a/MainModule/Client/UI/Default/Music/Signal.luau b/MainModule/Client/UI/Default/Music/Signal.luau deleted file mode 100644 index 6c1ddda242..0000000000 --- a/MainModule/Client/UI/Default/Music/Signal.luau +++ /dev/null @@ -1,243 +0,0 @@ --------------------------------------------------------------------------------- --- Batched Yield-Safe Signal Implementation -- --- This is a Signal class which has effectively identical behavior to a -- --- normal RBXScriptSignal, with the only difference being a couple extra -- --- stack frames at the bottom of the stack trace when an error is thrown. -- --- This implementation caches runner coroutines, so the ability to yield in -- --- the signal handlers comes at minimal extra cost over a naive signal -- --- implementation that either always or never spawns a thread. -- --- -- --- API: -- --- local Signal = require(THIS MODULE) -- --- local sig = Signal.new() -- --- local connection = sig:Connect(function(arg1, arg2, ...) ... end) -- --- sig:Fire(arg1, arg2, ...) -- --- connection:Disconnect() -- --- sig:DisconnectAll() -- --- local arg1, arg2, ... = sig:Wait() -- --- -- --- Licence: -- --- Licenced under the MIT licence. -- --- -- --- Authors: -- --- stravant - July 31st, 2021 - Created the file. -- --------------------------------------------------------------------------------- - ---[[ -MIT License - -Copyright (c) 2021 Mark Langen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] - --- The currently idle thread to run the next handler on -local freeRunnerThread = nil - --- Function which acquires the currently idle handler runner thread, runs the --- function fn on it, and then releases the thread, returning it to being the --- currently idle one. --- If there was a currently idle runner thread already, that's okay, that old --- one will just get thrown and eventually GCed. -local function acquireRunnerThreadAndCallEventHandler(fn, ...) - local acquiredRunnerThread = freeRunnerThread - freeRunnerThread = nil - fn(...) - -- The handler finished running, this runner thread is free again. - freeRunnerThread = acquiredRunnerThread -end - --- Coroutine runner that we create coroutines of. The coroutine can be --- repeatedly resumed with functions to run followed by the argument to run --- them with. -local function runEventHandlerInFreeThread() - -- Note: We cannot use the initial set of arguments passed to - -- runEventHandlerInFreeThread for a call to the handler, because those - -- arguments would stay on the stack for the duration of the thread's - -- existence, temporarily leaking references. Without access to raw bytecode - -- there's no way for us to clear the "..." references from the stack. - while true do - acquireRunnerThreadAndCallEventHandler(coroutine.yield()) - end -end - --- Connection class -local Connection = {} -Connection.__index = Connection - -function Connection.new(signal, fn) - return setmetatable({ - _connected = true, - _signal = signal, - _fn = fn, - _next = false, - }, Connection) -end - -function Connection:Disconnect() - self._connected = false - - -- Unhook the node, but DON'T clear it. That way any fire calls that are - -- currently sitting on this node will be able to iterate forwards off of - -- it, but any subsequent fire calls will not hit it, and it will be GCed - -- when no more fire calls are sitting on it. - if self._signal._handlerListHead == self then - self._signal._handlerListHead = self._next - else - local prev = self._signal._handlerListHead - while prev and prev._next ~= self do - prev = prev._next - end - if prev then - prev._next = self._next - end - end -end - --- Make Connection strict -setmetatable(Connection, { - __index = function(tb, key) - error(("Attempt to get Connection::%s (not a valid member)"):format(tostring(key)), 2) - end, - __newindex = function(tb, key, value) - error(("Attempt to set Connection::%s (not a valid member)"):format(tostring(key)), 2) - end -}) - --- Signal class -local Signal = {} -Signal.__index = Signal - -function Signal.new() - return setmetatable({ - _handlerListHead = false, - Event = {}, - }, Signal) -end - -function Signal:Connect(fn) - local connection = Connection.new(self, fn) - if self._handlerListHead then - connection._next = self._handlerListHead - self._handlerListHead = connection - else - self._handlerListHead = connection - end - local signalSelf = self - function connection:Fire(...) - signalSelf:Fire(fn) - end - function connection:fire(...) - signalSelf:Fire(fn) - end - function connection:disconnect() - self:Disconnect() - end - function connection:wait() - return signalSelf:Wait() - end - return connection -end - -function Signal:connect(fn) - return self:Connect(fn) -end - --- Disconnect all handlers. Since we use a linked list it suffices to clear the --- reference to the head handler. -function Signal:DisconnectAll() - self._handlerListHead = false -end - --- Signal:Fire(...) implemented by running the handler functions on the --- coRunnerThread, and any time the resulting thread yielded without returning --- to us, that means that it yielded to the Roblox scheduler and has been taken --- over by Roblox scheduling, meaning we have to make a new coroutine runner. -function Signal:Fire(...) - local item = self._handlerListHead - while item do - if item._connected then - if not freeRunnerThread then - freeRunnerThread = coroutine.create(runEventHandlerInFreeThread) - -- Get the freeRunnerThread to the first yield - coroutine.resume(freeRunnerThread) - end - task.spawn(freeRunnerThread, item._fn, ...) - end - item = item._next - end -end - -function Signal:fire(...) - self:Fire(...) -end - --- Implement Signal:Wait() in terms of a temporary connection using --- a Signal:Connect() which disconnects itself. -function Signal:Wait() - local waitingCoroutine = coroutine.running() - local cn; - cn = self:Connect(function(...) - cn:Disconnect() - task.spawn(waitingCoroutine, ...) - end) - return coroutine.yield() -end - -function Signal:wait() - return self:Wait() -end - --- Implement Signal:Once() in terms of a connection which disconnects --- itself before running the handler. -function Signal:Once(fn) - local cn; - cn = self:Connect(function(...) - if cn._connected then - cn:Disconnect() - end - fn(...) - end) - return cn -end - -function Signal:ConnectOnce(fn) - return self:Once(fn) -end - -function Signal:connectOnce(fn) - return self:Once(fn) -end - -function Signal:Destroy() - self:DisconnectAll() - setmetatable(self, nil) -end - --- Make signal strict -setmetatable(Signal, { - __index = function(tb, key) - error(("Attempt to get Signal::%s (not a valid member)"):format(tostring(key)), 2) - end, - __newindex = function(tb, key, value) - error(("Attempt to set Signal::%s (not a valid member)"):format(tostring(key)), 2) - end -}) - -return Signal diff --git a/MainModule/Client/UI/Default/Music/init.luau b/MainModule/Client/UI/Default/Music/init.luau index 8ed9af3ec1..3725aba090 100644 --- a/MainModule/Client/UI/Default/Music/init.luau +++ b/MainModule/Client/UI/Default/Music/init.luau @@ -5,7 +5,6 @@ return function(data, env) setfenv(1, env) end - -- Saving those microseconds from using the dot operator local Variables = client.Variables local Functions = client.Functions @@ -32,6 +31,12 @@ return function(data, env) local progressupdatewait = 0.05 local canUseGlobal = data.GlobalPerms + if not script:FindFirstChild("Signal") then + local clone = (client.Shared:FindFirstChild("GoodSignal") or client.Shared:FindFirstChild("Signal")):Clone() + clone.Name = "Signal" + clone.Parent = script + end + -- The audio visulaiser at the top of the menu. local visualiserModule = require(script:FindFirstChild("Visualizer")) local sliderModule = require(script:FindFirstChild("Slider")) @@ -64,7 +69,7 @@ return function(data, env) Autoplay = false } local fakePlaylist = {Position = 0} - local getRequestMade = service.GoodSignal.new() + local getRequestMade = service.Signal.new() if canUseGlobal then task.spawn(client.Remote.Get, "AudioLib", {"call", "GetSound"}) -- Create default container From 5fcc60e48c7f77fb17b8732828388d7b05a4fc32 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:09:54 +0200 Subject: [PATCH 099/189] Use a datastore cache for Adonis Alerts (#1729) * Use a datastore cache for Adonis Alerts * Fix typo * Blacklist urgent module id --- MainModule/Server/Core/Core.luau | 1 + .../Server/Plugins/Urgent_Messages.luau | 55 ++++++++++++++----- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index eb08ce669f..140334fe40 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -179,6 +179,7 @@ return function(Vargs, GetEnv) --// Not gonna let malicious stuff set DS_Blacklist to {} or anything! DS_BLACKLIST = true; + ["Variables.UrgentModuleId"] = true; }; --// Prevent certain keys from loading from the DataStore diff --git a/MainModule/Server/Plugins/Urgent_Messages.luau b/MainModule/Server/Plugins/Urgent_Messages.luau index 254ca7b2b2..8aea251fdd 100644 --- a/MainModule/Server/Plugins/Urgent_Messages.luau +++ b/MainModule/Server/Plugins/Urgent_Messages.luau @@ -7,16 +7,46 @@ return function(Vargs, GetEnv) server.Functions, server.Commands, server.Admin, server.Anti, server.Core, server.HTTP, server.Logs, server.Remote, server.Process, server.Variables, server.Deps local LastDateTime, Messages = "Loading...", {"The messages haven't loaded. Please comeback later..."} - task.spawn(xpcall, function() - if not server.Core.SilentStartup then - print("Requiring Alerts Module by ID; Expand for module URL > ", {URL = "https://www.roblox.com/library/8096250407/Adonis-Alerts-Module"}) - end + Variables.UrgentModuleId = Variables.UrgentModuleId or 8096250407 - local r, AlertTab = xpcall(require, function() - warn("Something went wrong while requiring the urgent messages module"); - end, 8096250407) + task.spawn(xpcall, function() + local Alerts = require(Deps.__URGENT_MESSAGES) + local assetInfo = type(Variables.UrgentModuleId) == "number" and service.GetProductInfo(Variables.UrgentModuleId, Enum.InfoType.Asset) + local version = (assetInfo and assetInfo.Created) and assetInfo.Updated + local lastVersion = Core.GetData("LastAlertVersion") - local Alerts = (r and AlertTab) or require(Deps.__URGENT_MESSAGES) + if not version or not lastVersion or version ~= lastVersion then + Logs:AddLog("Script", "Loading alerts from cloud module") + xpcall(function() + if not server.Core.SilentStartup then + print("Requiring Alerts Module by ID; Expand for module URL > ", {URL = `https://www.roblox.com/library/{Variables.UrgentModuleId}/Adonis-Alerts-Module`}) + end + + local alertTab = require(Variables.UrgentModuleId) + + if alertTab then + Alerts = alertTab + Logs:AddLog("Script", "Alerts cloud module returned proper data") + Core.SetData("LastAlertVersion", version) + Core.SetData("CachedAlerts", service.HttpService:JSONEncode(alertTab)) + end + end, function(reason) + warn(`Error occured while requiring the urgent messages module. Reason {reason}`) + Logs:AddLog("Errors", `Error occured while requiring the urgent messages module. Reason {reason}`) + table.insert(server.Messages, `Error occured while requiring the urgent messages module. Reason {reason}`) + end) + elseif version and lastVersion then + Logs:AddLog("Script", "Loading alerts from datastore") + xpcall(function() + Alerts = service.HttpService:JSONDecode(Core.GetData("CachedAlerts")) + end, function(reason) + warn(`Error occured while loading alerts from datastore. Reason {reason}`) + Logs:AddLog("Errors", `Error occured while loading alerts from datastore. Reason {reason}`) + table.insert(server.Messages, `Error occured while loading alerts from datastore. Reason {reason}`) + Core.RemoveData("LastAlertVersion") + Core.RemoveData("CachedAlerts") + end) + end local MessageVersion = Alerts.MessageVersion; --// Message version/number local MessageAdminType = Alerts.MessageAdminType; --// Minimum admin level to be notified (Or Donors or Players or nil to not notify) @@ -41,7 +71,7 @@ return function(Vargs, GetEnv) end end - Variables.UrgentMessageCounter = MessageVersion; + Variables.UrgentMessageCounter = MessageVersion local function onPlayerAdded(p: Player) if MessageAdminType then @@ -58,13 +88,12 @@ return function(Vargs, GetEnv) end service.Events.PlayerAdded:Connect(onPlayerAdded) - - Logs:AddLog("Script", "Successfully loaded alerts module data"); + Logs:AddLog("Script", "Successfully loaded alerts module data") end, warn) Commands.UrgentMessages = { Prefix = ":"; - Commands = { "adonisalerts", "urgentmessages", "urgentalerts", "adonismessages", "urgentadonismessages", "ulog"}; + Commands = {"adonisalerts", "urgentmessages", "urgentalerts", "adonismessages", "urgentadonismessages", "ulog"}; Args = {}; Description = "URGENT ADONIS RELATED MESSAGES"; AdminLevel = "Players"; @@ -80,5 +109,5 @@ return function(Vargs, GetEnv) end; }; - Logs:AddLog("Script", "Alerts Module Loaded"); + Logs:AddLog("Script", "Alerts Module Loaded") end From c710b38f2c7389434db55d8ad47d3d8ef108d17d Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:10:33 +0200 Subject: [PATCH 100/189] Cache F3X (#1710) * Cache F3X * Allow local loading of F3X via F3XDeps * Fix order --- MainModule/Server/Commands/Admins.luau | 27 ++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index 4e144bdfa0..a1f554f175 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -12,7 +12,6 @@ return function(Vargs, env) local Routine = env.Routine return { - SetRank = { Prefix = Settings.Prefix; Commands = {"setrank", "permrank", "permsetrank"}; @@ -555,7 +554,29 @@ return function(Vargs, env) Description = "Gives the target player(s) F3X building tools."; AdminLevel = "Admins"; Function = function(plr: Player, args: {string}) - local F3X = require(580330877)() + local F3X = Deps.Assets:FindFirstChild("F3X Deps") and (function(deps) + local F3X = service.New("Tool", { + GripPos = Vector3.new(0, 0, 0.4), + CanBeDropped = false, + ManualActivationOnly = false, + ToolTip = "Building Tools by F3X", + Name = "Building Tools" + }, true) + local clonedDeps = deps:Clone() + + for _, obj in clonedDeps:GetDescendants() do + if obj:IsA("BaseScript") then + obj.Disabled = false + end + end + for _, obj in clonedDeps:GetChildren() do + obj.Parent = F3X + end + + clonedDeps:Destroy() + return F3X + end)(Deps.Assets:FindFirstChild("F3X Deps")) or Variables.F3XCached and Variables.F3XCached:Clone() or require(580330877)() + Variables.F3XCached = Variables.F3XCached or F3X:Clone() service.New("StringValue", { Name = `__ADONIS_VARIABLES_{Variables.CodeName}`, Parent = F3X @@ -568,6 +589,8 @@ return function(Vargs, env) F3X:Clone().Parent = Backpack end end + + F3X:Destroy() end }; From b6bb04b6ae2d02fa6ba14d446e4c3e9ea2895937 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:11:16 +0200 Subject: [PATCH 101/189] Add preliminary support for oldlogs encryption (#1696) * Add preliminary support for oldlogs encryption * Preliminary support for oldlog encryption * Fix typo * Fix stupid typo * Fix another stupid typo * Fix support for oldlogs command * Fix typo * Use new decryption function --- MainModule/Server/Commands/Moderators.luau | 8 ++++---- MainModule/Server/Core/Logs.luau | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index 3734df252a..ab67df350d 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -6617,15 +6617,15 @@ return function(Vargs, env) AdminLevel = "Moderators"; ListUpdater = function(plr: Player) if Core.DataStore then - local tab = table.create(1000) + local tab = table.create(Logs.OldCommandLogsLimit) local data = Core.GetData("OldCommandLogs") if data then - for i, v in service.HttpService:JSONDecode(data) do - table.insert(tab, i, { + for i, v in Logs.DeserializeOldlogs(data) do + tab[i] = { Time = v.Time, Text = `{v.Text}: {v.Desc}`, Desc = v.Desc - }) + } end end return tab diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index 8d87dba5c7..7e18420b0b 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -100,6 +100,21 @@ return function(Vargs, GetEnv) service.Events.LogAdded:Fire(Logs.TabToType(tab), log, tab) end; + -- // Preliminary support for oldlog encryption + DeserializeOldlogs = function(data) + if string.sub(data, 1, 1) ~= "[" and string.match(data, "^[%w%+/=]+$") then + data = Remote.NewDecrypt(Functions.Base64Decode(data), Settings.DataStoreKey) + + if string.sub(data, 1, 2) == "\x1f\x8b" then -- Check for Gzip header and decode + data = assert(Functions.GzipDecompress, "No support for Gzip encoding!")(data) + elseif string.match(data, "^\x78[\x01\x5e\x9c\xda\x20\x7d\xbb\xf9]") then -- Check for Zlib header and decode + data = assert(Functions.ZlibDecompress, "No support for Zlib encoding!")(data) + end + end + + return service.HttpService:JSONDecode(data) + end; + SaveCommandLogs = function() --// Disable saving command logs in Studio; not required. if service.RunService:IsStudio() or service.RunService:IsRunMode() then @@ -121,7 +136,12 @@ return function(Vargs, GetEnv) Core.UpdateData("OldCommandLogs", function(oldLogs) if type(oldLogs) == "string" then - oldLogs = service.HttpService:JSONDecode(oldLogs) + xpcall(function() + oldLogs = Logs.DeserializeOldlogs(oldLogs) + end, function(reason) + oldLogs = {} + warn(`Deserializing oldlogs failed due to {reason}`) + end) end local temp = {} From 571893f33d5edca97cccc0a572c91ab047ed1b98 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:15:56 +0200 Subject: [PATCH 102/189] Delete MainModule/Client/Dependencies/Adonis.model.json (#1681) --- MainModule/Client/Dependencies/Adonis.model.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 MainModule/Client/Dependencies/Adonis.model.json diff --git a/MainModule/Client/Dependencies/Adonis.model.json b/MainModule/Client/Dependencies/Adonis.model.json deleted file mode 100644 index bbdaa00333..0000000000 --- a/MainModule/Client/Dependencies/Adonis.model.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "ClassName": "NumberValue" -} From cbf858120a9ecf8917b88f0c2cd7fcbe8553ec19 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:16:41 +0200 Subject: [PATCH 103/189] Fix vararg packing (#1679) * Fix arg packing * Fix typo * Fix loadstring log outputs * Fix yxpcall nil argument returns * Proper arg handling for multithreaded closures --- Loader/Loader/Loader.server.luau | 2 +- MainModule/Client/Core/Core.luau | 8 +-- MainModule/Client/Core/Process.luau | 6 +- MainModule/Client/Core/Remote.luau | 62 +++++++++---------- MainModule/Server/Commands/Moderators.luau | 21 +++---- MainModule/Server/Core/Admin.luau | 8 +-- MainModule/Server/Core/Core.luau | 6 +- MainModule/Server/Core/Process.luau | 10 +-- MainModule/Server/Core/Remote.luau | 57 ++++++++--------- MainModule/Server/Plugins/Debug_Specific.luau | 12 ++-- MainModule/Server/Shared/FiOne/init.luau | 2 +- MainModule/Server/Shared/Service.luau | 8 +-- 12 files changed, 99 insertions(+), 103 deletions(-) diff --git a/Loader/Loader/Loader.server.luau b/Loader/Loader/Loader.server.luau index 951eb4b03c..d3636c9c36 100644 --- a/Loader/Loader/Loader.server.luau +++ b/Loader/Loader/Loader.server.luau @@ -41,7 +41,7 @@ local function yxpcall(f, callback, ...) if not args[1] then callback(args[2]) else - return table.unpack(args, 2) + return table.unpack(args, 2, args.n) end end diff --git a/MainModule/Client/Core/Core.luau b/MainModule/Client/Core/Core.luau index bf4ea09769..b3af16e692 100644 --- a/MainModule/Client/Core/Core.luau +++ b/MainModule/Client/Core/Core.luau @@ -322,13 +322,13 @@ return function(Vargs, GetEnv) local AdonisDebugAPIBindable = ReplicatedStorage:FindFirstChild("Adonis_Debug_API") if AdonisDebugAPIBindable then - AdonisDebugAPIBindable.OnInvoke = function(DebugCommand,...) - local args = {...} + AdonisDebugAPIBindable.OnInvoke = function(DebugCommand, ...) + local args = table.unpack(...) if DebugCommand == "RunEnvFunc" then local FunctionInEnvToRunPath = args[1] if FunctionInEnvToRunPath and type(FunctionInEnvToRunPath) == "string" then local realEnvResult, isResultPointer = getRealEnvResult(FunctionInEnvToRunPath) - return realEnvResult(table.unpack(args,2,#args)) + return realEnvResult(table.unpack(args, 2, args.n)) end elseif DebugCommand == "GetEnvTableMeta" then local TableInEnvPath = args[1] @@ -342,7 +342,7 @@ return function(Vargs, GetEnv) if TableInEnvPath and type(TableInEnvPath) == "string" then local realEnvResult, isResultPointer = getRealEnvResult(TableInEnvPath) local metaTableInEnv = getmetatable(realEnvResult) - local result = metaTableInEnv[FuncToRun](realEnvResult,table.unpack(args,3,#args)) + local result = metaTableInEnv[FuncToRun](realEnvResult,table.unpack(args, 3, args.n)) local resultPointer = service.HttpService:GenerateGUID(false) pointers[resultPointer] = result diff --git a/MainModule/Client/Core/Process.luau b/MainModule/Client/Core/Process.luau index 30301a207a..540a1ccb13 100644 --- a/MainModule/Client/Core/Process.luau +++ b/MainModule/Client/Core/Process.luau @@ -89,7 +89,7 @@ return function(Vargs, GetEnv) }; Remote = function(data, com, ...) - local args = {...} + local args = table.pack(...) Remote.Received += 1 if type(com) == "string" then if com == `{client.DepsName}GIVE_KEY` then @@ -104,11 +104,11 @@ return function(Vargs, GetEnv) local comString = Remote.NewDecrypt(com,Core.Key) local command = (data.Mode == "Get" and Remote.Returnables[comString]) or Remote.Commands[comString] if command then - local rets = {service.TrackTask(`Remote: {comString}`, command, false, args)} + local rets = table.pack(service.TrackTask(`Remote: {comString}`, command, false, args)) if not rets[1] then logError(rets[2]) else - return {unpack(rets, 2)}; + return table.pack(table.unpack(rets, 2)) end end end diff --git a/MainModule/Client/Core/Remote.luau b/MainModule/Client/Core/Remote.luau index f4a8531d79..f9b21a046c 100644 --- a/MainModule/Client/Core/Remote.luau +++ b/MainModule/Client/Core/Remote.luau @@ -240,15 +240,15 @@ return function(Vargs, GetEnv) print("THE SERVER IS ASKING US FOR A RETURN"); local com = args[1] local key = args[2] - local parms = {unpack(args, 3)} + local parms = table.pack(table.unpack(args, 3)) local retfunc = Remote.Returnables[com] - local retable = (retfunc and {pcall(retfunc,parms)}) or {} + local retable = retfunc and table.pack(pcall(retfunc, parms)) or {} if retable[1] ~= true then logError(retable[2]) Remote.Send("GiveReturn", key, "__ADONIS_RETURN_ERROR", retable[2]) else print("SENT RETURN"); - Remote.Send("GiveReturn", key, unpack(retable,2)) + Remote.Send("GiveReturn", key, table.unpack(retable, 2)) end end; @@ -257,7 +257,7 @@ return function(Vargs, GetEnv) if Remote.PendingReturns[args[1]] then print("VALID PENDING RETURN") Remote.PendingReturns[args[1]] = nil - service.Events[args[1]]:Fire(unpack(args, 2)) + service.Events[args[1]]:Fire(table.unpack(args, 2)) end end; @@ -364,15 +364,15 @@ return function(Vargs, GetEnv) Fire = function(...) local limits = Process.RateLimits - local limit = (limits and limits.Remote) or 0.01; - local RemoteEvent = Core.RemoteEvent; - local extra = {...}; + local limit = (limits and limits.Remote) or 0.01 + local RemoteEvent = Core.RemoteEvent + local extra = table.pack(...) if RemoteEvent and RemoteEvent.Object then service.Queue("REMOTE_SEND", function() - Remote.Sent = Remote.Sent+1; - RemoteEvent.Object:FireServer({Mode = "Fire", Module = client.Module, Loader = client.Loader, Sent = Remote.Sent, Received = Remote.Received}, unpack(extra)); - task.wait(limit); + Remote.Sent = Remote.Sent + 1 + RemoteEvent.Object:FireServer({Mode = "Fire", Module = client.Module, Loader = client.Loader, Sent = Remote.Sent, Received = Remote.Received}, table.unpack(extra)) + task.wait(limit) end) end end; @@ -383,17 +383,17 @@ return function(Vargs, GetEnv) end; GetFire = function(...) - local RemoteEvent = Core.RemoteEvent; - local limits = Process.RateLimits; - local limit = (limits and limits.Remote) or 0.02; - local extra = {...}; - local returns; + local RemoteEvent = Core.RemoteEvent + local limits = Process.RateLimits + local limit = limits and limits.Remote or 0.02 + local extra = table.unpack(...) + local returns if RemoteEvent and RemoteEvent.Function then local Yield = service.Signal.new(); service.Queue("REMOTE_SEND", function() - Remote.Sent = Remote.Sent+1; + Remote.Sent = Remote.Sent + 1 task.delay(0, function() -- Wait for return in new thread; We don't want to hold the entire fire queue up while waiting for one thing to return since we just want to limit fire speed; returns = { RemoteEvent.Function:InvokeServer({ @@ -402,7 +402,7 @@ return function(Vargs, GetEnv) Loader = client.Loader, Sent = Remote.Sent, Received = Remote.Received - }, unpack(extra)) + }, table.unpack(extra)) } Yield:Fire(returns); @@ -412,10 +412,10 @@ return function(Vargs, GetEnv) end) if not returns then - Yield:Wait(); + Yield:Wait() end - Yield:Destroy(); + Yield:Destroy() if returns then return unpack(returns) @@ -424,34 +424,34 @@ return function(Vargs, GetEnv) end; RawGet = function(...) - local extra = {...}; - local RemoteEvent = Core.RemoteEvent; + local extra = table.pack(...) + local RemoteEvent = Core.RemoteEvent if RemoteEvent and RemoteEvent.Function then - Remote.Sent = Remote.Sent+1; - return RemoteEvent.Function:InvokeServer({Mode = "Get", Module = client.Module, Loader = client.Loader, Sent = Remote.Sent, Received = Remote.Received}, unpack(extra)); + Remote.Sent = Remote.Sent + 1 + return RemoteEvent.Function:InvokeServer({Mode = "Get", Module = client.Module, Loader = client.Loader, Sent = Remote.Sent, Received = Remote.Received}, table.unpack(extra)) end end; - Get = function(com,...) + Get = function(com, ...) Core.LastUpdate = os.time() local ret = Remote.GetFire(Remote.NewEncrypt(com,Core.Key),...) if type(ret) == "table" then - return unpack(ret); + return table.unpack(ret) else - return ret; + return ret end end; OldGet = function(com,...) local returns local key = service.HttpService:GenerateGUID(false) - local waiter = service.New("BindableEvent"); - local event = service.Events[key]:Connect(function(...) print("WE ARE GETTING A RETURN!") returns = {...} waiter:Fire() task.wait() waiter:Fire() waiter:Destroy() end) + local waiter = service.New("BindableEvent") + local event = service.Events[key]:Connect(function(...) print("WE ARE GETTING A RETURN!") returns = table.unpack(...) waiter:Fire() task.wait() waiter:Fire() waiter:Destroy() end) Remote.PendingReturns[key] = true - Remote.Send("GetReturn",com,key,...) + Remote.Send("GetReturn", com, key, ...) print(string.format("GETTING RETURNS? %s", tostring(returns))) - waiter.Event:Wait(); + waiter.Event:Wait() print(string.format("WE GOT IT! %s", tostring(returns))) event:Disconnect() @@ -460,7 +460,7 @@ return function(Vargs, GetEnv) if returns[1] == "__ADONIS_RETURN_ERROR" then error(returns[2]) else - return unpack(returns) + return table.unpack(returns) end else return nil diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index ab67df350d..61d4868e09 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -944,7 +944,7 @@ return function(Vargs, env) end; newSession:ConnectEvent(function(p, cmd, ...) - local args = {...} + local args = table.pack(...) if not p then -- System event(s) if cmd == "LastUserRemoved" then @@ -954,6 +954,7 @@ return function(Vargs, env) if cmd == "SendMessage" then local message = string.sub(tostring(args[1]), 1, 140) local filtered = service.BroadcastFilter(message, p) + if filtered ~= message then Remote.MakeGui(p, "Output", { Title = "Filter error", @@ -981,7 +982,6 @@ return function(Vargs, env) end elseif cmd == "LeaveSession" or cmd == "RemovedFromSession" then newSession:RemoveUser(p) - systemMessage(string.format("%s has left the session", p.Name)) newSession:SendToUsers("UpdatePeerList", getPeerList()) @@ -991,7 +991,6 @@ return function(Vargs, env) end elseif cmd == "EndSession" and p == plr then systemMessage("Session ended") - newSession:End() elseif cmd == "AddPlayerToSession" and (p == plr or Admin.CheckAdmin(p)) then local player = args[1] @@ -999,7 +998,6 @@ return function(Vargs, env) if player then newSession:AddUser(player) newSession:SendToUser(player, "AddedToSession") - systemMessage(string.format("%s added %s to the session", p.Name, player.Name)) Remote.MakeGui(player, "PrivateChat", { Owner = plr; @@ -1008,11 +1006,10 @@ return function(Vargs, env) History = history; CanManageUsers = Admin.CheckAdmin(player); }) - - newSession:SendToUsers("UpdatePeerList", getPeerList()); + newSession:SendToUsers("UpdatePeerList", getPeerList()) end elseif cmd == "RemovePlayerFromSession" and (p == plr or Admin.CheckAdmin(p)) then - local peer = args[1]; + local peer = args[1] if peer then for pr in newSession.Users do @@ -1034,22 +1031,21 @@ return function(Vargs, env) systemMessage("Chat session started") if args[2] then - local gotIcon, status = service.Players:GetUserThumbnailAsync(plr.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size48x48); - + local gotIcon, status = service.Players:GetUserThumbnailAsync(plr.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size48x48) local data = { Name = plr.Name; DisplayName = plr.DisplayName; UserId = plr.UserId; Icon = status and gotIcon or "rbxasset://textures/ui/GuiImagePlaceholder.png"; - }; + } table.insert(history, { Sender = data; Message = args[2]; - }); + }) end - newSession:AddUser(plr); + newSession:AddUser(plr) Remote.MakeGui(plr, "PrivateChat", { Owner = plr; SessionKey = newSession.SessionKey; @@ -1061,7 +1057,6 @@ return function(Vargs, env) for i, v in service.GetPlayers(plr, args[1]) do if v ~= plr then newSession:AddUser(v) - Remote.MakeGui(v, "PrivateChat", { Owner = plr; SessionKey = newSession.SessionKey; diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau index 8af44c182b..626c3e6fad 100644 --- a/MainModule/Server/Core/Admin.luau +++ b/MainModule/Server/Core/Admin.luau @@ -1384,16 +1384,16 @@ return function(Vargs, GetEnv) [`{playerPrefix}client`] = true; [`{playerPrefix}userpanel`] = true; [":adonissettings"] = true; - } --return Admin.CommandCache[alias:lower()] --// Alternatively, we could make it so you can't overwrite ANY existing commands... return blacklist[alias]; end; GetArgs = function(msg, num, ...) - local args = Functions.Split((string.match(msg, `^.-{Settings.SplitKey}(.+)`) or ''),Settings.SplitKey,num) or {} - for _, v in {...} do - table.insert(args, v) + local newArgs = table.pack(...) + local args = Functions.Split(string.match(msg, `^.-{Settings.SplitKey}(.+)`) or "", Settings.SplitKey, num) or table.create(newArgs.n) + for i = 1, newArgs.n do + table.insert(args, newArgs[i]) end return args end; diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index 140334fe40..2d18d007ba 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -1529,13 +1529,13 @@ return function(Vargs, GetEnv) AdonisDebugAPIBindable.Name = "Adonis_Debug_API" AdonisDebugAPIBindable.Parent = service.ReplicatedStorage AdonisDebugAPIBindable.OnInvoke = function(DebugCommand,...) - local args = {...} + local args = table.pack(...) if DebugCommand == "RunEnvFunc" then local FunctionInEnvToRunPath = args[1] if FunctionInEnvToRunPath and type(FunctionInEnvToRunPath) == "string" then local realEnvResult, isResultPointer = getRealEnvResult(FunctionInEnvToRunPath) - return realEnvResult(table.unpack(args,2,#args)) + return realEnvResult(table.unpack(args, 2, args.n)) end elseif DebugCommand == "GetEnvTableMeta" then local TableInEnvPath = args[1] @@ -1549,7 +1549,7 @@ return function(Vargs, GetEnv) if TableInEnvPath and type(TableInEnvPath) == "string" then local realEnvResult, isResultPointer = getRealEnvResult(TableInEnvPath) local metaTableInEnv = getmetatable(realEnvResult) - local result = metaTableInEnv[FuncToRun](realEnvResult,table.unpack(args,3,#args)) + local result = metaTableInEnv[FuncToRun](realEnvResult,table.unpack(args, 3, args.n)) local resultPointer = service.HttpService:GenerateGUID(false) pointers[resultPointer] = result diff --git a/MainModule/Server/Core/Process.luau b/MainModule/Server/Core/Process.luau index b12215611d..afae7505f7 100644 --- a/MainModule/Server/Core/Process.luau +++ b/MainModule/Server/Core/Process.luau @@ -353,7 +353,7 @@ return function(Vargs, GetEnv) else local keys = Remote.Clients[tostring(p.UserId)] if keys and select("#", ...) <= Process.RemoteMaxArgCount then - local args = {...} + local args = table.pack(...) local rateLimitCheck, _, _, curRemoteRate = RateLimit(p, "Remote") keys.LastUpdate = os.time() @@ -375,7 +375,7 @@ return function(Vargs, GetEnv) return keys.Key --else - --Anti.Detected(p, "kick","Communication Key Error (r10003)") + --Anti.Detected(p, "kick", "Communication Key Error (r10003)") end elseif cliData.Mode == "Fire" then if keys.LoadingStatus == "WAITING_FOR_KEY" then @@ -398,7 +398,7 @@ return function(Vargs, GetEnv) end elseif rateLimitCheck and string.len(com) <= Remote.MaxLen then local comString = Decrypt(com, keys.Key, keys.Cache) - local command = (cliData.Mode == "Get" and Remote.Returnables[comString]) or Remote.Commands[comString] + local command = cliData.Mode == "Get" and Remote.Returnables[comString] or Remote.Commands[comString] AddLog("RemoteFires", { Text = string.format("%s fired %s; Arg1: %s", p.Name, comString, service.MaxLen(tostring(args[1]), 50)); @@ -417,8 +417,8 @@ return function(Vargs, GetEnv) Anti.Detected(p, "Kick", "Invalid Remote Data (r10004)") end elseif rateLimitCheck and RateLimit(p, "RateLog") then - Anti.Detected(p, "Log", string.format("Firing RemoteEvent too quickly (>Rate: %s/sec)", curRemoteRate)); - warn(string.format("%s is firing Adonis's RemoteEvent too quickly (>Rate: %s/sec)", p.Name, curRemoteRate)); + Anti.Detected(p, "Log", string.format("Firing RemoteEvent too quickly (>Rate: %s/sec)", curRemoteRate)) + warn(string.format("%s is firing Adonis's RemoteEvent too quickly (>Rate: %s/sec)", p.Name, curRemoteRate)) end else Anti.Detected(p, "Log", "Out of Sync (r10005)") diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index 33d47f027a..a80598c333 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -598,9 +598,9 @@ return function(Vargs, GetEnv) Description = "Loads and runs the given lua string"; Function = function(p,args,data) local oError = error - local newenv = GetEnv(getfenv(),{ - print = function(...) local args, str = table.pack(...), "" for i = 1, args.n do str ..= `{(i > 1 and " " or "")}{args[i]}` end Remote.Terminal.LiveOutput(p, `PRINT: {str}`) end; - warn = function(...) local args, str = table.pack(...), "" for i = 1, args.n do str ..= `{(i > 1 and " " or "")}{args[i]}` end Remote.Terminal.LiveOutput(p, `WARN: {str}`) end; + local newenv = GetEnv(getfenv(), { + print = function(...) local args = table.pack(...) for i = 1, args.n do args[i] = tostring(args[i]) end Remote.Terminal.LiveOutput(p, `PRINT: {table.concat(args, " ")}`) end; + warn = function(...) local args = table.pack(...) for i = 1, args.n do args[i] = tostring(args[i]) end Remote.Terminal.LiveOutput(p, `WARN: {table.concat(args, " ")}`) end; error = function(reason, level) if level ~= nil and type(level) ~= "number" then oError(string.format("bad argument #2 to 'error' (number expected, got %s)", type(level)), 2) @@ -670,7 +670,7 @@ return function(Vargs, GetEnv) Description = "Disconnects the specified player from the server"; Function = function(p, args, data) local plrs = service.GetPlayers(p,args[1]) - if #plrs>0 then + if #plrs > 0 then local ret = {} for _,v in plrs do v:Kick(args[2] or "Disconnected by server") @@ -690,8 +690,8 @@ return function(Vargs, GetEnv) Description = "Calls :BreakJoints() on the target player's character"; Function = function(p,args,data) local plrs = service.GetPlayers(p,args[1]) - if #plrs>0 then - for _,v in plrs do + if #plrs > 0 then + for _, v in plrs do local ret = {} local char = v.Character if char and char.ClassName == "Model" then @@ -715,9 +715,9 @@ return function(Vargs, GetEnv) Description = "Calls :LoadCharacter() on the target player"; Function = function(p,args,data) local plrs = service.GetPlayers(p,args[1]) - if #plrs>0 then + if #plrs > 0 then local ret = {} - for _,v in plrs do + for _, v in plrs do v:LoadCharacter() table.insert(ret, `Respawned {service.FormatPlayer(v)}`) end @@ -737,7 +737,7 @@ return function(Vargs, GetEnv) p:Kick(args[1] or "No Given Reason") end) - for _,v in service.Players:GetPlayers() do + for _, v in service.Players:GetPlayers() do v:Kick(args[1] or "No Given Reason") end end @@ -753,21 +753,21 @@ return function(Vargs, GetEnv) GetReturn = function(p: Player, args: {[number]: any}) local com = args[1] local key = args[2] - local parms = {unpack(args,3)} + local parms = table.pack(table.unpack(args, 3)) local retfunc = Remote.Returnables[com] - local retable = (retfunc and {pcall(retfunc,p,parms)}) or {} + local retable = retfunc and table.pack(pcall(retfunc, p, parms)) or {} if retable[1] ~= true then - logError(p,retable[2]) + logError(p, retable[2]) Remote.Send(p, "GiveReturn", key, "__ADONIS_RETURN_ERROR", retable[2]) else - Remote.Send(p, "GiveReturn", key, unpack(retable,2)) + Remote.Send(p, "GiveReturn", key, table.unpack(retable, 2)) end end; GiveReturn = function(p: Player,args: {[number]: any}) if Remote.PendingReturns[args[1]] then Remote.PendingReturns[args[1]] = nil - service.Events[args[1]]:Fire(unpack(args,2)) + service.Events[args[1]]:Fire(table.unpack(args, 2)) end end; @@ -860,7 +860,7 @@ return function(Vargs, GetEnv) local value = args[2] if type(setting) == "string" then - if setting == 'Prefix' or setting == 'AnyPrefix' or setting == 'SpecialPrefix' then + if setting == "Prefix" or setting == "AnyPrefix" or setting == "SpecialPrefix" then local orig = Settings[setting] for _, v in Commands do if v.Prefix == orig then @@ -1020,15 +1020,15 @@ return function(Vargs, GetEnv) local Variable = se[Name] local oError = error - local newenv = GetEnv(getfenv(),{ - print = function(...) local args, str = table.pack(...), "" for i = 1, args.n do str ..= `{(i > 1 and " " or "")}{args[i]}` end Remote.Terminal.LiveOutput(p, `PRINT: {str}`) end; - warn = function(...) local args, str = table.pack(...), "" for i = 1, args.n do str ..= `{(i > 1 and " " or "")}{args[i]}` end Remote.Terminal.LiveOutput(p, `WARN: {str}`) end; + local newenv = GetEnv(getfenv(), { + print = function(...) local args = table.pack(...) for i = 1, args.n do args[i] = tostring(args[i]) end Remote.Terminal.LiveOutput(p, `PRINT: {table.concat(args, " ")}`) end; + warn = function(...) local args = table.pack(...) for i = 1, args.n do args[i] = tostring(args[i]) end Remote.Terminal.LiveOutput(p, `WARN: {table.concat(args, " ")}`) end; error = function(reason, level) if level ~= nil and type(level) ~= "number" then oError(string.format("bad argument #2 to 'error' (number expected, got %s)", type(level)), 2) end - Remote.MakeGui(p, "Output",{Title = 'LUA_DEMAND_ERROR'; Message = `{reason}`}) + Remote.MakeGui(p, "Output", {Title = 'LUA_DEMAND_ERROR'; Message = `{reason}`}) oError(`Adonis ScriptEditor error: {reason}`, (level or 1) + 1) end; }) @@ -1183,8 +1183,9 @@ return function(Vargs, GetEnv) end end; - OldGet = function(p: Player, com: string, ...) + OldGet = function(p: Player, com: string, ...) -- TODO: Add oldget (both on client and server) to backwards compatibility plugin local keys = Remote.Clients[tostring(p.UserId)] + if keys and keys.RemoteReady == true then local returns, finished local key = service.HttpService:GenerateGUID(false) @@ -1192,22 +1193,22 @@ return function(Vargs, GetEnv) local event = service.Events[key]:Connect(function(...) print("WE ARE GETTING A RETURN!") finished = true returns = {...} Yield:Fire() end) Remote.PendingReturns[key] = true - Remote.Send(p,"GetReturn",com,key,...) + Remote.Send(p, "GetReturn", com, key, ...) - print("GETTING RETURN"); + print("GETTING RETURN") if not finished and not returns and p.Parent then local pEvent = service.Players.PlayerRemoving:Connect(function(plr) if plr == p then event:Fire() end end) task.delay(600, function() if not finished then event:Fire() end end) - print(string.format("WAITING FOR RETURN %s", tostring(returns))); - Yield:Wait(); - Yield:Destroy(); + print(string.format("WAITING FOR RETURN %s", tostring(returns))) + Yield:Wait() + Yield:Destroy() - print(string.format("WE GOT IT! %s", tostring(returns))); + print(string.format("WE GOT IT! %s", tostring(returns))) pEvent:Disconnect() pEvent = nil end - print("GOT RETURN"); + print("GOT RETURN") event:Disconnect() event = nil @@ -1215,7 +1216,7 @@ return function(Vargs, GetEnv) if returns[1] == "__ADONIS_RETURN_ERROR" then error(returns[2]) else - return unpack(returns) + return table.unpack(returns) end else return diff --git a/MainModule/Server/Plugins/Debug_Specific.luau b/MainModule/Server/Plugins/Debug_Specific.luau index 99206586a2..f03793be6f 100644 --- a/MainModule/Server/Plugins/Debug_Specific.luau +++ b/MainModule/Server/Plugins/Debug_Specific.luau @@ -191,17 +191,17 @@ function WrapAdonisEnv(toWrap, chain) return toWrap elseif type(toWrap[k]) == "function" then return function(...) - local args = {...} - local unwrappedArgs = {} - - for i,arg in ipairs(args) do - if arg.GetObject then + local args = table.pack(...) + local unwrappedArgs = table.create(args.n) + + for i, arg in args do + if (type(arg) == "table" or type(arg) == "userdata") and arg.GetObject then unwrappedArgs[i] = arg.GetObject else unwrappedArgs[i] = arg end end - print(unwrappedArgs) + --print(unwrappedArgs) DebugApiBindable:Invoke("RunEnvFunc", tonumber(chain) and chain or curChain:sub(1, #curChain - 3), table.unpack(unwrappedArgs)) end else diff --git a/MainModule/Server/Shared/FiOne/init.luau b/MainModule/Server/Shared/FiOne/init.luau index ced6a41123..1c981eb375 100644 --- a/MainModule/Server/Shared/FiOne/init.luau +++ b/MainModule/Server/Shared/FiOne/init.luau @@ -511,7 +511,7 @@ local function new_threaded_closure(proto, env, upval) error(args[2], 2) end - return table.unpack(args, 2) + return table.unpack(args, 2, args.n) end end diff --git a/MainModule/Server/Shared/Service.luau b/MainModule/Server/Shared/Service.luau index 6ad48f0d00..099118de6f 100644 --- a/MainModule/Server/Shared/Service.luau +++ b/MainModule/Server/Shared/Service.luau @@ -122,7 +122,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) local function taskFunc(...) TrackedTasks[index] = data data.Status = "Running" - data.Returns = {xpcall(func, errHandler, ...)} + data.Returns = table.pack(xpcall(func, errHandler, ...)) if not data.Returns[1] then data.Status = "Errored" @@ -131,7 +131,7 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end TrackedTasks[index] = nil - return unpack(data.Returns) + return table.unpack(data.Returns) end if isThread then @@ -670,12 +670,12 @@ return function(errorHandler, eventChecker, fenceSpecific, env) end end - local args = {pcall(func, ...)} + local args = table.pack(pcall(func, ...)) local success = args[1] if not success then warn(args[2]) else - return unpack(args, 2) + return table.unpack(args, 2) end end }) From c4907528100b18045618cdec722b7d6b7619ca4f Mon Sep 17 00:00:00 2001 From: Sakari <36762684+sakari119@users.noreply.github.com> Date: Thu, 21 Nov 2024 04:25:20 +1100 Subject: [PATCH 104/189] Change :resize to use Model :ScaleTo() method (#1633) * Changed Resize to use :ScaleTo() Changes the resize command under "Fun" to use the new modern Roblox method https://create.roblox.com/docs/reference/engine/classes/Model#ScaleTo to change player size * Update Fun.luau * Removed code comments of pull request * Simplyfied Resize Function * Changed isA to IsA --- MainModule/Server/Commands/Fun.luau | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index c980a06fa3..a74f24c2eb 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -3702,7 +3702,9 @@ return function(Vargs, env) continue end - if human and human.RigType == Enum.HumanoidRigType.R15 then + if human and char:IsA("Model") then + char:ScaleTo(num) + elseif human and human.RigType == Enum.HumanoidRigType.R15 then for _, val in human:GetChildren() do if val:IsA("NumberValue") and val.Name:match(".*Scale") then val.Value *= num From e481a025114409feb791a3a183a714efe25c2ec8 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Wed, 20 Nov 2024 17:27:25 +0000 Subject: [PATCH 105/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 420811d83c..05b6ac6e9e 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -67,6 +67,18 @@ return { "(Git/ccuser44) Remove unnecessary cruft from server (#1682)"; "(Git/ccuser44) Fix many annoying bugs (#1647)"; "(Git/ccuser44) Remove FiOne copy artifact and update FiOne (#1736)"; + "(Git/ccuser44) Fix donor perks not updating live (#1741)"; + "(Git/ccuser44) Add more animatedheads (#1740)"; + "(Git/ccuser44) Fix incompatibility with legacy `service.Yield` (#1739)"; + "(Git/ccuser44) Optimise SanitizeString and filter functions (#1738)"; + "(Git/ccuser44) Improve service readability (#1737)"; + "(Git/ccuser44) Make AudioPlayer used shared GoodSignal library (#1735)"; + "(Git/ccuser44) Use a datastore cache for Adonis Alerts (#1729)"; + "(Git/ccuser44) Cache F3X (#1710)"; + "(Git/ccuser44) Add preliminary support for oldlogs encryption (#1696)"; + "(Git/ccuser44) Delete Dependencies/Adonis (#1681)"; + "(Git/ccuser44) Fix vararg packing (#1679)"; + "(Git/sakari119) Change :resize to use Model :ScaleTo() method (#1633)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 88840ca57055326f4d166648a78a4db97fa7eaf5 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Wed, 20 Nov 2024 21:57:49 +0000 Subject: [PATCH 106/189] Update labeling.yml --- .github/workflows/labeling.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeling.yml b/.github/workflows/labeling.yml index f6764ebc32..9384b026c6 100644 --- a/.github/workflows/labeling.yml +++ b/.github/workflows/labeling.yml @@ -7,7 +7,7 @@ permissions: on: issues: types: [opened] - pull_request: + pull_request_target: types: [opened] jobs: autotriage: From c25fdb8d1a6058a02fb3bd34b18e65262fcd760d Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Wed, 20 Nov 2024 22:12:12 +0000 Subject: [PATCH 107/189] Update labeling.yml --- .github/workflows/labeling.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/labeling.yml b/.github/workflows/labeling.yml index 9384b026c6..ba49463276 100644 --- a/.github/workflows/labeling.yml +++ b/.github/workflows/labeling.yml @@ -8,7 +8,7 @@ on: issues: types: [opened] pull_request_target: - types: [opened] + types: [opened, synchronize, ready_for_review, auto_merge_enabled, unlabeled] jobs: autotriage: runs-on: ubuntu-latest @@ -16,5 +16,6 @@ jobs: - uses: github/issue-labeler@v3.4 with: configuration-path: .github/labeler.yml - enable-versioned-regex: 0 - repo-token: ${{ github.token }} + enable-versioned-regex: false + repo-token: ${{ secrets.GITHUB_TOKEN }} + sync-labels: 1 From ccbfede323ca40cc727973e8935eceee6d6c67e8 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Thu, 21 Nov 2024 00:32:19 +0200 Subject: [PATCH 108/189] Fix :removecamera not working (#1746) * Fix `:removecamera` not working * Update Remote.luau * Nevermind --- MainModule/Client/Core/Remote.luau | 4 ++-- MainModule/Server/Commands/Moderators.luau | 13 +++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/MainModule/Client/Core/Remote.luau b/MainModule/Client/Core/Remote.luau index f9b21a046c..bc84ddcfee 100644 --- a/MainModule/Client/Core/Remote.luau +++ b/MainModule/Client/Core/Remote.luau @@ -386,7 +386,7 @@ return function(Vargs, GetEnv) local RemoteEvent = Core.RemoteEvent local limits = Process.RateLimits local limit = limits and limits.Remote or 0.02 - local extra = table.unpack(...) + local extra = table.pack(...) local returns if RemoteEvent and RemoteEvent.Function then @@ -446,7 +446,7 @@ return function(Vargs, GetEnv) local returns local key = service.HttpService:GenerateGUID(false) local waiter = service.New("BindableEvent") - local event = service.Events[key]:Connect(function(...) print("WE ARE GETTING A RETURN!") returns = table.unpack(...) waiter:Fire() task.wait() waiter:Fire() waiter:Destroy() end) + local event = service.Events[key]:Connect(function(...) print("WE ARE GETTING A RETURN!") returns = table.pack(...) waiter:Fire() task.wait() waiter:Fire() waiter:Destroy() end) Remote.PendingReturns[key] = true Remote.Send("GetReturn", com, key, ...) diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index 61d4868e09..d5c0b76446 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -1428,17 +1428,14 @@ return function(Vargs, env) Description = "Deletes the camera if it exists"; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) - for i,v in Variables.Cameras do - if string.lower(args[1]) == v.Name then - local cam = workspace:FindFirstChild(v) - - Variables.Cameras[i] = nil - - if cam and cam:IsA("Part") then - cam:Destroy() + for i, v in Variables.Cameras do + if string.sub(string.lower(v.Name), 1, #args[1]) == string.lower(args[1]) then + if v.Brick then + v.Brick:Destroy() end Functions.Hint(`Deleted camera {v.Name}`, {plr}) + table.remove(Variables.Cameras, i) end end end From fe9168995e723a512466c79864bdbd14dd6cc3ae Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:16:20 +0200 Subject: [PATCH 109/189] Fix issue workflow (#1756) --- .github/workflows/close_issues.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/close_issues.yml b/.github/workflows/close_issues.yml index 461542c629..109193e368 100644 --- a/.github/workflows/close_issues.yml +++ b/.github/workflows/close_issues.yml @@ -11,13 +11,13 @@ jobs: - uses: actions/checkout@v4.2.1 - name: Close issue - if: github.event.label.name == '❌ invalid' && !(contains(github.event.issue.body, 'F3X/Building Tools')) && + if: github.event.label.name == '❌ invalid' && !(contains(github.event.issue.body, 'F3X/Building Tools')) run: gh issue close --comment "This issue has been closed as invalid. Please look at our [contribution guide](https://github.com/Epix-Incorporated/Adonis/blob/master/CONTRIBUTING.md)" --reason "not planned" "1" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Close BTools issue - if: github.event.label.name == '❌ invalid' && (contains(github.event.issue.body, 'F3X/Building Tools')) && + if: github.event.label.name == '❌ invalid' && (contains(github.event.issue.body, 'F3X/Building Tools')) run: gh issue close --comment "We use F3X for our building tools system. Please [make an issue ticket](https://github.com/F3XTeam/RBX-Building-Tools/issues/new) on the F3X Team BTools repository." --reason "not planned" "1" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From cdefde6a5f9c6887afe911fc6c5455e8e8003053 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:31:10 +0000 Subject: [PATCH 110/189] Add local copy of runner --- .github/workflows/labeling.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/labeling.yml b/.github/workflows/labeling.yml index ba49463276..b415f05de6 100644 --- a/.github/workflows/labeling.yml +++ b/.github/workflows/labeling.yml @@ -2,7 +2,7 @@ name: Issue labeling permissions: issues: write - contents: read + contents: read on: issues: @@ -13,7 +13,10 @@ jobs: autotriage: runs-on: ubuntu-latest steps: - - uses: github/issue-labeler@v3.4 + - uses: actions/checkout@v4 # Uploads repository content to the runner + with: + repository: "Epix-Incorporated/Adonis" + - uses: actions/labeler@v5 with: configuration-path: .github/labeler.yml enable-versioned-regex: false From 10c3e6509a62c84e435d82382e9cb1123b202203 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:41:07 +0000 Subject: [PATCH 111/189] Fix lint until lint is fixed --- MainModule/Server/Core/Functions.luau | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 845c114c5b..934071e7c1 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1084,7 +1084,12 @@ return function(Vargs, GetEnv) end; Cape = function(player, isdon, material, color, decal, reflect) - material = assert(Enum.Material:FromName(material or "Neon"), "Invalid material value") + material = material or "Neon" + if not Functions.GetEnumValue(Enum.Material, material) then + error("Invalid material value") + end + --material = assert(Enum.Material:FromName(material or "Neon"), "Invalid material value") + Functions.UnCape(player) local torso = player.Character:FindFirstChild("HumanoidRootPart") @@ -1138,6 +1143,17 @@ return function(Vargs, GetEnv) end end; + GetEnumValue = function(enum, item) + local valid = false + for _,v in enum:GetEnumItems() do + if v.Name == item then + valid = v.Value + break + end + end + return valid + end; + ApplyBodyPart = function(character, model) -- NOTE: Use HumanoidDescriptions to apply body parts where possible, unless applying custom parts local humanoid = character:FindFirstChildOfClass("Humanoid") @@ -1162,7 +1178,8 @@ return function(Vargs, GetEnv) end elseif rigType == "R15" then for _,v in part:GetChildren() do - local value = Enum.BodyPartR15:FromName(v.Name) + local value = Functions.GetEnumValue(Enum.BodyPartR15, v.Name) + --local value = Enum.BodyPartR15:FromName(v.Name) if value then humanoid:ReplaceBodyPartR15(value, v:Clone()) end From 09edcbe10ce049970e7e6e81bfc4fc5fcd24de3b Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:45:14 +0000 Subject: [PATCH 112/189] Patch lint until selene fix --- MainModule/Server/Commands/Moderators.luau | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index d5c0b76446..28ac795b70 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -5416,7 +5416,15 @@ return function(Vargs, env) local AssetTypeNameDescriptionOverides = { DynamicHead = "Head" } - local typeEnum = Enum.AvatarAssetType:FromValue(productInfo.AssetTypeId) + --local typeEnum = Enum.AvatarAssetType:FromValue(productInfo.AssetTypeId) + local typeId = productInfo.AssetTypeId + local typeEnum + for _, enum in pairs(Enum.AvatarAssetType:GetEnumItems()) do + if enum.Value == typeId then + typeEnum = enum + break + end + end for _, v: Player in service.GetPlayers(plr, args[1]) do local humanoid: Humanoid? = v.Character and v.Character:FindFirstChildOfClass("Humanoid") From 23637789f06376097a5d02a1a5dfc06de355283a Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:00:57 +0200 Subject: [PATCH 113/189] Allow client side _G API to be accessed (#1687) * Create HashLib.luau * Add `Functions.SHA256` * Add `Functions.SHA256` * Fix name * Send _G API key to client * Allow client side _G API access via hashing * Pool more _G API settings * Allow client to pool _G API settings * Fix typo * Optimise assert * Fix client side API error --- MainModule/Client/Core/Core.luau | 49 ++++----- MainModule/Client/Core/Functions.luau | 2 + MainModule/Client/Core/Remote.luau | 6 +- MainModule/Server/Core/Functions.luau | 2 + MainModule/Server/Core/Process.luau | 7 +- MainModule/Server/Core/Remote.luau | 12 ++- MainModule/Server/Shared/HashLib.luau | 146 ++++++++++++++++++++++++++ 7 files changed, 189 insertions(+), 35 deletions(-) create mode 100644 MainModule/Server/Shared/HashLib.luau diff --git a/MainModule/Client/Core/Core.luau b/MainModule/Client/Core/Core.luau index b3af16e692..297a7629fa 100644 --- a/MainModule/Client/Core/Core.luau +++ b/MainModule/Client/Core/Core.luau @@ -178,8 +178,8 @@ return function(Vargs, GetEnv) local StartLoop = service.StartLoop local ReadOnly = service.ReadOnly local UnWrap = service.UnWrap - local service = nil - local client = nil + local service = service + local client = client local _G = _G local setmetatable = setmetatable local type = type @@ -217,8 +217,6 @@ return function(Vargs, GetEnv) } local API = { - Access = ReadOnly({}, nil, nil, true); - --[[ Access = service.MetaFunc(function(...) local args = {...} local key = args[1] @@ -233,33 +231,30 @@ return function(Vargs, GetEnv) targ = client[ind] end - if client.G_Access and key == client.G_Access_Key and targ and client.Allowed_API_Calls[ind] then - if type(targ) == "table" then - return service.NewProxy { - __index = function(tab,inde) - if targ[inde] ~= nil and API_Special[inde] == nil or API_Special[inde] == true then - if targ[inde]~=nil and type(targ[inde]) == "table" and client.G_Access_Perms == "Read" then - return service.ReadOnly(targ[inde]) - else - return targ[inde] - end - elseif API_Special[inde] == false then - error(`Access Denied: {inde}`) + assert(client.G_Access and (key == Variables.G_Access_Key or type(key) == "string" and Functions.SHA256(key..game.GameId) == Variables.G_Access_Key) and targ and client.Allowed_API_Calls[ind], "Incorrect key or G_Access is disabled") + + if type(targ) == "table" then + return service.NewProxy { + __index = function(tab, inde) + if targ[inde] ~= nil and API_Special[inde] == nil or API_Special[inde] == true then + if targ[inde] ~= nil and type(targ[inde]) == "table" and client.G_Access_Perms == "Read" then + return service.ReadOnly(targ[inde]) else - error(`Could not find {inde}`) + return targ[inde] end - end; - __newindex = function(tabl,inde,valu) - error("Read-only") - end; - __metatable = true; - } - end - else - error("Incorrect key or G_Access is disabled") + elseif API_Special[inde] == false then + error(`Access Denied: {inde}`) + else + error(`Could not find {inde}`) + end + end; + __newindex = function(tabl, inde, valu) + error("Read-only") + end; + __metatable = true; + } end end); - --]] Scripts = ReadOnly({ ExecutePermission = (function(srcScript, code) diff --git a/MainModule/Client/Core/Functions.luau b/MainModule/Client/Core/Functions.luau index 8c2c4bfc86..c657685c70 100644 --- a/MainModule/Client/Core/Functions.luau +++ b/MainModule/Client/Core/Functions.luau @@ -1911,6 +1911,8 @@ return function(Vargs, GetEnv) end end; + SHA256 = require(client.Shared.HashLib).SHA256; + GetFriendsOnline = function(maxFriends) return service.Players.LocalPlayer:GetFriendsOnline(maxFriends) end; diff --git a/MainModule/Client/Core/Remote.luau b/MainModule/Client/Core/Remote.luau index bc84ddcfee..df01b1a117 100644 --- a/MainModule/Client/Core/Remote.luau +++ b/MainModule/Client/Core/Remote.luau @@ -63,12 +63,12 @@ return function(Vargs, GetEnv) --// Get settings log("Get settings"); - local settings = client.Remote.Get("Setting",{"G_API","Allowed_API_Calls","HelpButtonImage"}) + local settings = client.Remote.Get("Setting",{"G_API","G_Access","G_Access_Perms","Allowed_API_Calls","HelpButtonImage"}) if settings then client.G_API = settings.G_API - --client.G_Access = settings.G_Access + client.G_Access = settings.G_Access --client.G_Access_Key = settings.G_Access_Key - --client.G_Access_Perms = settings.G_Access_Perms + client.G_Access_Perms = settings.G_Access_Perms client.Allowed_API_Calls = settings.Allowed_API_Calls client.HelpButtonImage = settings.HelpButtonImage else diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 934071e7c1..1701f2b057 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1634,6 +1634,8 @@ return function(Vargs, GetEnv) end end; + SHA256 = require(server.Shared.HashLib).SHA256; + ParseBrickColor = function(str: string, allowNil: boolean?) if not str and allowNil then return nil diff --git a/MainModule/Server/Core/Process.luau b/MainModule/Server/Core/Process.luau index afae7505f7..6520d11d48 100644 --- a/MainModule/Server/Core/Process.luau +++ b/MainModule/Server/Core/Process.luau @@ -81,6 +81,7 @@ return function(Vargs, GetEnv) end end) + Remote._globalAccessHash = Functions.SHA256(Settings.G_Access_Key..game.GameId) Process.Init = nil AddLog("Script", "Processing Module Initialized") end; @@ -946,7 +947,11 @@ return function(Vargs, GetEnv) Remote.Send(p, "Function", "KeyBindListener", PlayerData.Keybinds or {}) -- // Send server variables to client - Remote.Send(p, "SetVariables", { TopBarShift = Settings.TopBarShift, NightlyMode = server.Data.NightlyMode or server.Data.ModuleID == 8612978896 }) + Remote.Send(p, "SetVariables", { + TopBarShift = Settings.TopBarShift, + NightlyMode = server.Data.NightlyMode or server.Data.ModuleID == 8612978896, + G_Access_Key = Remote._globalAccessHash + }) --// Load some playerdata stuff if type(PlayerData.Client) == "table" then diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau index a80598c333..498fb89e48 100644 --- a/MainModule/Server/Core/Remote.luau +++ b/MainModule/Server/Core/Remote.luau @@ -83,6 +83,10 @@ return function(Vargs, GetEnv) PlayerPrefix = true; SpecialPrefix = true; ConsoleKeyCode = true; + G_API = true; + G_Access = true; + G_Access_Perms = true; + Allowed_API_Calls = true; MusicList = true; }; @@ -249,11 +253,11 @@ return function(Vargs, GetEnv) Trello_AppKey = true; Trello_Token = true; - G_API = true; - G_Access = true; + --G_API = true; + --G_Access = true; G_Access_Key = true; - G_Access_Perms = true; - Allowed_API_Calls = true; + --G_Access_Perms = true; + --Allowed_API_Calls = true; WebPanel_ApiKey = true; WebPanel_Enabled = true; diff --git a/MainModule/Server/Shared/HashLib.luau b/MainModule/Server/Shared/HashLib.luau new file mode 100644 index 0000000000..45fb92993a --- /dev/null +++ b/MainModule/Server/Shared/HashLib.luau @@ -0,0 +1,146 @@ +--!native +--!optimize 2 +--!strict +--[[ + Description: SHA256 digest hash + Author: XoifailTheGod + Date: 2024 + Link: https://devforum.roblox.com/t/fastest-sha256-module/3180016 +]] + +local MODULO = 2^32 +local BYTE, DWORD = 1, 4 + +local CONSTANTS = buffer.create(64 * DWORD) do -- CONSTANTS = k + local RoundConstants = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + } + + for Index, Constant in ipairs(RoundConstants) do + local BufferOffset = (Index - 1) * DWORD + buffer.writeu32(CONSTANTS, BufferOffset, Constant) + end +end + +local HASH_VALUES = buffer.create(8 * DWORD) do -- HASH_VALUES = h0-h7 + buffer.writeu32(HASH_VALUES, 0, 0x6a09e667) + buffer.writeu32(HASH_VALUES, 4, 0xbb67ae85) + buffer.writeu32(HASH_VALUES, 8, 0x3c6ef372) + buffer.writeu32(HASH_VALUES, 12, 0xa54ff53a) + buffer.writeu32(HASH_VALUES, 16, 0x510e527f) + buffer.writeu32(HASH_VALUES, 20, 0x9b05688c) + buffer.writeu32(HASH_VALUES, 24, 0x1f83d9ab) + buffer.writeu32(HASH_VALUES, 28, 0x5be0cd19) +end + +local function ProcessNumber(Input: number, Length: number): buffer + local OutputBuffer = buffer.create(Length) + + for Index = Length - 1, 0, -1 do + local Remainder = Input % 256 + buffer.writeu8(OutputBuffer, Index, Remainder) + Input = bit32.rshift(Input, 8) + end + + return OutputBuffer +end + +local function PreProcess(Content: buffer): (buffer, number) + local ContentLength = buffer.len(Content) + local Padding = (64 - ((ContentLength + 9) % 64)) % 64 + + local NewContentLength = ContentLength + 1 + Padding + 8 + local NewContent = buffer.create(NewContentLength) + buffer.copy(NewContent, 0, Content) + buffer.writeu8(NewContent, ContentLength, 128) + local Length8 = ContentLength * 8 + for Index = 7, 0, -1 do + local Remainder = Length8 % 256 + buffer.writeu8(NewContent, Index + ContentLength + 1 + Padding, Remainder) + Length8 = (Length8 - Remainder) / 256 + end + + return NewContent, NewContentLength +end + +local Offsets = buffer.create(256) +local function DigestBlock(Blocks: buffer, Offset: number, A: number, B: number, C: number, D: number, E: number, F: number, G: number, H: number) + for BlockIndex = 0, 60, 4 do + local BlockBufferIndex = Offset + BlockIndex + local Word = bit32.byteswap(buffer.readu32(Blocks, BlockBufferIndex)) + + buffer.writeu32(Offsets, BlockIndex, Word) + end + + for Index = 16 * 4, 63 * 4, 4 do + local Sub15 = buffer.readu32(Offsets, Index - (15 * 4)) + local Sub2 = buffer.readu32(Offsets, Index - (2 * 4)) + + local Sub16 = buffer.readu32(Offsets, Index - (16 * 4)) + local Sub7 = buffer.readu32(Offsets, Index - (7 * 4)) + + local S0 = bit32.bxor(bit32.rrotate(Sub15, 7), bit32.rrotate(Sub15, 18), bit32.rshift(Sub15, 3)) + local S1 = bit32.bxor(bit32.rrotate(Sub2, 17), bit32.rrotate(Sub2, 19), bit32.rshift(Sub2, 10)) + + buffer.writeu32(Offsets, Index, (Sub16 + S0 + Sub7 + S1)) + end + + local OldA, OldB, OldC, OldD, OldE, OldF, OldG, OldH = A, B, C, D, E, F, G, H + + for BufferIndex = 0, 63 * 4, 4 do + local S1 = bit32.bxor(bit32.rrotate(E, 6), bit32.rrotate(E, 11), bit32.rrotate(E, 25)) + local Ch = bit32.bxor(bit32.band(E, F), bit32.band(bit32.bnot(E), G)) + local Temp1 = H + S1 + Ch + buffer.readu32(CONSTANTS, BufferIndex) + buffer.readu32(Offsets, BufferIndex) + local S0 = bit32.bxor(bit32.rrotate(A, 2), bit32.rrotate(A, 13), bit32.rrotate(A, 22)) + local Maj = bit32.bxor(bit32.band(A, B), bit32.band(A, C), bit32.band(B, C)) + local Temp2 = S0 + Maj + + H = G + G = F + F = E + E = D + Temp1 + D = C + C = B + B = A + A = Temp1 + Temp2 + end + + return (A + OldA) % MODULO, (B + OldB) % MODULO, (C + OldC) % MODULO, (D + OldD) % MODULO, (E + OldE) % MODULO, (F + OldF) % MODULO, (G + OldG) % MODULO, (H + OldH) % MODULO +end + +local HashValues = buffer.create(32) +local FormatString = string.rep("%08x", 8) +local function SHA256(Message: buffer | string, Salt: (buffer | string)?): string + Message = type(Message) == "string" and buffer.fromstring(Message) or Message + Salt = type(Salt) == "string" and buffer.fromstring(Salt) or Salt + + if Salt and buffer.len(Salt) > 0 then + local MessageWithSalt = buffer.create(buffer.len(Message) + buffer.len(Salt)) + + buffer.copy(MessageWithSalt, 0, Message) + buffer.copy(MessageWithSalt, buffer.len(Message), Salt) + + Message = MessageWithSalt + end + + local A, B, C, D = 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a + local E, F, G, H = 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + + local ProcessedMessage, Length = PreProcess(Message) + for Index = 0, Length - 1, 64 do + A, B, C, D, E, F, G, H = DigestBlock(ProcessedMessage, Index, A, B, C, D, E, F, G, H) + end + + return string.format(FormatString, A, B, C, D, E, F, G, H) +end + +return { + SHA256 = SHA256 +} From a27f78221d6294fb20430eb56174a41e5c263848 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:01:51 +0000 Subject: [PATCH 114/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 05b6ac6e9e..fcc0a8aaae 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -79,6 +79,7 @@ return { "(Git/ccuser44) Delete Dependencies/Adonis (#1681)"; "(Git/ccuser44) Fix vararg packing (#1679)"; "(Git/sakari119) Change :resize to use Model :ScaleTo() method (#1633)"; + "(Git/ccuser44) Allow client side _G API to be accessed (#1687)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 36f836edb045f45d3a97c8ff28d3a258b31c141e Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:03:43 +0200 Subject: [PATCH 115/189] Fix respawn block handling (#1678) * Fix respawn block handling * Change name to stop boblox --------- Co-authored-by: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> --- MainModule/Server/Commands/Fun.luau | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index a74f24c2eb..c72d6fb418 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -1182,7 +1182,7 @@ return function(Vargs, env) Functions.Hint(`{service.FormatPlayer(p)} does not have a HumanoidRootPart/Humanoid`, {plr}) continue end - if char:FindFirstChild("ADONIS_UFO") then + if char:GetAttribute("ADONIS_Taken") then continue end @@ -1213,8 +1213,9 @@ return function(Vargs, env) local tPos = torso.CFrame local info = TweenInfo.new(5, Enum.EasingStyle.Quart, Enum.EasingDirection.Out, -1, true, 0) - humanoid.Name = "NoResetForYou" humanoid.WalkSpeed = 0 + char:SetAttribute("ADONIS_Taken", true) + Remote.Send(p, "Function", "SetCore", "ResetButtonCallback", false) ufo.Name = "ADONIS_UFO" ufo.Archivable = false @@ -1498,7 +1499,7 @@ return function(Vargs, env) Functions.Hint(`{service.FormatPlayer(p)} does not have a HumanoidRootPart/Humanoid`, {plr}) continue end - if char:FindFirstChild("ADONIS_VAN") then + if char:GetAttribute("ADONIS_Taken") then continue end @@ -1539,10 +1540,10 @@ return function(Vargs, env) van.ModelStreamingMode = Enum.ModelStreamingMode.PersistentPerPlayer van:AddPersistentPlayer(p) van.Parent = workspace - humanoid.Name = "NoResetForYou" humanoid.WalkSpeed = 0 + char:SetAttribute("ADONIS_Taken", true) sound.Pitch = 1.3 - + Remote.Send(p, "Function", "SetCore", "ResetButtonCallback", false) Remote.PlayAudio(p, 421358540, 0.2, 1, true) for i = 1, 200 do From 0ccd23639608002424fdbe866fe20b4c78f62681 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:30:08 +0000 Subject: [PATCH 116/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index fcc0a8aaae..0b491bf00b 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -80,6 +80,7 @@ return { "(Git/ccuser44) Fix vararg packing (#1679)"; "(Git/sakari119) Change :resize to use Model :ScaleTo() method (#1633)"; "(Git/ccuser44) Allow client side _G API to be accessed (#1687)"; + "(Git/ccuser44) Fix respawn block handling (#1678)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From ed050558296f0d40280b9f5ba235c5425106da31 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 22 Nov 2024 16:29:26 +0000 Subject: [PATCH 117/189] Update and rename labeling.yml to labeler.yml --- .github/workflows/labeler.yml | 18 ++++++++++++++++++ .github/workflows/labeling.yml | 24 ------------------------ 2 files changed, 18 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/labeler.yml delete mode 100644 .github/workflows/labeling.yml diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000000..c2f027b1b7 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,18 @@ +name: "Issue Labeler" +on: + issues: + types: [opened, edited] + +permissions: + issues: write + contents: read + +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: github/issue-labeler@v3.4 + with: + configuration-path: .github/labeler.yml + enable-versioned-regex: 0 + repo-token: ${{ github.token }} diff --git a/.github/workflows/labeling.yml b/.github/workflows/labeling.yml deleted file mode 100644 index b415f05de6..0000000000 --- a/.github/workflows/labeling.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Issue labeling - -permissions: - issues: write - contents: read - -on: - issues: - types: [opened] - pull_request_target: - types: [opened, synchronize, ready_for_review, auto_merge_enabled, unlabeled] -jobs: - autotriage: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 # Uploads repository content to the runner - with: - repository: "Epix-Incorporated/Adonis" - - uses: actions/labeler@v5 - with: - configuration-path: .github/labeler.yml - enable-versioned-regex: false - repo-token: ${{ secrets.GITHUB_TOKEN }} - sync-labels: 1 From a73d6e69181d1f17819943e6c264e0bb9d85adef Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 23 Nov 2024 00:08:18 +0200 Subject: [PATCH 118/189] Add build file shortcuts (#1759) * Add build for windows * Support more buildfile types * Add bash script for building Adonis * Enforce LF lineending for build files * Enforce editorconfig for build files * Update build.sh * Update build.bat --- .editorconfig | 12 ++++++++++++ .gitattributes | 4 ++++ .gitignore | 6 ++++++ build.bat | 24 ++++++++++++++++++++++++ build.sh | 7 +++++++ 5 files changed, 53 insertions(+) create mode 100644 build.bat create mode 100644 build.sh diff --git a/.editorconfig b/.editorconfig index 84ee9a295a..02eeec529d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -33,3 +33,15 @@ end_of_line = lf [*.txt] end_of_line = lf + +[*.bat] +indent_style = tab +indent_size = 4 +trim_trailing_whitespace = true +end_of_line = lf + +[*.sh] +indent_style = tab +indent_size = 4 +trim_trailing_whitespace = true +end_of_line = lf diff --git a/.gitattributes b/.gitattributes index ca5c68a17d..4b62f71500 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,3 +15,7 @@ *.yml eol=lf *.txt text=auto *.txt eol=lf +*.bat text=auto +*.bat eol=lf +*.sh text=auto +*.sh eol=lf diff --git a/.gitignore b/.gitignore index 547288d4b0..725fb6a7c9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,10 @@ # Build Files /Adonis_**.rbxm +/Adonis_**.rbxmx +/Adonis_**.rbxl +/Adonis_**.rbxlx /Adonis.rbxm +/Adonis.rbxmx +/Adonis.rbxl +/Adonis.rbxlx diff --git a/build.bat b/build.bat new file mode 100644 index 0000000000..a1023dba8c --- /dev/null +++ b/build.bat @@ -0,0 +1,24 @@ +@echo off +SETLOCAL + +where selene >nul 2>nul +IF %ERRORLEVEL% NEQ 0 ( + SET SELENE_COMMAND=.\selene.exe +) ELSE ( + SET SELENE_COMMAND=selene +) + +where rojo >nul 2>nul +IF %ERRORLEVEL% NEQ 0 ( + SET ROJO_COMMAND=.\rojo.exe +) ELSE ( + SET ROJO_COMMAND=rojo +) + +echo Checking for lint errors with %SELENE_COMMAND% from ./Loader and ./MainModule +%SELENE_COMMAND% ./MainModule ./Loader + +echo Running %ROJO_COMMAND% build -o Adonis.rbxm +%ROJO_COMMAND% build -o Adonis.rbxm + +ENDLOCAL diff --git a/build.sh b/build.sh new file mode 100644 index 0000000000..c6733cbc4e --- /dev/null +++ b/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +printf "Checking for lint errors from ./Loader and ./MainModule" +selene ./Loader ./MainModule + +printf "Running rojo build -o Adonis.rbxm" +rojo build -o Adonis.rbxm From 2c294d8547e026c6bdb92eedb6dccfb040c18001 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 23 Nov 2024 00:09:21 +0200 Subject: [PATCH 119/189] Better clarify messages description (#1758) * Fix messages setting description * Fix messagees setting description * Clarify admin level * Fix typo * Fix typo * Remove markdown formatting * Remove markdown formatting --- Loader/Config/Settings.luau | 4 ++-- MainModule/Server/Dependencies/DefaultSettings.luau | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Loader/Config/Settings.luau b/Loader/Config/Settings.luau index 3d91cb17cb..04a748438c 100644 --- a/Loader/Config/Settings.luau +++ b/Loader/Config/Settings.luau @@ -296,7 +296,7 @@ settings.SongHint = true -- Display a hint with the current song nam settings.TopBarShift = false -- By default hints and notifications will appear from the top edge of the window. Set this to true if you don't want hints/notifications to appear in that region. settings.DefaultTheme = "Default" -- Theme to be used as a replacement for "Default". The new replacement theme can still use "Default" as its Base_Theme however any other theme that references "Default" as its redirects to this theme. settings.HiddenThemes = {} -- Hide themes from the theme selector tab inside the userpanel. Each theme name must be the specific name such as "Mobilius" -settings.Messages = {} -- A list of notification messages to show HeadAdmins and above on join +settings.Messages = {} -- A list of notifications shown on join. Messages can either be strings or tables. Messages are shown to HeadAdmins+ by default but tables can define a different minimum level via .Level settings.AutoClean = false -- Will auto clean workspace of things like hats and tools settings.AutoCleanDelay = 60 -- Time between auto cleans settings.AutoBackup = false -- Run :backupmap automatically when the server starts. To restore the map, run :restoremap @@ -471,7 +471,7 @@ descs.TopBarShift = [[ By default hints and notifs will appear from the top edge descs.DefaultTheme = [[ Theme to be used as a replacement for "Default". The new replacement theme can still use "Default" as its Base_Theme however any other theme that references "Default" as its redirects to this theme. ]] descs.ReJail = [[ If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed ]] -descs.Messages = [[ A list of notification messages to show HeadAdmins and above on join ]] +descs.Messages = [[ A list of notifications shown on join. Messages can either be strings or tables. Messages are shown to HeadAdmins+ by default but tables can define a different minimum level via .Level ]] descs.AutoClean = [[ Will auto clean workspace of things like hats and tools ]] descs.AutoBackup = [[ (not recommended) Run a map backup command when the server starts, this is mostly useless as clients cannot modify the server. To restore the map run :restoremap ]] diff --git a/MainModule/Server/Dependencies/DefaultSettings.luau b/MainModule/Server/Dependencies/DefaultSettings.luau index ac5f5129af..c19cbef1d6 100644 --- a/MainModule/Server/Dependencies/DefaultSettings.luau +++ b/MainModule/Server/Dependencies/DefaultSettings.luau @@ -296,7 +296,7 @@ settings.Notification = true -- Whether or not to show the "You're an settings.SongHint = true -- Display a hint with the current song name and ID when a song is played via :music settings.TopBarShift = false -- By default hints and notifications will appear from the top edge of the window. Set this to true if you don't want hints/notifications to appear in that region. settings.HiddenThemes = {} -- Hide themes from the theme selector tab inside the userpanel. Each theme name must be the specific name such as "Mobilius" -settings.Messages = {} -- A list of notification messages to show HeadAdmins and above on join +settings.Messages = {} -- A list of notifications shown on join. Messages can either be strings or tables. Messages are shown to HeadAdmins+ by default but tables can define a different minimum level via .Level settings.AutoClean = false -- Will auto clean workspace of things like hats and tools settings.AutoCleanDelay = 60 -- Time between auto cleans settings.AutoBackup = false -- Run :backupmap automatically when the server starts. To restore the map, run :restoremap @@ -471,7 +471,7 @@ descs.SongHint = [[ Display a hint with the current song name and ID when a song descs.TopBarShift = [[ By default hints and notifs will appear from the top edge of the window. Set this to true if you don't want hints/notifications to appear in that region. ]] descs.ReJail = [[ If true then when a player rejoins they'll go back into jail. Or if the moderator leaves everybody gets unjailed ]] -descs.Messages = [[ A list of notification messages to show HeadAdmins and above on join ]] +descs.Messages = [[ A list of notifications shown on join. Messages can either be strings or tables. Messages are shown to HeadAdmins+ by default but tables can define a different minimum level via .Level ]] descs.AutoClean = [[ Will auto clean workspace of things like hats and tools ]] descs.AutoBackup = [[ (not recommended) Run a map backup command when the server starts, this is mostly useless as clients cannot modify the server. To restore the map run :restoremap ]] From 99a967eb5cc10a99dfa0113473d6dbf5fd4b5bea Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sun, 24 Nov 2024 11:58:17 +0200 Subject: [PATCH 120/189] Only show command errors during debugmode (#1763) --- MainModule/Server/Core/Process.luau | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MainModule/Server/Core/Process.luau b/MainModule/Server/Core/Process.luau index 6520d11d48..4b65e1b3a0 100644 --- a/MainModule/Server/Core/Process.luau +++ b/MainModule/Server/Core/Process.luau @@ -283,11 +283,11 @@ return function(Vargs, GetEnv) end if rateExceeded and not ratePass then - rateExceeded:fire(rateKey, rateCache.Rate, maxRate) + rateExceeded:Fire(rateKey, rateCache.Rate, maxRate) end if ratePassed and ratePass then - ratePassed:fire(rateKey, rateCache.Rate, maxRate) + ratePassed:Fire(rateKey, rateCache.Rate, maxRate) end return ratePass, didThrottle, canThrottle, rateCache.Rate, maxRate, throttleResetOs @@ -592,7 +592,9 @@ return function(Vargs, GetEnv) Remote.MakeGui(p, "Output", { Message = cmdError, }) - warn(`Encountered an error while running a command: {msg}\n{cmdError}\n{debug.traceback()}`) + if Core.DebugMode == true then + warn(`Encountered an error while running a command: {msg}\n{cmdError}\n{debug.traceback()}`) + end end elseif cmdError ~= nil and cmdError ~= true and not isSystem then Remote.MakeGui(p, "Output", { From 4e10aa544cf50bab9967ae4bb27d1125558124f3 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 24 Nov 2024 09:58:49 +0000 Subject: [PATCH 121/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 0b491bf00b..b75df69e92 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -81,6 +81,7 @@ return { "(Git/sakari119) Change :resize to use Model :ScaleTo() method (#1633)"; "(Git/ccuser44) Allow client side _G API to be accessed (#1687)"; "(Git/ccuser44) Fix respawn block handling (#1678)"; + "(Git/ccuser44) Only show command errors during debugmode (#1763)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 7d7c1848dedcd7bdc9596dd216e7b645313cc555 Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Sun, 24 Nov 2024 16:32:09 -0500 Subject: [PATCH 122/189] Fix command quotes showing up in other args (#1766) * Fix command quotes showing up in other args Fixes #1660 * Update Functions.luau --- MainModule/Server/Core/Functions.luau | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 1701f2b057..62f73678ef 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1319,7 +1319,7 @@ return function(Vargs, GetEnv) if #tab>=num then break elseif #tab>=num-1 then - table.insert(tab,string.sub(msg,#str+1,#msg)) + table.insert(tab,string.sub(msg,#str+3,#msg)) continue end @@ -1337,7 +1337,7 @@ return function(Vargs, GetEnv) table.insert(tab,result) end end - + return tab end; From f134a17059b36e57a92d6b203ccabe6fde77c7d9 Mon Sep 17 00:00:00 2001 From: Dimenpsyonal <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 24 Nov 2024 21:32:42 +0000 Subject: [PATCH 123/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index b75df69e92..a5d205332b 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -82,6 +82,7 @@ return { "(Git/ccuser44) Allow client side _G API to be accessed (#1687)"; "(Git/ccuser44) Fix respawn block handling (#1678)"; "(Git/ccuser44) Only show command errors during debugmode (#1763)"; + "(Git/WalkerOfBacon) Fix command quotes showing up in other args (#1766)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 114cb6bf9cc8385c0572634408020dccaf06a0d8 Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:47:42 -0500 Subject: [PATCH 124/189] Fixed arguments with quotes inside them (#1768) * Actually fixed quoted args A fix for a pr (#1766) I made * Update Split function --- MainModule/Server/Core/Functions.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 62f73678ef..74dd7a83a2 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1319,7 +1319,7 @@ return function(Vargs, GetEnv) if #tab>=num then break elseif #tab>=num-1 then - table.insert(tab,string.sub(msg,#str+3,#msg)) + table.insert(tab,string.sub(msg,#str+#tab+(if str.." " == key or #(str.." ")==5 then 0 elseif #(str.." ")<5 then num-2 else 2),#msg)) continue end From 649f7907994a38e8573fb0582d4b978cb6b3b5cb Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 26 Nov 2024 23:47:56 +0200 Subject: [PATCH 125/189] Remove anti animation (#1771) --- MainModule/Server/Plugins/Anti_Cheat.luau | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/MainModule/Server/Plugins/Anti_Cheat.luau b/MainModule/Server/Plugins/Anti_Cheat.luau index 89ab51ece2..8b7b40d60c 100644 --- a/MainModule/Server/Plugins/Anti_Cheat.luau +++ b/MainModule/Server/Plugins/Anti_Cheat.luau @@ -143,18 +143,6 @@ return function(Vargs, GetEnv) end) end - local animator = humanoid:WaitForChild("Animator") - - animator.AnimationPlayed:Connect(function(animationTrack) - local animationId = animationTrack.Animation.AnimationId - if animationId == "rbxassetid://148840371" or string.match(animationId, "[%d%l]+://[/%w%p%?=%-_%$&'%*%+%%]*148840371/*") then - task.defer(function() - animationTrack:Stop(1/60) - end) - Detected(player, "log", "Player played an inappropriate character animation") - end - end) - local connections = {} local function makeConnection(Conn) local connection From 0e75da823f510ecf93f3b209d6f9339db4fda5bf Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:48:25 +0000 Subject: [PATCH 126/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index a5d205332b..7d89083285 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -83,6 +83,7 @@ return { "(Git/ccuser44) Fix respawn block handling (#1678)"; "(Git/ccuser44) Only show command errors during debugmode (#1763)"; "(Git/WalkerOfBacon) Fix command quotes showing up in other args (#1766)"; + "(Git/ccuser44) Remove anti animation (#1771)"; ""; "[Patch v260.2 2024-08-11 21:50 UTC] @Dimenpsyonal"; "Fix alias arguments (#1581)"; From 34de1f4d40af127c6169ba1efc26aa041abad32a Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 26 Nov 2024 23:51:22 +0200 Subject: [PATCH 127/189] Fix disguise changing others usernames (#1772) --- MainModule/Server/Core/Admin.luau | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau index 626c3e6fad..0ad9ff97ae 100644 --- a/MainModule/Server/Core/Admin.luau +++ b/MainModule/Server/Core/Admin.luau @@ -74,8 +74,8 @@ return function(Vargs, GetEnv) return false end - if Variables.DisguiseBindings[textSource.UserId] then -- // Disguise command handler - chatMessage.PrefixText = Variables.DisguiseBindings[textSource.UserId].TargetUsername..":" + if Variables.DisguiseBindings[SenderId] then -- // Disguise command handler + chatMessage.PrefixText = Variables.DisguiseBindings[SenderId].TargetUsername..":" end if Admin.SlowMode and IsOriginalSender then From 199be611292ad75b467989542da176d1e57d5e7d Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Tue, 26 Nov 2024 23:57:58 +0200 Subject: [PATCH 128/189] Misc fixes and improvements (#1769) * Add clearnote alias * Optimise textureid pooling * Use script env for scriptbase * Optimise material * Better API checking * Create ClientScriptBase.server.luau * Create ClientScriptBase.meta.json * Update AnimateAvatar.meta.json * Update ClientScriptBase.meta.json * Add clientscript support for scriptbuilder * Use a clientscript for rainbowify * Add clientscript support for newscript * Delete MainModule/Server/Dependencies/Assets/Clipper.rbxmx * Create init.client.luau * Create Clip.model.json * Fix multiple issues with effect * Fix server mutex * Update Quacker.server.luau * Update Spinner.client.luau * Fix sfling creating local craters * Optimise terrain check * Fix balance name * Fix ClientScript not working * Fix rainbowify * Optimize and fix oldlogs conversion * Add `:seize` alias * Fix case * Fix lint --------- Co-authored-by: nichole <64012878+Dimenpsyonal@users.noreply.github.com> --- MainModule/Client/Plugins/Anti_Cheat.luau | 23 +-- MainModule/Client/UI/Default/Effect.luau | 134 +++++++++--------- MainModule/Server/Commands/Admins.luau | 4 +- MainModule/Server/Commands/Fun.luau | 11 +- MainModule/Server/Core/Core.luau | 8 +- MainModule/Server/Core/Logs.luau | 36 ++--- MainModule/Server/Core/Variables.luau | 2 +- .../Assets/AnimateAvatar.meta.json | 4 +- .../Server/Dependencies/Assets/Clipper.rbxmx | 67 --------- .../Assets/Clipper/Clip.model.json | 6 + .../Assets/Clipper/init.client.luau | 64 +++++++++ .../Dependencies/Assets/Quacker.server.luau | 1 + .../Server/Dependencies/Assets/Sfling.rbxmx | 2 +- .../Dependencies/Assets/Singer.server.luau | 2 +- .../Dependencies/Assets/Spinner.client.luau | 2 +- .../Dependencies/ClientScriptBase.meta.json | 6 + .../Dependencies/ClientScriptBase.server.luau | 10 ++ .../Dependencies/ScriptBase.server.luau | 7 +- MainModule/Server/Server.luau | 10 +- 19 files changed, 207 insertions(+), 192 deletions(-) delete mode 100644 MainModule/Server/Dependencies/Assets/Clipper.rbxmx create mode 100644 MainModule/Server/Dependencies/Assets/Clipper/Clip.model.json create mode 100644 MainModule/Server/Dependencies/Assets/Clipper/init.client.luau create mode 100644 MainModule/Server/Dependencies/ClientScriptBase.meta.json create mode 100644 MainModule/Server/Dependencies/ClientScriptBase.server.luau diff --git a/MainModule/Client/Plugins/Anti_Cheat.luau b/MainModule/Client/Plugins/Anti_Cheat.luau index 7c49fb78de..6c4187b325 100644 --- a/MainModule/Client/Plugins/Anti_Cheat.luau +++ b/MainModule/Client/Plugins/Anti_Cheat.luau @@ -293,29 +293,10 @@ return function(Vargs) xpcall(function() local function getCoreUrls() local coreUrls = {"rbxassetid://0", "rbxassetid://10066921516", "rbxassetid://13262267483", "rbxassetid://13253401424"} -- Whitelist for Roblox Camera SFX and Quest Controls Scheme - local backpack = Player:FindFirstChildOfClass("Backpack") - local character = Player.Character - local starterPack = service.StarterPack local screenshotHud = service.GuiService:FindFirstChildOfClass("ScreenshotHud") - if character then - for _, v in ipairs(character:GetChildren()) do - if v:IsA("BackpackItem") and service.Trim(v.TextureId) ~= "" then - table.insert(coreUrls, service.Trim(v.TextureId)) - end - end - end - - if backpack then - for _, v in ipairs(backpack:GetChildren()) do - if v:IsA("BackpackItem") and service.Trim(v.TextureId) ~= "" then - table.insert(coreUrls, service.Trim(v.TextureId)) - end - end - end - - if starterPack then - for _, v in ipairs(starterPack:GetChildren()) do + for _, container in {Player.Character, service.StarterPack, Player:FindFirstChildOfClass("Backpack")} do + for _, v in ipairs(container:GetChildren()) do if v:IsA("BackpackItem") and service.Trim(v.TextureId) ~= "" then table.insert(coreUrls, service.Trim(v.TextureId)) end diff --git a/MainModule/Client/UI/Default/Effect.luau b/MainModule/Client/UI/Default/Effect.luau index 3c51ad25f5..1208f278ba 100644 --- a/MainModule/Client/UI/Default/Effect.luau +++ b/MainModule/Client/UI/Default/Effect.luau @@ -11,8 +11,10 @@ return function(data, env) if env then setfenv(1, env) end - + local gui = service.New("ScreenGui") + gui.IgnoreGuiInset = true + gui.ClipToDeviceSafeArea = true local mode = data.Mode local gTable = client.UI.Register(gui, {Name = "Effect"}) local BindEvent = gTable.BindEvent @@ -26,12 +28,12 @@ return function(data, env) local frame = Instance.new("Frame") frame.Parent = gui local camera = workspace.CurrentCamera - local pixels = {} local resY = data.Resolution or 20 local resX = data.Resolution or 20 local depth = 0 local distance = data.Distance or 128 + local pixels = table.create((gui.AbsoluteSize.Y / resY) * (gui.AbsoluteSize.X / resX)) local function renderScreen() for _, pixel in pixels do @@ -43,23 +45,21 @@ return function(data, env) pixel.Pixel.BackgroundColor3 = if part and part.Transparency < 1 then part.BrickColor.Color else Color3.fromRGB(105, 170, 255) - else pixel.Pixel.BackgroundColor3 = Color3.fromRGB(105, 170, 255) end end end - frame.Size = UDim2.new(1, 0, 1, 40) - frame.Position = UDim2.new(0, 0, 0, -35) - for y = 0, gui.AbsoluteSize.Y+50, resY do - for x = 0, gui.AbsoluteSize.X+30, resX do - local pixel = service.New("TextLabel", { + frame.Size = UDim2.new(1, 0, 1, 0) + frame.Position = UDim2.new(0, 0, 0, 0) + for y = 0, gui.AbsoluteSize.Y, resY do + for x = 0, gui.AbsoluteSize.X, resX do + local pixel = service.New("Frame", { Parent = frame; - Text = ""; BorderSizePixel = 0; Size = UDim2.fromOffset(resX, resY); - Position = UDim2.fromOffset(x-(resX/2), y-(resY/2)); + Position = UDim2.fromOffset(x - (resX / 2), y - (resY / 2)); BackgroundColor3 = Color3.fromRGB(105, 170, 255); }) table.insert(pixels, {Pixel = pixel, X = x, Y = y}) @@ -92,26 +92,21 @@ return function(data, env) local bg = service.New("Frame", { Parent = gui; BackgroundTransparency = 1; - BackgroundColor3 = Color3.new(0,0,0); - Size = UDim2.new(2,0,2,0); - Position = UDim2.new(-0.5,0,-0.5,0); + BackgroundColor3 = Color3.new(0, 0, 0); + Size = UDim2.new(2, 0, 2, 0); + Position = UDim2.new(-1, 0, -1, 0); }) - for i = 1, 0, -0.01 do - bg.BackgroundTransparency = i - blur.Size = 56 * (1 - i); - task.wait(0.1) - end - - bg.BackgroundTransparency = 0 + service.TweenService:Create(bg, TweenInfo.new((1 / 0.01) * 0.1), { BackgroundTransparency = 0 }):Play() + service.TweenService:Create(blur, TweenInfo.new((1 / 0.01) * 0.1), { Size = (1 / 0.01) * 5.6 }):Play() elseif mode == "Trippy" then local v = service.Player local bg = Instance.new("Frame") - bg.BackgroundColor3 = Color3.new(0,0,0) + bg.BackgroundColor3 = Color3.new(0, 0, 0) bg.BackgroundTransparency = 0 - bg.Size = UDim2.new(10,0,10,0) - bg.Position = UDim2.new(-5,0,-5,0) + bg.Size = UDim2.new(10, 0, 10, 0) + bg.Position = UDim2.new(-5, 0, -5, 0) bg.ZIndex = 10 bg.Parent = gui @@ -123,15 +118,15 @@ return function(data, env) if gui then gui:Destroy() end elseif mode == "Spooky" then local frame = Instance.new("Frame") - frame.BackgroundColor3=Color3.new(0,0,0) - frame.Size=UDim2.new(1,0,1,50) - frame.Position=UDim2.new(0,0,0,-50) + frame.BackgroundColor3 = Color3.new(0, 0, 0) + frame.Size = UDim2.new(1, 0, 1, 0) + frame.Position = UDim2.new(0, 0, 0, 0) frame.Parent = gui local img = Instance.new("ImageLabel") - img.Position = UDim2.new(0,0,0,0) - img.Size = UDim2.new(1,0,1,0) + img.Position = UDim2.new(0, 0, 0, 0) + img.Size = UDim2.new(1, 0, 1, 0) img.BorderSizePixel = 0 - img.BackgroundColor3 = Color3.new(0,0,0) + img.BackgroundColor3 = Color3.new(0, 0, 0) img.Parent = frame local textures = { 299735022; @@ -158,25 +153,28 @@ return function(data, env) sound.Looped = true sound.Parent = gui sound:Play() + local lastImage while gui and gui.Parent do - for i=1,#textures do - img.Image = `rbxassetid://{textures[i]}` - task.wait(0.1) + local image = `rbxassetid://{textures[math.floor(os.clock() / 0.1) % #textures + 1]}` + if image ~= lastImage then + img.Image, lastImage = image, image end + task.wait() end + sound:Stop() elseif mode == "lifeoftheparty" then local frame = Instance.new("Frame") - frame.BackgroundColor3 = Color3.new(0,0,0) - frame.Size = UDim2.new(1,0,1,50) - frame.Position = UDim2.new(0,0,0,-50) + frame.BackgroundColor3 = Color3.new(0, 0, 0) + frame.Size = UDim2.new(1, 0, 1, 0) + frame.Position = UDim2.new(0, 0, 0, 0) frame.Parent = gui local img = Instance.new("ImageLabel") - img.Position = UDim2.new(0,0,0,0) - img.Size = UDim2.new(1,0,1,0) + img.Position = UDim2.new(0, 0, 0, 0) + img.Size = UDim2.new(1, 0, 1, 0) img.BorderSizePixel = 0 - img.BackgroundColor3 = Color3.new(0,0,0) + img.BackgroundColor3 = Color3.new(0, 0, 0) img.Parent = frame local textures = { 299733203; @@ -205,33 +203,34 @@ return function(data, env) 299733663; 299733674; 299733694; - } local sound = Instance.new("Sound") sound.SoundId = "rbxassetid://172906410" sound.Looped = true sound.Parent = gui sound:Play() + local lastImage while gui and gui.Parent do - for i=1,#textures do - img.Image = `rbxassetid://{textures[i]}` - task.wait(0.1) + local image = `rbxassetid://{textures[math.floor(os.clock() / 0.1) % #textures + 1]}` + if image ~= lastImage then + img.Image, lastImage = image, image end + task.wait() end sound:Stop() elseif mode == "trolling" then local frame = Instance.new("Frame") - frame.BackgroundColor3 = Color3.new(0,0,0) - frame.Size = UDim2.new(1,0,1,50) - frame.Position = UDim2.new(0,0,0,-50) + frame.BackgroundColor3 = Color3.new(0, 0, 0) + frame.Size = UDim2.new(1, 0, 1, 0) + frame.Position = UDim2.new(0, 0, 0, 0) frame.Parent = gui local img = Instance.new("ImageLabel") - img.Position = UDim2.new(0,0,0,0) - img.Size = UDim2.new(1,0,1,0) + img.Position = UDim2.new(0, 0, 0, 0) + img.Size = UDim2.new(1, 0, 1, 0) img.BorderSizePixel = 0 - img.BackgroundColor3 = Color3.new(0,0,0) + img.BackgroundColor3 = Color3.new(0, 0, 0) img.Parent = frame local textures = { "6172043688"; @@ -260,62 +259,63 @@ return function(data, env) "6172045193"; "6172044478"; "6172043688"; - } local sound = Instance.new("Sound") sound.SoundId = "rbxassetid://229681899" sound.Looped = true sound.Parent = gui sound:Play() + local lastImage while gui and gui.Parent do - for i=1,#textures do - img.Image = `rbxassetid://{textures[i]}` - task.wait(0.13) + local image = `rbxassetid://{textures[math.floor(os.clock() / 0.13) % #textures + 1]}` + if image ~= lastImage then + img.Image, lastImage = image, image end + task.wait() end sound:Stop() elseif mode == "Strobe" then local bg = Instance.new("Frame") - bg.BackgroundColor3 = Color3.new(0,0,0) + bg.BackgroundColor3 = Color3.new(0, 0, 0) bg.BackgroundTransparency = 0 - bg.Size = UDim2.new(10,0,10,0) - bg.Position = UDim2.new(-5,0,-5,0) + bg.Size = UDim2.new(10, 0, 10, 0) + bg.Position = UDim2.new(-5, 0, -5, 0) bg.ZIndex = 10 bg.Parent = gui while gui and gui.Parent do task.wait(1/44) - bg.BackgroundColor3 = Color3.new(1,1,1) + bg.BackgroundColor3 = Color3.new(1, 1, 1) task.wait(1/44) - bg.BackgroundColor3 = Color3.new(0,0,0) + bg.BackgroundColor3 = Color3.new(0, 0, 0) end if gui then gui:Destroy() end elseif mode == "Blind" then local bg = Instance.new("Frame") - bg.BackgroundColor3 = Color3.new(0,0,0) + bg.BackgroundColor3 = Color3.new(0, 0, 0) bg.BackgroundTransparency = 0 - bg.Size = UDim2.new(10,0,10,0) - bg.Position = UDim2.new(-5,0,-5,0) + bg.Size = UDim2.new(10, 0, 10, 0) + bg.Position = UDim2.new(-5, 0, -5, 0) bg.ZIndex = 10 bg.Parent = gui elseif mode == "ScreenImage" then local bg = Instance.new("ImageLabel") - bg.Image=`rbxassetid://{data.Image}` + bg.Image = `rbxassetid://{data.Image}` bg.BackgroundColor3 = Color3.new(0,0,0) bg.BackgroundTransparency = 0 - bg.Size = UDim2.new(1,0,1,0) - bg.Position = UDim2.new(0,0,0,0) + bg.Size = UDim2.new(1, 0, 1, 0) + bg.Position = UDim2.new(0, 0, 0, 0) bg.ZIndex = 10 bg.Parent = gui elseif mode == "ScreenVideo" then local bg = Instance.new("VideoFrame") - bg.Video=`rbxassetid://{data.Video}` - bg.BackgroundColor3 = Color3.new(0,0,0) + bg.Video = `rbxassetid://{data.Video}` + bg.BackgroundColor3 = Color3.new(0, 0, 0) bg.BackgroundTransparency = 0 - bg.Size = UDim2.new(1,0,1,0) - bg.Position = UDim2.new(0,0,0,0) + bg.Size = UDim2.new(1, 0, 1, 0) + bg.Position = UDim2.new(0, 0, 0, 0) bg.ZIndex = 10 bg.Parent = gui bg:Play() diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index a1f554f175..3ea208f9fb 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -799,6 +799,8 @@ return function(Vargs, env) if string.lower(class) == "script" or string.lower(class) == "s" then class = "Script" + elseif string.lower(class) == "clientscript" or string.lower(class) == "cs" then + class = "ClientScript" --elseif string.lower(class) == "localscript" or string.lower(class) == "ls" then -- class = "LocalScript" else @@ -1098,7 +1100,7 @@ return function(Vargs, env) DeleteNote = { Prefix = Settings.Prefix; - Commands = {"removenote", "remnote", "deletenote"}; + Commands = {"removenote", "remnote", "deletenote", "clearnote"}; Args = {"player", "note (specify 'all' to delete all notes)"}; Description = "Removes a note on the target player(s)"; AdminLevel = "Admins"; diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index c72d6fb418..3343588c6e 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -683,7 +683,7 @@ return function(Vargs, env) Fun = true; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) - local scr = Core.NewScript("Script",[[ + local scr = Core.NewScript("ClientScript", [[ local restore = {} local tween = game:GetService("TweenService") @@ -707,7 +707,7 @@ return function(Vargs, env) end script:Destroy() end - ]]) + ]], true) scr.Name = "Rainbowify" for i, v in service.GetPlayers(plr, args[1]) do @@ -780,12 +780,13 @@ return function(Vargs, env) Material = { Prefix = Settings.Prefix; - Commands = {"mat", "material"}; + Commands = {"material", "mat"}; Args = {"player", "material"}; Description = "Make the target the material you choose"; Fun = true; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) + --local chosenMat = if tonumber(args[2]) then Enum.Material:FromValue(tonumber(args[2])) elseif not args[2] then "Plastic" else Enum.Material:FromName(args[2]) local mats = { Plastic = 256; Wood = 512; @@ -825,7 +826,7 @@ return function(Vargs, env) for _, v in service.GetPlayers(plr, args[1]) do if v.Character then for _, p in v.Character:GetChildren() do - if p:IsA"BasePart" then + if p:IsA("BasePart") then p.Material = chosenMat end end @@ -3746,7 +3747,7 @@ return function(Vargs, env) Seizure = { Prefix = Settings.Prefix; - Commands = {"seizure"}; + Commands = {"seizure", "seize"}; Args = {"player"}; Description = "Make the target player(s)'s character spazz out on the floor"; Fun = true; diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index 2d18d007ba..f8b8fcdd38 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -517,7 +517,7 @@ return function(Vargs, GetEnv) local fixscr = service.UnWrap(scr) for _, val in Core.ExecuteScripts do - if not isLocal or (isLocal and val.Type == "LocalScript") then + if not isLocal or isLocal and (val.Type == "LocalScript" or val.Type == "ClientScript") then if (service.UnWrap(val.Script) == fixscr or code == val.Code) and (not val.runLimit or (val.runLimit ~= nil and val.Executions <= val.runLimit)) then val.Executions += 1 @@ -552,7 +552,7 @@ return function(Vargs, GetEnv) RegisterScript = function(data) data.Executions = 0 data.Time = os.time() - data.Type = data.Script.ClassName + data.Type = data.Type or data.Script.ClassName data.Wrapped = service.Wrap(data.Script) data.Wrapped:SetSpecial("Clone",function() return Core.RegisterScript({ @@ -597,6 +597,7 @@ return function(Vargs, GetEnv) NewScript = function(scriptType: string, source: string, allowCodes: boolean?, noCache: boolean?, runLimit: number?) local scr = assert( if scriptType == "Script" then Deps.ScriptBase:Clone() + elseif scriptType == "ClientScript" then Deps.ClientScriptBase:Clone() elseif scriptType == "LocalScript" then Deps.LocalScriptBase:Clone() else nil, `Invalid script type '{scriptType}'` @@ -617,7 +618,8 @@ return function(Vargs, GetEnv) local wrapped = Core.RegisterScript({ Script = scr; Code = execCode; - Source = scr:IsA("LocalScript") and Core.Bytecode(source) or source; + Type = scriptType; + Source = (scr:IsA("LocalScript") or scriptType == "ClientScript") and Core.Bytecode(source) or source; noCache = noCache; runLimit = runLimit; }) diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index 7e18420b0b..311492d0c2 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -144,29 +144,33 @@ return function(Vargs, GetEnv) end) end - local temp = {} + local temp = table.create(#oldLogs + #logsToSave + (Logs.Commands.__meta == "DLL" and Logs.Commands.count or 0)) + + local function insertLog(log) + local isTable = type(log) == "table" + local newTab = if isTable then table.clone(log) else log + + if (isTable and not log.NoSave) or not isTable then + if isTable and log.Player then + local p = log.Player + log.Player = { + Name = p.Name; + UserId = p.UserId; + } + end + table.insert(temp, log) + end + end for _, m in logsToSave do if m.__meta == "DLL" then local newTab = m:GetAsTable() - for i,v in pairs(newTab) do - table.insert(temp,v) + for _, v in ipairs(newTab) do + insertLog(v) end else - local isTable = type(m) == "table" - local newTab = if isTable then table.clone(m) else m - - if (isTable and not newTab.NoSave) or not isTable then - if isTable and newTab.Player then - local p = newTab.Player - newTab.Player = { - Name = p.Name; - UserId = p.UserId; - } - end - table.insert(temp, newTab)--{Time = m.Time; Text = `{m.Text}: {m.Desc}`; Desc = m.Desc}) - end + insertLog(m) end end diff --git a/MainModule/Server/Core/Variables.luau b/MainModule/Server/Core/Variables.luau index bfe7910b31..f7243ea007 100644 --- a/MainModule/Server/Core/Variables.luau +++ b/MainModule/Server/Core/Variables.luau @@ -189,7 +189,7 @@ return function(Vargs, GetEnv) {Name = "still", ID = 7023771708}, {Name = "sleep", ID = 7023407320}, {Name = "whatareyouwaitingfor", ID = 7028977687}, - {Name = "balace", ID = 7024183256}, + {Name = "balance", ID = 7024183256}, {Name = "brokenglass", ID = 7028799370}, {Name = "thelanguageofangels", ID = 7029031068}, {Name = "imprints", ID = 7023704173}, diff --git a/MainModule/Server/Dependencies/Assets/AnimateAvatar.meta.json b/MainModule/Server/Dependencies/Assets/AnimateAvatar.meta.json index 51c45b040c..6233c02da7 100644 --- a/MainModule/Server/Dependencies/Assets/AnimateAvatar.meta.json +++ b/MainModule/Server/Dependencies/Assets/AnimateAvatar.meta.json @@ -1,6 +1,6 @@ { "properties": { - "Disabled": true, - "RunContext": "Client" + "RunContext": "Client", + "Disabled": true } } diff --git a/MainModule/Server/Dependencies/Assets/Clipper.rbxmx b/MainModule/Server/Dependencies/Assets/Clipper.rbxmx deleted file mode 100644 index 71215654e0..0000000000 --- a/MainModule/Server/Dependencies/Assets/Clipper.rbxmx +++ /dev/null @@ -1,67 +0,0 @@ - - true - null - nil - - - - 0 - false - true - - Clipper - 0 - {CB07704A-5D5F-4007-B203-DA3FC3AFC116} - - -1 - - - - - - 0 - false - Clip - -1 - - false - - - - diff --git a/MainModule/Server/Dependencies/Assets/Clipper/Clip.model.json b/MainModule/Server/Dependencies/Assets/Clipper/Clip.model.json new file mode 100644 index 0000000000..c90e7ae102 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Clipper/Clip.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "BoolValue", + "Properties": { + "Value": false + } +} diff --git a/MainModule/Server/Dependencies/Assets/Clipper/init.client.luau b/MainModule/Server/Dependencies/Assets/Clipper/init.client.luau new file mode 100644 index 0000000000..c9713a4b98 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Clipper/init.client.luau @@ -0,0 +1,64 @@ +local RunService = game:GetService("RunService") + +local LIMB_NAMES = { + R6 = { + "Torso", + "HumanoidRootPart", + "Head" + }, + R15 = { + "HumanoidRootPart", + "LowerTorso", + "UpperTorso" + } +} + +local humanoid: Humanoid = script.Parent +local character = humanoid.Parent +local wasInside = false +local ignoreParams = OverlapParams.new() + +ignoreParams.FilterDescendantsInstances = {character, humanoid} +ignoreParams.FilterType = Enum.RaycastFilterType.Exclude +ignoreParams.MaxParts = 1 +ignoreParams.CollisionGroup = humanoid.RootPart and humanoid.RootPart.CollisionGroup or "Default" +ignoreParams.RespectCanCollide = true + +local function isInsideTerrain(position) + return workspace.Terrain:ReadVoxelChannels(Region3.new(position, position + Vector3.one):ExpandToGrid(4), 4, {"SolidOccupancy"}).SolidOccupancy[1][1][1] > 0 +end + +RunService.PreSimulation:Connect(function() + if script.Clip.Value then + for _, object in ipairs(character:GetDescendants()) do + if object:IsA("BasePart") and object.CanCollide then + object.CanCollide = false + end + end + + local rootPart = humanoid.RootPart + local velocity = rootPart and rootPart.AssemblyLinearVelocity + + if velocity and velocity.Y <= 0 and (#workspace:GetPartsInPart(rootPart, ignoreParams) > 0 or isInsideTerrain(rootPart.Position - Vector3.new(0, humanoid.HipHeight, 0))) then + wasInside = true + rootPart.AssemblyLinearVelocity = Vector3.new(velocity.X, math.clamp(velocity.Y, 0, math.huge), velocity.Z) + --humanoid:ChangeState(Enum.HumanoidStateType.StrafingNoPhysics) -- Enum.HumanoidStateType.StrafingNoPhysics (semi-depricated but still working and fixes the colliding if in water). + + if humanoid.Jump then + humanoid:ChangeState(Enum.HumanoidStateType.Jumping) + end + elseif wasInside then + wasInside = false + humanoid:ChangeState(Enum.HumanoidStateType.None) + end + else + for _, object in ipairs(character:GetDescendants()) do + if table.find(LIMB_NAMES[humanoid.RigType.Name] or {}, object.Name) and object:IsA("BasePart") then + object.CanCollide = true + end + end + + humanoid:ChangeState(Enum.HumanoidStateType.None) -- Enum.HumanoidStateType.None (Allows roblox to set set a state that isn't Enum.HumanoidStateType.StrafingNoPhysics) + script:Destroy() + end +end) diff --git a/MainModule/Server/Dependencies/Assets/Quacker.server.luau b/MainModule/Server/Dependencies/Assets/Quacker.server.luau index 5301e27d70..aa57c4ef3c 100644 --- a/MainModule/Server/Dependencies/Assets/Quacker.server.luau +++ b/MainModule/Server/Dependencies/Assets/Quacker.server.luau @@ -4,6 +4,7 @@ while true do if script.Parent ~= nil then script.Parent:FindFirstChild(`Quack{math.random(1, 4)}`):Play() else + script:Destroy() break end end diff --git a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx b/MainModule/Server/Dependencies/Assets/Sfling.rbxmx index c58966959f..c37215ed6a 100644 --- a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx +++ b/MainModule/Server/Dependencies/Assets/Sfling.rbxmx @@ -22,7 +22,7 @@ for i = 1, 100 do ex.Position = torso.Position + Vector3.new(math.random(-5, 5), -10, math.random(-5, 5)) ex.BlastRadius = 35 ex.BlastPressure = strength - ex.ExplosionType = Enum.ExplosionType.Craters + ex.ExplosionType = Enum.ExplosionType.NoCraters--Enum.ExplosionType.Craters ex.DestroyJointRadiusPercent = 0 ex.Archivable = false ex.Parent = cam diff --git a/MainModule/Server/Dependencies/Assets/Singer.server.luau b/MainModule/Server/Dependencies/Assets/Singer.server.luau index 30b558859e..8fe0633941 100644 --- a/MainModule/Server/Dependencies/Assets/Singer.server.luau +++ b/MainModule/Server/Dependencies/Assets/Singer.server.luau @@ -46,7 +46,7 @@ local WIDTH_SUPRESS = 20000 local HEIGHT_SUPRESS = 1000 local ANGLE_MULTIPLY = 100 -game:GetService("RunService").Heartbeat:connect(function() +game:GetService("RunService").Heartbeat:Connect(function() local relativeSize = head.Size / (isR15 and Vector3.new(1.2, 1.2, 1.2) or Vector3.new(2, 1, 1)) local loudness = script.Parent.PlaybackLoudness mouthMesh.Scale = mouthMesh.Scale:Lerp(Vector3.new(originalSize.X + loudness/WIDTH_SUPRESS * relativeSize.X, loudness/HEIGHT_SUPRESS * relativeSize.Y, originalSize.Z), SIZE_SMOOTHNESS) diff --git a/MainModule/Server/Dependencies/Assets/Spinner.client.luau b/MainModule/Server/Dependencies/Assets/Spinner.client.luau index 3a72663733..8354a48dbf 100644 --- a/MainModule/Server/Dependencies/Assets/Spinner.client.luau +++ b/MainModule/Server/Dependencies/Assets/Spinner.client.luau @@ -2,5 +2,5 @@ local torso = script.Parent local bg = torso:FindFirstChild("ADONIS_SPIN_GYRO") repeat task.wait(1/44) - bg.CFrame *= CFrame.Angles(0,math.rad(12),0) + bg.CFrame *= CFrame.Angles(0, math.rad(12), 0) until not bg or bg.Parent ~= torso diff --git a/MainModule/Server/Dependencies/ClientScriptBase.meta.json b/MainModule/Server/Dependencies/ClientScriptBase.meta.json new file mode 100644 index 0000000000..6233c02da7 --- /dev/null +++ b/MainModule/Server/Dependencies/ClientScriptBase.meta.json @@ -0,0 +1,6 @@ +{ + "properties": { + "RunContext": "Client", + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/ClientScriptBase.server.luau b/MainModule/Server/Dependencies/ClientScriptBase.server.luau new file mode 100644 index 0000000000..ac51390b6b --- /dev/null +++ b/MainModule/Server/Dependencies/ClientScriptBase.server.luau @@ -0,0 +1,10 @@ +while rawget(_G, "Adonis") == nil do + task.wait() +end +local execute = script:FindFirstChild("Execute") +local code, loadCode = rawget(_G, "Adonis").Scripts.ExecutePermission(script, execute and execute.Value) +local env = getfenv() + +if code then + loadCode(code, env)() +end diff --git a/MainModule/Server/Dependencies/ScriptBase.server.luau b/MainModule/Server/Dependencies/ScriptBase.server.luau index 390e7201bd..e5b1613c8d 100644 --- a/MainModule/Server/Dependencies/ScriptBase.server.luau +++ b/MainModule/Server/Dependencies/ScriptBase.server.luau @@ -1,8 +1,11 @@ -task.wait() +while rawget(_G, "Adonis") == nil do + task.wait() +end local execute = script:FindFirstChild("Execute") local code, loadCode = rawget(_G, "Adonis").Scripts.ExecutePermission(script, execute and execute.Value) local canUseLoadstring = loadstring and pcall(loadstring, "local a = 5 local b = a + 5") or false +local env = getfenv() if code then - (canUseLoadstring and loadstring(code) or loadCode(code--[[, getfenv()]]))() + (canUseLoadstring and loadstring(code) or loadCode(code, env))() end diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index 8b9fa6638e..75245fb231 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -460,7 +460,7 @@ return service.NewProxy({ script:Destroy() return "FAILED" else - mutex = service.New("StringValue", {Name = "__Adonis_MODULE_MUTEX", Archivable = false, Value = "Running"}) + mutex = service.New("StringValue", {Name = "__Adonis_MODULE_MUTEX", Value = "Running"}) local mutexBackup = mutex:Clone() local function makePersistent(m) local connection1, connection2 = nil, nil @@ -469,9 +469,10 @@ return service.NewProxy({ connection1:Disconnect() connection2:Disconnect() warn("Adonis module mutex removed; Regenerating...") - makePersistent(mutexBackup) - mutexBackup.Parent = service.RunService - mutexBackup = mutexBackup:Clone() + mutex = mutexBackup:Clone() + mutex.Archivable = false + mutex.Parent = service.RunService + makePersistent(mutex) end end) connection2 = m:GetPropertyChangedSignal("Name"):Connect(function() @@ -482,6 +483,7 @@ return service.NewProxy({ end) end makePersistent(mutex) + mutex.Archivable = false mutex.Parent = service.RunService end From 8830fecb4a12eb5d1579012f74894eaa67d4e064 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 27 Nov 2024 00:50:06 +0200 Subject: [PATCH 129/189] Use JIT compiler optimization for Linked List, GoodSignal and Type Checker modules (#1770) * Use native for linked list module * Use native for GoodSignal * Use native for typechecker --- MainModule/Server/Shared/DoubleLinkedList.luau | 1 + MainModule/Server/Shared/GoodSignal.luau | 1 + MainModule/Server/Shared/Typechecker.luau | 1 + 3 files changed, 3 insertions(+) diff --git a/MainModule/Server/Shared/DoubleLinkedList.luau b/MainModule/Server/Shared/DoubleLinkedList.luau index 4b6301730a..62d4a668e5 100644 --- a/MainModule/Server/Shared/DoubleLinkedList.luau +++ b/MainModule/Server/Shared/DoubleLinkedList.luau @@ -1,3 +1,4 @@ +--!native --// File: LinkedList.lua --// Desc: Provides a more performance-friendly alternative to large tables that get shifted in indexes constantly --// Author: Coasterteam diff --git a/MainModule/Server/Shared/GoodSignal.luau b/MainModule/Server/Shared/GoodSignal.luau index 046cba8a77..5bed213c20 100644 --- a/MainModule/Server/Shared/GoodSignal.luau +++ b/MainModule/Server/Shared/GoodSignal.luau @@ -1,3 +1,4 @@ +--!native -------------------------------------------------------------------------------- -- Batched Yield-Safe Signal Implementation -- -- This is a Signal class which has effectively identical behavior to a -- diff --git a/MainModule/Server/Shared/Typechecker.luau b/MainModule/Server/Shared/Typechecker.luau index 3abc92022f..fd6409cf2b 100644 --- a/MainModule/Server/Shared/Typechecker.luau +++ b/MainModule/Server/Shared/Typechecker.luau @@ -1,3 +1,4 @@ +--!native --[[ t: a runtime typechecker for Roblox From fb864de756b3c8e3bdd6a73801102144efb68b41 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 27 Nov 2024 12:44:41 +0200 Subject: [PATCH 130/189] Small optimization (#1773) --- MainModule/Client/UI/Default/Effect.luau | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/MainModule/Client/UI/Default/Effect.luau b/MainModule/Client/UI/Default/Effect.luau index 1208f278ba..7840b6aa78 100644 --- a/MainModule/Client/UI/Default/Effect.luau +++ b/MainModule/Client/UI/Default/Effect.luau @@ -83,22 +83,18 @@ return function(data, env) pcall(function() if v ~= gui then v:Destroy() end end) end - local blur = service.New("BlurEffect", { - Name = "Adonis_FadeOut_Blur"; - Parent = service.Lighting; - Size = 0; - }) - - local bg = service.New("Frame", { + service.TweenService:Create(service.New("Frame", { Parent = gui; BackgroundTransparency = 1; BackgroundColor3 = Color3.new(0, 0, 0); Size = UDim2.new(2, 0, 2, 0); Position = UDim2.new(-1, 0, -1, 0); - }) - - service.TweenService:Create(bg, TweenInfo.new((1 / 0.01) * 0.1), { BackgroundTransparency = 0 }):Play() - service.TweenService:Create(blur, TweenInfo.new((1 / 0.01) * 0.1), { Size = (1 / 0.01) * 5.6 }):Play() + }), TweenInfo.new((1 / 0.01) * 0.1), { BackgroundTransparency = 0 }):Play() + service.TweenService:Create(service.New("BlurEffect", { + Name = "Adonis_FadeOut_Blur"; + Parent = service.Lighting; + Size = 0; + }), TweenInfo.new((1 / 0.01) * 0.1), { Size = (1 / 0.01) * 5.6 }):Play() elseif mode == "Trippy" then local v = service.Player local bg = Instance.new("Frame") From 451505b4a2a63b0fcbf702b0d877b9398bbb937c Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 16 Dec 2024 23:00:36 +0000 Subject: [PATCH 131/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 7d89083285..e258e992db 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -3,7 +3,7 @@ return { "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; - "[v261 2024-11-18 13:35 UTC] @Dimenpsyonal"; + "[v261 2024-12-16 23:00 UTC] @Dimenpsyonal"; "(Git/Expertcoderz) Add :ckick command (#1614)"; ""; "(Git/24rr) New System: Audit Logs (#1568)"; From 81e374a764b27b9c41940bcd1f3836c06596d4ac Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Fri, 20 Dec 2024 14:58:55 -0500 Subject: [PATCH 132/189] Fix string parsing (#1789) * Fix quote thing AGAIN * Fix an issue with :slock * Update Functions.luau --- MainModule/Server/Commands/Admins.luau | 2 +- MainModule/Server/Core/Functions.luau | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index 3ea208f9fb..000c532f70 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -334,7 +334,7 @@ return function(Vargs, env) AdminLevel = "Admins"; Function = function(plr: Player, args: {string}) local arg = args[1] and string.lower(args[1]) - Functions.LogAdminAction(plr, "Server Lock", "Server is now " .. (arg == "on" or arg == "true" and "locked" or "unlocked"), "") + Functions.LogAdminAction(plr, "Server Lock", "Server is now " .. (if (arg == "on" or arg == "true") then "locked" else "unlocked"), "") if (not arg and Variables.ServerLock ~= true) or arg == "on" or arg == "true" then Variables.ServerLock = true Functions.Hint("Server Locked", service.Players:GetPlayers()) diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 74dd7a83a2..893548bac8 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1319,7 +1319,7 @@ return function(Vargs, GetEnv) if #tab>=num then break elseif #tab>=num-1 then - table.insert(tab,string.sub(msg,#str+#tab+(if str.." " == key or #(str.." ")==5 then 0 elseif #(str.." ")<5 then num-2 else 2),#msg)) + table.insert(tab,string.sub(msg,#str+#tab+(if str.." " == key or #(str.." ")==5 then 0 elseif #(str.." ")<5 then num-2 elseif #(str.." ") > num then -1 else 2),#msg)) continue end From c503bff92fe1f966904dc878244f3b485d825372 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 20 Dec 2024 20:02:22 +0000 Subject: [PATCH 133/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index e258e992db..0996e09701 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -1,8 +1,11 @@ return { - "Version: 261"; + "Version: 261.1"; "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; + "[Patch v261.1 2024-12-20 20:02 UTC] @Dimenpsyonal"; + "(Git/WalkerOfBacon) Fix string parsing (#1789)"; + ""; "[v261 2024-12-16 23:00 UTC] @Dimenpsyonal"; "(Git/Expertcoderz) Add :ckick command (#1614)"; ""; From 95b3d44a75c7e4be684bb1514512e1388fcc16ad Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:47:50 -0500 Subject: [PATCH 134/189] Fix argument handling AGAIN (#1791) --- MainModule/Server/Core/Functions.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 893548bac8..47a86cb053 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1319,7 +1319,7 @@ return function(Vargs, GetEnv) if #tab>=num then break elseif #tab>=num-1 then - table.insert(tab,string.sub(msg,#str+#tab+(if str.." " == key or #(str.." ")==5 then 0 elseif #(str.." ")<5 then num-2 elseif #(str.." ") > num then -1 else 2),#msg)) + table.insert(tab,string.sub(msg,#str+#tab+(if str.." " == key or #(str.." ")==5 then 0 elseif #(str.." ")<5 then num-2 elseif (#(str.." ") > num or #(str.."") == num) then -1 else 2),#msg)) continue end From 881c00243a331e92bcbd8fa4c297575e21e293a2 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:48:22 +0000 Subject: [PATCH 135/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 0996e09701..858f77582e 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -5,6 +5,7 @@ return { ""; "[Patch v261.1 2024-12-20 20:02 UTC] @Dimenpsyonal"; "(Git/WalkerOfBacon) Fix string parsing (#1789)"; + "(Git/WalkerOfBacon) Fix argument handling AGAIN (#1791)"; ""; "[v261 2024-12-16 23:00 UTC] @Dimenpsyonal"; "(Git/Expertcoderz) Add :ckick command (#1614)"; From df657ee53614fbd73a663264daa8ea07f46b473d Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 21 Dec 2024 17:25:52 +0000 Subject: [PATCH 136/189] Revert quote fix --- MainModule/Server/Core/Functions.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 47a86cb053..62f73678ef 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1319,7 +1319,7 @@ return function(Vargs, GetEnv) if #tab>=num then break elseif #tab>=num-1 then - table.insert(tab,string.sub(msg,#str+#tab+(if str.." " == key or #(str.." ")==5 then 0 elseif #(str.." ")<5 then num-2 elseif (#(str.." ") > num or #(str.."") == num) then -1 else 2),#msg)) + table.insert(tab,string.sub(msg,#str+3,#msg)) continue end From b7504c3af5e43a2e4601eb5707ed40e6f7e38a7d Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 21 Dec 2024 17:26:41 +0000 Subject: [PATCH 137/189] Update Changelog --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 858f77582e..d3052a93ad 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -4,6 +4,7 @@ return { "*Report bugs/issues on our GitHub repository*"; ""; "[Patch v261.1 2024-12-20 20:02 UTC] @Dimenpsyonal"; + "Revert argument handling change"; "(Git/WalkerOfBacon) Fix string parsing (#1789)"; "(Git/WalkerOfBacon) Fix argument handling AGAIN (#1791)"; ""; From b2881d134f09fdda6f476326389fbe4d92a4bc58 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 21 Dec 2024 20:23:19 +0000 Subject: [PATCH 138/189] Fix parsing function --- MainModule/Server/Core/Functions.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 62f73678ef..3cfb23da83 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1319,7 +1319,7 @@ return function(Vargs, GetEnv) if #tab>=num then break elseif #tab>=num-1 then - table.insert(tab,string.sub(msg,#str+3,#msg)) + table.insert(tab,string.sub(msg,#str+1,#msg)) continue end From ff457b272a787ed8fe6d4c653e29a850124c35bb Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 21 Dec 2024 20:24:13 +0000 Subject: [PATCH 139/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index d3052a93ad..7493692ffc 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -1,8 +1,11 @@ return { - "Version: 261.1"; + "Version: 261.2"; "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; + "[Patch v261.2 2024-12-21 20:23 UTC] @Dimenpsyonal"; + "ACTUALLY fix argument handling"; + ""; "[Patch v261.1 2024-12-20 20:02 UTC] @Dimenpsyonal"; "Revert argument handling change"; "(Git/WalkerOfBacon) Fix string parsing (#1789)"; From 81241506df0b761c54a0570b1217fc408579bf2f Mon Sep 17 00:00:00 2001 From: GalacticInspired <73362346+GalacticInspired@users.noreply.github.com> Date: Mon, 30 Dec 2024 17:40:25 +0100 Subject: [PATCH 140/189] Partially revert PR-1673 due to unhandled error --- MainModule/Server/Dependencies/TrelloAPI.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Dependencies/TrelloAPI.luau b/MainModule/Server/Dependencies/TrelloAPI.luau index 7d9721993d..e00b2101ba 100644 --- a/MainModule/Server/Dependencies/TrelloAPI.luau +++ b/MainModule/Server/Dependencies/TrelloAPI.luau @@ -10,8 +10,8 @@ ------------------------------------------------------------------------------------------------------------------------------------------------------------------- local print = function(...) warn("[Adonis TrelloAPI]: INFO:", ...) end +local error = function(...) warn("[Adonis TrelloAPI]: ERROR:", ...) end local warn = function(...) warn("[Adonis TrelloAPI]: WARN:", ...) end -local error = function(message, level) warn("[Adonis TrelloAPI]: ERROR:", message) return error("[Adonis TrelloAPI]: ERROR:"..message, level == 0 and 0 or 1 + (level or 1)) end local HttpService = game:GetService("HttpService") local Weeks = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} From 66d8d26737b66ac12e761837cb518209d70729b4 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 30 Dec 2024 19:47:03 +0300 Subject: [PATCH 141/189] Update Changelog v261.3 --- MainModule/Server/Shared/Changelog.luau | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 7493692ffc..e6b4f6aaeb 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -1,8 +1,11 @@ return { - "Version: 261.2"; + "Version: 261.3"; "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; + "[Patch v261.3 2024-12-30 16:46 UTC] @Dimenpsyonal"; + "Fix trello erroring instead of warning (#1805)"; + ""; "[Patch v261.2 2024-12-21 20:23 UTC] @Dimenpsyonal"; "ACTUALLY fix argument handling"; ""; @@ -497,7 +500,7 @@ return { "(Git/DaRealGandhi20) [Add Text Selectable + New Text Format] :selectplayers/:count (#1132)"; "Git/Dimenpsyonal) Add atmosphere support (#1139)"; "(Git/Deniernal354) Add myself to credits (#1144)"; - "Git/wilsontultus) Update Moderators.lua - :invisible and :visible command... (#1146)"; + "(Git/wilsontultus) Update Moderators.lua - :invisible and :visible command... (#1146)"; "(Git/wilsontulus) Update !playerinfo command - Mail & Phone/ID Verified Status (#1147)"; "(Git/Dimenpsyonal) Add age restriction settings (#1149)"; "(Git/Dimenpsyonal) Remove GitHub link (#1150)"; From 66fdb87cbad54c1e9a8cf039ee4af347f0a2b341 Mon Sep 17 00:00:00 2001 From: fxe Date: Fri, 3 Jan 2025 12:25:04 +0000 Subject: [PATCH 142/189] Fixed TextBox capability warning (#1812) Resolves bug where if the TextBox wasn't accessible (Usually CoreGui instances) it would error due to not having the correct capabilities to access the instance. --- MainModule/Client/Core/Process.luau | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MainModule/Client/Core/Process.luau b/MainModule/Client/Core/Process.luau index 540a1ccb13..0b868b7ed2 100644 --- a/MainModule/Client/Core/Process.luau +++ b/MainModule/Client/Core/Process.luau @@ -169,7 +169,7 @@ return function(Vargs, GetEnv) end local textbox = service.UserInputService:GetFocusedTextBox() - if textbox then + if textbox and service.CheckProperty(textbox, "ReleaseFocus") then textbox:ReleaseFocus() end @@ -179,7 +179,7 @@ return function(Vargs, GetEnv) HandleTextChatCommands = function() local data = Remote.Get("PlayerData") local adminLevel, isDonor = data.AdminLevel, data.isDonor - + if service.TextChatService and service.TextChatService.ChatVersion == Enum.ChatVersion.TextChatService then local function onCommandAdded(command) if not command:IsA("TextChatCommand") then From d71b97a4c5269f8bcfe53e899d53af818ede7694 Mon Sep 17 00:00:00 2001 From: kaiserandaxl <122803145+kaiserandaxl@users.noreply.github.com> Date: Fri, 3 Jan 2025 06:27:48 -0600 Subject: [PATCH 143/189] Fix indexing nil tab (#1800) * Fix indexing nil tab * Move the LogAdded event into the if statement --- MainModule/Server/Core/Logs.luau | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/MainModule/Server/Core/Logs.luau b/MainModule/Server/Core/Logs.luau index 311492d0c2..8d36db06a3 100644 --- a/MainModule/Server/Core/Logs.luau +++ b/MainModule/Server/Core/Logs.luau @@ -88,16 +88,18 @@ return function(Vargs, GetEnv) log.Time = os.time() end - if tab.__meta == "DLL" then - tab:AddToStartAndRemoveEndIfEnd(log, Logs.MaxLogs) - else - table.insert(tab, 1, log) - if #tab > tonumber(Logs.MaxLogs) then - table.remove(tab, #tab) + if tab then + if tab.__meta == "DLL" then + tab:AddToStartAndRemoveEndIfEnd(log, Logs.MaxLogs) + else + table.insert(tab, 1, log) + if #tab > tonumber(Logs.MaxLogs) then + table.remove(tab, #tab) + end end + + service.Events.LogAdded:Fire(Logs.TabToType(tab), log, tab) end - - service.Events.LogAdded:Fire(Logs.TabToType(tab), log, tab) end; -- // Preliminary support for oldlog encryption From 71b63366b61429eb295cc92a9e6547f56ce3bb3a Mon Sep 17 00:00:00 2001 From: fxe Date: Fri, 3 Jan 2025 12:28:23 +0000 Subject: [PATCH 144/189] Fix BrickColor typo inside sing command (#1811) Changed from incorrect "Lily White" to "Lily white" --- MainModule/Server/Commands/Fun.luau | 42 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index 3343588c6e..bc8a76aba6 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -154,7 +154,7 @@ return function(Vargs, env) --// Apparently Rojo doesn't handle mesh parts very well, so I'm loading this remotely (using require to bypass insertservice restrictions) --// The model is free to take so feel free to that 👍 --// Here's the URL https://www.roblox.com/library/7679952474/Adonis-Assets-Module - if not gerald then -- TODO: Add gerald to deps and remove require, I think the Rojo plugin (up to date) now supports loading + if not gerald then -- TODO: Add gerald to deps and remove require, I think the Rojo plugin (up to date) now supports loading warn("Requiring Assets Module by ID; Expand for module URL > ", {URL = "https://www.roblox.com/library/7679952474/Adonis-Assets-Module"}) gerald = require(7679952474).Gerald --// This apparently caches, so don't delete anything else future usage breaks end @@ -626,7 +626,7 @@ return function(Vargs, env) TorsoColor = BrickColor.new("Artichoke").Color, Face = math.random(1, 3) == 3 and 173789114 or 133360789, } - + local ActionProperties = { Speed = args[2] or nil, Health = args[3] or nil, @@ -644,7 +644,7 @@ return function(Vargs, env) end task.defer(humanoid.ApplyDescription, humanoid, description, Enum.AssetTypeVerification.Always) - + if ActionProperties.Speed then humanoid.WalkSpeed = ActionProperties.Speed end if ActionProperties.Jumppower then humanoid.JumpPower = ActionProperties.Jumppower end if ActionProperties.Health then humanoid.MaxHealth = ActionProperties.Health; humanoid.Health = ActionProperties.Health end @@ -3326,29 +3326,29 @@ return function(Vargs, env) torso.Anchored = true torso.BottomSurface = 0 torso.TopSurface = 0 - + for _, v in char:GetChildren() do if v:IsA("BasePart") then v.Anchored = true end end - + local function size(part) for _, v in part:GetChildren() do if (v:IsA("Weld") or v:IsA("Motor") or v:IsA("Motor6D")) and v.Part1 and v.Part1:IsA("Part") then local p1 = v.Part1 local c0 = {v.C0:components()} local c1 = {v.C1:components()} - + c0[3] = c0[3]*num c1[3] = c1[3]*num - + p1.Anchored = true v.Part1 = nil - + v.C0 = CFrame.new(unpack(c0)) v.C1 = CFrame.new(unpack(c1)) - + if p1.Name ~= "Head" and p1.Name ~= "Torso" then p1.Size = Vector3.new(p1.Size.X, p1.Size.Y, num) elseif p1.Name ~= "Torso" then @@ -3359,9 +3359,9 @@ return function(Vargs, env) m.Part1.Anchored = true end end - + p1.Size = Vector3.new(p1.Size.X, p1.Size.Y, num) - + for _, m in p1:GetChildren() do if m:IsA("Weld") then m.Part0 = p1 @@ -3369,15 +3369,15 @@ return function(Vargs, env) end end end - + if v.Parent == torso then p1.BottomSurface = 0 p1.TopSurface = 0 end - + p1.Anchored = false v.Part1 = p1 - + if v.Part0 == torso then table.insert(welds, v) p1.Anchored = true @@ -3389,24 +3389,24 @@ return function(Vargs, env) size(v) end end - + size(char) - + torso.Size = Vector3.new(torso.Size.X, torso.Size.Y, num) - + for i, v in welds do v.Part0 = torso v.Part1.Anchored = false end - + for i, v in char:GetChildren() do if v:IsA("BasePart") then v.Anchored = false end end - + Functions.MakeWeld(root, torso, CFrame.new(), CFrame.new()) - + local cape = char:FindFirstChild("ADONIS_CAPE") if cape then cape.Size = cape.Size*num @@ -5029,7 +5029,7 @@ return function(Vargs, env) local humanoid = character:FindFirstChildOfClass("Humanoid") local isR15 = humanoid and humanoid.RigType == Enum.HumanoidRigType.R15 or false local relativeSize = head.Size / (isR15 and Vector3.new(1.2, 1.2, 1.2) or Vector3.new(2, 1, 1)) - local partsColor = ({head.Color:ToHSV()})[3] < 0.26 and BrickColor.new("Lily White") or BrickColor.new("Black") + local partsColor = ({head.Color:ToHSV()})[3] < 0.26 and BrickColor.new("Lily white") or BrickColor.new("Black") local sound = head:FindFirstChild("ADONIS_SOUND") or Instance.new("Sound") sound.SoundId = `rbxassetid://{id}` From 8e557b39e2a87b75dab8ae1a7c3d3538f66a8982 Mon Sep 17 00:00:00 2001 From: kaiserandaxl <122803145+kaiserandaxl@users.noreply.github.com> Date: Fri, 3 Jan 2025 06:30:33 -0600 Subject: [PATCH 145/189] Add override for TShirt Asset Type (#1799) --- MainModule/Server/Commands/Moderators.luau | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index 28ac795b70..af76d904f4 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -5414,7 +5414,8 @@ return function(Vargs, env) assert(success and productInfo, "Invalid item ID") local AssetTypeNameDescriptionOverides = { - DynamicHead = "Head" + DynamicHead = "Head"; + TShirt = "GraphicTShirt" } --local typeEnum = Enum.AvatarAssetType:FromValue(productInfo.AssetTypeId) local typeId = productInfo.AssetTypeId From 5f18af773c27811a128a1974cb95b58cc6109fcf Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 3 Jan 2025 12:35:16 +0000 Subject: [PATCH 146/189] v262 prelim changelog --- MainModule/Server/Shared/Changelog.luau | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index e6b4f6aaeb..0e3b3be59a 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -1,8 +1,15 @@ return { - "Version: 261.3"; + "Version: 262"; "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; + "[v262 2025-01-03 12:35 UTC] @Dimenpsyonal"; + "*First update of 2025 (!!!)"; + "(Git/kaiserandaxl) Add override for TShirt Asset Type (#1799)"; + "(Git/kaiserandaxl) Fix indexing nil tab (#1800)"; + "(Git/fxeP1) Fix BrickColor typo inside sing command (#1811)"; + "(Git/fxeP1) Fixed TextBox capability warning (#1812)"; + ""; "[Patch v261.3 2024-12-30 16:46 UTC] @Dimenpsyonal"; "Fix trello erroring instead of warning (#1805)"; ""; From 463e105fab34051de281c5ac1b77b1b4f83fb58d Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 4 Jan 2025 15:47:46 +0000 Subject: [PATCH 147/189] Fix non-extant log logging --- MainModule/Server/Plugins/Server-SoftShutdown.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Plugins/Server-SoftShutdown.luau b/MainModule/Server/Plugins/Server-SoftShutdown.luau index 4c5cc16f3d..2e6b95f180 100644 --- a/MainModule/Server/Plugins/Server-SoftShutdown.luau +++ b/MainModule/Server/Plugins/Server-SoftShutdown.luau @@ -30,7 +30,7 @@ return function(Vargs, GetEnv) TeleportService:Teleport(game.PlaceId, player, {[PARAMETER_2_NAME] = true}) else Logs:AddLog("Script", `Failed to teleport {player.Name} {isReservedServer and "back to the main game" or "to a temporary softshutdown server"} due to {result.Name}. Details: {message}`) - Logs:AddLog("Error", `Failed to teleport {player.Name} {isReservedServer and "back to the main game" or "to a temporary softshutdown server"} to {result.Name}. Details: {message}`) + Logs:AddLog("Errors", `Failed to teleport {player.Name} {isReservedServer and "back to the main game" or "to a temporary softshutdown server"} to {result.Name}. Details: {message}`) Functions.Notification("Teleport failed", `SoftShutdown failed to teleport {isReservedServer and "back to the main game" or "to a temporary softshutdown server"}. Details {message}`, {player}, 35, "MatIcon://Error") end end From 80754b15437aaed748b534cc80e8a7704efce3ae Mon Sep 17 00:00:00 2001 From: Bargain Bucket <122705147+NoobBucket@users.noreply.github.com> Date: Sat, 4 Jan 2025 15:48:32 +0000 Subject: [PATCH 148/189] Fix ServerNewDex not logging correctly (#1814) Fix a typo that caused an error --- MainModule/Server/Plugins/ServerNewDex.rbxmx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Plugins/ServerNewDex.rbxmx b/MainModule/Server/Plugins/ServerNewDex.rbxmx index a6ff9ffaad..5f9e16528b 100644 --- a/MainModule/Server/Plugins/ServerNewDex.rbxmx +++ b/MainModule/Server/Plugins/ServerNewDex.rbxmx @@ -61,7 +61,7 @@ Logs:AddLog("Script", "Successfully loaded reflection metadata to Dex") else Logs:AddLog("Script", "Access to HttpService is not enabled! Dex api dump could not be fetched!") - Logs:AddLog("Error", "Access to HttpService is not enabled! Dex api dump could not be fetched!") + Logs:AddLog("Errors", "Access to HttpService is not enabled! Dex api dump could not be fetched!") --logError("Access to HttpService is not enabled! Dex api dump could not be fetched!") end end) From f16549c79b07cfdcd5ea23eda603544075c81855 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 4 Jan 2025 15:49:12 +0000 Subject: [PATCH 149/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 0e3b3be59a..49beabc0a7 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -9,6 +9,7 @@ return { "(Git/kaiserandaxl) Fix indexing nil tab (#1800)"; "(Git/fxeP1) Fix BrickColor typo inside sing command (#1811)"; "(Git/fxeP1) Fixed TextBox capability warning (#1812)"; + "(Git/NoobBucket) Fix ServerNewDex not logging correctly (#1814)"; ""; "[Patch v261.3 2024-12-30 16:46 UTC] @Dimenpsyonal"; "Fix trello erroring instead of warning (#1805)"; From 2616b83adc50725cae3a796269ba87b58bb2fbb9 Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Wed, 8 Jan 2025 05:07:36 -0500 Subject: [PATCH 150/189] Fix :oddliest (#1775) Fixes #1762 --- MainModule/Server/Commands/Fun.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index bc8a76aba6..ed910455e6 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -4733,7 +4733,7 @@ return function(Vargs, env) AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) for i, v in service.GetPlayers(plr, args[1]) do - Admin.RunCommand(`{Settings.Prefix}char`, v.Name, "userid-51310503") + Admin.RunCommand(`{Settings.Prefix}char`, v.Name, "id-51310503") end end }; From 1e2c3607feed66ddf5415f88e2937df1fb47532f Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:09:49 +0000 Subject: [PATCH 151/189] Convert test case to nightly mode (#1669) --- MainModule/Server/Plugins/Anti_Cheat.luau | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MainModule/Server/Plugins/Anti_Cheat.luau b/MainModule/Server/Plugins/Anti_Cheat.luau index 8b7b40d60c..fe74aedf5c 100644 --- a/MainModule/Server/Plugins/Anti_Cheat.luau +++ b/MainModule/Server/Plugins/Anti_Cheat.luau @@ -1,4 +1,3 @@ - --// Anti-Exploit return function(Vargs, GetEnv) local server = Vargs.Server; @@ -27,7 +26,7 @@ return function(Vargs, GetEnv) player.CharacterAdded:Wait() end - if Admin.GetLevel(player) < Settings.Ranks.Moderators.Level or Core.DebugMode then + if Admin.GetLevel(player) < Settings.Ranks.Moderators.Level or server.Data.NightlyMode then Anti.CharacterCheck(player) end end From ca5d04fd0948005aa38b4fc5fb987aa3bef9c21e Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:10:41 +0000 Subject: [PATCH 152/189] Update urgent messages module on publish (#1697) * Create alerts.deploy.project.json * Publish alerts module too --- .github/alerts.deploy.project.json | 6 ++++++ .github/workflows/publish.yml | 13 +++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 .github/alerts.deploy.project.json diff --git a/.github/alerts.deploy.project.json b/.github/alerts.deploy.project.json new file mode 100644 index 0000000000..c15a3de83d --- /dev/null +++ b/.github/alerts.deploy.project.json @@ -0,0 +1,6 @@ +{ + "name": "MainModule", + "tree": { + "$path": "../MainModule/Server/Dependencies/__URGENT_MESSAGES.luau" + } +} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d91694631e..2e334559bb 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -71,6 +71,9 @@ jobs: - name: Build MainModule run: rojo build -o module.rbxm .github/module.deploy.project.json + + - name: Build Alerts Module + run: rojo build -o alertsmodule.rbxm .github/alerts.deploy.project.json - name: Send Standalone Release to Discord channel uses: tsickert/discord-webhook@v6.0.0 @@ -97,3 +100,13 @@ jobs: files: '{ "file": "module.rbxm" }' customHeaders: '{ "upload-secret": "${{ secrets.PUBURL2_SECRET }}" }' timeout: 10000 + + - name: Publish Alerts Module + uses: fjogeleit/http-request-action@v1.16.1 + with: + url: "${{ secrets.PUBURL2 }}/?assetId=${{ secrets.ALERTS_MODULE_ID }}" + method: "POST" + contentType: "multipart/form-data" + files: '{ "file": "alertsmodule.rbxm" }' + customHeaders: '{ "upload-secret": "${{ secrets.PUBURL2_SECRET }}" }' + timeout: 10000 From 31934980cfe01095f826698095dae180384f56f8 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:11:42 +0000 Subject: [PATCH 153/189] Update Roblox StandardLib before lint (#1764) * Generate Roblox standard library before lint * Generate Roblox standard library before lint * Update build.sh * Update build.bat --- build.bat | 7 +++++-- build.sh | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/build.bat b/build.bat index a1023dba8c..1d299b378f 100644 --- a/build.bat +++ b/build.bat @@ -15,10 +15,13 @@ IF %ERRORLEVEL% NEQ 0 ( SET ROJO_COMMAND=rojo ) +echo Updating Roblox standard library with %SELENE_COMMAND% +%SELENE_COMMAND% generate-roblox-std + echo Checking for lint errors with %SELENE_COMMAND% from ./Loader and ./MainModule %SELENE_COMMAND% ./MainModule ./Loader -echo Running %ROJO_COMMAND% build -o Adonis.rbxm -%ROJO_COMMAND% build -o Adonis.rbxm +echo Running %ROJO_COMMAND% build -o Adonis.rbxl +%ROJO_COMMAND% build -o Adonis.rbxl ENDLOCAL diff --git a/build.sh b/build.sh index c6733cbc4e..5da0cb392a 100644 --- a/build.sh +++ b/build.sh @@ -1,7 +1,10 @@ #!/bin/bash +printf "Updating Roblox standard library" +selene generate-roblox-std + printf "Checking for lint errors from ./Loader and ./MainModule" selene ./Loader ./MainModule -printf "Running rojo build -o Adonis.rbxm" -rojo build -o Adonis.rbxm +printf "Running rojo build -o Adonis.rbxl" +rojo build -o Adonis.rbxl From b78a5e4b4beaf88c670024baf31cec3b187bf7a6 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:12:32 +0000 Subject: [PATCH 154/189] Use JIT for Visualizer and Slider and use optimization level 2 for Visualizer (#1774) * Use native and optimize for visualizer * Use native for slider --- MainModule/Client/UI/Default/Music/Slider.luau | 1 + MainModule/Client/UI/Default/Music/Visualizer.luau | 2 ++ 2 files changed, 3 insertions(+) diff --git a/MainModule/Client/UI/Default/Music/Slider.luau b/MainModule/Client/UI/Default/Music/Slider.luau index f24cc2065b..6dcd7d7722 100644 --- a/MainModule/Client/UI/Default/Music/Slider.luau +++ b/MainModule/Client/UI/Default/Music/Slider.luau @@ -1,3 +1,4 @@ +--!native -------------------------------------------------------------------------------------------- -------------------------------------- Slider Module --------------------------------------- -- [Adonis Maintainer]: P3tray diff --git a/MainModule/Client/UI/Default/Music/Visualizer.luau b/MainModule/Client/UI/Default/Music/Visualizer.luau index 6772f56c24..7c089564cf 100644 --- a/MainModule/Client/UI/Default/Music/Visualizer.luau +++ b/MainModule/Client/UI/Default/Music/Visualizer.luau @@ -1,3 +1,5 @@ +--!native +--!optimize 2 local RunService = game:GetService("RunService") local module = {} From cf15da50b8f49207a0ff3b4fef16f3922c01f51f Mon Sep 17 00:00:00 2001 From: TheSkout001 Date: Wed, 8 Jan 2025 13:14:14 +0300 Subject: [PATCH 155/189] add !sit command (#1776) * add !sit command yes * add * move !sit command from Players to Donors * Sit -> DonorSit --- MainModule/Server/Commands/Donors.luau | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Commands/Donors.luau b/MainModule/Server/Commands/Donors.luau index 855c5603f4..bdf434c22f 100644 --- a/MainModule/Server/Commands/Donors.luau +++ b/MainModule/Server/Commands/Donors.luau @@ -390,5 +390,19 @@ return function(Vargs, env) end }; + DonorSit = { + Prefix = Settings.PlayerPrefix; + Commands = {"sit"}; + Args = {}; + Description = "Makes your character sit"; + Donors = true; + AdminLevel = "Players"; + Function = function(plr: Player, args: {string}) + local humanoid = plr.Character and plr.Character:FindFirstChildOfClass("Humanoid") + if humanoid then + humanoid.Sit = true + end + end + }; } -end +end \ No newline at end of file From 03e233dd21013ba5c50d7b395865ff041ffc1a72 Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Wed, 8 Jan 2025 05:15:02 -0500 Subject: [PATCH 156/189] Add a way to define cameras in settings (#1777) * Update Settings.luau * Update DefaultSettings.luau * Update Variables.luau --- Loader/Config/Settings.luau | 12 ++++++++++++ MainModule/Server/Core/Variables.luau | 15 +++++++++++++++ .../Server/Dependencies/DefaultSettings.luau | 13 +++++++++++++ 3 files changed, 40 insertions(+) diff --git a/Loader/Config/Settings.luau b/Loader/Config/Settings.luau index 04a748438c..88b54846dd 100644 --- a/Loader/Config/Settings.luau +++ b/Loader/Config/Settings.luau @@ -210,6 +210,16 @@ settings.Aliases = { [":examplealias "] = ":ff | :fling | :fire " --// Order arguments appear in alias string determines their required order in the command message when ran later }; +settings.Cameras = { +--[[ + "Camera Name" would be the name of your camera + { + Name = "Camera Name"; + Position = Vector3.new(0, 0, 0) + } +]] +} + settings.Banned = {} -- List of people banned from the game Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Muted = {} -- List of people muted (cannot send chat messages) Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Blacklist = {} -- List of people banned from running commands Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} @@ -406,6 +416,7 @@ descs.Creators = [[ Anyone to be identified as a place owner; Format: {"Username descs.Permissions = [[ Command permissions; Format: {"Command:NewLevel";} ]] descs.Aliases = [[ Command aliases; Format: {[":alias ..."] = ":command ..."} ]] +descs.Cameras = [[ Cameras; Format: {Name = "CamName", Position = Vector3.new(X, Y, Z)} ]] descs.Commands = [[ Custom commands ]] descs.Banned = [[ List of people banned from the game; Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID";} ]] @@ -523,6 +534,7 @@ order = { " "; "Permissions"; "Aliases"; + "Cameras"; " "; "Commands"; "Banned"; diff --git a/MainModule/Server/Core/Variables.luau b/MainModule/Server/Core/Variables.luau index f7243ea007..dc5132804d 100644 --- a/MainModule/Server/Core/Variables.luau +++ b/MainModule/Server/Core/Variables.luau @@ -32,6 +32,21 @@ return function(Vargs, GetEnv) Variables.ChatCreateRobloxCommands = Settings.ChatCreateRobloxCommands == nil and Variables.ChatCreateRobloxCommands or Settings.ChatCreateRobloxCommands Variables.DisableRejoinAtMaxPlayers = Settings.DisableRejoinAtMaxPlayers or Variables.DisableRejoinAtMaxPlayers + for _, v in Settings.Cameras or {} do + local cam = service.New("Part", { + Parent = workspace; + Name = `Camera: {v.Name}`; + Position = v.Position; + Anchored = true; + CanCollide = false; + Locked = true; + Size = Vector3.new(1, 1, 1); + Transparency = 1; + }) + + table.insert(Variables.Cameras, {Brick = cam, Name = v.Name}) + end + for _, v in Settings.MusicList or {} do table.insert(Variables.MusicList, v) end for _, v in Settings.InsertList or {} do table.insert(Variables.InsertList, v) end for _, v in Settings.CapeList or {} do table.insert(Variables.Capes, v) end diff --git a/MainModule/Server/Dependencies/DefaultSettings.luau b/MainModule/Server/Dependencies/DefaultSettings.luau index c19cbef1d6..8bde88b275 100644 --- a/MainModule/Server/Dependencies/DefaultSettings.luau +++ b/MainModule/Server/Dependencies/DefaultSettings.luau @@ -211,6 +211,17 @@ settings.Aliases = { [":examplealias "] = ":ff | :fling | :fire " --// Order arguments appear in alias string determines their required order in the command message when ran later }; +--// Use the below table to define pre-set cameras +settings.Cameras = { +--[[ + "Camera Name" would be the name of your camera + { + Name = "Camera Name"; + Position = Vector3.new(0, 0, 0) + } +]] +} + settings.Banned = {} -- List of people banned from the game Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Muted = {} -- List of people muted (cannot send chat messages) Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} settings.Blacklist = {} -- List of people banned from running commands Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";} @@ -407,6 +418,7 @@ descs.Creators = [[ Anyone to be identified as a place owner; Format: {"Username descs.Permissions = [[ Command permissions; Format: {"Command:NewLevel";} ]] descs.Aliases = [[ Command aliases; Format: {[":alias ..."] = ":command ..."} ]] +descs.Cameras = [[ Cameras; Format: {Name = "CamName", Position = Vector3.new(X, Y, Z)} ]] descs.Commands = [[ Custom commands ]] descs.Banned = [[ List of people banned from the game; Format: {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID";} ]] @@ -524,6 +536,7 @@ order = { " "; "Permissions"; "Aliases"; + "Cameras"; " "; "Commands"; "Banned"; From 082769ef97649670d9193daa8fd477cc2bc630d2 Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Wed, 8 Jan 2025 05:15:40 -0500 Subject: [PATCH 157/189] Allow team names with spaced to be created via :teams (#1778) --- MainModule/Client/UI/Default/Teams.luau | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MainModule/Client/UI/Default/Teams.luau b/MainModule/Client/UI/Default/Teams.luau index 957c721914..000b102175 100644 --- a/MainModule/Client/UI/Default/Teams.luau +++ b/MainModule/Client/UI/Default/Teams.luau @@ -85,7 +85,7 @@ return function(data, env) self.Active = false self.AutoButtonColor = false self.Text = "..." - client.Remote.Send("ProcessCommand", string.format("%snewteam%s%s%s%s", data.CmdPrefix, data.CmdSplitKey, teamName.Text, data.CmdSplitKey, teamColor.Text)); + client.Remote.Send("ProcessCommand", string.format("%snewteam%s%s%s%s", data.CmdPrefix, data.CmdSplitKey, `"{teamName.Text}"`, data.CmdSplitKey, teamColor.Text)); teamName.Text = "" teamColor.Text = "" wait(1.2) @@ -98,9 +98,6 @@ return function(data, env) end; }) - teamName:GetPropertyChangedSignal("Text"):Connect(function() - teamName.Text = string.gsub(teamName.Text, data.CmdSplitKey, "") - end) teamColor:GetPropertyChangedSignal("Text"):Connect(function() teamColor.TextColor3 = BrickColor.new(teamColor.Text).Color --teamColor.TextColor3 = `{BrickColor.new(teamColor.Text:sub(1, 1):upper()}{teamColor.Text:sub(2):lower()).Color}` -- unfortunately we have BrickColors with names like "New Yeller" From 2998ebf749eff75dd936e22047d5e32e30201790 Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Wed, 8 Jan 2025 05:16:23 -0500 Subject: [PATCH 158/189] Add R15 support for :dog (#1781) --- MainModule/Server/Commands/Fun.luau | 51 ++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index ed910455e6..dd67eec326 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -2707,7 +2707,56 @@ return function(Vargs, env) end end elseif human.RigType == Enum.HumanoidRigType.R15 then - Remote.MakeGui(plr, "Output", {Title = "Nonfunctional"; Message = `This command does not yet support R15.`; Color = Color3.new(1,1,1)}) + if plr.Character:FindFirstChild("Shirt") then + plr.Character.Shirt.Parent = plr.Character.HumanoidRootPart + end + if plr.Character:FindFirstChild("Pants") then + plr.Character.Pants.Parent = plr.Character.HumanoidRootPart + end + local char, uppertorso, lowertorso, ca1, ca2 = plr.Character, plr.Character:FindFirstChild("UpperTorso"), plr.Character:FindFirstChild("LowerTorso"), CFrame.Angles(0, 0, 0), CFrame.Angles(0, 0, 0) + local head = char:FindFirstChild("Head") + + uppertorso.Transparency = 1 + lowertorso.Transparency = 1 + + for _, v in uppertorso:GetChildren() do + if v:IsA("Motor6D") then + local lc0 = service.New("CFrameValue", {Name = "LastC0";Value = v.C0;Parent = v}) + end + end + + for _, v in lowertorso:GetChildren() do + if v:IsA("Motor6D") then + local lc0 = service.New("CFrameValue", {Name = "LastC0";Value = v.C0;Parent = v}) + end + end + + head.Neck.C0 = CFrame.new(0, -.5, -2) * CFrame.Angles(0, 0, 0) + + char.RightUpperArm["RightShoulder"].C0 = CFrame.new(.5, -1, -1.5) * ca1 + char.LeftUpperArm["LeftShoulder"].C0 = CFrame.new(-.5, -1, -1.5) * ca2 + char.RightUpperLeg["RightHip"].C0 = CFrame.new(1, -0.3, 1.5) * ca1 + char.LeftUpperLeg["LeftHip"].C0 = CFrame.new(-1, -0.3, 1.5) * ca2 + local st = service.New("Seat", { + Name = "Adonis_Torso", + TopSurface = 0, + BottomSurface = 0, + Size = Vector3.new(3, 1, 4), + }) + + local attachment = service.New("Attachment", {Parent = st}) + local bf = service.New("VectorForce", {Force = Vector3.new(0, 2e3, 0), Parent = st, Attachment0 = attachment}) + + st.CFrame = uppertorso.CFrame + st.Parent = char + + Functions.MakeWeld(uppertorso, st, CFrame.new(), CFrame.new(0, .5, 0)) + + for _, v in char:GetDescendants() do + if v:IsA("BasePart") then + v.BrickColor = BrickColor.new("Brown") + end + end end end end From 88bcd0f231b5761fa9618ed67a6ac7249c89dd7f Mon Sep 17 00:00:00 2001 From: Wilson Simanjuntak Date: Wed, 8 Jan 2025 17:18:48 +0700 Subject: [PATCH 159/189] [Core.luau] Add task.wait workaround for loading large data in Studio (#1803) * [Core.luau] Add task.wait workaround for Studio if the table length exceeds 1000 This will mitigate the extreme lag at the first 5-10 seconds caused by huge amounts of stored data such as BannedList. * [Server.Core.luau] Optimize a bit and increase the length requirement Sorry for the mistake - constantly getting table length each iteration is also a bad idea though --- MainModule/Server/Core/Core.luau | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Core/Core.luau b/MainModule/Server/Core/Core.luau index f8b8fcdd38..5f191d1429 100644 --- a/MainModule/Server/Core/Core.luau +++ b/MainModule/Server/Core/Core.luau @@ -1289,9 +1289,11 @@ return function(Vargs, GetEnv) local data = GetData(tData.TableKey) if data then --// TODO: Possibly find a better way to "batch" TableUpdates to prevent script exhaustion + local isStudio = service.RunService:IsStudio() -- Studio lag workaround for loading larger data such as BannedList + local isHugeTable = #data > 1000 for i = 1, #data do LoadData("TableUpdate", data[i]) - if i % 250 == 0 then + if (isStudio and isHugeTable and i % 25 == 0) or i % 250 == 0 then task.wait() end end From a8ffdd16c0053d15fbec102141ead4161921384b Mon Sep 17 00:00:00 2001 From: GalacticInspired <73362346+GalacticInspired@users.noreply.github.com> Date: Wed, 8 Jan 2025 11:19:58 +0100 Subject: [PATCH 160/189] New "clear" sub-command on "whitelist" for easy whitelist clearing (#1805) * Create a new sub-command on whitelist called "wipe" * a * actualy change to clear lol * Partially revert PR-1673 due to unhandled error * nuh uh --- MainModule/Server/Commands/Admins.luau | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index 000c532f70..dd10d2f70d 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -348,8 +348,8 @@ return function(Vargs, env) Whitelist = { Prefix = Settings.Prefix; Commands = {"wl", "enablewhitelist", "whitelist"}; - Args = {"on/off/add/remove/list", "optional player"}; - Description = "Enables/disables the whitelist; :wl username to add them to the whitelist"; + Args = {"on/off/add/remove/list/clear", "optional player"}; + Description = "Enables/disables the server whitelist; :wl username to add them to the whitelist"; AdminLevel = "Admins"; Function = function(plr: Player, args: {string}) local sub = string.lower(args[1]) @@ -399,8 +399,11 @@ return function(Vargs, env) end end Remote.MakeGui(plr, "List", {Title = "Whitelist List"; Tab = Tab;}) + elseif sub == "clear" then + Variables.Whitelist.Lists.Settings = {} + Functions.Hint("Cleared server whitelist", service.Players:GetPlayers()) else - error("Invalid subcommand (on/off/add/remove/list)") + error("Invalid subcommand (on/off/add/remove/list/clear)") end end }; From e1c0bcc38bf738d4c3532dcad8b7dafd0d0cb29a Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:21:15 +0000 Subject: [PATCH 161/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 49beabc0a7..73a893e337 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -5,6 +5,17 @@ return { ""; "[v262 2025-01-03 12:35 UTC] @Dimenpsyonal"; "*First update of 2025 (!!!)"; + "(Git/TheSkout001) Add donor !sit command (#1776)"; + "(Git/WalkerOfBacon) Add a way to define cameras in settings (#1777)"; + "(Git/WalkerOfBacon) Allow team names with spaced to be created via :teams (#1778)"; + "(Git/WalkerOfBacon) Add R15 support for :dog (#1781)"; + "(Git/ccuser44) Convert test case to nightly mode (#1669)"; + "(Git/ccuser44) Update urgent messages module on publish (#1697)"; + "(Git/ccuser44) Update Roblox StandardLib before lint (#1764)"; + "(Git/ccuser44) Use JIT for Visualizer and Slider (#1774)"; + "(Git/wilsontulus) Fix for loading large data in Studio (#1803)"; + "(Git/GalacticInspired) New "clear" sub-command on "whitelist" for easy whitelist clearing (#1805)"; + "(Git/WalkerOfBacon) Fix :oddliest (#1775)"; "(Git/kaiserandaxl) Add override for TShirt Asset Type (#1799)"; "(Git/kaiserandaxl) Fix indexing nil tab (#1800)"; "(Git/fxeP1) Fix BrickColor typo inside sing command (#1811)"; From 258b376c6ad68db023dd748113bde542cee423e8 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:21:39 +0000 Subject: [PATCH 162/189] Fix quotation --- MainModule/Server/Shared/Changelog.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 73a893e337..d67eb8977b 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -14,7 +14,7 @@ return { "(Git/ccuser44) Update Roblox StandardLib before lint (#1764)"; "(Git/ccuser44) Use JIT for Visualizer and Slider (#1774)"; "(Git/wilsontulus) Fix for loading large data in Studio (#1803)"; - "(Git/GalacticInspired) New "clear" sub-command on "whitelist" for easy whitelist clearing (#1805)"; + "(Git/GalacticInspired) New 'clear' sub-command on :whitelist (#1805)"; "(Git/WalkerOfBacon) Fix :oddliest (#1775)"; "(Git/kaiserandaxl) Add override for TShirt Asset Type (#1799)"; "(Git/kaiserandaxl) Fix indexing nil tab (#1800)"; From 3f21e395086795debc6c5d766585f5f9dcfbeed1 Mon Sep 17 00:00:00 2001 From: fxe Date: Thu, 9 Jan 2025 20:59:40 +0000 Subject: [PATCH 163/189] Attempt to fix unbanning on changed player names (#1819) * Attempt to fix unbanning on changed player names * Proactive fix for Banning API plugin GetUserIdFromNameAsync & GetNameFromUserIdAsync returns the UserId/Name if a player Instance is passed. --- MainModule/Server/Commands/Admins.luau | 2 +- MainModule/Server/Commands/HeadAdmins.luau | 4 ++-- MainModule/Server/Core/Functions.luau | 14 +++++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index dd10d2f70d..fae7da28af 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -1402,7 +1402,7 @@ return function(Vargs, env) UseFakePlayer = true; }) do - if Admin.RemoveBan(v.Name) then + if Admin.RemoveBan(v) then Functions.LogAdminAction(plr, "Unban", v.Name, "User has been unbanned.") Functions.Hint(`{service.FormatPlayer(v, true)} has been unbanned`, {plr}) else diff --git a/MainModule/Server/Commands/HeadAdmins.luau b/MainModule/Server/Commands/HeadAdmins.luau index acddf436f0..b1dea981cf 100644 --- a/MainModule/Server/Commands/HeadAdmins.luau +++ b/MainModule/Server/Commands/HeadAdmins.luau @@ -102,7 +102,7 @@ return function(Vargs, env) do Functions.LogAdminAction(plr, "Un-Time Ban", v.Name, "Removed from timeban list") Functions.Hint( - if Admin.RemoveTimeBan(v.Name) + if Admin.RemoveTimeBan(v) then `{service.FormatPlayer(v, true)} has been un-time-banned` else `{service.FormatPlayer(v, true)} is not currently time-banned`, {plr} @@ -153,7 +153,7 @@ return function(Vargs, env) do Functions.LogAdminAction(plr, "Unbanned", v.Name, "N/A") Functions.Hint( - if Admin.RemoveBan(v.Name, true) + if Admin.RemoveBan(v, true) then `{service.FormatPlayer(v, true)} has been unbanned from the game` else `{service.FormatPlayer(v, true)} is not currently banned`, {plr} diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 3cfb23da83..5f3b0d3d8f 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -1337,7 +1337,7 @@ return function(Vargs, GetEnv) table.insert(tab,result) end end - + return tab end; @@ -1405,7 +1405,11 @@ return function(Vargs, GetEnv) return AllGrabbedPlayers end; - GetUserIdFromNameAsync = function(name) + GetUserIdFromNameAsync = function(name: string | Player) + if type(name) == "userdata" and name:IsA("Player") then + return name.UserId + end + local cache = Admin.UserIdCache[name] if not cache then local success, UserId = pcall(service.Players.GetUserIdFromNameAsync, service.Players, name) @@ -1419,7 +1423,11 @@ return function(Vargs, GetEnv) return cache end; - GetNameFromUserIdAsync = function(id) + GetNameFromUserIdAsync = function(id: number | Player) + if type(id) == "userdata" and id:IsA("Player") then + return id.Name + end + local cache = Admin.UsernameCache[id] if not cache then local success, Username = pcall(service.Players.GetNameFromUserIdAsync, service.Players, id) From 071e1487106a919a28f9628305f8a75758302004 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Thu, 9 Jan 2025 21:00:17 +0000 Subject: [PATCH 164/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index d67eb8977b..106e21aa21 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -5,7 +5,7 @@ return { ""; "[v262 2025-01-03 12:35 UTC] @Dimenpsyonal"; "*First update of 2025 (!!!)"; - "(Git/TheSkout001) Add donor !sit command (#1776)"; + "(Git/fxeP1) Attempt to fix unbanning on changed player names (#1819)"; "(Git/WalkerOfBacon) Add a way to define cameras in settings (#1777)"; "(Git/WalkerOfBacon) Allow team names with spaced to be created via :teams (#1778)"; "(Git/WalkerOfBacon) Add R15 support for :dog (#1781)"; From 7aceaaf31a8aa8b9164e274962c71eaf1b4e2318 Mon Sep 17 00:00:00 2001 From: connor <85421634+ScriptedConnor@users.noreply.github.com> Date: Fri, 10 Jan 2025 18:08:30 -0500 Subject: [PATCH 165/189] Fixed friends tab on the !profile command. (#1821) --- MainModule/Client/UI/Default/Profile.luau | 33 +++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/MainModule/Client/UI/Default/Profile.luau b/MainModule/Client/UI/Default/Profile.luau index b1105632bf..1abefa1804 100644 --- a/MainModule/Client/UI/Default/Profile.luau +++ b/MainModule/Client/UI/Default/Profile.luau @@ -162,29 +162,40 @@ return function(data, env) window:Ready() do --// Friends Tab + local function pagesToTable(pages) + local items = {} + while true do + table.insert(items, pages:GetCurrentPage()) + if pages.IsFinished then + break + end + pages:AdvanceToNextPageAsync() + end + return items + end local function iterPageItems(pages) + local contents = pagesToTable(pages) + local pagenum = 1 + local lastpagenum = #contents return coroutine.wrap(function() local pagenum = 1 - while true do - for _, item in ipairs(pages:GetCurrentPage()) do + while pagenum <= lastpagenum do + for _, item in ipairs(contents[pagenum]) do coroutine.yield(item, pagenum) end - if pages.IsFinished then - break - end - pages:AdvanceToNextPageAsync() + pagenum += 1 end end) end - local LOCATION_TYPE = {"Mobile Website", "Mobile InGame", "Webpage", "Studio", "InGame", "Xbox", "Team Create"} + local LOCATION_TYPE = {"Mobile Website", "Mobile In-Game", "Webpage", "Studio", "In-Game", "Xbox", "Team Create"} local ACTIVITY_COLOR_CODES = { ["Mobile Website"] = Color3.fromRGB(50, 140, 231); - ["Mobile InGame"] = Color3.fromRGB(55, 200, 55); + ["Mobile In-Game"] = Color3.fromRGB(55, 200, 55); ["Webpage"] = Color3.fromRGB(50, 140, 231); ["Studio"] = Color3.fromRGB(231, 112, 0); - ["InGame"] = Color3.fromRGB(55, 200, 55); + ["In-Game"] = Color3.fromRGB(55, 200, 55); ["Xbox"] = Color3.fromRGB(127, 0, 127); ["Team Create"] = Color3.fromRGB(231, 112, 0); } @@ -210,7 +221,7 @@ return function(data, env) Routine(function() for item, pageNo in iterPageItems(friendPages) do table.insert(sortedFriends, item.Username) - local userId = item.id + local userId = item.Id local activity = onlineFriends[userId] friendInfoRef[item.Username] = { id = userId; @@ -467,4 +478,4 @@ return function(data, env) else gametab:Disable() end -end +end \ No newline at end of file From 74cff736fe3364ed385573f1ae730b6d07dc84b5 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 11 Jan 2025 02:10:27 +0300 Subject: [PATCH 166/189] Revert "add !sit command (#1776)" (#1820) This reverts commit cf15da50b8f49207a0ff3b4fef16f3922c01f51f. --- MainModule/Server/Commands/Donors.luau | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/MainModule/Server/Commands/Donors.luau b/MainModule/Server/Commands/Donors.luau index bdf434c22f..855c5603f4 100644 --- a/MainModule/Server/Commands/Donors.luau +++ b/MainModule/Server/Commands/Donors.luau @@ -390,19 +390,5 @@ return function(Vargs, env) end }; - DonorSit = { - Prefix = Settings.PlayerPrefix; - Commands = {"sit"}; - Args = {}; - Description = "Makes your character sit"; - Donors = true; - AdminLevel = "Players"; - Function = function(plr: Player, args: {string}) - local humanoid = plr.Character and plr.Character:FindFirstChildOfClass("Humanoid") - if humanoid then - humanoid.Sit = true - end - end - }; } -end \ No newline at end of file +end From f93b7118b0b708f5ddf7def3fb4d8d47364bdc26 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Fri, 10 Jan 2025 23:29:19 +0000 Subject: [PATCH 167/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 1 + 1 file changed, 1 insertion(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 106e21aa21..9ede01a5c0 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -21,6 +21,7 @@ return { "(Git/fxeP1) Fix BrickColor typo inside sing command (#1811)"; "(Git/fxeP1) Fixed TextBox capability warning (#1812)"; "(Git/NoobBucket) Fix ServerNewDex not logging correctly (#1814)"; + "(Git/ScriptedConnor) Fixed friends tab on the !profile command (#1821)"; ""; "[Patch v261.3 2024-12-30 16:46 UTC] @Dimenpsyonal"; "Fix trello erroring instead of warning (#1805)"; From 3608b08995bce944fd7b7e011cc2a72b02b3425d Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Sat, 11 Jan 2025 02:05:16 -0500 Subject: [PATCH 168/189] Fix :pchat glitching (#1809) --- MainModule/Client/UI/Default/PrivateChat.luau | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MainModule/Client/UI/Default/PrivateChat.luau b/MainModule/Client/UI/Default/PrivateChat.luau index a60b8db2bd..f4312fe6fc 100644 --- a/MainModule/Client/UI/Default/PrivateChat.luau +++ b/MainModule/Client/UI/Default/PrivateChat.luau @@ -321,7 +321,7 @@ return function(data, env) Parent = chatlog; FillDirection = "Vertical"; HorizontalAlignment = "Left"; - VerticalAlignment = "Bottom"; + VerticalAlignment = "Top"; SortOrder = "LayoutOrder"; }) @@ -358,7 +358,6 @@ return function(data, env) local p = vargs[1] local message = vargs[2] if newMessage then - print('sdf') newMessage({ PlayerName = p.Name; PlayerDisplayName = p.DisplayName; From c367391e36c4cda7b8016eaf0f1220f072b5ef92 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Sat, 11 Jan 2025 07:29:29 +0000 Subject: [PATCH 169/189] Use standardized naming for build files that respects gitignore (#1817) Co-authored-by: Expertcoderz --- .github/workflows/publish.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2e334559bb..71780ea74e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -67,14 +67,14 @@ jobs: path: ${{ steps.naming.outputs.output_name }}.rbxm - name: Build Loader - run: rojo build -o loader.rbxm .github/loader.deploy.project.json + run: rojo build -o Adonis_Loader.rbxm .github/loader.deploy.project.json - name: Build MainModule - run: rojo build -o module.rbxm .github/module.deploy.project.json + run: rojo build -o Adonis_MainModule.rbxm .github/module.deploy.project.json - name: Build Alerts Module - run: rojo build -o alertsmodule.rbxm .github/alerts.deploy.project.json - + run: rojo build -o Adonis_AlertsModule.rbxm .github/alerts.deploy.project.json + - name: Send Standalone Release to Discord channel uses: tsickert/discord-webhook@v6.0.0 with: @@ -87,7 +87,7 @@ jobs: url: "${{ secrets.PUBURL2 }}/?assetId=${{ secrets.LOADER_ID }}" method: "POST" contentType: "multipart/form-data" - files: '{ "file": "loader.rbxm" }' + files: '{ "file": "Adonis_Loader.rbxm" }' customHeaders: '{ "upload-secret": "${{ secrets.PUBURL2_SECRET }}" }' timeout: 10000 @@ -97,7 +97,7 @@ jobs: url: "${{ secrets.PUBURL2 }}/?assetId=${{ secrets.MODULE_ID }}" method: "POST" contentType: "multipart/form-data" - files: '{ "file": "module.rbxm" }' + files: '{ "file": "Adonis_MainModule.rbxm" }' customHeaders: '{ "upload-secret": "${{ secrets.PUBURL2_SECRET }}" }' timeout: 10000 @@ -107,6 +107,6 @@ jobs: url: "${{ secrets.PUBURL2 }}/?assetId=${{ secrets.ALERTS_MODULE_ID }}" method: "POST" contentType: "multipart/form-data" - files: '{ "file": "alertsmodule.rbxm" }' + files: '{ "file": "Adonis_AlertsModule.rbxm" }' customHeaders: '{ "upload-secret": "${{ secrets.PUBURL2_SECRET }}" }' timeout: 10000 From 4aff151701921256e4b466a6da36fce11dbf9c57 Mon Sep 17 00:00:00 2001 From: ImFirstPlace <38781655+ImFirstPlace@users.noreply.github.com> Date: Sat, 11 Jan 2025 18:38:49 +1100 Subject: [PATCH 170/189] Update TextField PlaceholderColor3 (#1806) --- MainModule/Client/UI/Windows XP/Window.rbxmx | 159 +++++++++++-------- 1 file changed, 91 insertions(+), 68 deletions(-) diff --git a/MainModule/Client/UI/Windows XP/Window.rbxmx b/MainModule/Client/UI/Windows XP/Window.rbxmx index cd162b580f..3439b8f3b3 100644 --- a/MainModule/Client/UI/Windows XP/Window.rbxmx +++ b/MainModule/Client/UI/Windows XP/Window.rbxmx @@ -2,7 +2,7 @@ true null nil - + false @@ -25,7 +25,7 @@ 0 - + false @@ -69,6 +69,7 @@ null null null + 0 0 @@ -118,7 +119,7 @@ false 2 - + true @@ -164,6 +165,7 @@ null null null + 0.699999988 0.699999988 @@ -222,7 +224,7 @@ 2 - + 0 @@ -234,7 +236,7 @@ - + false @@ -297,7 +299,7 @@ false 2 - + 0 @@ -308,7 +310,7 @@ 0 - + false @@ -372,7 +374,7 @@ 2 - + false @@ -469,7 +471,7 @@ 2 - + false @@ -567,7 +569,7 @@ - + false @@ -630,7 +632,7 @@ false 999999 - + false @@ -674,6 +676,7 @@ null null null + 0 5 @@ -725,7 +728,7 @@ - + false @@ -788,7 +791,7 @@ false 1 - + true @@ -834,6 +837,7 @@ null null null + 0 0 @@ -886,7 +890,7 @@ 1 - + true @@ -989,7 +993,7 @@ 1 - + false @@ -1054,7 +1058,7 @@ - + 0 @@ -1063,7 +1067,7 @@ -1 - + 0 @@ -1074,14 +1078,14 @@ true - + 0 false Code.OLD - {0506ffb7-ad3b-489a-9bef-cfd7dbff8f3e} + {31a3c2a2-a077-40a7-9010-52f827d566fa} - + 0 @@ -2713,14 +2717,14 @@ end]]> true - + 0 false NoEnv-Modifier - {9840b665-71ba-4ed0-acd6-04d535842c43} + {396ac619-0995-414c-a5c6-7c78f71f014a} - + false @@ -2879,6 +2887,7 @@ end]]> null null null + 0 0 @@ -2928,7 +2937,7 @@ end]]> false 2 - + true @@ -2974,6 +2983,7 @@ end]]> null null null + 1 -50 @@ -3026,7 +3036,7 @@ end]]> 2 - + 0 @@ -3038,7 +3048,7 @@ end]]> - + false @@ -3082,6 +3092,7 @@ end]]> null null null + 0 0 @@ -3131,7 +3142,7 @@ end]]> false 2 - + true @@ -3177,6 +3188,7 @@ end]]> null null null + 1 -100 @@ -3229,7 +3241,7 @@ end]]> 2 - + 0 @@ -3241,7 +3253,7 @@ end]]> - + true @@ -3273,7 +3285,7 @@ end]]> rbxasset://fonts/families/LegacyArial.json 400 - rbxasset://fonts/arial.ttf + rbxasset://fonts/Arimo-Regular.ttf true 0 @@ -3287,6 +3299,7 @@ end]]> null null null + 0 400 @@ -3338,7 +3351,7 @@ end]]> true 1 - + true @@ -3441,7 +3454,7 @@ end]]> 2 - + false @@ -3485,6 +3498,7 @@ end]]> null null null + 0 34 @@ -3535,7 +3549,7 @@ end]]> 9 - + false @@ -3631,7 +3645,7 @@ end]]> true 1 - + true @@ -3702,7 +3716,7 @@ end]]> 0 0 0 - false + true null 0 @@ -3721,7 +3735,7 @@ end]]> 1 - + false @@ -3824,7 +3838,7 @@ end]]> 1 - + false @@ -3927,7 +3941,7 @@ end]]> 1 - + false @@ -4030,7 +4044,7 @@ end]]> 1 - + false @@ -4133,7 +4147,7 @@ end]]> 1 - + false @@ -4236,7 +4250,7 @@ end]]> 1 - + false @@ -4339,7 +4353,7 @@ end]]> 1 - + false @@ -4442,7 +4456,7 @@ end]]> 1 - + false @@ -4545,7 +4559,7 @@ end]]> 1 - + false @@ -4642,7 +4656,7 @@ end]]> 1 - + false @@ -4740,7 +4754,7 @@ end]]> - + true @@ -4786,6 +4800,7 @@ end]]> null null null + 1 -52 @@ -4837,7 +4852,7 @@ end]]> true 2 - + true @@ -4941,7 +4956,7 @@ end]]> - + true @@ -4987,6 +5002,7 @@ end]]> null null null + 1 -76 @@ -5038,7 +5054,7 @@ end]]> true 2 - + true @@ -5141,7 +5157,7 @@ end]]> 1 - + false @@ -5239,7 +5255,7 @@ end]]> - + true @@ -5285,6 +5301,7 @@ end]]> null null null + 1 -28 @@ -5336,7 +5353,7 @@ end]]> true 2 - + false @@ -5380,6 +5397,7 @@ end]]> null null null + 0.5 0 @@ -5430,7 +5448,7 @@ end]]> 10 - + true @@ -5534,7 +5552,7 @@ end]]> - + false @@ -5632,7 +5650,7 @@ end]]> - + 0 @@ -5643,7 +5661,7 @@ end]]> true - + false @@ -5706,7 +5724,7 @@ end]]> false 1 - + false @@ -5777,7 +5795,7 @@ end]]> 0 0 0 - false + true null 0 @@ -5796,7 +5814,7 @@ end]]> 1 - + false @@ -5861,7 +5879,7 @@ end]]> - + false @@ -5905,6 +5923,7 @@ end]]> null null null + 0 0 @@ -5954,7 +5973,7 @@ end]]> false 2 - + true @@ -6000,6 +6019,7 @@ end]]> null null null + 1 -100 @@ -6052,7 +6072,7 @@ end]]> 2 - + 0 @@ -6064,7 +6084,7 @@ end]]> - + false @@ -6127,7 +6147,7 @@ end]]> false 2 - + 0 @@ -6138,7 +6158,7 @@ end]]> TestDesc - + false @@ -6182,6 +6202,7 @@ end]]> null null null + 0 5 @@ -6232,7 +6253,7 @@ end]]> 2 - + false @@ -6276,6 +6297,7 @@ end]]> null null null + 1 -10 @@ -6327,7 +6349,7 @@ end]]> - + true @@ -6373,6 +6395,7 @@ end]]> null null null + 1 -100 @@ -6426,4 +6449,4 @@ end]]> - + \ No newline at end of file From c6a288435bdf6eb4a4735b4805d47d6ac933adb5 Mon Sep 17 00:00:00 2001 From: Jacob <147295502+Jgard12521@users.noreply.github.com> Date: Sat, 11 Jan 2025 03:35:52 -0600 Subject: [PATCH 171/189] Update the Licence Date (#1815) * Update LICENSE.luau * Update LICENSE.md --- LICENSE.luau | 2 +- LICENSE.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE.luau b/LICENSE.luau index 1c2b089369..a81c1f3dbe 100644 --- a/LICENSE.luau +++ b/LICENSE.luau @@ -2,7 +2,7 @@ MIT License - Copyright (c) 2016-2024 Sceleratis (https://github.com/Sceleratis), Epix Incorporated, and the Adonis Community. + Copyright (c) 2016-2025 Sceleratis (https://github.com/Sceleratis), Epix Incorporated, and the Adonis Community. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LICENSE.md b/LICENSE.md index cca960237f..f35d57aa81 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016-2024 Sceleratis (https://github.com/Sceleratis), Epix Incorporated, and the Adonis Community. +Copyright (c) 2016-2025 Sceleratis (https://github.com/Sceleratis), Epix Incorporated, and the Adonis Community. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 0cf0aa0b9c7382c4e320830483c28088d0a3d643 Mon Sep 17 00:00:00 2001 From: Speeder323 <61844671+Speeder323@users.noreply.github.com> Date: Sat, 11 Jan 2025 10:46:25 +0100 Subject: [PATCH 172/189] Fix debounce for antiexploit notifications (#1783) * Fix notification debounce not being utilized The debounce was being set to 1 if the value was set, but other than that, it was not being increased, hence the debounce never kicked in. * off by one; make it 3 notifications again * Debounce table gets cleared within 60 seconds, not after --- MainModule/Server/Core/Anti.luau | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Core/Anti.luau b/MainModule/Server/Core/Anti.luau index accd3a746d..fbdb70ebd4 100644 --- a/MainModule/Server/Core/Anti.luau +++ b/MainModule/Server/Core/Anti.luau @@ -187,7 +187,7 @@ return function(Vargs, GetEnv) if Settings.AENotifs == true or Settings.ExploitNotifications == true then -- AENotifs for old loaders local debounceIndex = `{action}{player}{info}` - if os.clock() < antiNotificationResetTick then + if os.clock() > antiNotificationResetTick then antiNotificationDebounce = {} antiNotificationResetTick = os.clock() + 60 end @@ -201,6 +201,8 @@ return function(Vargs, GetEnv) return end + antiNotificationDebounce[debounceIndex] += 1 + for _, plr in service.Players:GetPlayers() do if Admin.GetLevel(plr) >= Settings.Ranks.Moderators.Level then Functions.Notification("Notification", string.format( From 559683dd88cbd783f1df57b158701bf36a472b08 Mon Sep 17 00:00:00 2001 From: Expertcoderz Date: Sat, 11 Jan 2025 13:28:25 +0000 Subject: [PATCH 173/189] Set argument range limits on :lowres (#1823) Prevents severe lag issues. --- MainModule/Server/Commands/Fun.luau | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau index dd67eec326..93715fec68 100644 --- a/MainModule/Server/Commands/Fun.luau +++ b/MainModule/Server/Commands/Fun.luau @@ -429,7 +429,9 @@ return function(Vargs, env) AdminLevel = "Admins"; Function = function(plr: Player, args: {string}) local size = tonumber(args[2]) or 19 + assert(size >= 10, "Pixel size too small (< 10)") local dist = tonumber(args[3]) or 100 + assert(dist <= 10_000, "Render distance too large (> 10,000)") for i, v in service.GetPlayers(plr, args[1]) do Remote.MakeGui(v, "Effect", { Mode = "Pixelize"; @@ -2724,7 +2726,7 @@ return function(Vargs, env) local lc0 = service.New("CFrameValue", {Name = "LastC0";Value = v.C0;Parent = v}) end end - + for _, v in lowertorso:GetChildren() do if v:IsA("Motor6D") then local lc0 = service.New("CFrameValue", {Name = "LastC0";Value = v.C0;Parent = v}) From 5ef191afb65cabca4c4498a9cf4702ef37523367 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sat, 11 Jan 2025 17:13:59 +0000 Subject: [PATCH 174/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 9ede01a5c0..abb535de75 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -5,6 +5,7 @@ return { ""; "[v262 2025-01-03 12:35 UTC] @Dimenpsyonal"; "*First update of 2025 (!!!)"; + "Set argument range limits on :lowres"; "(Git/fxeP1) Attempt to fix unbanning on changed player names (#1819)"; "(Git/WalkerOfBacon) Add a way to define cameras in settings (#1777)"; "(Git/WalkerOfBacon) Allow team names with spaced to be created via :teams (#1778)"; @@ -22,6 +23,9 @@ return { "(Git/fxeP1) Fixed TextBox capability warning (#1812)"; "(Git/NoobBucket) Fix ServerNewDex not logging correctly (#1814)"; "(Git/ScriptedConnor) Fixed friends tab on the !profile command (#1821)"; + "(Git/WalkerOfBacon) Fix :pchat glitching (#1809)"; + "(Git/ImFirstPlace) Update TextField PlaceholderColor3 (#1806)"; + "(Git/Speeder323) Fix debounce for antiexploit notifications (#1783)"; ""; "[Patch v261.3 2024-12-30 16:46 UTC] @Dimenpsyonal"; "Fix trello erroring instead of warning (#1805)"; From 07c77c49954028b2b8395ad928b12527e895de88 Mon Sep 17 00:00:00 2001 From: connor <85421634+convxors@users.noreply.github.com> Date: Sun, 12 Jan 2025 01:13:48 -0500 Subject: [PATCH 175/189] Github Username Changed (#1825) * Fixed friends tab on the !profile command. * Update Changelog.luau Github username changes from ScriptedConnor to convxors * Update Credits.luau Github username change from ScriptedConnor to convxors --------- Co-authored-by: connor <85421634+ScriptedConnor@users.noreply.github.com> --- MainModule/Server/Shared/Changelog.luau | 6 +++--- MainModule/Server/Shared/Credits.luau | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index abb535de75..14dfc25792 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -22,7 +22,7 @@ return { "(Git/fxeP1) Fix BrickColor typo inside sing command (#1811)"; "(Git/fxeP1) Fixed TextBox capability warning (#1812)"; "(Git/NoobBucket) Fix ServerNewDex not logging correctly (#1814)"; - "(Git/ScriptedConnor) Fixed friends tab on the !profile command (#1821)"; + "(Git/convxors) Fixed friends tab on the !profile command (#1821)"; "(Git/WalkerOfBacon) Fix :pchat glitching (#1809)"; "(Git/ImFirstPlace) Update TextField PlaceholderColor3 (#1806)"; "(Git/Speeder323) Fix debounce for antiexploit notifications (#1783)"; @@ -47,9 +47,9 @@ return { "(Git/Mars7383) Fix typo in Loadstring dependency affecting :ss (#1587)"; "(Git/PurpleCreativity) Remove ;cut command (#1590)"; "(Git/EasternBloxxer) Make dex fetch api dump on server start (#1591)"; - "(Git/ScriptedConnor) Fix TopBarShift for :setmessage (#1593)"; + "(Git/convxors) Fix TopBarShift for :setmessage (#1593)"; "(Git/jun022222222) Replace Coords.luau (#1595)"; - "(Git/ScriptedConnor) Add Text Selections to the :players Command (#1597)"; + "(Git/convxors) Add Text Selections to the :players Command (#1597)"; "(Git/omwot) Improve Modern theme (#1598)"; "(Git/jun022222222) Make mats & colors list selectable (#1599)"; "(Git/24rr) Add a search player bar for :privatechat (#1594)"; diff --git a/MainModule/Server/Shared/Credits.luau b/MainModule/Server/Shared/Credits.luau index e38134a0e3..413a1bc2f1 100644 --- a/MainModule/Server/Shared/Credits.luau +++ b/MainModule/Server/Shared/Credits.luau @@ -96,7 +96,7 @@ return { {Text = "@Hedreon", Desc = "Open Source Contributor"}; {Text = "@Mars7383", Desc = "Open Source Contributor"}; {Text = "@PurpleCreativity",Desc = "Open Source Contributor"}; - {Text = "@ScriptedConnor", Desc = "Open Source Contributor"}; + {Text = "@convxors", Desc = "Open Source Contributor"}; {Text = "@omwot", Desc = "Open Source Contributor"}; }; From 250d0a3dfc0dc883d2ae4c8a372560ec427f4a58 Mon Sep 17 00:00:00 2001 From: bt <49007543+btt-t@users.noreply.github.com> Date: Sun, 12 Jan 2025 21:57:58 +1100 Subject: [PATCH 176/189] GitHub Username Changed (#1826) * Update Changelog.luau * Update Credits.luau --- MainModule/Server/Shared/Changelog.luau | 10 +++++----- MainModule/Server/Shared/Credits.luau | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 14dfc25792..3d0523a491 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -1252,7 +1252,7 @@ return { "*Dex updated and moved to its own module; Also added server-side action support"; "*Fixed :countdown"; "*Fixed :slowmode"; - "(Git/happyman090) Fix for sp00ky and k1tty on MeshPart head places"; + "(Git/btt-t) Fix for sp00ky and k1tty on MeshPart head places"; "(Git/Expertcoderz) Mistake fixing + Aero theme"; "(Git/Expertcoderz) Add :transparency command"; "(Git/Expertcoderz) Command-related additions #379"; @@ -1315,7 +1315,7 @@ return { "(Git/ccuser44) Made print and warn work properly. Also fixed some indentation."; "(Git/ccuser44) Removed unnecessary references to filtering enabled."; "(Git/ccuser44) Fixed incorrect string literals"; - "(Git/happyman090) Refresh command update"; + "(Git/btt-t) Refresh command update"; ""; "[v217 5.9.2021 19:15 EST]"; "* Random bug fixes & changes"; @@ -1327,8 +1327,8 @@ return { "(Git/imskyyc) Updated TrelloAPI"; "(Git/ccuser44) Added unprotected metatable detection with tamper protection"; "(Git/LolloDev5123) :admins now correctly shows \"Head Admin\" instead of \"Supervisor\""; - "(Git/happyman090) Character animations for clones"; - "(Git/happyman090) Modified behaviour of kill command"; + "(Git/btt-t) Character animations for clones"; + "(Git/btt-t) Modified behaviour of kill command"; "(Git/p3tray & pbstFusion) Added :pban and :unpban as aliases for :gameban and :ungameban"; "(Git/p3tray) Added _G.Adonis.RunCommandAsNonAdmin(command, playerToRunCommandAs)"; "(Git/Expertcoderz) Revamped server details UI"; @@ -1351,7 +1351,7 @@ return { "*Removed some debug prints and debug/old code"; "*Fixed some typos"; "*Minor bug/security changes"; - "(Git/happyman090) Fixed donor neon command"; + "(Git/btt-t) Fixed donor neon command"; "(Git/Expertcoderz) Removed 'besties' from !usage"; "(Git/fxeP1) Updated ServerInfo command, HTTP.CheckHttp, and RunCommandAsPlayer"; "(Git/Expercoderz) Added :promptpremiumpurchase "; diff --git a/MainModule/Server/Shared/Credits.luau b/MainModule/Server/Shared/Credits.luau index 413a1bc2f1..2fe59fe052 100644 --- a/MainModule/Server/Shared/Credits.luau +++ b/MainModule/Server/Shared/Credits.luau @@ -39,7 +39,7 @@ return { {Text = "@NeoInversion", Desc = "Open Source Contributor"}; {Text = "@imskyyc", Desc = "Open Source Contributor"}; {Text = "@LolloDev5123", Desc = "Open Source Contributor"}; - {Text = "@happyman090", Desc = "Open Source Contributor"}; + {Text = "@btt-t", Desc = "Open Source Contributor"}; {Text = "@GalacticInspired",Desc = "Open Source Contributor"}; {Text = "@flgx16", Desc = "Open Source Contributor"}; {Text = "@DrewBokman", Desc = "Open Source Contributor"}; From 0f20c275122fdf016ddb3198268dd0368f282538 Mon Sep 17 00:00:00 2001 From: Project_HSI <57279339+ProjectHSI@users.noreply.github.com> Date: Sun, 12 Jan 2025 21:12:26 +1000 Subject: [PATCH 177/189] Update SECURITY.md to match CoasterTeam's message (#1810) --- SECURITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index c51c053726..a4ebe97558 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -11,7 +11,7 @@ Only the *live* (release) version of Adonis is officially supported and given se ## Reporting a Vulnerability in Adonis -👉 **If the vulnerability is *severe* or highly damaging**, join the [Epix Incorporated Discord server](https://discord.gg/H5RvTP3) and DM an *Adonis Maintainer*. +👉 **If the vulnerability is *severe* or highly damaging**, join the [Epix Incorporated Discord server](https://discord.gg/H5RvTP3) and DM an *Moderator*, *Developer, or *Maintainer*. 👉 **If the vulnerability is relatively minor and can be safely discussed in public**, create a bug report [on GitHub](https://github.com/Epix-Incorporated/Adonis/issues/new/choose) or in our Discord server. From 1d89bf41f83b185856b3b4de16367810f6281c16 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Sun, 12 Jan 2025 11:16:23 +0000 Subject: [PATCH 178/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 3d0523a491..2db3d51843 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -3,7 +3,7 @@ return { "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; - "[v262 2025-01-03 12:35 UTC] @Dimenpsyonal"; + "[v262 2025-01-12 11:16 UTC] @Dimenpsyonal"; "*First update of 2025 (!!!)"; "Set argument range limits on :lowres"; "(Git/fxeP1) Attempt to fix unbanning on changed player names (#1819)"; From 303fec808f56ec6838683f9f935c82d0d15900e0 Mon Sep 17 00:00:00 2001 From: Expertcoderz Date: Mon, 13 Jan 2025 03:06:12 +0000 Subject: [PATCH 179/189] Clamp #num selector to max players Prevents crashes e.g. due to `!inspect #999999999`. --- MainModule/Server/Core/Functions.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Core/Functions.luau b/MainModule/Server/Core/Functions.luau index 5f3b0d3d8f..e81407b0e3 100644 --- a/MainModule/Server/Core/Functions.luau +++ b/MainModule/Server/Core/Functions.luau @@ -355,7 +355,7 @@ return function(Vargs, GetEnv) return; end - for i = 1,num do + for i = 1, math.min(num, #service.Players:GetPlayers()) do Functions.PlayerFinders.random.Function(msg, plr, ...) end end From fda83d8fe32312857cd3a0c15c78a3254d247ba2 Mon Sep 17 00:00:00 2001 From: Expertcoderz Date: Mon, 13 Jan 2025 03:08:58 +0000 Subject: [PATCH 180/189] Load plugins asynchronously (#1822) --- MainModule/Client/Client.luau | 8 +++++--- MainModule/Server/Server.luau | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/MainModule/Client/Client.luau b/MainModule/Client/Client.luau index 4d6133487c..9b59dfc27a 100644 --- a/MainModule/Client/Client.luau +++ b/MainModule/Client/Client.luau @@ -218,7 +218,7 @@ do task.wait(1) service.Player:Kick(info) end) - + if not isStudio then spawn(pcall, function() task.wait(5) @@ -575,7 +575,7 @@ return service.NewProxy({ for i, line in ipairs(client.Changelog) do client.FormattedChangelog[i] = applyColour(line) end - + --// Setup MatIcons do local MaterialIcons = oldReq(service_UnWrap(client.Shared.MatIcons)) @@ -752,7 +752,9 @@ return service.NewProxy({ continue end - LoadModule(module, false, { script = module, cPcall = client.cPcall }) --noenv + task.defer(LoadModule, module, false, { --noenv + script = module, cPcall = client.cPcall + }) end --// We need to do some stuff *after* plugins are loaded (in case we need to be able to account for stuff they may have changed before doing something, such as determining the max length of remote commands) diff --git a/MainModule/Server/Server.luau b/MainModule/Server/Server.luau index 75245fb231..486f3ca2ae 100644 --- a/MainModule/Server/Server.luau +++ b/MainModule/Server/Server.luau @@ -632,7 +632,7 @@ return service.NewProxy({ server.FormattedChangelog[i] = applyColour(line) end - --// Setup MaterialIcons + --// Setup MaterialIcons do local MaterialIcons = require(server.Shared.MatIcons) server.MatIcons = setmetatable({}, { @@ -712,7 +712,7 @@ return service.NewProxy({ end for _, module in ipairs(data.ServerPlugins or {}) do - xpcall(LoadModule, function(reason) + task.defer(xpcall, LoadModule, function(reason) warn(`The plugin {type(module) == "string" and string.sub(module, 1, 15) or module} failed to load! Reason: {reason}`) logError(`The plugin {type(module) == "string" and string.sub(module, 1, 15) or module} failed to load! Reason: {reason}`) table.insert(server.messages, { From f4176fac76ea1775002a6afecc154fd100b63476 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:18:29 +0000 Subject: [PATCH 181/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 2db3d51843..fba90c3184 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -1,8 +1,12 @@ return { - "Version: 262"; + "Version: 263"; "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; + "[v263 2025-01-13 16:17 UTC] @Dimenpsyonal"; + "Load plugins asynchronously"; + "Clamp #num selector to max players"; + ""; "[v262 2025-01-12 11:16 UTC] @Dimenpsyonal"; "*First update of 2025 (!!!)"; "Set argument range limits on :lowres"; From 3c13b22754972f285fbb66ab65b0248a1cc16ce4 Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:18:51 +0000 Subject: [PATCH 182/189] Update Version.model to 263 --- Loader/Version.model.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Loader/Version.model.json b/Loader/Version.model.json index 50b0f991a1..6cde8b08e1 100644 --- a/Loader/Version.model.json +++ b/Loader/Version.model.json @@ -1,6 +1,6 @@ { "ClassName": "NumberValue", "Properties": { - "Value": 261 + "Value": 263 } } From 34d67746a624b3f465cacaf84c4531382b189fd0 Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Fri, 17 Jan 2025 19:37:11 +0200 Subject: [PATCH 183/189] Convert more models out of XML (#1831) * Delete MainModule/Server/Dependencies/RebootHandler.rbxmx * Create init.server.lua * Create init.meta.json * Create Mode.model.json * Create Model.model.json * Create mParent.model.json * Create Runner.model.json * Create init.server.lua * Create init.meta.json * Create Event.model.json * Delete MainModule/Server/Dependencies/Assets/BotBrain.rbxmx * Create init.client.lua * Create init.meta.json * Create Mode.model.json * Create Target.model.json * Delete MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx * Create init.client.lua * Create init.meta.json * Create Num.model.json * Create Type.model.json * Update Num.model.json * Delete MainModule/Server/Dependencies/Assets/Glitcher.rbxmx * Create init.client.lua * Create init.meta.json * Create Strength.model.json * Delete MainModule/Server/Dependencies/Assets/Sfling.rbxmx * Fix lint * Fix lint --- .../Assets/BotBrain/Event.model.json | 3 + .../Assets/BotBrain/init.meta.json | 5 + .../init.server.lua} | 43 ++----- .../Assets/ClickTeleport/Mode.model.json | 6 + .../Assets/ClickTeleport/Target.model.json | 6 + .../init.client.lua} | 38 +----- .../Assets/ClickTeleport/init.meta.json | 5 + .../Server/Dependencies/Assets/Glitcher.rbxmx | 60 ---------- .../Assets/Glitcher/Num.model.json | 6 + .../Assets/Glitcher/Type.model.json | 6 + .../Assets/Glitcher/init.client.lua | 26 ++++ .../Assets/Glitcher/init.meta.json | 5 + .../Server/Dependencies/Assets/Sfling.rbxmx | 44 ------- .../Assets/Sfling/Strength.model.json | 6 + .../Assets/Sfling/init.client.lua | 19 +++ .../Dependencies/Assets/Sfling/init.meta.json | 5 + .../Server/Dependencies/RebootHandler.rbxmx | 113 ------------------ .../RebootHandler/Mode.model.json | 6 + .../RebootHandler/Model.model.json | 3 + .../RebootHandler/Runner.model.json | 3 + .../Dependencies/RebootHandler/init.meta.json | 5 + .../RebootHandler/init.server.lua | 62 ++++++++++ .../RebootHandler/mParent.model.json | 3 + 23 files changed, 190 insertions(+), 288 deletions(-) create mode 100644 MainModule/Server/Dependencies/Assets/BotBrain/Event.model.json create mode 100644 MainModule/Server/Dependencies/Assets/BotBrain/init.meta.json rename MainModule/Server/Dependencies/Assets/{BotBrain.rbxmx => BotBrain/init.server.lua} (80%) create mode 100644 MainModule/Server/Dependencies/Assets/ClickTeleport/Mode.model.json create mode 100644 MainModule/Server/Dependencies/Assets/ClickTeleport/Target.model.json rename MainModule/Server/Dependencies/Assets/{ClickTeleport.rbxmx => ClickTeleport/init.client.lua} (60%) create mode 100644 MainModule/Server/Dependencies/Assets/ClickTeleport/init.meta.json delete mode 100644 MainModule/Server/Dependencies/Assets/Glitcher.rbxmx create mode 100644 MainModule/Server/Dependencies/Assets/Glitcher/Num.model.json create mode 100644 MainModule/Server/Dependencies/Assets/Glitcher/Type.model.json create mode 100644 MainModule/Server/Dependencies/Assets/Glitcher/init.client.lua create mode 100644 MainModule/Server/Dependencies/Assets/Glitcher/init.meta.json delete mode 100644 MainModule/Server/Dependencies/Assets/Sfling.rbxmx create mode 100644 MainModule/Server/Dependencies/Assets/Sfling/Strength.model.json create mode 100644 MainModule/Server/Dependencies/Assets/Sfling/init.client.lua create mode 100644 MainModule/Server/Dependencies/Assets/Sfling/init.meta.json delete mode 100644 MainModule/Server/Dependencies/RebootHandler.rbxmx create mode 100644 MainModule/Server/Dependencies/RebootHandler/Mode.model.json create mode 100644 MainModule/Server/Dependencies/RebootHandler/Model.model.json create mode 100644 MainModule/Server/Dependencies/RebootHandler/Runner.model.json create mode 100644 MainModule/Server/Dependencies/RebootHandler/init.meta.json create mode 100644 MainModule/Server/Dependencies/RebootHandler/init.server.lua create mode 100644 MainModule/Server/Dependencies/RebootHandler/mParent.model.json diff --git a/MainModule/Server/Dependencies/Assets/BotBrain/Event.model.json b/MainModule/Server/Dependencies/Assets/BotBrain/Event.model.json new file mode 100644 index 0000000000..4c86de4ed5 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/BotBrain/Event.model.json @@ -0,0 +1,3 @@ +{ + "ClassName": "BindableEvent" +} diff --git a/MainModule/Server/Dependencies/Assets/BotBrain/init.meta.json b/MainModule/Server/Dependencies/Assets/BotBrain/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/BotBrain/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/Assets/BotBrain.rbxmx b/MainModule/Server/Dependencies/Assets/BotBrain/init.server.lua similarity index 80% rename from MainModule/Server/Dependencies/Assets/BotBrain.rbxmx rename to MainModule/Server/Dependencies/Assets/BotBrain/init.server.lua index 0db12f9a55..ad580461d6 100644 --- a/MainModule/Server/Dependencies/Assets/BotBrain.rbxmx +++ b/MainModule/Server/Dependencies/Assets/BotBrain/init.server.lua @@ -1,18 +1,4 @@ - - true - null - nil - - - - 0 - false - true - - BotBrain - 1 - {57C75EF3-A7BD-4721-AC2E-EF182347E0A6} - - -1 - - - - - - 0 - false - Event - -1 - - - - - \ No newline at end of file +end) diff --git a/MainModule/Server/Dependencies/Assets/ClickTeleport/Mode.model.json b/MainModule/Server/Dependencies/Assets/ClickTeleport/Mode.model.json new file mode 100644 index 0000000000..35572a4e92 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/ClickTeleport/Mode.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "StringValue", + "Properties": { + "Value": "" + } +} diff --git a/MainModule/Server/Dependencies/Assets/ClickTeleport/Target.model.json b/MainModule/Server/Dependencies/Assets/ClickTeleport/Target.model.json new file mode 100644 index 0000000000..35572a4e92 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/ClickTeleport/Target.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "StringValue", + "Properties": { + "Value": "" + } +} diff --git a/MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx b/MainModule/Server/Dependencies/Assets/ClickTeleport/init.client.lua similarity index 60% rename from MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx rename to MainModule/Server/Dependencies/Assets/ClickTeleport/init.client.lua index a1602fc675..6c2fb848b4 100644 --- a/MainModule/Server/Dependencies/Assets/ClickTeleport.rbxmx +++ b/MainModule/Server/Dependencies/Assets/ClickTeleport/init.client.lua @@ -1,15 +1,4 @@ - - true - null - nil - - - - true - - ClickTeleport - {BDAA343E-7C81-459C-A2DB-06B5F4C8C90A} - - -1 - - - - - - Mode - -1 - - - - - - - - Target - -1 - - - - - - +humanoid.Died:Connect(function() tool:Destroy() end) diff --git a/MainModule/Server/Dependencies/Assets/ClickTeleport/init.meta.json b/MainModule/Server/Dependencies/Assets/ClickTeleport/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/ClickTeleport/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/Assets/Glitcher.rbxmx b/MainModule/Server/Dependencies/Assets/Glitcher.rbxmx deleted file mode 100644 index af0d4db9a1..0000000000 --- a/MainModule/Server/Dependencies/Assets/Glitcher.rbxmx +++ /dev/null @@ -1,60 +0,0 @@ - - true - null - nil - - - - true - - Glitcher - {53875408-B9EB-48D7-AF56-6C82B2C7F77E} - - -1 - - - - - - Num - -1 - - 3214.431999999999789 - - - - - - Type - -1 - - - - - - diff --git a/MainModule/Server/Dependencies/Assets/Glitcher/Num.model.json b/MainModule/Server/Dependencies/Assets/Glitcher/Num.model.json new file mode 100644 index 0000000000..9381de9457 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Glitcher/Num.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "NumberValue", + "Properties": { + "Value": 3214.431999999999789 + } +} diff --git a/MainModule/Server/Dependencies/Assets/Glitcher/Type.model.json b/MainModule/Server/Dependencies/Assets/Glitcher/Type.model.json new file mode 100644 index 0000000000..35572a4e92 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Glitcher/Type.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "StringValue", + "Properties": { + "Value": "" + } +} diff --git a/MainModule/Server/Dependencies/Assets/Glitcher/init.client.lua b/MainModule/Server/Dependencies/Assets/Glitcher/init.client.lua new file mode 100644 index 0000000000..58f18b99b9 --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Glitcher/init.client.lua @@ -0,0 +1,26 @@ +task.wait() +local torso = script.Parent +local posed = false +local type = script:WaitForChild("Type").Value +local int = tonumber(script:WaitForChild("Num").Value) or 50 + +game:GetService("RunService").RenderStepped:Connect(function() + if type == "ghost" then + torso.CFrame += Vector3.new(tonumber(int) * (posed and 4 or -2), 0, 0) + elseif type == "trippy" then + torso.CFrame *= CFrame.new(tonumber(int) * (posed and 4 or -2), 0, 0) + elseif type == "vibrate" then + local num = math.random(1,4) + + if num == 1 then + torso.CFrame *= CFrame.new(tonumber(int) * 2, 0, 0) + elseif num == 2 then + torso.CFrame *= CFrame.new(-tonumber(int) * 2, 0, 0) + elseif num == 3 then + torso.CFrame *= CFrame.new(0, 0, -tonumber(int) * 2) + elseif num == 4 then + torso.CFrame *= CFrame.new(0 ,0, tonumber(int) * 2) + end + end + posed = not posed +end) diff --git a/MainModule/Server/Dependencies/Assets/Glitcher/init.meta.json b/MainModule/Server/Dependencies/Assets/Glitcher/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Glitcher/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx b/MainModule/Server/Dependencies/Assets/Sfling.rbxmx deleted file mode 100644 index c37215ed6a..0000000000 --- a/MainModule/Server/Dependencies/Assets/Sfling.rbxmx +++ /dev/null @@ -1,44 +0,0 @@ - - true - null - nil - - - - true - - Sfling - {61F447BE-6192-4214-8938-59EF4489FA89} - - -1 - - - - - - Strength - -1 - - 0 - - - - diff --git a/MainModule/Server/Dependencies/Assets/Sfling/Strength.model.json b/MainModule/Server/Dependencies/Assets/Sfling/Strength.model.json new file mode 100644 index 0000000000..e21ad5d0af --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Sfling/Strength.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "NumberValue", + "Properties": { + "Value": 0 + } +} diff --git a/MainModule/Server/Dependencies/Assets/Sfling/init.client.lua b/MainModule/Server/Dependencies/Assets/Sfling/init.client.lua new file mode 100644 index 0000000000..49ed248e3b --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Sfling/init.client.lua @@ -0,0 +1,19 @@ +task.wait() +local cam = workspace.CurrentCamera +local torso = script.Parent +local humanoid = torso.Parent:FindFirstChildOfClass("Humanoid") +local strength = script:WaitForChild("Strength").Value + +for i = 1, 100 do + task.wait(0.1) + humanoid.Sit = true + local ex = Instance.new("Explosion") + ex.Position = torso.Position + Vector3.new(math.random(-5, 5), -10, math.random(-5, 5)) + ex.BlastRadius = 35 + ex.BlastPressure = strength + ex.ExplosionType = Enum.ExplosionType.NoCraters--Enum.ExplosionType.Craters + ex.DestroyJointRadiusPercent = 0 + ex.Archivable = false + ex.Parent = cam +end +script:Destroy() diff --git a/MainModule/Server/Dependencies/Assets/Sfling/init.meta.json b/MainModule/Server/Dependencies/Assets/Sfling/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/Assets/Sfling/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/RebootHandler.rbxmx b/MainModule/Server/Dependencies/RebootHandler.rbxmx deleted file mode 100644 index 02ee5ff485..0000000000 --- a/MainModule/Server/Dependencies/RebootHandler.rbxmx +++ /dev/null @@ -1,113 +0,0 @@ - - true - null - nil - - - - true - - RebootHandler - {62D59941-4C6D-45EB-9E45-D4A6587DB801} - - -1 - - - - - - Mode - -1 - - - - - - - - Model - -1 - - null - - - - - - mParent - -1 - - null - - - - - - Runner - -1 - - null - - - - diff --git a/MainModule/Server/Dependencies/RebootHandler/Mode.model.json b/MainModule/Server/Dependencies/RebootHandler/Mode.model.json new file mode 100644 index 0000000000..35572a4e92 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/Mode.model.json @@ -0,0 +1,6 @@ +{ + "ClassName": "StringValue", + "Properties": { + "Value": "" + } +} diff --git a/MainModule/Server/Dependencies/RebootHandler/Model.model.json b/MainModule/Server/Dependencies/RebootHandler/Model.model.json new file mode 100644 index 0000000000..186993e282 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/Model.model.json @@ -0,0 +1,3 @@ +{ + "ClassName": "ObjectValue" +} diff --git a/MainModule/Server/Dependencies/RebootHandler/Runner.model.json b/MainModule/Server/Dependencies/RebootHandler/Runner.model.json new file mode 100644 index 0000000000..186993e282 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/Runner.model.json @@ -0,0 +1,3 @@ +{ + "ClassName": "ObjectValue" +} diff --git a/MainModule/Server/Dependencies/RebootHandler/init.meta.json b/MainModule/Server/Dependencies/RebootHandler/init.meta.json new file mode 100644 index 0000000000..5077db135e --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} diff --git a/MainModule/Server/Dependencies/RebootHandler/init.server.lua b/MainModule/Server/Dependencies/RebootHandler/init.server.lua new file mode 100644 index 0000000000..fa02ab72a8 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/init.server.lua @@ -0,0 +1,62 @@ +--# selene: allow(incorrect_standard_library_use) +if script.Parent then + local dTargetVal = script:WaitForChild("Runner") + local parentVal = script:WaitForChild("mParent") + local modelVal = script:WaitForChild("Model") + local modeVal = script:WaitForChild("Mode") + + warn("Reloading in 5 seconds...") + task.wait(5) + script.Parent = nil + + local dTarget = dTargetVal.Value + local tParent = parentVal.Value + local model = modelVal.Value + local mode = modeVal.Value + + local function CleanUp() + warn("TARGET DISABLED") + dTarget.Disabled = true + pcall(function() dTarget.Parent = game:GetService("ServerScriptService") end) + task.wait() + pcall(function() dTarget:Destroy() end) + + warn("TARGET DESTROYED") + task.wait() + + warn("CLEANING") + + if not table.isfrozen(_G) then + rawset(_G, "Adonis", nil) + rawset(_G, "__Adonis_MODULE_MUTEX", nil) + rawset(_G, "__Adonis_MUTEX", nil) + end + + warn("_G VARIABLES CLEARED") + + warn("MOVING MODEL") + model.Parent = tParent + end + + if mode == "REBOOT" then + warn("ATTEMPTING TO RELOAD ADONIS") + CleanUp() + task.wait() + + warn("MOVING") + model.Parent = tParent + + task.wait() + + dTarget.Disabled = false + warn("RUNNING") + elseif mode == "STOP" then + warn("ATTEMPTING TO STOP ADONIS") + CleanUp() + end + + warn("COMPLETE") + + warn("Destroying reboot handler...") + script:Destroy() +end diff --git a/MainModule/Server/Dependencies/RebootHandler/mParent.model.json b/MainModule/Server/Dependencies/RebootHandler/mParent.model.json new file mode 100644 index 0000000000..186993e282 --- /dev/null +++ b/MainModule/Server/Dependencies/RebootHandler/mParent.model.json @@ -0,0 +1,3 @@ +{ + "ClassName": "ObjectValue" +} From 6a735fc1d29351fb6edcb13383b6da7fa9eb368b Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Wed, 22 Jan 2025 04:54:37 -0500 Subject: [PATCH 184/189] Prevent creating a team with the same name (#1836) --- MainModule/Server/Commands/Admins.luau | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MainModule/Server/Commands/Admins.luau b/MainModule/Server/Commands/Admins.luau index fae7da28af..f3312c057b 100644 --- a/MainModule/Server/Commands/Admins.luau +++ b/MainModule/Server/Commands/Admins.luau @@ -679,6 +679,12 @@ return function(Vargs, env) Function = function(plr: Player, args: {string}) local teamName = assert(args[1], "Missing team name (argument #1)") local teamColor = Functions.ParseBrickColor(args[2]) + + if service.Teams:FindFirstChild(teamName) then + Functions.Hint(string.format("Team '%s' already exists!", teamName), {plr}) + return; + end + service.New("Team", { Parent = service.Teams; Name = teamName; From 85d985bf447eb14298195101b373d3b3ca50424d Mon Sep 17 00:00:00 2001 From: Alex Yerkes Date: Wed, 22 Jan 2025 17:57:26 +0800 Subject: [PATCH 185/189] Update :watchcam description (#1835) --- MainModule/Server/Commands/Moderators.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau index af76d904f4..95b0420985 100644 --- a/MainModule/Server/Commands/Moderators.luau +++ b/MainModule/Server/Commands/Moderators.luau @@ -1445,7 +1445,7 @@ return function(Vargs, env) Prefix = Settings.Prefix; Commands = {"viewcam", "viewc", "camview", "watchcam", "cam"}; Args = {"camera"}; - Description = "Makes you view the target player"; + Description = "Makes you view the target camera"; AdminLevel = "Moderators"; Function = function(plr: Player, args: {string}) for i, v in Variables.Cameras do From acbff4a1d3868ad44631c5f3cb788293656af5e9 Mon Sep 17 00:00:00 2001 From: WalkerOfBacon <50679909+WalkerOfBacon@users.noreply.github.com> Date: Wed, 22 Jan 2025 04:59:41 -0500 Subject: [PATCH 186/189] Show command aliases in :commands (#1833) * Show command aliases in :commands * oops forgot this * Remove prefix showing up * Actually made it accurate --- MainModule/Server/Commands/Players.luau | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/MainModule/Server/Commands/Players.luau b/MainModule/Server/Commands/Players.luau index 33b54e3335..233703bd1b 100644 --- a/MainModule/Server/Commands/Players.luau +++ b/MainModule/Server/Commands/Players.luau @@ -23,14 +23,25 @@ return function(Vargs, env) local cmdCount = 0 for _, cmd in Admin.SearchCommands(plr, "all") do + local cmdAliases = table.create(#cmd.Commands) + if cmd.Hidden or cmd.Disabled then continue end + for _,alias in cmd.Commands do + if #cmdAliases >= 4 and (#cmd.Commands - #cmdAliases) ~= 0 then + table.insert(cmdAliases, `and {#cmd.Commands - #cmdAliases} more...`) + break + end + end + + table.remove(cmdAliases, 1) + local permissionDesc = Admin.FormatCommandAdminLevel(cmd) table.insert(tab, { Text = Admin.FormatCommand(cmd), - Desc = `[{permissionDesc}] {cmd.Description or "(No description provided)"}`, + Desc = `[{permissionDesc}] {if #cmdAliases >= 1 then `\nAliases: {table.concat(cmdAliases, ", ")}` else ""} \n\n{cmd.Description or "(No description provided)"}`, Filter = permissionDesc }) cmdCount += 1 From ee457e824d00e72019e803d89ce991456f5f9cda Mon Sep 17 00:00:00 2001 From: ccuser44 <68124053+ccuser44@users.noreply.github.com> Date: Wed, 22 Jan 2025 12:01:50 +0200 Subject: [PATCH 187/189] Disable visualizer when window is minimized (#1832) --- MainModule/Client/UI/Default/Music/init.luau | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/MainModule/Client/UI/Default/Music/init.luau b/MainModule/Client/UI/Default/Music/init.luau index 3725aba090..5bbd19740a 100644 --- a/MainModule/Client/UI/Default/Music/init.luau +++ b/MainModule/Client/UI/Default/Music/init.luau @@ -205,7 +205,14 @@ return function(data, env) Position = UDim2.new(0, 10, 1, -410); OnClose = function() doOnClose() - end + end, + OnMinimized = function(opened) + if opened and not visualiser.Sound then + visualiser:LinkToSound(audioLib:GetSound()) + elseif not opened and visualiser.Sound then + visualiser:UnlinkFromSound() + end + end, }) -- The controls frame at the bottom of the window From 0435a942db21f7358b678cde3fb4bcccc87c30fc Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Wed, 22 Jan 2025 11:12:19 +0000 Subject: [PATCH 188/189] Update Changelog.luau --- MainModule/Server/Shared/Changelog.luau | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index fba90c3184..0a197a31a1 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -6,6 +6,10 @@ return { "[v263 2025-01-13 16:17 UTC] @Dimenpsyonal"; "Load plugins asynchronously"; "Clamp #num selector to max players"; + "(Git/ccuser44) Disable visualiser when window is minimised (#1832)"; + "(Git/WalkerOfBacon) Show command aliases in :commands (#1833)"; + "(Git/Z3phrz) Update :watchcam description (#1835)"; + "(Git/WalkerOfBacon) Prevent creating a team with the same name (#1836)"; ""; "[v262 2025-01-12 11:16 UTC] @Dimenpsyonal"; "*First update of 2025 (!!!)"; From ba62ee2d2f03ef40e4ae0f72d595238fd09a15df Mon Sep 17 00:00:00 2001 From: nichole <64012878+Dimenpsyonal@users.noreply.github.com> Date: Wed, 22 Jan 2025 11:28:38 +0000 Subject: [PATCH 189/189] Update time --- MainModule/Server/Shared/Changelog.luau | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainModule/Server/Shared/Changelog.luau b/MainModule/Server/Shared/Changelog.luau index 0a197a31a1..ad2f09c540 100644 --- a/MainModule/Server/Shared/Changelog.luau +++ b/MainModule/Server/Shared/Changelog.luau @@ -3,7 +3,7 @@ return { "*Drag edges to expand*"; "*Report bugs/issues on our GitHub repository*"; ""; - "[v263 2025-01-13 16:17 UTC] @Dimenpsyonal"; + "[v263 2025-01-22 11:29 UTC] @Dimenpsyonal"; "Load plugins asynchronously"; "Clamp #num selector to max players"; "(Git/ccuser44) Disable visualiser when window is minimised (#1832)";