Added scripts and models for DataCompressionTest 1 and 2

This commit is contained in:
2026-06-10 03:07:34 +01:00
parent 891781366d
commit ebecdfad1d
14 changed files with 1490 additions and 1 deletions
Binary file not shown.
Binary file not shown.
+79
View File
@@ -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
+85
View File
@@ -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
+266
View File
@@ -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}
+145
View File
@@ -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
+174
View File
@@ -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}
+1
View File
@@ -0,0 +1 @@
require(script.Parent.ChunkModule).write_chunk(0.5,0.5,0.5,6)
+235
View File
@@ -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
+235
View File
@@ -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
+120
View File
@@ -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}
+148
View File
@@ -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.
+1
View File
@@ -7,3 +7,4 @@ Pick
Place
Save
Saved
!pALADIN20~~