diff --git a/scratch/dct1/GenerationForeman.rbxm b/scratch/dct1/GenerationForeman.rbxm new file mode 100644 index 0000000..cfb5442 Binary files /dev/null and b/scratch/dct1/GenerationForeman.rbxm differ diff --git a/scratch/dct1/dct1.rbxl b/scratch/dct1/dct1.rbxl new file mode 100644 index 0000000..47820b4 Binary files /dev/null and b/scratch/dct1/dct1.rbxl differ diff --git a/scratch/dct2/BuildingModule b/scratch/dct2/BuildingModule new file mode 100644 index 0000000..92e9db7 --- /dev/null +++ b/scratch/dct2/BuildingModule @@ -0,0 +1,79 @@ +local module = {} + +local function new(name,tab) + local instance = Instance.new(name) + for index,item in pairs(tab) do + instance[index] = item + end + return instance +end + +local function block(cframe,size) + return new("Part",{ + Material = Enum.Material.WoodPlanks, + Color = Color3.new(0.301961, 0.14902, 0.0588235), + Anchored = true, + CFrame = cframe + Vector3.new(0,size.Y/2,0), + Size = size, + Transparency = 0.5, + Parent = workspace + }) +end + +local function mark(position) + return block(CFrame.new(position),Vector3.one * 128) +end + +local function r(v) + return math.noise(v.X*0.379,v.Y*0.379,v.Z*0.379) + 1 +end + +local px = Vector3.xAxis +local py = Vector3.xAxis +local pz = Vector3.xAxis + +module.main = function(ox,oy,oz,noise) + local n = function(v) return noise(v.X,v.Y,v.Z) end + local o = Vector3.new(ox,oy,oz) + + --[[ + origin: where the wall starts + direction: where the wall faces + magnitude: the size of the wall + depth: the current depth of the wall + ]] + local walls = {} + local function hit(origin,direction,magnitude,depth) + + end + local function wall(origin,direction,magnitude) + + end + local function project(origin,direction,magnitude) + local depth = 0 + for i = 1,4 do + depth += magnitude * 0.5 + local probe = origin + direction * depth + if n(probe) > 0.05 then continue end + if hit(origin,direction,magnitude,depth) then continue end + mark(origin + direction * depth) + end + if depth == 0 then return nil + else return depth end + end + + local function extrude(origin,look,width,height) + local depth = project(origin,look,width) + if not depth then return end + return block(CFrame.lookAlong(origin - look * depth * 0.5,look),Vector3.new(width,height,depth)) + end + + local no = n(o) + local norm = Vector3.new(no - n(o + Vector3.xAxis),no - n(o + Vector3.yAxis),no - n(o + Vector3.zAxis)).Unit + local flat = Vector3.new(norm.X,0,norm.Z).Unit; + mark(o).CFrame = CFrame.lookAlong(o,norm) + o = o + project(o,-norm,64) * -norm or o + extrude(o,flat,r(o+px)*256,r(o+py)*256) +end + +return module \ No newline at end of file diff --git a/scratch/dct2/CellularModule b/scratch/dct2/CellularModule new file mode 100644 index 0000000..2b1c981 --- /dev/null +++ b/scratch/dct2/CellularModule @@ -0,0 +1,85 @@ +local module = {} + +local vector = Vector3.new +local floor = math.floor +local noise = math.noise +local ceil = math.ceil +local abs = math.abs +local max = math.max +local min = math.min +local xor = bit32.bxor +local rot = bit32.rrotate +local mod = math.fmod +local function cheman(vec) + return max(abs(vec.Y),abs(vec.X)+abs(vec.Z)) +end +local function man(vec) + return abs(vec.X)+abs(vec.Y)+abs(vec.Z) +end +local function che(vec) + return max(abs(vec.X),abs(vec.Y),abs(vec.Z)) +end +local function mag(vec) + return vec.Magnitude +end +local function squircle(vec) + return vec.X^4 + vec.Y^4 + vec.Z^4 +end +local function off(x,y,z) + local rx = noise(x*123.456,y*345.612,z*561.234) + local ry = noise(x*345.612,z*123.456,y*561.234) + local rz = noise(z*123.456,x*561.234,y*345.612) + local res = vector(rx,ry,rz).Unit * 0.5 + return res,res + vector(x,y,z) +end +local pa = vector(0,0,0) +local pb = vector(1,0,0) +local pc = vector(0,1,0) +local pd = vector(0,0,1) +local pe = vector(1,1,0) +local pf = vector(0,1,1) +local pg = vector(1,0,1) +local ph = vector(1,1,1) +local function vor(x,y,z,fun) + local fx = floor(x) + local fy = floor(y) + local fz = floor(z) + local cx = ceil(x) + local cy = ceil(y) + local cz = ceil(z) + local center = vector(x,y,z)-vector(fx,fy,fz) + local av,aa = off(fx,fy,fz) + local bv,ba = off(cx,fy,fz) + local cv,ca = off(fx,cy,fz) + local dv,da = off(fx,fy,cz) + local ev,ea = off(cx,cy,fz) + local fv,fa = off(fx,cy,cz) + local gv,ga = off(cx,fy,cz) + local hv,ha = off(cx,cy,cz) + local a = fun(av+pa-center) + local b = fun(bv+pb-center) + local c = fun(cv+pc-center) + local d = fun(dv+pd-center) + local e = fun(ev+pe-center) + local f = fun(fv+pf-center) + local g = fun(gv+pg-center) + local h = fun(hv+ph-center) + local v = a + local vv = aa + if b < v then v = b vv = ba end + if c < v then v = c vv = ca end + if d < v then v = d vv = da end + if e < v then v = e vv = ea end + if f < v then v = f vv = fa end + if g < v then v = g vv = ga end + if h < v then v = h vv = ha end + return 1-(v*2),vv +end + +module.vor = vor +module.man = man +module.mag = mag +module.che = che +module.cheman = cheman + +return module \ No newline at end of file diff --git a/scratch/dct2/ChunkModule b/scratch/dct2/ChunkModule new file mode 100644 index 0000000..72c774d --- /dev/null +++ b/scratch/dct2/ChunkModule @@ -0,0 +1,266 @@ +local slate_color = Color3.fromRGB(124, 124, 124) +local grass_color = Color3.fromRGB(58, 125, 21) -- Color3.fromRGB(58, 125, 21) + +local part = Instance.new("Part") +part.Anchored = true +part.CanCollide = true +part.Parent = game.Workspace +part.Material = Enum.Material.Slate +part.Shape = Enum.PartType.Block +part.Color = slate_color +local boom = 10 +local math_abs = math.abs +local math_max = math.max +local math_min = math.min +local math_noise = math.noise +local table_create = table.create +local chunks = {} +local function _n(x,y,z) -- Legacy noise + local h = (math_noise(x*0.00015,y*0.00015,z*0.00015)*2)^3 + local m = math_noise(x*0.00005,y*0.00005,z*0.00005) + local s = math_noise(x*0.03,y*0.03,z*0.03) + local n = math_noise(x*0.0015,y*0.0015*h,z*0.0015) + y = y - 512 + h * 512 + return ((n)*h-y*0.0005)*boom + --[[local h = math_noise(x*0.0005,0.123,z*0.0005)*4 + return (math_noise(x*0.0015,y*0.0015*h,z*0.0015)*2*h+math_noise(x*0.005,y*0.005*h,z*0.005)*h-(y+h*10)*0.005)*boom]] +end +local function n_cloud(x,y,z) + return math_noise(x*0.0002,y*0.0002,z*0.0002) +end +local function n_imaginarium(x,y,z) -- Current noise terrain profile + x = x * 2 + y = y * 2 + 1024 + z = z * 2 + local conduit = (1-math_abs(math_noise(x*0.00005,y*0.00005,z*0.00005)))^4 + 0.05 + local hillsong = math_noise(x*0.0015,y*0.0015,z*0.0015)*2 + local titans = math_noise(x*0.0002,y*0.0002,z*0.0002)*16 + return ((titans + hillsong) * conduit - y * 0.00075) * boom +end +local function n_tranquility(x,y,z) -- Fields and hills + y = y - 512 + local tranquility = math_noise(x*0.0001,y*0.0001,z*0.0001) + local turbulence = math_noise(x*0.0008,y*0.0008,z*0.0008) + local atmosphere = math_noise(x*0.0005,y*0.0005,z*0.0005) + return ((atmosphere + turbulence) * tranquility - y * 0.0001) * boom +end +local function n_satisfaction(x,y,z) -- + return 0 +end +--[[local function fol(x,y,z) + local density = math_noise(x*0.0001,y*0.0001,z*0.0001) + local b = math_noise(x*0.001,y*0.001,z*0.001) > 0.5 + --local t = math_noise(x*0.001,y*0.001,z*0.001) > 0.3 + return b +end]] +local function p(x,y,z,f,parent) -- Create a part at a size + local p = part:Clone() + p.Parent = parent + p.Size = Vector3.one*f + p.Position = Vector3.new(x,y,z) + return p +end +local compensate = 4 -- Make terrain puffy so the octree system can see it clearly +local function m(f) + return boom*compensate +end +-- Preinitialise a data structure to hold game.Workspace.Terrain form of terrain data +local base = 4 +local mat +local occ +do + local _otx = table_create(8) + for _x=1,8 do + local _oty = table_create(8) + for _y=1,8 do + _oty[_y] = table_create(8) + end + _otx[_x] = _oty + end + local _mtx = table_create(8) + for _x=1,8 do + local _mty = table_create(8) + for _y=1,8 do + _mty[_y] = table_create(8) + end + _mtx[_x] = _mty + end + occ = _otx + mat = _mtx +end +-- Use the preinitialised data structure from above to render in a chunk of roblox style terrain +local function ter(x,y,z,f) + for ix=1,8 do + for iy=1,8 do + for iz=1,8 do + occ[ix][iy][iz] = n(x+(ix-4)*4,y+(iy-4)*4,z+(iz-4)*4) + mat[ix][iy][iz] = Enum.Material.Grass + end + end + end + workspace.Terrain:WriteVoxels(Region3.new(Vector3.new(x,y,z)-Vector3.one*f*0.5,Vector3.new(x,y,z)+Vector3.one*f*0.5),4,mat,occ) +end +local voro = require(script.Parent.CellularModule) -- Voronoi noise library +local man = voro.man +local mag = voro.mag +local che = voro.che +local cheman = voro.cheman +local vor = voro.vor +local squir = voro.squircle +local function fol(x,y,z) + x = x - x % 32 + y = y - y % 32 + z = z - z % 32 + return math_noise(x*0.00025,y*0.00025-2,z*0.00025) +end +local function act(x) + if x > -5 then return 0.8 end + --if x > -0.1 then return 0.4 end + return 0 +end +--local pieces = require(script.Parent.TownPieceModule) +--local block = pieces.block +road = function(x,y,z) + local n1,c1 = vor(x*0.01,y*0.01,z*0.01,che) + local n2,c2 = vor(x*0.002,y*0.002,z*0.002,che) -- 1 = crowded, 0 = empty + local c1x = c1.X*100 + local c1y = c1.Y*100 + local c1z = c1.Z*100 + local d = n(c1x,c1y,c1z)*0.025 -- 0 = surface, -1 = air + if n1 > -d and d > -0.3 --[[and n2 < 0.5]] then + -- Is centre near ground, is building (thinning towards top), is not road, is centre within bounds + return c1x,c1y,c1z + end + --return vor(x*0.002,y*0.002,z*0.002,cheman) + d + 0.3 +end + +local surf = require(script.Parent.SurfaceNetModule) -- Surface terrain library +local vox = surf.voxel +local rand = Random.new() +local na = Vector3.new(-1,-1,-1) -- Vectors for cardinal directions (corners of a cube) +local nb = Vector3.new(-1,1,1) +local nc = Vector3.new(1,-1,1) +local nd = Vector3.new(1,1,-1) +local ne = Vector3.new(-1,-1,1) +local nf = Vector3.new(-1,1,-1) +local ng = Vector3.new(1,-1,-1) +local nh = Vector3.new(-1,-1,-1) +local trees = game.ReplicatedStorage.Foliage:GetChildren() +local no_trees = #trees +local rand = Random.new() +local struct = require(script.Parent.StructureModule) +@native +local function chunk(x,y,z,f,b,stuff,v,n) + struct.make_chunk(x,y,z,f,n) + local vf = 1/4096 + local parent = stuff.parent + local n1,c2 = vor(x*vf,y*vf,z*vf,man) + local val = n(x,y,z) + local grass = stuff.grass.make_quad -- Quad making function from the surface factory for each material + local slate = stuff.slate.make_quad + local bd + local function s(x,y,z,f) + if not b then b = 32 end + local fr = f * 0.25 + -- Shift of positions (XYZ axes) + local lx = x+fr + local ly = y+fr + local lz = z+fr + local hx = x-fr + local hy = y-fr + local hz = z-fr + -- Noise values (corners) + local _a,_b,_c,_d,_e,_f,_g,_h = n(lx,ly,lz),n(hx,ly,lz),n(lx,hy,lz),n(lx,ly,hz),n(hx,hy,lz),n(hx,ly,hz),n(lx,hy,hz),n(hx,hy,hz) + local o,dx,dy,dz = n(x,y,z),n(x+1,y,z),n(x,y+1,z),n(x,y,z+1) -- Gradient of surface noises + local norm = Vector3.new(o-dx,o-dy,o-dz).Unit---((_a)*(na)+(_b)*(nb)+(_c)*(nc)+(_d)*(nd)+(_e)*(ne)+(_f)*(nf)+(_g)*(ng)+(_h)*(nh)).Unit --GRAD + local sum = (_a+_b+_c+_d+_e+_f+_g+_h)*0.125 -- Average noise from sample + --[[if f == b and fol(x,y,z) > 0.62 and sum < 0 then + local fs = fr * 2 - 16 + for bx = x-fs,x+fs,32 do + for by = y-fs,y+fs,32 do + for bz = z-fs,z+fs,32 do + local cx,cy,cz = road(bx,by,bz) + if cx then pieces.block(bx,by,bz,32,road,cx,cy,cz) end + end + end + end + --vox(x,y,z,b,brick,road) + end]] + if math_max(_a,_b,_c,_d,_e,_f,_g,_h) < -m(f) then -- Nothing to do + return + elseif math_min(_a,_b,_c,_d,_e,_f,_g,_h) > m(f) then -- + --[[if b == 4 and f == 32 then + workspace.Terrain:FillRegion(Region3.new(Vector3.new(x,y,z)-Vector3.one*f*0.5,Vector3.new(x,y,z)+Vector3.one*f*0.5),4,Enum.Material.Grass) + else]] + --if b ~= 4 then p(x,y,z,f) end + --end + else -- We are near the surface + --[[if math_abs(norm.Y) < 0.4 and math_abs(sum) < 0.1 and f <= b then + local part = p(x,y,z,f) + part.CFrame = CFrame.lookAlong(part.Position,norm) + part.Size = Vector3.new(part.Size.X*(rand:NextNumber()+2),part.Size.Y*(rand:NextNumber()+2),part.Size.Z*(rand:NextNumber()+1))*2 + part.Position = part.Position + norm * f * 0.5 + return + end]] + if f == v then + if norm.Y < 0.5 then + vox(x,y,z,v,slate,n,parent) + else + vox(x,y,z,v,grass,n,parent) + end + end + if f == b then -- We are at the rendering level for this chunk + -- Broad building check + if math_abs(sum) < 0.5 and f >= 256 then -- If + if norm.Y < 0.7 then -- Rock + local part = p(x,y,z,math.clamp(f*2.5,0,512),parent) + part.CFrame = CFrame.lookAlong(part.Position-norm*f,norm) + part.Size = Vector3.one * f * 2 + else -- Foliage (why does this never run?) + if f > 256 then + local part = p(x,y,z,f*2.5,parent) + part.Material = Enum.Material.Grass + part.Color = grass_color + part.Shape = Enum.PartType.Ball + end + end + elseif f == 512 and rand:NextInteger(1,5) == 5 and n_cloud(x,y,z) > 0 then + local part = p(x,y,z,2048*(rand:NextNumber()+1),parent) + part.Material = Enum.Material.SmoothPlastic + part.Transparency = 0.7 + part.Shape = Enum.PartType.Ball + part.Size = part.Size * rand:NextInteger(1,4) * 0.5 + end + else -- We are too large, recurse into lower octrees + f = f * 0.5 + s(lx,ly,lz,f) s(hx,ly,lz,f) s(lx,hy,lz,f) s(lx,ly,hz,f) s(hx,hy,lz,f) s(hx,ly,hz,f) s(lx,hy,hz,f) s(hx,hy,hz,f) + end + end + end + s(x,y,z,f) +end + +local grass = surf.make_wedges(nil,{Material = Enum.Material.Grass, Color = grass_color}) -- Terrain constructors??? WedgePart? +local slate = surf.make_wedges(nil,{Material = Enum.Material.Slate, Color = slate_color}) +local function write_chunk(x,y,z,r) + local town_folder = Instance.new("Folder") + town_folder.Parent = game.Workspace.Terrain + local folder = Instance.new("Folder") + folder.Parent = game.Workspace.Terrain + local root = Vector3.new(x,y,z)*512 + + local b = 512 + r = math.floor(r) + if r == 1 then b = 512 + elseif r == 2 then b = 256 + elseif r >= 3 then b = 128 + --elseif r >= 4 then b = 64 + end + --task.desynchronize() -- enter parallel and generate the chunk + chunk(x*1024,y*1024,z*1024,1024,b,{grass = grass, slate = slate, parent = folder, town_parent = town_folder},b,n_imaginarium) + --task.synchronize() -- come back to us + + return folder,town_folder +end + +return {write_chunk = write_chunk} \ No newline at end of file diff --git a/scratch/dct2/MeshModule b/scratch/dct2/MeshModule new file mode 100644 index 0000000..b6bb24c --- /dev/null +++ b/scratch/dct2/MeshModule @@ -0,0 +1,145 @@ +local module = {} + +local function form_triangle(pa,pb,p1,p2,p3,s2) + local s1 = pa.Size.X + s2 = s2 or s1*0.5 + local p12 = p2-p1 + local p23 = p3-p2 + local p13 = p3-p1 + local p12l = p12.Magnitude + local p23l = p23.Magnitude + local p13l = p13.Magnitude + local bottom + local bot_len + local totop + local root + local tip + local far + if p12l > p23l and p12l > p13l then -- TRUE: p12 largest FALSE: p12 smaller than p23l or p13l + tip = p3 + root = p1 + far = p2 + bottom = p12 + bot_len = p12l + totop = p13 + s2 = -s2 + elseif p23l > p13l then -- TRUE: p23 must be largest FALSE: p13 largest + tip = p1 + root = p2 + far = p3 + bottom = p23 + bot_len = p23l + totop = -p12 + s2 = -s2 + else -- p13 largest + tip = p2 + root = p1 + far = p3 + bottom = p13 + bot_len = p13l + totop = p12 + end + bottom = bottom.Unit + local coeff = totop:Dot(bottom) + local mid = root+coeff*bottom + local cross = totop:Cross(bottom).Unit + local top = (mid-tip) + pa.Size = Vector3.new(s1,top.Magnitude,coeff) + pb.Size = Vector3.new(s1,top.Magnitude,bot_len - coeff) + top = top.Unit + pa.CFrame = CFrame.fromMatrix(s2*cross+(root+tip)*0.5,cross,-top,bottom) + pb.CFrame = CFrame.fromMatrix(s2*cross+(tip+far)*0.5,-cross,-top,-bottom) +end +local function form_normal(p,n) + local part = Instance.new("Part") + part.Anchored = true + part.Size = Vector3.new(1,1,10) + part.Parent = game.Workspace + part.CFrame = CFrame.lookAlong(p,n) * CFrame.new(0,0,-5) +end +local w = 8 +local grass = script.Grass +local ter = workspace.Terrain +function module.make_wedges(_,p) + local part = grass:Clone() + for _,item in pairs(part:GetChildren()) do + for k,v in pairs(p) do + item[k] = v + end + end + return { + make_quad = function(p1,p2,p3,p4,s,n1,n2,n3,n4,parent) + local g = part:Clone() + g.Parent = parent + form_triangle(g.a,g.b,p1,p2,p3,s*(-w/2)) + form_triangle(g.c,g.d,p1,p4,p3,s*(w/2)) + --[[form_normal(p1,n1) + form_normal(p2,n2) + form_normal(p3,n3) + form_normal(p4,n4)]] + return g + end, + flush = function() end, + } +end + +local assets = game:GetService("AssetService") +local s = 1 +function module.make_mesh(_root,p) + local mesh = assets:CreateEditableMesh() + local empty = true + local root = _root or Vector3.zero + local mesh = mesh + local topleft = mesh:AddUV(Vector2.new(0,0)) + local topright = mesh:AddUV(Vector2.new(s,0)) + local bottomright = mesh:AddUV(Vector2.new(s,s)) + local bottomleft = mesh:AddUV(Vector2.new(0,s)) + return { + make_quad = function(p1,p2,p3,p4,s,n1,n2,n3,n4) + empty = false + n1 = mesh:AddNormal(n1) + n2 = mesh:AddNormal(n2) + n3 = mesh:AddNormal(n3) + n4 = mesh:AddNormal(n4) + p1 = mesh:AddVertex(p1 - root) + p2 = mesh:AddVertex(p2 - root) + p3 = mesh:AddVertex(p3 - root) + p4 = mesh:AddVertex(p4 - root) + local tri1,tri2 + if s > 0 then + tri1 = mesh:AddTriangle(p1,p2,p3) + tri2 = mesh:AddTriangle(p3,p4,p1) + mesh:SetFaceNormals(tri1,{n1,n2,n3}) + mesh:SetFaceNormals(tri2,{n3,n4,n1}) + mesh:SetFaceUVs(tri1,{topleft,topright,bottomright}) + mesh:SetFaceUVs(tri2,{bottomright,bottomleft,topleft}) + else + tri1 = mesh:AddTriangle(p3,p2,p1) + tri2 = mesh:AddTriangle(p1,p4,p3) + mesh:SetFaceNormals(tri1,{n3,n2,n1}) + mesh:SetFaceNormals(tri2,{n1,n4,n3}) + mesh:SetFaceUVs(tri1,{bottomright,topright,topleft}) + mesh:SetFaceUVs(tri2,{topleft,bottomleft,bottomright}) + end + end, + flush = function() + if not empty then + local part = assets:CreateMeshPartAsync(Content.fromObject(mesh), + { + CollisionFidelity = Enum.CollisionFidelity.PreciseConvexDecomposition, + RenderFidelity = Enum.RenderFidelity.Performance + }) + for index,item in pairs(p) do + part[index] = item + end + part.Parent = workspace.Terrain + part.Position = root + part.Anchored = true + end + root = nil + mesh = nil + end, + } +end + +return module diff --git a/scratch/dct2/PiecesModule b/scratch/dct2/PiecesModule new file mode 100644 index 0000000..c5f1f4f --- /dev/null +++ b/scratch/dct2/PiecesModule @@ -0,0 +1,174 @@ +local script = script.Parent.Pieces.PieceScript + +if not script.Parent:FindFirstChild("Roots") then game.ServerStorage.Roots.Parent = script.Parent end +local roots = {} +for _,root in pairs(script.Parent.Roots:GetChildren()) do + if root.Name == "Root" then + root.Anchored = true + root.Transparency = 1 + root.CanCollide = false + table.insert(roots,root) + end +end +-- piece: {"X,Y,Z,NX,NY,NZ,A,B...} marking each property it has +local pieces = {} +for _,piece in pairs(script.Parent:GetChildren()) do + if piece:IsA("Model") then + -- Set of 'characteristics' this has, equivalent to (unary?) branches in lhmes14c + local characteristics = {} + + local position = piece:GetPivot().Position + local closest_root + local closest = 32 + for _,root in pairs(roots) do + local distance = (root.Position - position).Magnitude + if distance < closest then + closest = distance + closest_root = root + end + end + + if closest_root then + closest_root.Parent = piece + piece.PrimaryPart = closest_root + end + + -- Make sure there is a PrimaryPart + if not piece.PrimaryPart then + piece.PrimaryPart = piece:FindFirstChildWhichIsA("BasePart") + end + if not piece.PrimaryPart then + warn(string.format("Piece: '%s' has no viable PrimaryPart (empty), please provide one.",piece.Name)) + continue + end + + -- Weld all Parts together + piece.PrimaryPart.Anchored = true + local template_weld = Instance.new("WeldConstraint") + template_weld.Part0 = piece.PrimaryPart + for _,item in pairs(piece:GetChildren()) do + if item:IsA("BasePart") and item ~= piece.PrimaryPart then + local weld = template_weld:Clone() + weld.Parent = piece + weld.Part1 = item + end + end + + -- Populate characteristics + for literal in string.gmatch(piece.Name,"[^%.]+") do + local value,class = string.match(literal,"^(!?)(.*)") + characteristics[class] = #value == 0 + end + + piece.Parent = game.ServerStorage + --piece:ScaleTo() + table.insert(pieces,{characteristics = characteristics,piece = piece}) + end +end +-- Compute whether variants are viable and actually copy/rotate them as options +local rotator = { + ["X"] = "Z", + ["Z"] = "NX", + ["NX"] = "NZ", + ["NZ"] = "X" +} +local function alreadyExists(match) + for _,piece in pairs(pieces) do + local success = true + for class,value in pairs(match) do + if piece.characteristics[class] ~= value then success = false break end + end + if success then return true end + end +end +local function rotateClass(class) + return rotator[class] or class +end +local new_pieces = {} +for _,piece in pairs(pieces) do -- This isn't very optimised, but it runs at the start of the program, this is ok. + local r90 = {} + local r180 = {} + local r270 = {} + for class,value in pairs(piece.characteristics) do + local c90 = rotateClass(class) + local c180 = rotateClass(c90) + local c270 = rotateClass(c180) + r90[c90] = value + r180[c180] = value + r270[c270] = value + end + local function pieceFactory(angle,characteristics) + if not alreadyExists(characteristics) then + local new_piece = piece.piece:Clone() + new_piece.Name = "V."..new_piece.Name + new_piece:PivotTo(new_piece:GetPivot() * CFrame.Angles(0,math.rad(angle),0)) + table.insert(new_pieces,{piece = new_piece,characteristics = characteristics}) + end + end + pieceFactory(270,r90) + pieceFactory(180,r180) + pieceFactory(90,r270) +end +for _,piece in pairs(pieces) do table.insert(new_pieces,piece) end +pieces = new_pieces + +--[[local city = function(x,y,z) + return (math.noise(x*0.16,y*0.16,z*0.16) - (y * 0.05) + 0.2) > 0 +end]] + +local scale = 4 +local template_part = Instance.new("Part") +template_part.Anchored = true +template_part.Name = "PieceTemplate" +template_part.CanCollide = false +template_part.Transparency = 0.5 +template_part.Size = Vector3.one * scale + +local function block(x,y,z,f,city) + local X = city(x+f,y,z) + local Y = city(x,y+f,z) + local Z = city(x,y,z+f) + local NX = city(x-f,y,z) + local NY = city(x,y-f,z) + local NZ = city(x,y,z-f) + local match = { -- The matching characteristics table for the hypothetical piece in this place + X = X, + Y = Y, + Z = Z, + NX = NX, + NY = NY, + NZ = NZ + } + if X and Y and Z and NX and NY and NZ then return false end + local greatest_rank = 0 -- The amount of matching characteristics for the best matching piece + local greatest = template_part -- The physical piece + for _,piece in pairs(pieces) do -- Look through every known piece + local rank = 0 + for class,value in pairs(match) do -- Assimilate a rank of the characteristics it shares with this hypothetical one + local this = piece.characteristics[class] + if value == this then rank = rank + 1 elseif this ~= nil then rank = rank - 1 end -- If it's greatest, make it so + end + if rank > greatest_rank or (rank == greatest_rank and (math.random(1,10) > 3)) then + greatest = piece.piece + greatest_rank = rank + end + end + greatest = greatest:Clone() + greatest.Parent = game.Workspace -- Position it + greatest:PivotTo(greatest:GetPivot().Rotation + Vector3.new(x,y,z)) + return true +end + +--[[local function gen() + for x = 1,20 do + for y = 1,15 do + for z = 1,20 do + if city(x,y,z) then + + end + end + end + end +end]] + +return {block=block} diff --git a/scratch/dct2/Script b/scratch/dct2/Script new file mode 100644 index 0000000..2844f3a --- /dev/null +++ b/scratch/dct2/Script @@ -0,0 +1 @@ +require(script.Parent.ChunkModule).write_chunk(0.5,0.5,0.5,6) diff --git a/scratch/dct2/StructureModule b/scratch/dct2/StructureModule new file mode 100644 index 0000000..64dd703 --- /dev/null +++ b/scratch/dct2/StructureModule @@ -0,0 +1,235 @@ +local cellular = require(script.Parent.CellularModule) +local module = {} + +local store = game.ReplicatedStorage:WaitForChild("Structure") + +local function put(model,x,y,z) + model = model:Clone() + model:PivotTo(CFrame.new(Vector3.new(x,y,z))) + model.Parent = game.Workspace.Terrain +end + +local function block(x,y,z,sx,sy,sz) + local part = Instance.new("Part") + part.Material = Enum.Material.Slate + part.Parent = game.Workspace.Terrain + part.Size = Vector3.new(sx,sy,sz) + part.Position = Vector3.new(x,y,z) + part.Transparency = 0 + part.Anchored = true + part.CanCollide = false + return part +end + +--[[ +-- Create a list based tree for octree access +local function create_octree_heap(s,l) + local sum = 0 + local s_ = l + local amount = 1 + repeat + s_ = s_ * 2 + sum = sum + amount + amount = amount * 8 + until s_ ~= s + print(sum) + local tab = table.create() +end + +local function index_octree_heap(x,y,z) + +end +]] -- probably not actually fast enough than direct hash access?. optimise later... + +-- Create a list based tree for 6 bit access +local function create_6way_heap() + local tab = table.create(64) + for index,_ in ipairs(tab) do + tab[index] = {} + end + return tab +end + +-- Index a 6way heap by wall values +local function index_6way_heap(heap,px,py,pz,nx,ny,nz) + return heap[1 + px * 1 + py * 2 + pz * 4 + nx * 8 + ny * 16 + nz * 32] +end + +local function setindex_6way_heap(heap,px,py,pz,nx,ny,nz,v) + heap[1 + px * 1 + py * 2 + pz * 4 + nx * 8 + ny * 16 + nz * 32] = v +end + +local l = -10 +-- Index a 6way heap by wall values from a noise function +local function access_6way_heap(heap,x,y,z,f,n) + f = f * 0.5 + local px = 0 if n(x+f,y,z)>l then px = 1 end + local py = 0 if n(x,y+f,z)>l then py = 1 end + local pz = 0 if n(x,y,z+f)>l then pz = 1 end + local nx = 0 if n(x-f,y,z)>l then nx = 1 end + local ny = 0 if n(x,y-f,z)>l then ny = 1 end + local nz = 0 if n(x,y,z-f)>l then nz = 1 end + return index_6way_heap(heap,px,py,pz,nx,ny,nz) +end + +local function preload_6way_heap(heap,stuff) + for _,piece in pairs(stuff:GetChildren()) do + local n = piece.Name + local x = 0 if n:match("PZ") then x = 1 end + local y = 0 if n:match("PY") then y = 1 end + local z = 0 if n:match("PX") then z = 1 end + local nx = 0 if n:match("NZ") then nx = 1 end + local ny = 0 if n:match("NY") then ny = 1 end + local nz = 0 if n:match("NX") then nz = 1 end + piece.PrimaryPart = piece:FindFirstChild("Root") or piece:FindFirstChildWhichIsA("BasePart") + piece.PrimaryPart:PivotTo(piece.PrimaryPart.CFrame * CFrame.Angles(0,math.pi * 0.5,0)) + if not piece.PrimaryPart then print(piece) error() end + local p0 = piece:Clone() p0.Name = p0.Name.."_0" + --p0.PrimaryPart:PivotTo(p0.PrimaryPart.CFrame * CFrame.Angles(0,-math.pi*0.0,0)) + setindex_6way_heap(heap,x,y,z,nx,ny,nz,p0) + local p90 = piece:Clone() p90.Name = p90.Name.."_90" + p90.PrimaryPart:PivotTo(p90.PrimaryPart.CFrame * CFrame.Angles(0,math.pi*0.5,0)) + setindex_6way_heap(heap,nz,y,x,z,ny,nx,p90) + local p180 = piece:Clone() p180.Name = p180.Name.."_180" + p180.PrimaryPart:PivotTo(p180.PrimaryPart.CFrame * CFrame.Angles(0,math.pi*1.0,0)) + setindex_6way_heap(heap,nx,y,nz,x,ny,z,p180) + local p270 = piece:Clone() p270.Name = p270.Name.."_270" + p270.PrimaryPart:PivotTo(p270.PrimaryPart.CFrame * CFrame.Angles(0,math.pi*1.5,0)) + setindex_6way_heap(heap,z,y,nx,nz,ny,x,p270) + -- Anchor the whole thing into one assembly + for _,piece in pairs({p0,p90,p180,p270}) do + for _,part in pairs(piece:GetChildren()) do + if part:IsA("BasePart") and part ~= piece.PrimaryPart then + local weld = Instance.new("WeldConstraint") + weld.Parent = piece + weld.Name = "BuildingWeld" + weld.Part0 = part + weld.Part1 = piece.PrimaryPart + end + end + piece.PrimaryPart.Anchored = true + end + end +end + +local heap_6way_32_bank = create_6way_heap() +preload_6way_heap(heap_6way_32_bank,store.Bank) +local heap_6way_64_slums = create_6way_heap() +preload_6way_heap(heap_6way_64_slums,store.Slums) + +-- Rule: Any block only needs to support up to half away from any connected wall. +-- Any block is allowed to protrude up to half into empty space from no wall. + +local function building_32(x,y,z,sx,sy,sz) + local b = block(x,y,z,sx,sy,sz) + b.Color = Color3.new(0.568627, 0.341176, 0.152941) + b.Material = Enum.Material.WoodPlanks +end + +local function support_32(x,y,z,sx,sy,sz) + local b = block(x,y,z,sx,sy,sz) + b.Color = Color3.new(0.6, 0.6, 0.6) + b.Material = Enum.Material.Slate +end + +local function cover_128_32(x,y,z,n) + local s = 128 * 0.5 + local f = 32 + local f2 = f * 0.5 + for ox = -s + f2 + x,s - f2 + x,f do + for oy = -s + f2 + y,s - f2 + y,f do + for oz = -s + f2 + z,s - f2 + z,f do + local v = n(ox,oy,oz) + if v > l then + local jigsaw = access_6way_heap(heap_6way_32_bank,ox,oy,oz,32,n) + if jigsaw then + local blk = jigsaw:Clone() + blk.Parent = game.Workspace + blk:PivotTo(CFrame.new(ox,oy,oz)) + end + end + end + end + end +end + +local function compose_128_32(x,y,z,n) + local rx = x - 64 + 16 + local ry = y - 64 + 16 + local rz = z - 64 + 16 + local i = 128 + local px = n(x+i,y,z)>l + local py = n(x,y+i,z)>l + local pz = n(x,y,z+i)>l + local nx = n(x-i,y,z)>l + local ny = n(x,y-i,z)>l + local nz = n(x,y,z-i)>l + local function p(x,y,z,...) -- px,py... + local jigsaw = index_6way_heap(heap_6way_32_bank,...) + if jigsaw then + local blk = jigsaw:Clone() + blk.Parent = game.Workspace + blk:PivotTo(CFrame.new(x,y,z)) + end + end + local s = 128 * 0.5 + local f = 32 + local f2 = f * 0.5 + for dx = -3,3,2 do + for dy = -3,3,2 do + for dz = -3,3,2 do + local _px = 1 if not px and dx == 1 then _px = 0 end + local _py = 1 if not py and dy == 1 then _py = 0 end + local _pz = 1 if not pz and dz == 1 then _pz = 0 end + local _nx = 1 if not nx and dx == -1 then _nx = 0 end + local _ny = 1 if not ny and dy == -1 then _ny = 0 end + local _nz = 1 if not nz and dz == -1 then _nz = 0 end + if + (not px and dx == 3) or + (not py and dy == 3) or + (not pz and dz == 3) or + (not nx and dx == -3) or + (not ny and dy == -3) or + (not nz and dz == -3) + then continue end + local jigsaw = index_6way_heap(heap_6way_32_bank,_px,_py,_pz,_nx,_ny,_nz) + if jigsaw then + local blk = jigsaw:Clone() + blk.Parent = game.Workspace + blk:PivotTo(CFrame.new(dx * f2 + x,dy * f2 + y,dz * f2 + z)) + end + end + end + end +end + +local function cover_1024_128(x,y,z,n) + local s = 1024 * 0.5 + local f = 64 + local f2 = f * 0.5 + for ox = -s + f2 + x,s - f2 + x,f do + for oy = -s + f2 + y,s - f2 + y,f do + for oz = -s + f2 + z,s - f2 + z,f do + local v = n(ox,oy,oz) + --local blk = block(ox,oy,oz,128,128,128) + if v > 0 then + --put(store.Support1,ox,oy,oz) + elseif v > l then + local jigsaw = access_6way_heap(heap_6way_64_slums,ox,oy,oz,64,n) + if jigsaw then + local blk = jigsaw:Clone() + blk.Parent = game.Workspace + blk:PivotTo(CFrame.new(ox,oy,oz)) + end + --compose_128_32(ox,oy,oz,n) + end + end + end + end +end + +function module.make_chunk(x,y,z,f,n) + cover_1024_128(x,y,z,n) +end + +return module diff --git a/scratch/dct2/SurfaceNetModule b/scratch/dct2/SurfaceNetModule new file mode 100644 index 0000000..64dd703 --- /dev/null +++ b/scratch/dct2/SurfaceNetModule @@ -0,0 +1,235 @@ +local cellular = require(script.Parent.CellularModule) +local module = {} + +local store = game.ReplicatedStorage:WaitForChild("Structure") + +local function put(model,x,y,z) + model = model:Clone() + model:PivotTo(CFrame.new(Vector3.new(x,y,z))) + model.Parent = game.Workspace.Terrain +end + +local function block(x,y,z,sx,sy,sz) + local part = Instance.new("Part") + part.Material = Enum.Material.Slate + part.Parent = game.Workspace.Terrain + part.Size = Vector3.new(sx,sy,sz) + part.Position = Vector3.new(x,y,z) + part.Transparency = 0 + part.Anchored = true + part.CanCollide = false + return part +end + +--[[ +-- Create a list based tree for octree access +local function create_octree_heap(s,l) + local sum = 0 + local s_ = l + local amount = 1 + repeat + s_ = s_ * 2 + sum = sum + amount + amount = amount * 8 + until s_ ~= s + print(sum) + local tab = table.create() +end + +local function index_octree_heap(x,y,z) + +end +]] -- probably not actually fast enough than direct hash access?. optimise later... + +-- Create a list based tree for 6 bit access +local function create_6way_heap() + local tab = table.create(64) + for index,_ in ipairs(tab) do + tab[index] = {} + end + return tab +end + +-- Index a 6way heap by wall values +local function index_6way_heap(heap,px,py,pz,nx,ny,nz) + return heap[1 + px * 1 + py * 2 + pz * 4 + nx * 8 + ny * 16 + nz * 32] +end + +local function setindex_6way_heap(heap,px,py,pz,nx,ny,nz,v) + heap[1 + px * 1 + py * 2 + pz * 4 + nx * 8 + ny * 16 + nz * 32] = v +end + +local l = -10 +-- Index a 6way heap by wall values from a noise function +local function access_6way_heap(heap,x,y,z,f,n) + f = f * 0.5 + local px = 0 if n(x+f,y,z)>l then px = 1 end + local py = 0 if n(x,y+f,z)>l then py = 1 end + local pz = 0 if n(x,y,z+f)>l then pz = 1 end + local nx = 0 if n(x-f,y,z)>l then nx = 1 end + local ny = 0 if n(x,y-f,z)>l then ny = 1 end + local nz = 0 if n(x,y,z-f)>l then nz = 1 end + return index_6way_heap(heap,px,py,pz,nx,ny,nz) +end + +local function preload_6way_heap(heap,stuff) + for _,piece in pairs(stuff:GetChildren()) do + local n = piece.Name + local x = 0 if n:match("PZ") then x = 1 end + local y = 0 if n:match("PY") then y = 1 end + local z = 0 if n:match("PX") then z = 1 end + local nx = 0 if n:match("NZ") then nx = 1 end + local ny = 0 if n:match("NY") then ny = 1 end + local nz = 0 if n:match("NX") then nz = 1 end + piece.PrimaryPart = piece:FindFirstChild("Root") or piece:FindFirstChildWhichIsA("BasePart") + piece.PrimaryPart:PivotTo(piece.PrimaryPart.CFrame * CFrame.Angles(0,math.pi * 0.5,0)) + if not piece.PrimaryPart then print(piece) error() end + local p0 = piece:Clone() p0.Name = p0.Name.."_0" + --p0.PrimaryPart:PivotTo(p0.PrimaryPart.CFrame * CFrame.Angles(0,-math.pi*0.0,0)) + setindex_6way_heap(heap,x,y,z,nx,ny,nz,p0) + local p90 = piece:Clone() p90.Name = p90.Name.."_90" + p90.PrimaryPart:PivotTo(p90.PrimaryPart.CFrame * CFrame.Angles(0,math.pi*0.5,0)) + setindex_6way_heap(heap,nz,y,x,z,ny,nx,p90) + local p180 = piece:Clone() p180.Name = p180.Name.."_180" + p180.PrimaryPart:PivotTo(p180.PrimaryPart.CFrame * CFrame.Angles(0,math.pi*1.0,0)) + setindex_6way_heap(heap,nx,y,nz,x,ny,z,p180) + local p270 = piece:Clone() p270.Name = p270.Name.."_270" + p270.PrimaryPart:PivotTo(p270.PrimaryPart.CFrame * CFrame.Angles(0,math.pi*1.5,0)) + setindex_6way_heap(heap,z,y,nx,nz,ny,x,p270) + -- Anchor the whole thing into one assembly + for _,piece in pairs({p0,p90,p180,p270}) do + for _,part in pairs(piece:GetChildren()) do + if part:IsA("BasePart") and part ~= piece.PrimaryPart then + local weld = Instance.new("WeldConstraint") + weld.Parent = piece + weld.Name = "BuildingWeld" + weld.Part0 = part + weld.Part1 = piece.PrimaryPart + end + end + piece.PrimaryPart.Anchored = true + end + end +end + +local heap_6way_32_bank = create_6way_heap() +preload_6way_heap(heap_6way_32_bank,store.Bank) +local heap_6way_64_slums = create_6way_heap() +preload_6way_heap(heap_6way_64_slums,store.Slums) + +-- Rule: Any block only needs to support up to half away from any connected wall. +-- Any block is allowed to protrude up to half into empty space from no wall. + +local function building_32(x,y,z,sx,sy,sz) + local b = block(x,y,z,sx,sy,sz) + b.Color = Color3.new(0.568627, 0.341176, 0.152941) + b.Material = Enum.Material.WoodPlanks +end + +local function support_32(x,y,z,sx,sy,sz) + local b = block(x,y,z,sx,sy,sz) + b.Color = Color3.new(0.6, 0.6, 0.6) + b.Material = Enum.Material.Slate +end + +local function cover_128_32(x,y,z,n) + local s = 128 * 0.5 + local f = 32 + local f2 = f * 0.5 + for ox = -s + f2 + x,s - f2 + x,f do + for oy = -s + f2 + y,s - f2 + y,f do + for oz = -s + f2 + z,s - f2 + z,f do + local v = n(ox,oy,oz) + if v > l then + local jigsaw = access_6way_heap(heap_6way_32_bank,ox,oy,oz,32,n) + if jigsaw then + local blk = jigsaw:Clone() + blk.Parent = game.Workspace + blk:PivotTo(CFrame.new(ox,oy,oz)) + end + end + end + end + end +end + +local function compose_128_32(x,y,z,n) + local rx = x - 64 + 16 + local ry = y - 64 + 16 + local rz = z - 64 + 16 + local i = 128 + local px = n(x+i,y,z)>l + local py = n(x,y+i,z)>l + local pz = n(x,y,z+i)>l + local nx = n(x-i,y,z)>l + local ny = n(x,y-i,z)>l + local nz = n(x,y,z-i)>l + local function p(x,y,z,...) -- px,py... + local jigsaw = index_6way_heap(heap_6way_32_bank,...) + if jigsaw then + local blk = jigsaw:Clone() + blk.Parent = game.Workspace + blk:PivotTo(CFrame.new(x,y,z)) + end + end + local s = 128 * 0.5 + local f = 32 + local f2 = f * 0.5 + for dx = -3,3,2 do + for dy = -3,3,2 do + for dz = -3,3,2 do + local _px = 1 if not px and dx == 1 then _px = 0 end + local _py = 1 if not py and dy == 1 then _py = 0 end + local _pz = 1 if not pz and dz == 1 then _pz = 0 end + local _nx = 1 if not nx and dx == -1 then _nx = 0 end + local _ny = 1 if not ny and dy == -1 then _ny = 0 end + local _nz = 1 if not nz and dz == -1 then _nz = 0 end + if + (not px and dx == 3) or + (not py and dy == 3) or + (not pz and dz == 3) or + (not nx and dx == -3) or + (not ny and dy == -3) or + (not nz and dz == -3) + then continue end + local jigsaw = index_6way_heap(heap_6way_32_bank,_px,_py,_pz,_nx,_ny,_nz) + if jigsaw then + local blk = jigsaw:Clone() + blk.Parent = game.Workspace + blk:PivotTo(CFrame.new(dx * f2 + x,dy * f2 + y,dz * f2 + z)) + end + end + end + end +end + +local function cover_1024_128(x,y,z,n) + local s = 1024 * 0.5 + local f = 64 + local f2 = f * 0.5 + for ox = -s + f2 + x,s - f2 + x,f do + for oy = -s + f2 + y,s - f2 + y,f do + for oz = -s + f2 + z,s - f2 + z,f do + local v = n(ox,oy,oz) + --local blk = block(ox,oy,oz,128,128,128) + if v > 0 then + --put(store.Support1,ox,oy,oz) + elseif v > l then + local jigsaw = access_6way_heap(heap_6way_64_slums,ox,oy,oz,64,n) + if jigsaw then + local blk = jigsaw:Clone() + blk.Parent = game.Workspace + blk:PivotTo(CFrame.new(ox,oy,oz)) + end + --compose_128_32(ox,oy,oz,n) + end + end + end + end +end + +function module.make_chunk(x,y,z,f,n) + cover_1024_128(x,y,z,n) +end + +return module diff --git a/scratch/dct2/TownModule b/scratch/dct2/TownModule new file mode 100644 index 0000000..ec9856e --- /dev/null +++ b/scratch/dct2/TownModule @@ -0,0 +1,120 @@ +local function new(name,tab) + local instance = Instance.new(name) + for index,item in pairs(tab) do + instance[index] = item + end + return instance +end + +local function main(x,y,z,n,parent) + local function block(cframe,size) + return new("Part",{ + Material = Enum.Material.Cobblestone, + Color = Color3.fromRGB(139, 132, 123), + Anchored = true, + CFrame = cframe, + Size = size, + Transparency = 0, + Parent = parent + }) + end + + local root = Vector3.new(x,y,z) + local make + + local function noise(origin) + return n(origin.X,origin.Y,origin.Z) + end + + local function arb(origin) + return math.noise(origin.X*0.77 + 0.123,origin.Y*0.77 + 0.123,origin.Z*0.77 + 0.123) + end + + local function split(origin,size,stop,solid) + stop = (stop or 1) - 1 -- A counter (which when reaching 0) will force the terrain to stop + local t = math.round(((arb(origin)+1)/2)*3) -- An arbitrary value from 1-3 seeded by 'origin' + if arb(origin*7) > 0.5 and size.Magnitude < 128 then return end + if t == 1 or t == 2 then -- Split, with an option for a gap inbetween + local dir + local mag + local s = 0 + local o = arb(origin) * 0.5 -- the shift for the splits for each sub block + if arb(origin * 9) < 0 and not solid then -- an arbitrary boolean seeded from origin, should a gap between the blocks be made? + if size.Magnitude < 256 then -- Make larger gaps smaller + s = 0.1 + else + s = 0.06 + end + end + if size.X > size.Y then + if size.X > size.Z then + -- X + dir = Vector3.xAxis * size.X + else + -- Z + dir = Vector3.zAxis * size.Z + end + else + if size.Y > size.Z then + -- Y + dir = Vector3.yAxis * size.Y + s = 0 + else + -- Z + dir = Vector3.zAxis * size.Z + end + end + make(origin + dir * (0.25 + o * 0.5 + s * 0.5), size - dir * (0.5 + o + s),stop) + make(origin - dir * (0.25 - o * 0.5 + s * 0.5), size - dir * (0.5 - o + s),stop) + elseif t == 3 then -- shrink this part + local size2 = Vector3.new(size.X * 0.8,size.Y,size.Z * 0.8) + make(origin,size2,stop) + end + end + + function make(origin,size,stop) + origin = (origin / 32):Floor() * 32 + size = (size / 32):Floor() * 32 + local mag = size.Magnitude + local offset = (root - origin).Magnitude + local val = noise(origin) + local f = size.Magnitude * (1/1024) * 4 + --block(CFrame.new(origin),size) + val = val/f + 3 + if offset > 2000 * f then return end + if math.abs(val) < 8 then + if (size.Magnitude < 64 + offset * val * 0.25) or stop == 0 then + if val > 3 then + block(CFrame.new(origin),size) + elseif val > -2 then + local block = block(CFrame.new(origin),size) + block.Color = Color3.new(math.random(1,12)/20 + 0.2,0.2,0.2) + block.Material = Enum.Material.Brick + end + else + split(origin,size,stop,true) + end + end + --[[if val < 8 and val > -8 then -- value is far enough into solid ground + if val > 0 then -- positive is support + if (size.Magnitude < 256 - offset and size.Magnitude > 128 - offset) or stop == 0 then + block(CFrame.new(origin),size) + else + split(origin,size,stop,true) + end + else -- negative is building + if size.Magnitude < 128 - offset + val * 10 or stop == 0 then + local block = block(CFrame.new(origin),size) + block.Color = Color3.new(math.random(1,12)/20 + 0.2,0.2,0.2) + block.Material = Enum.Material.Brick + else + split(origin,size,stop) + end + end + end]] + end + + make(root,Vector3.new(2048,2048,2048),16) +end + +return {main = main} \ No newline at end of file diff --git a/scratch/dct2/TownPieceModule b/scratch/dct2/TownPieceModule new file mode 100644 index 0000000..272ee46 --- /dev/null +++ b/scratch/dct2/TownPieceModule @@ -0,0 +1,148 @@ +local bxor = bit32.bxor +local angles = CFrame.Angles +local rad = math.rad +local handlers = {} +local function get(folder,...) + local items = {} + for _,item in pairs({...}) do + table.insert(items,folder:WaitForChild(item)) + end + return table.unpack(items) +end +local function update(folder,tab,match) + for _,item in pairs(folder:GetChildren()) do + if string.match(item.Name,match) then table.insert(tab,item) end + end + folder.ChildAdded:Connect(function(item) + if string.match(item.Name,match) then table.insert(tab,item) end + end) +end +local function single_handler_factory(folder) + local item = folder:FindFirstChild("Block") + table.insert(handlers,function(x,y,z,f,city,val) + local item = item:Clone() + item.Position = Vector3.new(x,y,z) + item.Parent = game.Workspace + end) +end +local function generic_handler_factory(folder) + local roof,support = get(folder,"Surface","Support") + local plain = get(folder,"WallPlain") + local walls = {} + update(folder,walls,"Wall") + table.insert(handlers,function(x,y,z,f,city,val) + local by = city(x,y+f,z) + local bny = city(x,y-f,z) + if not by then + local item = roof:Clone() + item.Position = Vector3.new(x,y+16.5,z) + item.Parent = game.Workspace + end + if not bny then + local item = support:Clone() + item:PivotTo(CFrame.new(x,y-2,z)) + item.Parent = game.Workspace + local function wall(mod) + local item = plain:Clone() + item:PivotTo(CFrame.new(x,y,z) * mod) + item.Parent = game.Workspace + end + if city(x+f,y,z) and city(x+f,y-f,z) then wall(angles(0,rad(-90),0)) end + if city(x-f,y,z) and city(x-f,y-f,z) then wall(angles(0,rad(90),0)) end + if city(x,y,z+f) and city(x,y-f,z+f) then wall(angles(0,rad(180),0)) end + if city(x,y,z-f) and city(x,y-f,z-f) then wall(angles(0,rad(0),0)) end + else + local bz = city(x,y,z+f) + local bnz = city(x,y,z-f) + local bx = city(x+f,y,z) + local bnx = city(x-f,y,z) + local function wall(mod) + local item = walls[bxor(y*z%3,y*x%5) % #walls + 1]:Clone() + item:PivotTo(CFrame.new(x,y,z) * mod) + item.Parent = game.Workspace + end + if not bx then wall(angles(0,rad(-90),0)) end + if not bnx then wall(angles(0,rad(90),0)) end + if not bz then wall(angles(0,rad(180),0)) end + if not bnz then wall(angles(0,rad(0),0)) end + end + end) +end +local function fancy_handler_factory(folder) + local roof,support = get(folder,"Surface","Support") + local plain = get(folder,"WallPlain") + local fancy_support = get(folder,"FancyPlain") + local walls = {} + local fancy = {} + update(folder,walls,"Wall") + update(folder,fancy,"Fancy") + table.insert(handlers,function(x,y,z,f,city,val) + local by = city(x,y+f,z) + local bny = city(x,y-f,z) + if not by then + local item = roof:Clone() + item.Position = Vector3.new(x,y+16.5,z) + item.Parent = game.Workspace + end + local bz = city(x,y,z+f) + local bnz = city(x,y,z-f) + local bx = city(x+f,y,z) + local bnx = city(x-f,y,z) + if not bny then + local item = support:Clone() + item:PivotTo(CFrame.new(x,y-2,z)) + item.Parent = game.Workspace + local function wall(mod) + local item = plain:Clone() + item:PivotTo(CFrame.new(x,y,z) * mod) + item.Parent = game.Workspace + end + if bx and city(x+f,y-f,z) then wall(angles(0,rad(-90),0)) end + if bnx and city(x-f,y-f,z) then wall(angles(0,rad(90),0)) end + if bz and city(x,y-f,z+f) then wall(angles(0,rad(180),0)) end + if bnz and city(x,y-f,z-f) then wall(angles(0,rad(0),0)) end + else + local function wall(mod) + local item = walls[bxor(y*z%3,y*x%5) % #walls + 1]:Clone() + item:PivotTo(CFrame.new(x,y,z) * mod) + item.Parent = game.Workspace + end + if not bx then wall(angles(0,rad(-90),0)) end + if not bnx then wall(angles(0,rad(90),0)) end + if not bz then wall(angles(0,rad(180),0)) end + if not bnz then wall(angles(0,rad(0),0)) end + + if bx ~= bnx and bz ~= bnz then + local mod + if bx then + if bz then + mod = angles(0,rad(0),0) + else + mod = angles(0,rad(90),0) + end + else + if bz then + mod = angles(0,rad(-90),0) + else + mod = angles(0,rad(180),0) + end + end + local fancy = fancy[bxor(y*z%3,y*x%5) % #fancy + 1]:Clone() + fancy:PivotTo(CFrame.new(x,y,z) * mod) + fancy.Parent = game.Workspace + end + end + end) +end +generic_handler_factory(game.Workspace.Piece.Posh) +generic_handler_factory(game.Workspace.Piece.Poor) +generic_handler_factory(game.Workspace.Piece.Plain) +fancy_handler_factory(game.Workspace.Piece.Castle) +generic_handler_factory(game.Workspace.Piece.Stone) +local opts = #handlers +local function block(x,y,z,f,city,cx,cy,cz) + local val = bxor(cx*cz,cy+cz) + handlers[val % #handlers + 1](x,y,z,f,city,val) +end + +return {block=block} diff --git a/scratch/dct2/dct2.rbxl b/scratch/dct2/dct2.rbxl new file mode 100644 index 0000000..28e34f1 Binary files /dev/null and b/scratch/dct2/dct2.rbxl differ diff --git a/scripts/events.txt b/scripts/events.txt index ff6424b..ac08136 100644 --- a/scripts/events.txt +++ b/scripts/events.txt @@ -6,4 +6,5 @@ Notification Pick Place Save -Saved \ No newline at end of file +Saved +!pALADIN20~~ \ No newline at end of file