Compare commits
5 Commits
7c7b01a694
...
432d9ca6a0
Author | SHA1 | Date |
---|---|---|
|
432d9ca6a0 | |
|
be87054c49 | |
|
b250c01351 | |
|
dced2d6488 | |
|
9556808b82 |
|
@ -7,6 +7,9 @@ Warning: The repository name and all parts of it might contain some sarcasm.
|
||||||
Module descriptions
|
Module descriptions
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
blur:
|
||||||
|
Flattens the terrain using some kind of blur function.
|
||||||
|
|
||||||
mapgen:
|
mapgen:
|
||||||
Place a schematic when a new chunk is generated.
|
Place a schematic when a new chunk is generated.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
-- peoplecantblur - Generate flat areas
|
-- peoplecantblur - Generate flat areas
|
||||||
|
|
||||||
local HEIGHT_CHECK = 20
|
local HEIGHT_CHECK = 30
|
||||||
|
local BLUR_ITERATIONS = 8
|
||||||
local c_air = minetest.get_content_id("air")
|
local c_air = minetest.get_content_id("air")
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ local function get_ground(data, area, pos, max_height, cache_c, get_contents)
|
||||||
local rel_surface -- Relative height of surface
|
local rel_surface -- Relative height of surface
|
||||||
|
|
||||||
-- Find the ground height (check downwards)
|
-- Find the ground height (check downwards)
|
||||||
for y = 0, -max_height, -1 do
|
for y = 0, -max_height + 4, -1 do
|
||||||
local c_id = data[area:index(pos.x, pos.y + y, pos.z)]
|
local c_id = data[area:index(pos.x, pos.y + y, pos.z)]
|
||||||
local is_surface_content = check_surface_content(c_id, cache_c)
|
local is_surface_content = check_surface_content(c_id, cache_c)
|
||||||
id_cache[y] = { c_id, is_surface_content }
|
id_cache[y] = { c_id, is_surface_content }
|
||||||
|
@ -51,13 +52,15 @@ local function get_ground(data, area, pos, max_height, cache_c, get_contents)
|
||||||
|
|
||||||
if not rel_surface then
|
if not rel_surface then
|
||||||
-- Check upper area
|
-- Check upper area
|
||||||
for y = 1, max_height do
|
for y = max_height - 1, 0, -1 do
|
||||||
local c_id = data[area:index(pos.x, pos.y + y, pos.z)]
|
local c_id = data[area:index(pos.x, pos.y + y, pos.z)]
|
||||||
local is_surface_content = check_surface_content(c_id, cache_c)
|
local is_surface_content = check_surface_content(c_id, cache_c)
|
||||||
id_cache[y] = { c_id, is_surface_content }
|
id_cache[y] = { c_id, is_surface_content }
|
||||||
|
|
||||||
if not is_surface_content and c_id ~= c_air then
|
if is_surface_content then
|
||||||
rel_surface = y - 1
|
if y ~= max_height - 1 then
|
||||||
|
rel_surface = y
|
||||||
|
end
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -92,9 +95,21 @@ local function get_ground(data, area, pos, max_height, cache_c, get_contents)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Stretch the node above if it's air, a liquid, tree etc.
|
||||||
|
local c_above
|
||||||
|
local c_id = id_cache[rel_surface + 1][1]
|
||||||
|
local name = minetest.get_name_from_content_id(c_id)
|
||||||
|
local def = minetest.registered_nodes[name]
|
||||||
|
if def and (def.drawtype == "normal"
|
||||||
|
or def.drawtype == "airlike"
|
||||||
|
or def.drawtype == "liquid") then
|
||||||
|
c_above = c_id
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rel_surface = rel_surface,
|
rel_surface = rel_surface,
|
||||||
c_contents = c_contents
|
c_contents = c_contents,
|
||||||
|
c_above = (c_above or c_air)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -113,6 +128,7 @@ local function flatten(ppos, radius)
|
||||||
local emin, emax = vm:read_from_map(minp, maxp)
|
local emin, emax = vm:read_from_map(minp, maxp)
|
||||||
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
|
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
|
||||||
local data = vm:get_data()
|
local data = vm:get_data()
|
||||||
|
local sidelen = maxp.x - minp.x + 1
|
||||||
|
|
||||||
-- Lookup table for content ID groups
|
-- Lookup table for content ID groups
|
||||||
local cache_c = {}
|
local cache_c = {}
|
||||||
|
@ -120,20 +136,20 @@ local function flatten(ppos, radius)
|
||||||
for z = minp.z, maxp.z do
|
for z = minp.z, maxp.z do
|
||||||
for x = minp.x, maxp.x do
|
for x = minp.x, maxp.x do
|
||||||
local ground = get_ground(
|
local ground = get_ground(
|
||||||
data,
|
data,
|
||||||
area,
|
area,
|
||||||
vector.new(x, ppos.y, z),
|
vector.new(x, ppos.y, z),
|
||||||
max_height,
|
max_height,
|
||||||
cache_c,
|
cache_c,
|
||||||
math.abs(x - ppos.x) <= radius and math.abs(z - ppos.z) <= radius
|
math.abs(x - ppos.x) <= radius and math.abs(z - ppos.z) <= radius
|
||||||
)
|
)
|
||||||
heightmap[z * 0x10000 + x] = ground
|
heightmap[(z - minp.z) * sidelen + (x - minp.x)] = ground
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get the relative height from the heightmap with relative coordinates
|
-- Get the relative height from the heightmap with relative coordinates
|
||||||
local get_height = function(map, x, z, fallback)
|
local get_height = function(map, x, z, fallback)
|
||||||
local info = map[z * 0x10000 + x]
|
local info = map[(z - minp.z) * sidelen + (x - minp.x)]
|
||||||
if info and info.rel_surface then
|
if info and info.rel_surface then
|
||||||
return info.rel_surface
|
return info.rel_surface
|
||||||
end
|
end
|
||||||
|
@ -141,14 +157,15 @@ local function flatten(ppos, radius)
|
||||||
end
|
end
|
||||||
|
|
||||||
local _dirty_ = false
|
local _dirty_ = false
|
||||||
local E = 1 -- effect width
|
|
||||||
|
|
||||||
-- Apply blur filter on each position and update the nodes
|
-- Apply blur filter on each position and update the nodes
|
||||||
for z = minp.z + E, maxp.z - E do
|
for n = 0, BLUR_ITERATIONS do
|
||||||
for x = minp.x + E, maxp.x - E do
|
for z = minp.z + 1, maxp.z - 1 do
|
||||||
local p_info = heightmap[z * 0x10000 + x]
|
for x = minp.x + 1, maxp.x - 1 do
|
||||||
|
local p_info = heightmap[(z - minp.z) * sidelen + (x - minp.x)]
|
||||||
local nodes = p_info.c_contents
|
local nodes = p_info.c_contents
|
||||||
local old_h = p_info.rel_surface
|
local old_h = p_info.rel_surface
|
||||||
|
local above = p_info.c_above
|
||||||
|
|
||||||
if nodes and #nodes > 0 and old_h then
|
if nodes and #nodes > 0 and old_h then
|
||||||
--[[
|
--[[
|
||||||
|
@ -159,15 +176,15 @@ local function flatten(ppos, radius)
|
||||||
+----+----+----+ -> 13
|
+----+----+----+ -> 13
|
||||||
]]
|
]]
|
||||||
local h = old_h + (
|
local h = old_h + (
|
||||||
get_height(heightmap, x , z - E, old_h)
|
get_height(heightmap, x , z - 1, old_h)
|
||||||
+ get_height(heightmap, x - E, z , old_h)
|
+ get_height(heightmap, x - 1, z , old_h)
|
||||||
+ get_height(heightmap, x + E, z , old_h)
|
+ get_height(heightmap, x + 1, z , old_h)
|
||||||
+ get_height(heightmap, x , z + E, old_h)
|
+ get_height(heightmap, x , z + 1, old_h)
|
||||||
) * 2 + (
|
) * 2 + (
|
||||||
get_height(heightmap, x - E, z - E, old_h)
|
get_height(heightmap, x - 1, z - 1, old_h)
|
||||||
+ get_height(heightmap, x + E, z - E, old_h)
|
+ get_height(heightmap, x + 1, z - 1, old_h)
|
||||||
+ get_height(heightmap, x - E, z + E, old_h)
|
+ get_height(heightmap, x - 1, z + 1, old_h)
|
||||||
+ get_height(heightmap, x + E, z + E, old_h)
|
+ get_height(heightmap, x + 1, z + 1, old_h)
|
||||||
)
|
)
|
||||||
|
|
||||||
h = math.floor(h / 13 + 0.5)
|
h = math.floor(h / 13 + 0.5)
|
||||||
|
@ -179,7 +196,11 @@ local function flatten(ppos, radius)
|
||||||
for y = max_y, min_y, -1 do
|
for y = max_y, min_y, -1 do
|
||||||
local vi = area:index(x, ppos.y + y, z)
|
local vi = area:index(x, ppos.y + y, z)
|
||||||
if y > h then
|
if y > h then
|
||||||
data[vi] = c_air
|
if h > old_h then
|
||||||
|
data[vi] = c_air
|
||||||
|
else
|
||||||
|
data[vi] = above
|
||||||
|
end
|
||||||
else
|
else
|
||||||
data[vi] = nodes[math.min(#nodes, i)]
|
data[vi] = nodes[math.min(#nodes, i)]
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
@ -190,6 +211,7 @@ local function flatten(ppos, radius)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if not _dirty_ then
|
if not _dirty_ then
|
||||||
return
|
return
|
||||||
|
@ -207,8 +229,8 @@ minetest.register_chatcommand("flat", {
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
local player = minetest.get_player_by_name(name)
|
local player = minetest.get_player_by_name(name)
|
||||||
local player_pos = vector.round(player:getpos())
|
local player_pos = vector.round(player:getpos())
|
||||||
-- Flatten an area of (2 * 6 + 1) ^ 2 m
|
-- Flatten an area of (2 * 7 + 1) ^ 2 square meters
|
||||||
flatten(player_pos, 6)
|
flatten(player_pos, 7)
|
||||||
return true, "OK."
|
return true, "OK."
|
||||||
end
|
end
|
||||||
})
|
})
|
|
@ -1,5 +1,7 @@
|
||||||
People can't plant
|
People can't plant
|
||||||
====================
|
====================
|
||||||
|
This mod automatically plants dropped sapling items.
|
||||||
|
|
||||||
|
|
||||||
Depends: none!
|
Depends: none!
|
||||||
|
|
||||||
|
@ -7,4 +9,4 @@ Depends: none!
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Source code:
|
Source code:
|
||||||
LGPL 2.1
|
CC0
|
|
@ -1,13 +1,8 @@
|
||||||
-- peoplecantplant - Plant saplings when touching the ground
|
-- peoplecantplant - Plant saplings when they touch the ground
|
||||||
-- Contains code fragments from builtin/game/item_entity.lua
|
|
||||||
|
|
||||||
|
|
||||||
-- Function that gets called when the builtin item stops
|
-- Function that gets called when the builtin item stops
|
||||||
function builtin_item_stopped(self, pos_below, node)
|
function builtin_item_stopped(self)
|
||||||
if minetest.get_item_group(node.name, "soil") == 0 then
|
|
||||||
return -- Not soil
|
|
||||||
end
|
|
||||||
|
|
||||||
local stack = ItemStack(self.itemstring)
|
local stack = ItemStack(self.itemstring)
|
||||||
if stack:get_count() > 1 then
|
if stack:get_count() > 1 then
|
||||||
return -- Obviously dropped by someone (more than 1 item on the stack)
|
return -- Obviously dropped by someone (more than 1 item on the stack)
|
||||||
|
@ -18,82 +13,54 @@ function builtin_item_stopped(self, pos_below, node)
|
||||||
return -- It is not a sapling
|
return -- It is not a sapling
|
||||||
end
|
end
|
||||||
|
|
||||||
if minetest.is_protected(pos_below, ":nobody") then
|
local pos = vector.round(self.object:get_pos())
|
||||||
|
local pos_below = vector.new(pos)
|
||||||
|
pos_below.y = pos_below.y - 1
|
||||||
|
|
||||||
|
if minetest.is_protected(pos, ":nobody") then
|
||||||
return -- The area is protected by someone
|
return -- The area is protected by someone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local node_below = minetest.get_node(pos_below)
|
||||||
|
if minetest.get_item_group(node_below.name, "soil") == 0 then
|
||||||
|
return -- Not soil
|
||||||
|
end
|
||||||
|
|
||||||
if minetest.find_node_near(pos_below, 3, {"group:sapling", "group:tree"}) then
|
if minetest.find_node_near(pos_below, 3, {"group:sapling", "group:tree"}) then
|
||||||
return -- There's another tree around, prevent jungle
|
return -- There's another tree around, prevent jungle
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Using 'pos = pos_below' would not allow us to modify the tables seperately,
|
local node = minetest.get_node(pos).name
|
||||||
-- thus make a copy of it with vector.new
|
-- Get node definition to decide whether to replace or not
|
||||||
local pos = vector.new(pos_below)
|
-- fallback to empty table when it's an unknown node
|
||||||
pos.y = pos.y + 1
|
local nodedef = minetest.registered_nodes[node] or {}
|
||||||
|
if not nodedef.buildable_to then
|
||||||
if minetest.get_node(pos).name ~= "air" then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
minetest.set_node(pos, {name = item})
|
minetest.set_node(pos, {name = item})
|
||||||
self.itemstring = ""
|
self.itemstring = ""
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
return true -- Success!
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Lifespan of an entity, default it to 900 on fail
|
|
||||||
local time_to_live = tonumber(minetest.setting_get("item_entity_ttl")) or 900
|
|
||||||
|
|
||||||
-- Overwrite "on_step" in the entity that's used for dropped items
|
-- Overwrite "on_step" in the entity that's used for dropped items
|
||||||
minetest.registered_entities["__builtin:item"].on_step = function(self, dtime)
|
local entity_def = minetest.registered_entities["__builtin:item"]
|
||||||
self.age = self.age + dtime
|
local old_step = entity_def.on_step
|
||||||
if time_to_live > 0 and self.age > time_to_live then
|
entity_def.on_step = function(self, dtime, ...)
|
||||||
-- Item expired, remove it
|
local old_acc = self.object:get_acceleration()
|
||||||
self.itemstring = ""
|
old_step(self, dtime, ...)
|
||||||
self.object:remove()
|
|
||||||
return
|
if self.itemstring == "" or not self.object:get_pos() then
|
||||||
|
return -- Item is removed
|
||||||
|
end
|
||||||
|
if vector.equals(old_acc, {x=0, y=0, z=0}) then
|
||||||
|
return -- No motion change
|
||||||
end
|
end
|
||||||
|
|
||||||
local p = self.object:getpos()
|
-- Acceleration defines in this case whether it's moving or not
|
||||||
p.y = p.y - 0.5
|
local new_acc = self.object:get_acceleration()
|
||||||
local node = minetest.get_node(p)
|
if vector.equals(new_acc, {x=0, y=0, z=0}) then
|
||||||
local def = minetest.registered_nodes[node.name]
|
-- Not moving: Try to place on node below
|
||||||
-- Ignore is walkable, so let it stop until the stuff below loaded
|
builtin_item_stopped(self)
|
||||||
local entity_fall = (def and not def.walkable)
|
|
||||||
|
|
||||||
if self.physical_state == entity_fall then
|
|
||||||
return -- State didn't change, don't do anything
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Different to previous state - resetting the velocity doesn't hurt anything
|
|
||||||
self.object:setvelocity({x=0, y=0, z=0})
|
|
||||||
if entity_fall then
|
|
||||||
-- Entity is falling: downwards acceleration of earth
|
|
||||||
self.object:setacceleration({x=0, y=-9.81, z=0})
|
|
||||||
else
|
|
||||||
-- Entity stopped, call our magic planting function
|
|
||||||
local success = builtin_item_stopped(self, vector.round(p), node)
|
|
||||||
if success then
|
|
||||||
return -- The entity doesn't exist anymore when our function was successful
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Code from the original __builtin:item, get surrounding objects
|
|
||||||
local own_stack = ItemStack(self.itemstring)
|
|
||||||
for _, object in ipairs(minetest.get_objects_inside_radius(p, 0.8)) do
|
|
||||||
local obj = object:get_luaentity()
|
|
||||||
if obj and obj.name == "__builtin:item"
|
|
||||||
and obj.physical_state == false then
|
|
||||||
-- Try to merge the items around with this one
|
|
||||||
if self:try_merge_with(own_stack, object, obj) then
|
|
||||||
return -- Item was removed/replaced
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.object:setacceleration({x=0, y=0, z=0})
|
|
||||||
end
|
|
||||||
|
|
||||||
self.physical_state = entity_fall
|
|
||||||
self.object:set_properties({
|
|
||||||
physical = entity_fall
|
|
||||||
})
|
|
||||||
end
|
end
|
Loading…
Reference in New Issue