Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local module = {}
- local Network = shared.Network;
- local NetworkInit = shared.NetworkInit;
- local LoadSharedModule = shared.LoadSharedModule;
- local SharedUtils = LoadSharedModule("Utils");
- local Resources = shared.Resources;
- local BuildingAssets = Resources:WaitForChild("Building");
- local Ignore = workspace:WaitForChild("Ignore");
- local Terrain = workspace:WaitForChild("Terrain");
- local NewRay = Ray.new;
- local Cells = {};
- local floor = math.floor;
- local function Round(x,int)
- return floor(x/int + 0.5) * int;
- end
- local function Round3D(v3)
- return Round(v3.x,12),Round(v3.y,12),Round(v3.z,12);
- end
- local Cell = {};
- function Cell.new(x,y,z)
- local self = setmetatable({},{__index=Cell});
- self.x=x;
- self.y=y;
- self.z=z;
- self.touchingblocks=0;
- return self;
- end
- function Cell:RemoveGhost()
- if self.ghost then
- self.ghost:Destroy();
- self.ghost=nil;
- end
- end
- function Cell:GiveGhost()
- if not self.block and not self.ghost then -- If there isn't a block or a ghost here
- local part1 = Instance.new("Part");
- part1.Parent=workspace;
- part1.Transparency=1;
- part1.Name="Ghost";
- part1.Anchored=true;
- part1.CanCollide=false;
- part1.Size=Vector3.new(12,1,12);
- part1.CFrame=CFrame.new(self.x,self.y,self.z);
- self.ghost=part1;
- end
- end
- local function CreateCell(x,y,z)
- if not Cells[x] then
- Cells[x]={};
- end
- if not Cells[x][y] then
- Cells[x][y] = {};
- end
- if not Cells[x][y][z] then
- local cell = Cell.new(x,y,z);
- Cells[x][y][z]=cell;
- return cell;
- end
- end
- local function GetCell(x,y,z)
- local cellx = Cells[x];
- if cellx then
- local celly = cellx[y];
- if celly then
- local cell = celly[z];
- if cell then
- return cell;
- end
- end
- end
- return CreateCell(x,y,z);
- end
- local function GetAdjacentCells2D(x,y,z)
- local cells = {};
- local t = {{x+12,y,z},{x-12,y,z},{x,y,z+12},{x,y,z-12}};
- for _,v in pairs(t) do
- cells[#cells+1]=GetCell(unpack(v));
- end
- return cells;
- end
- local function GetAdjacentCells3D(x,y,z)
- local cells = {};
- local t = {{x+12,y,z},{x-12,y,z},{x,y,z+12},{x,y,z-12},{x,y-12,z},{x,y+12,z}};
- for _,v in pairs(t) do
- cells[#cells+1]=GetCell(unpack(v));
- end
- return cells;
- end
- -- Start at cell x,y,z
- -- Recursively scan adjacent cells if cell has a block and cell isn't already marked by a raft
- local ThreeDScan;
- local function ScanAdjacent(rafts,raftindex,adjacent)
- local block = adjacent.block;
- if block then
- local marked;
- for i,raft in pairs(rafts) do
- if raft[block] then
- marked=true;
- end
- end
- if not marked then
- rafts[raftindex][block]=true;
- ThreeDScan(rafts,raftindex,adjacent.x,adjacent.y,adjacent.z);
- end
- end
- end
- function ThreeDScan(rafts,raftindex,x,y,z)
- local adjacents = GetAdjacentCells3D(x,y,z);
- for _,adjacent in pairs(adjacents) do
- ScanAdjacent(rafts,raftindex,adjacent)
- end
- end
- local function MarkRafts(x,y,z)
- local adjacents = GetAdjacentCells2D(x,y,z);
- local rafts = {};
- for i = 1,#adjacents do
- local adjacent = adjacents[i];
- rafts[i]={};
- ScanAdjacent(rafts,i,adjacent);
- end
- local markedrafts = {};
- for _,raft in pairs(rafts) do
- if next(raft) ~= nil then
- markedrafts[#markedrafts+1]=raft;
- end
- end
- print("Marked rafts: ",#markedrafts);
- end
- local function GiveGhostParts(model)
- local cf = model:GetModelCFrame();
- local tab = {Vector3.new(12,0,0),Vector3.new(-12,0,0),Vector3.new(0,0,12),Vector3.new(0,0,-12)};
- for _,v in pairs(tab) do
- local cf = CFrame.new(cf.p+v);
- local x,y,z = Round3D(cf.p);
- local cell = GetCell(x,y,z);
- cell:GiveGhost();
- end
- end
- local function PlaceObject(name,cf)
- local obj = BuildingAssets:FindFirstChild(name,true);
- if obj then
- obj = obj:clone();
- obj:SetPrimaryPartCFrame(cf);
- GiveGhostParts(obj);
- local x,y,z = Round3D(cf.p);
- local cell = GetCell(x,y,z);
- cell.Active=true;
- cell.block=obj;
- cell:RemoveGhost();
- local adjacents = GetAdjacentCells2D(x,y,z);
- for _,adjacent in pairs(adjacents) do
- adjacent.touchingblocks=adjacent.touchingblocks+1;
- end
- SharedUtils.OnObjectRemoved(obj,function()
- cell.block=nil;
- for _,adjacent in pairs(adjacents) do
- adjacent.touchingblocks=adjacent.touchingblocks-1;
- if adjacent.touchingblocks < 1 then
- adjacent:RemoveGhost();
- end
- end
- for _,adjacent in pairs(adjacents) do
- if adjacent.block then
- for _,v in pairs(GetAdjacentCells2D(adjacent.x,adjacent.y,adjacent.z)) do
- v:GiveGhost();
- end
- end
- end
- end)
- obj.Parent=workspace;
- end
- end
- Network:BindEvents(NetworkInit,
- {
- PlaceObject=function(clientState,client,name,cf)
- PlaceObject(name,cf);
- end,
- RemoveObject=function(clientState,client,obj)
- local p = obj:GetModelCFrame().p;
- local x,y,z = Round3D(p);
- obj:Destroy();
- MarkRafts(x,y,z);
- end
- }
- )
- return module
Advertisement
Add Comment
Please, Sign In to add comment