mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
Fix seg fault if popping from empty stack (L-system trees)
See: https://github.com/minetest/minetest/issues/1525 Background Wuzzy2: If you attempt to spawn a L-system tree with minetest.spawn_tree, you can make Minetest crash if it is attempted to pop an empty stack. ShadowNinja: This shouldn't cause a segmentation fault, but it should throw a Lua error Commit Description This commit throws a Lua error instead of causing a segmentation fault. The server will still "crash" but will include a Lua backtrace. L-Systems fix randomness Unless a random seed is provided (via Lua treedef) seed the PRNG with a different seed for each tree Resolves: https://github.com/minetest/minetest/issues/1469 Fix l-system crash when treedef random_level not set by Lua
This commit is contained in:
parent
996ea60642
commit
f33d31693e
@ -2208,7 +2208,7 @@ treedef={
|
|||||||
thin_branches, - boolean true -> use thin (1 node) branches
|
thin_branches, - boolean true -> use thin (1 node) branches
|
||||||
fruit, - string fruit node name
|
fruit, - string fruit node name
|
||||||
fruit_chance, - num chance (0-100) to replace leaves with fruit node
|
fruit_chance, - num chance (0-100) to replace leaves with fruit node
|
||||||
seed, - num random seed
|
seed, - num random seed; if no seed is provided, the engine will create one
|
||||||
}
|
}
|
||||||
|
|
||||||
Key for Special L-System Symbols used in Axioms
|
Key for Special L-System Symbols used in Axioms
|
||||||
|
@ -747,7 +747,8 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
|
|||||||
}
|
}
|
||||||
getintfield(L, 2, "angle", tree_def.angle);
|
getintfield(L, 2, "angle", tree_def.angle);
|
||||||
getintfield(L, 2, "iterations", tree_def.iterations);
|
getintfield(L, 2, "iterations", tree_def.iterations);
|
||||||
getintfield(L, 2, "random_level", tree_def.iterations_random_level);
|
if (!getintfield(L, 2, "random_level", tree_def.iterations_random_level))
|
||||||
|
tree_def.iterations_random_level = 0;
|
||||||
getstringfield(L, 2, "trunk_type", tree_def.trunk_type);
|
getstringfield(L, 2, "trunk_type", tree_def.trunk_type);
|
||||||
getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
|
getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
|
||||||
tree_def.fruit_chance=0;
|
tree_def.fruit_chance=0;
|
||||||
@ -757,11 +758,20 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
|
|||||||
tree_def.fruitnode=ndef->getId(fruit);
|
tree_def.fruitnode=ndef->getId(fruit);
|
||||||
getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
|
getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
|
||||||
}
|
}
|
||||||
getintfield(L, 2, "seed", tree_def.seed);
|
tree_def.explicit_seed = getintfield(L, 2, "seed", tree_def.seed);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
treegen::spawn_ltree (env, p0, ndef, tree_def);
|
|
||||||
|
treegen::error e;
|
||||||
|
if ((e = treegen::spawn_ltree (env, p0, ndef, tree_def)) != treegen::SUCCESS) {
|
||||||
|
if (e == treegen::UNBALANCED_BRACKETS) {
|
||||||
|
luaL_error(L, "spawn_tree(): closing ']' has no matching opening bracket");
|
||||||
|
} else {
|
||||||
|
luaL_error(L, "spawn_tree(): unknown error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,14 +118,19 @@ void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// L-System tree LUA spawner
|
// L-System tree LUA spawner
|
||||||
void spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition)
|
treegen::error spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition)
|
||||||
{
|
{
|
||||||
ServerMap *map = &env->getServerMap();
|
ServerMap *map = &env->getServerMap();
|
||||||
std::map<v3s16, MapBlock*> modified_blocks;
|
std::map<v3s16, MapBlock*> modified_blocks;
|
||||||
ManualMapVoxelManipulator vmanip(map);
|
ManualMapVoxelManipulator vmanip(map);
|
||||||
v3s16 tree_blockp = getNodeBlockPos(p0);
|
v3s16 tree_blockp = getNodeBlockPos(p0);
|
||||||
|
treegen::error e;
|
||||||
|
|
||||||
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,3,1));
|
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,3,1));
|
||||||
make_ltree (vmanip, p0, ndef, tree_definition);
|
e = make_ltree (vmanip, p0, ndef, tree_definition);
|
||||||
|
if (e != SUCCESS)
|
||||||
|
return e;
|
||||||
|
|
||||||
vmanip.blitBackAll(&modified_blocks);
|
vmanip.blitBackAll(&modified_blocks);
|
||||||
|
|
||||||
// update lighting
|
// update lighting
|
||||||
@ -142,15 +147,25 @@ void spawn_ltree(ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDe
|
|||||||
event.modified_blocks.insert(i->first);
|
event.modified_blocks.insert(i->first);
|
||||||
}
|
}
|
||||||
map->dispatchEvent(&event);
|
map->dispatchEvent(&event);
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//L-System tree generator
|
//L-System tree generator
|
||||||
void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
|
treegen::error make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
|
||||||
TreeDef tree_definition)
|
TreeDef tree_definition)
|
||||||
{
|
{
|
||||||
MapNode dirtnode(ndef->getId("mapgen_dirt"));
|
MapNode dirtnode(ndef->getId("mapgen_dirt"));
|
||||||
|
int seed;
|
||||||
|
if (tree_definition.explicit_seed)
|
||||||
|
{
|
||||||
|
seed = tree_definition.seed+14002;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
seed = p0.X*2 + p0.Y*4 + p0.Z; // use the tree position to seed PRNG
|
||||||
|
}
|
||||||
|
PseudoRandom ps(seed);
|
||||||
|
|
||||||
PseudoRandom ps(tree_definition.seed+14002);
|
|
||||||
// chance of inserting abcd rules
|
// chance of inserting abcd rules
|
||||||
double prop_a = 9;
|
double prop_a = 9;
|
||||||
double prop_b = 8;
|
double prop_b = 8;
|
||||||
@ -354,6 +369,8 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
|
|||||||
stack_position.push(position);
|
stack_position.push(position);
|
||||||
break;
|
break;
|
||||||
case ']':
|
case ']':
|
||||||
|
if (stack_orientation.empty())
|
||||||
|
return UNBALANCED_BRACKETS;
|
||||||
rotation=stack_orientation.top();
|
rotation=stack_orientation.top();
|
||||||
stack_orientation.pop();
|
stack_orientation.pop();
|
||||||
position=stack_position.top();
|
position=stack_position.top();
|
||||||
@ -393,6 +410,8 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
|
void tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0,
|
||||||
|
@ -30,6 +30,11 @@ class ServerEnvironment;
|
|||||||
|
|
||||||
namespace treegen {
|
namespace treegen {
|
||||||
|
|
||||||
|
enum error {
|
||||||
|
SUCCESS,
|
||||||
|
UNBALANCED_BRACKETS
|
||||||
|
};
|
||||||
|
|
||||||
struct TreeDef {
|
struct TreeDef {
|
||||||
std::string initial_axiom;
|
std::string initial_axiom;
|
||||||
std::string rules_a;
|
std::string rules_a;
|
||||||
@ -50,6 +55,7 @@ namespace treegen {
|
|||||||
MapNode fruitnode;
|
MapNode fruitnode;
|
||||||
int fruit_chance;
|
int fruit_chance;
|
||||||
int seed;
|
int seed;
|
||||||
|
bool explicit_seed;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add default tree
|
// Add default tree
|
||||||
@ -60,10 +66,10 @@ namespace treegen {
|
|||||||
INodeDefManager *ndef, int seed);
|
INodeDefManager *ndef, int seed);
|
||||||
|
|
||||||
// Add L-Systems tree (used by engine)
|
// Add L-Systems tree (used by engine)
|
||||||
void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
|
treegen::error make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef,
|
||||||
TreeDef tree_definition);
|
TreeDef tree_definition);
|
||||||
// Spawn L-systems tree from LUA
|
// Spawn L-systems tree from LUA
|
||||||
void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef,
|
treegen::error spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef,
|
||||||
TreeDef tree_definition);
|
TreeDef tree_definition);
|
||||||
|
|
||||||
// L-System tree gen helper functions
|
// L-System tree gen helper functions
|
||||||
|
Loading…
Reference in New Issue
Block a user