243 lines
5.2 KiB
Lua
243 lines
5.2 KiB
Lua
local CollectionService = game:GetService("CollectionService")
|
|
local HttpService = game:GetService("HttpService")
|
|
local Players = game:GetService("Players")
|
|
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
|
|
local ServerStorage = game:GetService("ServerStorage")
|
|
|
|
local loadBuildTools = ServerStorage:FindFirstChild("LoadBuildTools")
|
|
if not (loadBuildTools and loadBuildTools.Value) then
|
|
return
|
|
end
|
|
|
|
local looseBranches = ServerStorage:FindFirstChild("LooseBranches")
|
|
|
|
if looseBranches and looseBranches:IsA("BoolValue") then
|
|
looseBranches = looseBranches.Value
|
|
else
|
|
looseBranches = false
|
|
end
|
|
|
|
local toolList = loadBuildTools.Value
|
|
if toolList == true then -- If it's a BoolValue, load all of them.
|
|
toolList = "GameTool;Clone;Delete"
|
|
end
|
|
|
|
local DraggerService = Instance.new("Folder")
|
|
DraggerService.Name = "DraggerService"
|
|
DraggerService.Parent = ReplicatedStorage
|
|
|
|
local draggerGateway = Instance.new("RemoteFunction")
|
|
draggerGateway.Name = "DraggerGateway"
|
|
draggerGateway.Parent = DraggerService
|
|
|
|
local submitUpdate = Instance.new("RemoteEvent")
|
|
submitUpdate.Name = "SubmitUpdate"
|
|
submitUpdate.Parent = DraggerService
|
|
|
|
local draggerScript = script:WaitForChild("Dragger")
|
|
|
|
local activeKeys = {}
|
|
local debounce = {}
|
|
|
|
local weakTable = { __mode = 'k' }
|
|
|
|
local playerToKey = setmetatable({}, weakTable)
|
|
local partToKey = setmetatable({}, weakTable)
|
|
|
|
local SIMULATE_TAG = "SimulateAfterDrag"
|
|
local NO_BREAK_TAG = "GorillaGlue"
|
|
|
|
local function assertClass(obj, class)
|
|
assert(obj)
|
|
assert(typeof(obj) == "Instance")
|
|
assert(obj:IsA(class))
|
|
end
|
|
|
|
local function canGiveKey(player, part)
|
|
if part.Locked then
|
|
return false
|
|
end
|
|
|
|
local playerHasKey = playerToKey[player]
|
|
local partHasKey = partToKey[part]
|
|
|
|
if playerHasKey or partHasKey then
|
|
return false
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
local function claimAssembly(player, part)
|
|
if part:CanSetNetworkOwnership() then
|
|
part:SetNetworkOwner(player)
|
|
end
|
|
end
|
|
|
|
local function removePartKey(key)
|
|
local data = activeKeys[key]
|
|
|
|
if data then
|
|
local player = data.Player
|
|
local part = data.Part
|
|
|
|
if player then
|
|
playerToKey[player] = nil
|
|
end
|
|
|
|
if part then
|
|
part:MakeJoints()
|
|
part.Anchored = data.Anchored
|
|
|
|
claimAssembly(player, part)
|
|
partToKey[part] = nil
|
|
end
|
|
|
|
activeKeys[key] = nil
|
|
end
|
|
end
|
|
|
|
function draggerGateway.OnServerInvoke(player, request, ...)
|
|
if request == "GetKey" then
|
|
local part, asClone = ...
|
|
assertClass(part, "BasePart")
|
|
|
|
if asClone then
|
|
local newPart = part:Clone()
|
|
newPart.Parent = workspace
|
|
|
|
newPart:BreakJoints()
|
|
newPart.CFrame = CFrame.new(part.Position + Vector3.new(0, part.Size.Y, 0))
|
|
|
|
local copySound = Instance.new("Sound")
|
|
copySound.SoundId = "rbxasset://sounds/electronicpingshort.wav"
|
|
copySound.PlayOnRemove = true
|
|
copySound.Parent = newPart
|
|
|
|
wait()
|
|
|
|
part = newPart
|
|
copySound:Destroy()
|
|
end
|
|
|
|
if canGiveKey(player, part) then
|
|
local key = HttpService:GenerateGUID(false)
|
|
claimAssembly(player, part)
|
|
|
|
playerToKey[player] = key
|
|
partToKey[part] = key
|
|
|
|
local anchored = part.Anchored
|
|
part.Anchored = true
|
|
part:BreakJoints()
|
|
|
|
activeKeys[key] =
|
|
{
|
|
Player = player;
|
|
Part = part;
|
|
Anchored = anchored;
|
|
}
|
|
|
|
return true, key, part
|
|
else
|
|
return false
|
|
end
|
|
elseif request == "ClearKey" then
|
|
local key = ...
|
|
|
|
if not key then
|
|
key = playerToKey[player]
|
|
end
|
|
|
|
if key then
|
|
local data = activeKeys[key]
|
|
if data then
|
|
local owner = data.Player
|
|
if player == owner then
|
|
removePartKey(key)
|
|
end
|
|
end
|
|
end
|
|
elseif request == "RequestDelete" then
|
|
if not debounce[player] then
|
|
local part = ...
|
|
assertClass(part, "BasePart")
|
|
|
|
debounce[player] = true
|
|
|
|
if canGiveKey(player, part) then
|
|
local e = Instance.new("Explosion")
|
|
e.BlastPressure = 0
|
|
e.Position = part.Position
|
|
e.Parent = workspace
|
|
|
|
local s = Instance.new("Sound")
|
|
s.SoundId = "rbxasset://sounds/collide.wav"
|
|
s.Volume = 1
|
|
s.PlayOnRemove = true
|
|
s.Parent = part
|
|
|
|
part:Destroy()
|
|
end
|
|
|
|
wait(.1)
|
|
debounce[player] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
local function onChildAdded(child)
|
|
if child:IsA("Backpack") then
|
|
for draggerTool in toolList:gmatch("[^;]+") do
|
|
local tool = Instance.new("Tool")
|
|
tool.Name = draggerTool
|
|
tool.RequiresHandle = false
|
|
tool.CanBeDropped = false
|
|
|
|
local newDragger = draggerScript:Clone()
|
|
newDragger.Parent = tool
|
|
newDragger.Disabled = false
|
|
|
|
tool.Parent = child
|
|
end
|
|
end
|
|
end
|
|
|
|
local function onPlayerAdded(player)
|
|
for _, v in pairs(player:GetChildren()) do
|
|
onChildAdded(v)
|
|
end
|
|
|
|
player.ChildAdded:Connect(onChildAdded)
|
|
end
|
|
|
|
local function onPlayerRemoved(player)
|
|
local key = playerToKey[player]
|
|
if key then
|
|
removePartKey(key)
|
|
end
|
|
end
|
|
|
|
local function onSubmitUpdate(player, key, cframe)
|
|
local keyData = activeKeys[key]
|
|
if keyData then
|
|
local owner = keyData.Player
|
|
if owner == player then
|
|
local part = keyData.Part
|
|
if part and part:IsDescendantOf(workspace) then
|
|
part:BreakJoints()
|
|
part.CFrame = cframe
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, player in pairs(game.Players:GetPlayers()) do
|
|
onPlayerAdded(player)
|
|
end
|
|
|
|
submitUpdate.OnServerEvent:Connect(onSubmitUpdate)
|
|
|
|
Players.PlayerAdded:Connect(onPlayerAdded)
|
|
Players.PlayerRemoving:Connect(onPlayerRemoved) |