Skip to content

Instantly share code, notes, and snippets.

@GreenXenith
Last active August 24, 2021 04:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GreenXenith/76e22d52d33e2f085c5cad893b8fe556 to your computer and use it in GitHub Desktop.
Save GreenXenith/76e22d52d33e2f085c5cad893b8fe556 to your computer and use it in GitHub Desktop.
sideways world?
vector.ZERO = function() return {x = 0, y = 0, z = 0} end
local apply_rotation = function(dir, rot)
local axis_x = {x = 1, y = 0, z = 0}
local axis_y = {x = 0, y = 1, z = 0}
local axis_z = {x = 0, y = 0, z = 1}
dir = vector.rotate_around_axis(dir, axis_z, rot.z)
dir = vector.rotate_around_axis(dir, axis_y, rot.y)
dir = vector.rotate_around_axis(dir, axis_x, rot.x)
return dir
end
-- Rotate pos1 and rot1 about pos2 by rot2
local rotate_about = function(pos1, pos2, rot1, rot2)
local r = vector.add(rot1, rot2)
local rot = vector.dir_to_rotation(apply_rotation({x = 0, y = 0, z = 1}, r), apply_rotation({x = 0, y = 1, z = 0}, r))
local pos = vector.multiply(vector.rotate(vector.direction(pos2, pos1), rot2), vector.distance(pos2, pos1))
return pos, rot
end
local cache = {}
-- This is the callback for emerge_area in on_generated
local function copy_and_restore(data)
local vm = minetest.get_voxel_manip()
local va = VoxelArea:new({MinEdge = data.source_minp, MaxEdge = data.source_maxp})
-- Read our emerged source
local vmin, vmax = vm:read_from_map(data.source_minp, data.source_maxp)
local vdim = vector.subtract(vmax, vmin)
local source = vm:get_data()
-- Restore the original source mapblock
vm:set_data(cache[data.id])
vm:write_to_map(true)
cache[data.id] = nil
local source_rotated = {}
local va_rotated = VoxelArea:new({MinEdge = data.minp, MaxEdge = data.maxp})
-- Rotate the block
for idx, id in pairs(source) do
local pos = vector.subtract(va:position(idx), vmin)
local center = vector.add(pos, vector.divide(vdim, 2))
local rotated = rotate_about(pos, center, vector.ZERO(), {x = -math.pi / 2, y = 0, z = 0})
source_rotated[va_rotated:indexp(rotated)] = id
end
-- Paste rotated to target mapblock
vm:read_from_map(data.minp, data.maxp)
vm:set_data(source_rotated)
vm:write_to_map(true)
end
minetest.register_on_generated(function(minp, maxp)
-- Rotate our "mapblock pos" about the world origin 90deg
local source_p1 = rotate_about(minp, vector.ZERO(), vector.ZERO(), {x = -math.pi / 2, y = 0, z = 0})
local source_p2 = rotate_about(maxp, vector.ZERO(), vector.ZERO(), {x = -math.pi / 2, y = 0, z = 0})
local source_minp, source_maxp = vector.sort(source_p1, source_p2)
-- Load the area to steal terrain
minetest.load_area(source_minp, source_maxp)
print(("loaded block at %s to replace block at %s"):format(minetest.pos_to_string(source_minp), minetest.pos_to_string(minp)))
-- Read and backup anything already there
local vm = minetest.get_voxel_manip()
vm:read_from_map(source_minp, source_maxp)
local id = #cache + 1
cache[id] = vm:get_data()
-- Delete and re-gnerate it
minetest.delete_area(source_minp, source_maxp)
minetest.emerge_area(source_minp, source_maxp, function(_, _, remaining, data)
if remaining == 0 then
copy_and_restore(data)
end
end, {id = id, minp = minp, maxp = maxp, source_minp = source_minp, source_maxp = source_maxp})
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment