-- src/ServerScriptService/ConstructionManager.server.lua local CollectionService = game:GetService("CollectionService") local ReplicatedStorage = game:GetService("ReplicatedStorage") local Players = game:GetService("Players") local BuildingConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("BuildingConfig")) local PlaceBlueprintEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("PlaceBlueprintEvent") local FillBlueprintEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("FillBlueprintEvent") local function getPartVolume(part) return part.Size.X * part.Size.Y * part.Size.Z end -- Validate and place a blueprint local function onPlaceBlueprint(player, structureType, cframe) local config = BuildingConfig.Structures[structureType] if not config then return end -- In a real game, you would verify if `cframe` is inside the player's Claimed Plot -- Verification skipped here for brevity local blueprintModel = Instance.new("Part") blueprintModel.Size = Vector3.new(10, 10, 1) -- Example dimensions blueprintModel.CFrame = cframe -- Visual Blueprint state blueprintModel.Transparency = 0.5 blueprintModel.BrickColor = BrickColor.new("Neon blue") blueprintModel.Material = Enum.Material.ForceField blueprintModel.Anchored = true -- Attributes for tracking blueprintModel:SetAttribute("StructureType", structureType) blueprintModel:SetAttribute("WoodFilled", 0) blueprintModel:SetAttribute("WoodRequired", config.Cost.WoodVolume) blueprintModel:SetAttribute("MaterialRequired", config.Cost.SpecificMaterial) blueprintModel:SetAttribute("OwnerId", player.UserId) CollectionService:AddTag(blueprintModel, "Blueprint") blueprintModel.Parent = workspace.Terrain -- Bind touched event so players can "throw" wood into the blueprint to fill it local debounce = {} blueprintModel.Touched:Connect(function(hit) -- Make sure it's fully processed wood touching it if CollectionService:HasTag(hit, "TreeSegment") and not debounce[hit] then debounce[hit] = true local requiredMaterial = blueprintModel:GetAttribute("MaterialRequired") local hitMaterial = hit:GetAttribute("ProcessState") or "Raw" if hitMaterial == requiredMaterial then local volume = getPartVolume(hit) local currentFill = blueprintModel:GetAttribute("WoodFilled") local required = blueprintModel:GetAttribute("WoodRequired") local newFill = currentFill + volume blueprintModel:SetAttribute("WoodFilled", newFill) -- Visual feedback: change transparency based on fill % local fillPercent = math.clamp(newFill / required, 0, 1) blueprintModel.Transparency = 0.5 - (0.5 * fillPercent) hit:Destroy() if newFill >= required then -- Construct! blueprintModel.Transparency = 0 blueprintModel.BrickColor = BrickColor.new("Burlap") blueprintModel.Material = Enum.Material.WoodPlanks blueprintModel.CanCollide = true CollectionService:RemoveTag(blueprintModel, "Blueprint") CollectionService:AddTag(blueprintModel, "ConstructedPart") end end task.delay(0.5, function() debounce[hit] = nil end) end end) end PlaceBlueprintEvent.OnServerEvent:Connect(onPlaceBlueprint)