diff --git a/rpui/menu.lua b/rpui/menu.lua new file mode 100644 index 0000000..1f3938b --- /dev/null +++ b/rpui/menu.lua @@ -0,0 +1,479 @@ +--[[ + The following legacy code is created by blocco. + + This code created the menu that was present on both the server and the client. + One menu. One script. Simple. + + Here is where I used locally persistent data, to store the IP and Port of the + last connected to server. It saved a lot of time, and it was a nice feature. + + You'll notice I had a little structure for generating the menu. + + It contains many comments for documentation purposes. + It is to be used for educational purposes. + + This code is from RBXPri (Blocco Edition). + This file is "menu.lua". +--]] + +local uiBase = game.CoreGui.RPUI; +local btnShield = uiBase.UIShield; + +function createMenu(layout, fn) + + local validTypes={ + Button={"string", "string", "boolean", "function", "table"}; + Separator={}; + InformationRow={"string", "string", "string", "boolean"}; + } + + local function isValidType(tbl) + for i, v in pairs(validTypes) do + if tbl[1] == i then return true; end + end + return false; + end + local function isValidEntry(tbl) + for i, v in ipairs(tbl) do + if i ~= 1 then + if type(v) ~= validTypes[tbl[1]][i-1] then return false; end + end + end + return true; + end + + local function createButton(main, nam, txt, act, fn, i) + local btn = Instance.new("TextButton"); + btn.AutoButtonColor=false; + btn.Name = nam or "MenuButton"; + btn.Text = txt; + btn.TextTransparency = act and 0.2 or 0.5; + btn.TextColor3 = Color3.new(0, 0, 0); + btn.Font = "ArialBold"; + btn.FontSize = main and "Size14" or "Size12"; + btn.BackgroundTransparency = act and 0.8 or 0.6; + btn.BackgroundColor3 = act and Color3.new(1, 1, 1) or Color3.new(0.8, 0.8, 0.8); + btn.Size = UDim2.new(0, 100, 0, main and 20 or 16);--main and UDim2.new(0, 100, 0, 20) or UDim2.new(0, 120, 0, 16); + btn.BorderSizePixel = 0; + btn.Active = act; + btn.MouseEnter:connect(function() + if btn.Active then + btn.TextTransparency = 0.2 + btn.BackgroundTransparency = 0; + end + end) + btn.MouseLeave:connect(function() + if btn.Active then + btn.TextTransparency = 0.2 + btn.BackgroundTransparency = 0.8; + end + end) + btn.MouseButton1Down:connect(function() + if btn.Active then + btn.TextTransparency = 0 + btn.BackgroundTransparency = 0; + end + end) + btn.MouseButton1Up:connect(function() + if btn.Active then + btn.TextTransparency = 0.2 + btn.BackgroundTransparency = 0; + end + end) + btn.MouseButton1Click:connect(function() + if btn.Active then + fn(btn); + end + end) + btn.Changed:connect(function(p) + if p == "Active" then + btn.TextTransparency = btn.Active and 0.2 or 0.5; + btn.BackgroundTransparency = btn.Active and 0.8 or 0.6; + btn.BackgroundColor3 = btn.Active and Color3.new(1, 1, 1) or Color3.new(0.8, 0.8, 0.8); + end + end) + return btn; + end + + local function createSeparator(main, i) + local sep=Instance.new("Frame"); + sep.Size = UDim2.new(0, main and 1 or 96, 0, main and 16 or 1)--UDim2.new(0, main and 1 or 116, 0, main and 16 or 1); + sep.BackgroundColor3 = Color3.new(0, 0, 0); + sep.Active=true; + sep.BorderSizePixel=0; + sep.Name = "Separator"; + return sep; + end + + local function createInformationRow(main, nam, txt, typ, sav) + valLookup={ + ["string"]=""; + ["int"]="0"; + ["number"]="0"; + } + local val=valLookup[typ]; + local infRow = Instance.new("Frame"); + infRow.Name = nam; + infRow.Size = UDim2.new(0, 100, 0, main and 20 or 16)--UDim2.new(0, 120, 0, main and 20 or 16); + infRow.BackgroundColor3 = Color3.new(1, 1, 1); + infRow.BackgroundTransparency = 0.8; + infRow.BorderSizePixel=0; + infRow.Active=true; + + local function isValidEntry(typ, val) + if type(val) ~= "string" then return false end; + if typ == "string" then return true; + elseif typ == "number" then return tonumber(val) ~= nil; + elseif typ == "int" then + if not tonumber(val) then return false end + return tonumber(val)%1 == 0; + end + end + + local tonumber=tonumber; + local floor=math.floor; + + local function convertVal(v, t) + if t == "int" then v=floor(tonumber(v)+0.5) + elseif t == "number" then v=tonumber(v) end + return t:sub(1, 1):upper() .. t:sub(2), v + end + + local lbl = Instance.new("TextLabel"); + lbl.Name = "Label"; + lbl.Text = txt; + lbl.TextTransparency = 0.2; + lbl.Size = UDim2.new(1, typ == "boolean" and -20 or -60, 1, 0); + lbl.Font = "ArialBold"; + lbl.BackgroundTransparency=1; + lbl.TextXAlignment = "Right"; + lbl.FontSize = main and "Size14" or "Size12"; + lbl.TextColor3 = Color3.new(0, 0, 0) + lbl.Active = true; + lbl.Parent = infRow; + + local typInd = Instance.new("StringValue"); + typInd.Name = "TypeIndicator"; + typInd.Value = typ; + typInd.Parent = infRow; + + if typ == "boolean" then + local val=RbxData.GetValue(nam) or false; + local cbox = Instance.new("TextButton"); + cbox.AutoButtonColor=false; + cbox.BackgroundColor3 = Color3.new(1, 1, 1); + cbox.BorderColor3 = Color3.new(0, 0, 0); + cbox.BackgroundTransparency = 0.6 + cbox.Font = "Arial"; + cbox.FontSize = "Size12" + if sav then cbox.Text = (val and "X" or "") else cbox.Text = "" end + cbox.Name = "Input"; + cbox.TextColor3 = Color3.new(0, 0, 0) + cbox.Position = UDim2.new(1, -14, 1, -14); + cbox.Size = UDim2.new(0, 12, 0, 12); + cbox.MouseButton1Click:connect(function() + val = not RbxData.GetValue(nam); + cbox.Text = val and "X" or ""; + if sav then RbxData.SetValue(nam, "Bool", val) end + end) + cbox.MouseEnter:connect(function() cbox.BackgroundTransparency = 0 end) + cbox.MouseLeave:connect(function() cbox.BackgroundTransparency = 0.6 end) + cbox.Parent = infRow + else + local focus=false; + local ibox = Instance.new("TextBox"); + ibox.Name = "Input"; + ibox.BackgroundColor3 = Color3.new(1, 1, 1); + ibox.BorderColor3 = Color3.new(0, 0, 0); + ibox.BackgroundTransparency = 0.6; + ibox.ClearTextOnFocus=false; + ibox.Font = "Arial"; + ibox.FontSize = "Size12"; + ibox.Text = tostring(sav and (RbxData.GetValue(nam) or val) or val) + ibox.TextColor3 = Color3.new(0, 0, 0); + ibox.Position = UDim2.new(1, -54, 1, -14); + ibox.Size = UDim2.new(0, 52, 0, 12); + ibox.TextXAlignment = "Left"; + ibox.Parent = infRow; + local fakeibox=Instance.new("TextButton"); + fakeibox.Size = UDim2.new(1, 0, 1, 0) + fakeibox.Name = "fakebutton"; + fakeibox.BackgroundTransparency = 1; + fakeibox.TextTransparency = 1; + fakeibox.ZIndex = 2; + fakeibox.MouseButton1Click:connect(function() + ibox:CaptureFocus(); + focus=true; + ibox.BackgroundTransparency = 0; + fakeibox.Visible=false; + end) + fakeibox.MouseEnter:connect(function() ibox.BackgroundTransparency = 0 end) + fakeibox.MouseLeave:connect(function() ibox.BackgroundTransparency = 0.6 end) + fakeibox.Parent = ibox; + ibox.FocusLost:connect(function() if isValidEntry(typ, ibox.Text) then val=ibox.Text; else ibox.Text=val; end if sav then RbxData.SetValue(nam, convertVal(val, typ)) end fakeibox.Visible=true; ibox.BackgroundTransparency = 0.6; end) + end + + return infRow + end + + local layoutFns={Button=createButton, Separator=createSeparator, InformationRow=createInformationRow} + + local uiMenu = Instance.new("Frame"); + uiMenu.Name = "UIMenu" + uiMenu.BackgroundTransparency = 1; + uiMenu.BackgroundColor3 = Color3.new(0, 0, 0); + uiMenu.BorderSizePixel = 0; + uiMenu.Size = UDim2.new(0, 0, 0, 0); + uiMenu.Position = UDim2.new(0, 0, 0, 0); + + local validMainButtons=0; + local validMainSeps=0; + + for i, v in ipairs(layout) do + if isValidType(v) and isValidEntry(v) then + if v[1] == "Button" then + validMainButtons = validMainButtons + 1; + elseif v[1] == "Separator" then + validMainSeps = validMainSeps + 1; + end + end + end + + uiMenu.Size = UDim2.new(0, validMainButtons*100 + validMainSeps*3, 0, 20); + uiMenu.Position = UDim2.new(0.5, -(validMainButtons*100 + validMainSeps*3)/2, 0, 0) + + local posVars={Button={[true]=100, [false]=16}, Separator={[true]=3, [false]=3}, InformationRow={[true]=120, [false]=16}} + local function createLayout(tab) + local function recurseCreateLayout(tab, obj, main) + main = main or false; + local posVar=0; + for i, v in pairs(tab) do + if isValidType(v) and isValidEntry(v) then + local ptab={}; + for ii, vv in ipairs(v) do + if ii ~= 1 then + ptab[ii-1]=vv + end + end + local gobj=layoutFns[v[1]](main, unpack(ptab)); + gobj.Position = UDim2.new(0, main and (v[1] == "Separator" and posVar+1 or posVar) or (v[1] == "Separator" and 2 or 0), 0, main and (v[1] == "Separator" and 2 or 0) or (v[1] == "Separator" and posVar+1 or posVar)+20) + gobj.Visible=main + gobj.Parent = obj; + local typVal = Instance.new("StringValue"); + typVal.Name = "ElementType" + typVal.Value = v[1]; + typVal.Parent = gobj; + posVar=posVar+posVars[v[1]][main] + if v[1] == "Button" then + gobj.MouseButton1Click:connect( + function() + if main or not gobj.Active then return end; + for i, v in pairs(uiMenu:GetChildren()) do + for ii, vv in pairs(v:children()) do + if vv:IsA("GuiObject") then vv.Visible=false; end + end + end + btnShield.Visible=false; + end + ) recurseCreateLayout(v[6], gobj) + end + end + end + end + recurseCreateLayout(tab, uiMenu, true); + end + createLayout(layout); + + for i, v in pairs(uiMenu:GetChildren()) do + if v.ElementType.Value == "Button" then + v.MouseEnter:connect(function() + if not v.Active then return end + for ii, vv in pairs(uiMenu:GetChildren()) do + for iii, vvv in pairs(vv:children()) do + if vvv:IsA("GuiObject") then vvv.Visible=false; end + end + end + for ii, vv in pairs(v:children()) do + if vv:IsA("GuiObject") then vv.Visible=true; end + end + btnShield.Visible=true; + end) + end + end + btnShield.MouseButton1Down:connect(function() + for i, v in pairs(uiMenu:GetChildren()) do + for ii, vv in pairs(v:children()) do + if vv:IsA("GuiObject") then vv.Visible=false; end + end + end + btnShield.Visible=false; + end) + btnShield.MouseButton2Down:connect(function() + for i, v in pairs(uiMenu:GetChildren()) do + for ii, vv in pairs(v:children()) do + if vv:IsA("GuiObject") then vv.Visible=false; end + end + end + btnShield.Visible=false; + end) + + return uiMenu; +end + +local CliButFn = function(btn) + if (RbxData.GetValue("IP") and RbxData.GetValue("CPort")) or RbxData.GetValue("CJoinString") or RbxData.GetValue("RPTPString") then + _G.ClientUtilities.SetCommandBarVisibility(RbxData.GetValue("IGCB")) + _G.ClientUtilities.SetGuestTalk(RbxData.GetValue("GT")) + _G.ClientUtilities.SetToolSpawn(RbxData.GetValue("TS")); + local success; + if not RbxData.GetValue("RPTPString") and not RbxData.GetValue("CJoinString") then + _G.ClientUtilities.Connect(RbxData.GetValue("PName") or "Player", RbxData.GetValue("PID") or 0, RbxData.GetValue("IP"), RbxData.GetValue("CPort")); + success = true; + elseif RbxData.GetValue("CJoinString") then + local b, ip, prt = pcall(CJoinEx.Decode, RbxData.GetValue("CJoinString")); + if not b then print("ERROR: " .. ip) else _G.ClientUtilities.Connect(RbxData.GetValue("PName") or "Player", RbxData.GetValue("PID") or 0, ip, prt) success = true end + elseif RbxData.GetValue("RPTPString") or (RbxData.GetValue("CJoinString") and not success) then + local b, ip, prt = pcall(RPTP2.Decode, RbxData.GetValue("RPTPString")); + if not b then print("ERROR: " .. ip) else _G.ClientUtilities.Connect(RbxData.GetValue("PName") or "Player", RbxData.GetValue("PID") or 0, ip, prt) success = true end + end + + if not success then return end; + + RbxData.AddChangeCallback(function(nam) + if nam == "IGCB" then + _G.ClientUtilities.SetCommandBarVisibility(RbxData.GetValue("IGCB")); + elseif nam == "GT" then + _G.ClientUtilities.SetGuestTalk(RbxData.GetValue("GT")); + elseif nam == "TS" then + _G.ClientUtilities.SetToolSpawn(RbxData.GetValue("TS")); + end + end) + + for i, v in pairs(btn.Parent:GetChildren()) do + if v:IsA("GuiObject") then v.Visible=false end + end + btn.Parent.Active=false; + end +end +local CliButFn2 = function(btn) + if (RbxData.GetValue("IP") and RbxData.GetValue("CPort")) or RbxData.GetValue("CJoinString") or RbxData.GetValue("RPTPString") then + _G.ClientUtilities.SetCommandBarVisibility(RbxData.GetValue("IGCB")) + _G.ClientUtilities.SetGuestTalk(RbxData.GetValue("IGCB")) + _G.ClientUtilities.SetToolSpawn(RbxData.GetValue("TS")); + local success; + if not RbxData.GetValue("RPTPString") and not RbxData.GetValue("CJoinString") then + _G.ClientUtilities.ConnectAsGuest(RbxData.GetValue("IP"), RbxData.GetValue("CPort")); + success = true; + elseif RbxData.GetValue("CJoinString") then + local b, ip, prt = pcall(CJoinEx.Decode, RbxData.GetValue("CJoinString")); + if not b then print("ERROR: " .. ip) else _G.ClientUtilities.ConnectAsGuest(CJoinEx.Decode(RbxData.GetValue("CJoinString"))) success = true end + elseif RbxData.GetValue("RPTPString") or (RbxData.GetValue("CJoinString") and not success) then -- uses this if CJoinString doesn't work + local b, ip, prt = pcall(RPTP2.Decode, RbxData.GetValue("RPTPString")); + if not b then print("ERROR: " .. ip) else _G.ClientUtilities.ConnectAsGuest(RPTP2.Decode(RbxData.GetValue("RPTPString"))) success = true end + end + + if not success then return end; + + RbxData.AddChangeCallback(function(nam) + if nam == "IGCB" then + _G.ClientUtilities.SetCommandBarVisibility(RbxData.GetValue("IGCB")); + elseif nam == "GT" then + _G.ClientUtilities.SetGuestTalk(RbxData.GetValue("GT")); + elseif nam == "TS" then + _G.ClientUtilities.SetToolSpawn(RbxData.GetValue("TS")); + end + end) + + for i, v in pairs(btn.Parent:GetChildren()) do + if v:IsA("GuiObject") then v.Visible=false end + end + btn.Parent.Active=false; + end +end +local num; +local SerButFn = function(btn) + if not RbxData.GetValue("SPort") then return end + _G.ServerUtilities.Start(RbxData.GetValue("SPort") or 53640) + math.randomseed(tick()+2) + num = num or math.random(16) - 9; + print("RPTP2:", RPTP2.Encode(RbxData.GetValue("SIP") or "127.0.0.1", RbxData.GetValue("SPort") or 53640, num)); + print("CJoinEx:", CJoinEx.Encode(RbxData.GetValue("SIP") or "127.0.0.1", RbxData.GetValue("SPort") or 53640)); +end +local SerStopButFn = function(btn) + _G.ServerUtilities.Stop(); +end +local RdFn = function(btn) + for i, v in pairs(btn.Parent:children()) do + if v:IsA("GuiObject") and v.ElementType.Value == "InformationRow" then + RbxData.SetValue(v.Name, nil); + if v.TypeIndicator.Value == "number" or v.TypeIndicator.Value == "int" then + v.Input.Text = "0"; + else + v.Input.Text = ""; + end + end + end +end +local RadFn = function(btn) + for i, v in pairs(btn.Parent.Parent:children()) do + for i, v in pairs(v:children()) do + if v:IsA("GuiObject") and v.ElementType.Value == "InformationRow" then + RbxData.SetValue(v.Name, nil); + if v.TypeIndicator.Value == "number" or v.TypeIndicator.Value == "int" then + v.Input.Text = "0"; + else + v.Input.Text = ""; + end + end + end + end +end +local ExitFn = function(btn) + game:Shutdown(); +end + +local menuLayout={ + {"Button", "ClientButton", "Client", false, function() end, + { + {"InformationRow", "IP", "IP", "string", true}; + {"InformationRow", "CPort", "Port", "int", true}; + {"InformationRow", "CJoinString", "CJoinEx", "string", true}; + {"InformationRow", "RPTPString", "RPTP2", "string", true}; + {"InformationRow", "PName", "Name", "string", true}; + {"InformationRow", "PID", "ID", "int", true}; + {"Button", "JoinButton", "Join As Guest", true, CliButFn2, {}}; + {"Button", "JoinButton", "Join Game", true, CliButFn, {}}; + {"Separator"}; + {"Button", "RD1Button", "Reset Data", true, RdFn, {}}; + }; + }; + {"Button", "ServerButton", "Server", false, function() end, + { + {"InformationRow", "SIP", "IP", "string", true}; -- used for creation of RPTPStrings + {"InformationRow", "SPort", "Port", "int", true}; + {"Button", "StartButton", "Start Game", true, SerButFn, {}}; + {"Button", "StopButton", "Stop Game", true, SerStopButFn, {}}; + {"Separator"}; + {"Button", "RD2Button", "Reset Data", true, RdFn, {}}; + }; + }; + {"Button", "OptionsButton", "Options", true, function() end, + { + {"InformationRow", "GT", "Guest Talk", "boolean", true}; + {"InformationRow", "IGCB", "IG Cmd Bar", "boolean", true}; + {"InformationRow", "TS", "Tools Spawn", "boolean", true}; + {"Separator"}; + {"Button", "RD3Button", "Reset Data", true, RdFn, {}}; + {"Button", "RADButton", "Reset All Data", true, RadFn, {}}; + }; + }; + {"Separator"}; + {"Button", "ExitButton", "Exit", true, ExitFn, {}}; +} + +local uiMenu = createMenu(menuLayout); +uiMenu.Parent = uiBase; + +-- This is to make sure that the client can't access server stuff and vice versa +coroutine.resume(coroutine.create(function() repeat wait() until _G.ClientUtilities; uiMenu.ClientButton.Active=true; end)) +coroutine.resume(coroutine.create(function() repeat wait() until _G.ServerUtilities; uiMenu.ServerButton.Active=true; end))