This commit is contained in:
watrabi
2025-09-18 17:55:52 -04:00
commit 977f1ff4b8
15030 changed files with 17324420 additions and 0 deletions
@@ -0,0 +1,174 @@
-- Responsible for giving out tools in personal servers
-- first, lets see if buildTools have already been created
-- create the object in ReplicatedStorage if not
local container = game:GetService("ReplicatedStorage")
local toolsArray = container:FindFirstChild("BuildToolsModel")
local ownerArray = container:FindFirstChild("OwnerToolsModel")
local hasBuildTools = false
local function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
waitForProperty(game:GetService("Players"),"LocalPlayer")
waitForProperty(game:GetService("Players").LocalPlayer,"userId")
local player = game:GetService("Players").LocalPlayer
if not player then
script:Destroy()
return
end
function getIds(idTable, assetTable)
for i = 1, #idTable do
local model = Game:GetService("InsertService"):LoadAsset(idTable[i])
if model then
local children = model:GetChildren()
for i = 1, #children do
if children[i]:IsA("Tool") then
table.insert(assetTable,children[i])
end
end
end
end
end
function storeInContainer(modelName, assetTable)
local model = Instance.new("Model")
model.Archivable = false
model.Name = modelName
for i = 1, #assetTable do
assetTable[i].Parent = model
end
if not container:FindFirstChild(modelName) then -- no one beat us to it, we get to insert
model.Parent = container
end
end
if not toolsArray then -- no one has made build tools yet, we get to!
local buildToolIds = {}
local ownerToolIds = {}
local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
if BaseUrl:find("www.watrbx.wtf") or BaseUrl:find("gametest1") then
table.insert(buildToolIds,73089166) -- PartSelectionTool
table.insert(buildToolIds,73089190) -- DeleteTool
table.insert(buildToolIds,73089204) -- CloneTool
table.insert(buildToolIds,73089214) -- RotateTool
table.insert(buildToolIds,73089229) -- RecentPartTool
table.insert(buildToolIds,73089239) -- ConfigTool
table.insert(buildToolIds,73089259) -- WiringTool
elseif BaseUrl:find("gametest2") then
table.insert(buildToolIds,70353315) -- PartSelectionTool
table.insert(buildToolIds,70353317) -- DeleteTool
table.insert(buildToolIds,70353314) -- CloneTool
table.insert(buildToolIds,70353318) -- RotateTool
table.insert(buildToolIds,70353316) -- RecentPartTool
table.insert(buildToolIds,70353319) -- ConfigTool
table.insert(buildToolIds,70353320) -- WiringTool
end
table.insert(buildToolIds,58921588) -- ClassicTool
table.insert(ownerToolIds, 65347268) -- OwnerCameraTool
-- next, create array of our tools
local buildTools = {}
local ownerTools = {}
getIds(buildToolIds, buildTools)
getIds(ownerToolIds, ownerTools)
storeInContainer("BuildToolsModel",buildTools)
storeInContainer("OwnerToolsModel",ownerTools)
toolsArray = container:FindFirstChild("BuildToolsModel")
ownerArray = container:FindFirstChild("OwnerToolsModel")
end
local localBuildTools = {}
function giveBuildTools()
if not hasBuildTools then
hasBuildTools = true
local theTools = toolsArray:GetChildren()
for i = 1, #theTools do
local toolClone = theTools[i]:Clone()
if toolClone then
toolClone.Parent = player:FindFirstChild("Backpack")
table.insert(localBuildTools,toolClone)
end
end
end
end
function giveOwnerTools()
local theOwnerTools = ownerArray:GetChildren()
for i = 1, #theOwnerTools do
local ownerToolClone = theOwnerTools[i]:Clone()
if ownerToolClone then
ownerToolClone.Parent = player:FindFirstChild("Backpack")
table.insert(localBuildTools,ownerToolClone)
end
end
end
function removeBuildTools()
if not hasBuildTools then return end
hasBuildTools = false
for k,v in pairs(localBuildTools) do
v:Destroy()
end localBuildTools = {}
end
if player.HasBuildTools then
giveBuildTools()
end
if player.PersonalServerRank >= 255 then
giveOwnerTools()
end
local debounce = false
player.Changed:connect(function(prop)
if prop == "HasBuildTools" then
while debounce do
wait(0.5)
end
debounce = true
if player.HasBuildTools then
giveBuildTools()
else
removeBuildTools()
end
if player.PersonalServerRank >= 255 then
giveOwnerTools()
end
debounce = false
elseif prop == "PersonalServerRank" then
if player.PersonalServerRank >= 255 then
giveOwnerTools()
elseif player.PersonalServerRank <= 0 then
player:Kick() -- you're banned, goodbye!
Game:SetMessage("You're banned from this PBS")
end
end
end)
player.CharacterAdded:connect(function()
hasBuildTools = false
if player.HasBuildTools then
giveBuildTools()
end
if player.PersonalServerRank >= 255 then
giveOwnerTools()
end
end)
@@ -0,0 +1,214 @@
-- This script is responsible for loading in all build tools for build mode
-- Script Globals
local buildTools = {}
local currentTools = {}
local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
if BaseUrl:find("www.watrbx.wtf") or BaseUrl:find("gametest1") then
DeleteToolID = 73089190
PartSelectionID = 73089166
CloneToolID = 73089204
RotateToolID = 73089214
ConfigToolID = 73089239
WiringToolID = 73089259
classicToolID = 58921588
elseif BaseUrl:find("gametest2") then
DeleteToolID = 70353317
PartSelectionID = 70353315
CloneToolID = 70353314
RotateToolID = 70353318
ConfigToolID = 70353319
WiringToolID = 70353320
classicToolID = 58921588
end
local player = nil
local backpack = nil
-- Basic Functions
local function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForProperty(game:GetService("Players"),"LocalPlayer")
waitForProperty(game:GetService("Players").LocalPlayer,"userId")
-- we aren't in a true build mode session, don't give build tools and delete this script
if game:GetService("Players").LocalPlayer.userId < 1 then
script:Destroy()
return -- this is probably not necessesary, doing it just in case
end
-- Functions
function getLatestPlayer()
waitForProperty(game:GetService("Players"),"LocalPlayer")
player = game:GetService("Players").LocalPlayer
waitForChild(player,"Backpack")
backpack = player.Backpack
end
function waitForCharacterLoad()
local startTick = tick()
local playerLoaded = false
local success = pcall(function() playerLoaded = player.AppearanceDidLoad end) --TODO: remove pcall once this in client on prod
if not success then return false end
while not playerLoaded do
player.Changed:wait()
playerLoaded = player.AppearanceDidLoad
end
return true
end
function showBuildToolsTutorial()
local tutorialKey = "BuildToolsTutorial"
if UserSettings().GameSettings:GetTutorialState(tutorialKey) == true then return end --already have shown tutorial
local RbxGui = LoadLibrary("RbxGuiThirteen")
local frame, showTutorial, dismissTutorial, gotoPage = RbxGui.CreateTutorial("Build", tutorialKey, false)
local firstPage = RbxGui.CreateImageTutorialPage(" ", "http://www.watrbx.wtf/asset/?id=59162193", 359, 296, function() dismissTutorial() end, true)
RbxGui.AddTutorialPage(frame, firstPage)
frame.Parent = game:GetService("CoreGui"):FindFirstChild("RobloxGui")
game:GetService("GuiService"):AddCenterDialog(frame, Enum.CenterDialogType.UnsolicitedDialog,
--showFunction
function()
frame.Visible = true
showTutorial()
end,
--hideFunction
function()
frame.Visible = false
end
)
wait(1)
showTutorial()
end
function clearLoadout()
currentTools = {}
local backpackChildren = game:GetService("Players").LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
if backpackChildren[i]:IsA("Tool") or backpackChildren[i]:IsA("HopperBin") then
table.insert(currentTools,backpackChildren[i])
end
end
if game:GetService("Players").LocalPlayer["Character"] then
local characterChildren = game:GetService("Players").LocalPlayer.Character:GetChildren()
for i = 1, #characterChildren do
if characterChildren[i]:IsA("Tool") or characterChildren[i]:IsA("HopperBin") then
table.insert(currentTools,characterChildren[i])
end
end
end
for i = 1, #currentTools do
currentTools[i].Parent = nil
end
end
function giveToolsBack()
for i = 1, #currentTools do
currentTools[i].Parent = game:GetService("Players").LocalPlayer.Backpack
end
end
function backpackHasTool(tool)
local backpackChildren = backpack:GetChildren()
for i = 1, #backpackChildren do
if backpackChildren[i] == tool then
return true
end
end
return false
end
function getToolAssetID(assetID)
local newTool = game:GetService("InsertService"):LoadAsset(assetID)
local toolChildren = newTool:GetChildren()
for i = 1, #toolChildren do
if toolChildren[i]:IsA("Tool") then
return toolChildren[i]
end
end
return nil
end
-- remove legacy identifiers
-- todo: determine if we still need this
function removeBuildToolTag(tool)
if tool:FindFirstChild("RobloxBuildTool") then
tool.RobloxBuildTool:Destroy()
end
end
function giveAssetId(assetID,toolName)
local theTool = getToolAssetID(assetID,toolName)
if theTool and not backpackHasTool(theTool) then
removeBuildToolTag(theTool)
theTool.Parent = backpack
table.insert(buildTools,theTool)
end
end
function loadBuildTools()
giveAssetId(PartSelectionID)
giveAssetId(DeleteToolID)
giveAssetId(CloneToolID)
giveAssetId(RotateToolID)
giveAssetId(WiringToolID)
giveAssetId(ConfigToolID)
-- deprecated tools
giveAssetId(classicToolID)
end
function givePlayerBuildTools()
getLatestPlayer()
clearLoadout()
loadBuildTools()
giveToolsBack()
end
function takePlayerBuildTools()
for k,v in ipairs(buildTools) do
v.Parent = nil
end
buildTools = {}
end
-- Script start
getLatestPlayer()
waitForCharacterLoad()
givePlayerBuildTools()
-- If player dies, we make sure to give them build tools again
player.CharacterAdded:connect(function()
takePlayerBuildTools()
givePlayerBuildTools()
end)
showBuildToolsTutorial()
@@ -0,0 +1,206 @@
-- Personal Server Script
-----------------
--| Constants |--
-----------------
local CHANGES_PER_PLAYER = 100 -- Saving also occurs every time the number of edits reaches this number times the number of players
local SAVE_CHECK_INTERVAL = 1800 -- should be set in seconds, this is how long we wait to force a save, as long as at least one change has been made
local MIN_SAVE_TIME = 900 -- At least this many seconds will pass before saving again
-----------------
--| Variables |--
-----------------
local ContentProviderService = game:GetService('ContentProvider')
local PlayersService = game:GetService('Players')
local RunService = game:GetService("RunService")
local StartingPlayerRanks = {}
local RbxUtil = nil
local LastSaveTime = 0
local ChangeCount = 0
local TryingToSave = false
local NumberOfChangesBeforeSaveAbsolute = CHANGES_PER_PLAYER
local GameRunning = true
local WaitingToSave = false
local PlaceId = game.PlaceId
local Url = ContentProviderService.BaseUrl
local UrlBase = Url:match('^http://www\.(.-)/?$') -- Turns "http://www.gametest1.pizzaboxer.fun/" into "gametest1.pizzaboxer.fun"
local ApiProxyUrl = 'https://api.' .. UrlBase
local DataFarmProtocol = 'http'
local DataFarmUsesHttpsFlagExists, DataFarmUsesHttpsFlagValue = pcall(function () return settings():GetFFlag("DataFarmUsesHttps") end)
if DataFarmUsesHttpsFlagExists and DataFarmUsesHttpsFlagValue then
DataFarmProtocol = 'https'
end
local DataFarmUrl = DataFarmProtocol .. '://data.' .. UrlBase
-----------------
--| Functions |--
-----------------
function GetRbxUtil()
if not RbxUtil then
RbxUtil = LoadLibrary("RbxUtility")
end
return RbxUtil
end
-- Checks the full hierarchy of an instance for archivability
local function IsArchivable(instance)
if instance == workspace then
return true
elseif not instance.Archivable then
return false
else
return IsArchivable(instance.Parent)
end
end
local function UpdateSaveOnChangeAmount()
local players = PlayersService:GetPlayers()
NumberOfChangesBeforeSaveAbsolute = #players * CHANGES_PER_PLAYER
end
local function OnPlayerAdded(player)
if player:IsA('Player') then
local getRankUrl = ApiProxyUrl .. '/RoleSets/GetRoleSetForUser?placeId=' .. tostring(PlaceId) .. '&userId=' .. tostring(player.userId)
local serverRankTable = nil
pcall(function()
serverRankTable = GetRbxUtil().DecodeJSON(game:HttpGetAsync(getRankUrl))
end)
local playerRank = 0
if serverRankTable and type(serverRankTable) == 'table' then
for k, v in pairs(serverRankTable) do
if k == "data" then
if v["Rank"] then
playerRank = v["Rank"]
end
end
end
end
player.PersonalServerRank = playerRank
StartingPlayerRanks[player] = playerRank
UpdateSaveOnChangeAmount()
end
end
local function OnPlayerRemoved(player)
if player:IsA('Player') then
UpdateSaveOnChangeAmount()
if StartingPlayerRanks[player] then
local playerRank = player.PersonalServerRank
if StartingPlayerRanks[player] ~= playerRank then -- Don't need to make web call if rank is the same
local setRankUrl = ApiProxyUrl .. '/RoleSets/PrivilegedSetUserRoleSetRank?placeId=' .. tostring(PlaceId) .. '&userId=' .. tostring(player.userId) .. '&newRank=' .. tostring(playerRank)
ypcall(function() game:HttpPostAsync(setRankUrl, 'SetPersonalServerRank') end)
end
StartingPlayerRanks[player] = nil
end
end
end
local function DoSave()
if GameRunning then
ChangeCount = 0
LastSaveTime = tick()
game:ServerSave()
end
end
local function TrySave()
if not TryingToSave then
TryingToSave = true
local now = tick()
if now - LastSaveTime >= MIN_SAVE_TIME then
DoSave()
elseif not WaitingToSave then -- Save after cooldown
WaitingToSave = true
delay(LastSaveTime + MIN_SAVE_TIME - now, function()
DoSave()
WaitingToSave = false
end)
end
TryingToSave = false
end
end
-- Save based on number of edits to workspace
local function OnEdit(descendant)
if IsArchivable(descendant) then
ChangeCount = ChangeCount + 1
if ChangeCount >= NumberOfChangesBeforeSaveAbsolute then
TrySave()
end
end
end
-- Make sure we save every interval regardless of number of edits, so long as there is one
local function CheckForSaveOnInterval()
while true do
wait(SAVE_CHECK_INTERVAL)
if tick() - LastSaveTime >= SAVE_CHECK_INTERVAL and ChangeCount > 0 then
TrySave()
end
end
end
--------------------
--| Script Logic |--
--------------------
game:WaitForChild('Workspace')
pcall(function()
game.IsPersonalServer = true
if not workspace:FindFirstChild("PSVariable") then
local psVar = Instance.new("BoolValue")
psVar.Name = "PSVariable"
psVar.Archivable = false
psVar.Parent = workspace
end
end)
PlayersService.PlayerAdded:connect(OnPlayerAdded)
PlayersService.ChildRemoved:connect(OnPlayerRemoved)
for _, player in pairs(PlayersService:GetPlayers()) do
OnPlayerAdded(player)
end
local useSubdomainsFlagExists, useSubdomainsFlagValue = pcall(function () return settings():GetFFlag("UseNewSubdomainsInCoreScripts") end)
local saveUrlBase = Url
if(useSubdomainsFlagExists and useSubdomainsFlagValue and DataFarmUrl~=nil) then
saveUrlBase = DataFarmUrl
end
if saveUrlBase~=nil then
game:SetServerSaveUrl(saveUrlBase .. "/Data/AutoSave.ashx?assetId=" .. PlaceId)
end
if pcall(function()
game.Close:connect(
function()
GameRunning = false
game:ServerSave()
end)
end) == false then
print("!Error in Game.Close:connect")
end
RunService:Run()
game:GetService("Workspace").DescendantAdded:connect(OnEdit)
game:GetService("Workspace").DescendantRemoving:connect(OnEdit)
spawn(CheckForSaveOnInterval)