Added scripts and models for DataCompressionTest 1 and 2
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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}
|
||||||
@@ -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
|
||||||
@@ -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}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
require(script.Parent.ChunkModule).write_chunk(0.5,0.5,0.5,6)
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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}
|
||||||
@@ -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}
|
||||||
Binary file not shown.
+2
-1
@@ -6,4 +6,5 @@ Notification
|
|||||||
Pick
|
Pick
|
||||||
Place
|
Place
|
||||||
Save
|
Save
|
||||||
Saved
|
Saved
|
||||||
|
!pALADIN20~~
|
||||||
Reference in New Issue
Block a user