diff --git a/builtin/item.lua b/builtin/item.lua index 80c665c99..acc1e6262 100644 --- a/builtin/item.lua +++ b/builtin/item.lua @@ -192,11 +192,15 @@ function minetest.item_place_node(itemstack, placer, pointed_thing) -- Add node and update minetest.env:add_node(place_to, newnode) + local take_item = true + -- Run callback if def.after_place_node then -- Copy place_to because callback can modify it local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z} - def.after_place_node(place_to_copy, placer) + if def.after_place_node(place_to_copy, placer, itemstack) then + take_item = false + end end -- Run script hook @@ -206,10 +210,14 @@ function minetest.item_place_node(itemstack, placer, pointed_thing) local place_to_copy = {x=place_to.x, y=place_to.y, z=place_to.z} local newnode_copy = {name=newnode.name, param1=newnode.param1, param2=newnode.param2} local oldnode_copy = {name=oldnode.name, param1=oldnode.param1, param2=oldnode.param2} - callback(place_to_copy, newnode_copy, placer, oldnode_copy) + if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack) then + take_item = false + end end - itemstack:take_item() + if take_item then + itemstack:take_item() + end return itemstack end diff --git a/cmake/Modules/FindCURL.cmake b/cmake/Modules/FindCURL.cmake index ec0503fd9..3644d192e 100644 --- a/cmake/Modules/FindCURL.cmake +++ b/cmake/Modules/FindCURL.cmake @@ -5,13 +5,38 @@ # CURL_LIBRARY - List of libraries when using curl. # CURL_FOUND - True if curl found. -# Look for the header file. -FIND_PATH(CURL_INCLUDE_DIR NAMES curl/curl.h) +if( UNIX ) + FIND_PATH(CURL_INCLUDE_DIR NAMES curl.h + PATHS + /usr/local/include/curl + /usr/include/curl + ) -# Look for the library. -FIND_LIBRARY(CURL_LIBRARY NAMES curl) + FIND_LIBRARY(CURL_LIBRARY NAMES curl + PATHS + /usr/local/lib + /usr/lib + ) +else( UNIX ) + FIND_PATH(CURL_INCLUDE_DIR NAMES curl/curl.h) # Look for the header file. + FIND_LIBRARY(CURL_LIBRARY NAMES curl) # Look for the library. + INCLUDE(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE if + FIND_PACKAGE_HANDLE_STANDARD_ARGS(CURL DEFAULT_MSG CURL_LIBRARY CURL_INCLUDE_DIR) # all listed variables are TRUE +endif( UNIX ) -# handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(CURL DEFAULT_MSG CURL_LIBRARY CURL_INCLUDE_DIR) +if( WIN32 ) + if( CURL_LIBRARY AND CURL_INCLUDE_DIR AND CURL_DLL ) # libcurl.dll is required on Windows + SET(CURL_FOUND TRUE) + else( CURL_LIBRARY AND CURL_INCLUDE_DIR AND CURL_DLL ) + SET(CURL_FOUND FALSE) + endif( CURL_LIBRARY AND CURL_INCLUDE_DIR AND CURL_DLL ) +else ( WIN32 ) + if( CURL_LIBRARY AND CURL_INCLUDE_DIR ) + SET(CURL_FOUND TRUE) + else( CURL_LIBRARY AND CURL_INCLUDE_DIR ) + SET(CURL_FOUND FALSE) + endif( CURL_LIBRARY AND CURL_INCLUDE_DIR ) +endif ( WIN32 ) + +MESSAGE(STATUS "CURL_INCLUDE_DIR = ${CURL_INCLUDE_DIR}") +MESSAGE(STATUS "CURL_LIBRARY = ${CURL_LIBRARY}") diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 60d1b2cb9..117d4b24e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -810,8 +810,9 @@ minetest.register_on_shutdown(func()) ^ WARNING: If the server terminates abnormally (i.e. crashes), the registered callbacks WILL LIKELY NOT BE RUN. Data should be saved at semi-frequent intervals as well as on server shutdown. -minetest.register_on_placenode(func(pos, newnode, placer, oldnode)) +minetest.register_on_placenode(func(pos, newnode, placer, oldnode, itemstack)) ^ Called when a node has been placed +^ If return true no item is taken from itemstack ^ Deprecated: Use on_construct or after_place_node in node definition instead minetest.register_on_dignode(func(pos, oldnode, digger)) ^ Called when a node has been dug. @@ -1062,6 +1063,60 @@ methods: ^ Return world-specific perlin noise (int(worldseed)+seeddiff) - clear_objects() ^ clear all objects in the environments +- spawn_tree (pos, {treedef}) + ^ spawns L-System tree at given pos with definition in treedef table + treedef={ + axiom, - string initial tree axiom + rules_a, - string rules set A + rules_b, - string rules set B + rules_c, - string rules set C + rules_d, - string rules set D + trunk, - string trunk node name + leaves, - string leaves node name + angle, - num angle in deg + iterations, - num max # of iterations, usually 2 -5 + random_level, - num factor to lower nr of iterations, usually 0 - 3 + thin_trunks, - boolean true -> use thin trunks + fruit_tree, - boolean true -> is a fruit tree + fruit - string fruit node name + } + + Key for Special L-System Symbols used in Axioms + G - move forward one unit with the pin down + F - move forward one unit with the pin up + A - replace with rules set A + B - replace with rules set B + C - replace with rules set C + D - replace with rules set D + a - replace with rules set A, chance 90% + b - replace with rules set B, chance 80% + c - replace with rules set C, chance 70% + d - replace with rules set D, chance 60% + + - yaw the turtle right by angle parameter + - - yaw the turtle left by angle parameter + & - pitch the turtle down by angle parameter + ^ - pitch the turtle up by angle parameter + / - roll the turtle to the right by angle parameter + * - roll the turtle to the left by angle parameter + [ - save in stack current state info + ] - recover from stack state info + + Example usage: spawn small apple tree + apple_tree={ + axiom="FFFFFAFFBF", + rules_a="[&&&FFFFF&&FFFF][&&&++++FFFFF&&FFFF][&&&----FFFFF&&FFFF]", + rules_b="[&&&++FFFFF&&FFFF][&&&--FFFFF&&FFFF][&&&------FFFFF&&FFFF]", + trunk="default:tree", + leaves="default:leaves", + angle=30, + iterations=2, + random_level=0, + thin_trunks=true, + fruit_tree=true, + fruit="default:apple" + } + minetest.env:spawn_tree(pos,apple_tree) + Deprecated: - add_rat(pos): Add C++ rat object (no-op) - add_firefly(pos): Add C++ firefly object (no-op) @@ -1405,9 +1460,10 @@ Node definition (register_node) ^ Node destructor; always called after removing node ^ default: nil - after_place_node = func(pos, placer), + after_place_node = func(pos, placer, itemstack), ^ Called after constructing node when node was placed using minetest.item_place_node / minetest.env:place_node + ^ If return true no item is taken from itemstack ^ default: nil after_dig_node = func(pos, oldnode, oldmetadata, digger), ^ oldmetadata is in table format diff --git a/minetest.conf.example b/minetest.conf.example index e80991936..34a2acebc 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -124,6 +124,12 @@ #console_color = (0,0,0) # In-game chat console background alpha (opaqueness, between 0 and 255) #console_alpha = 200 +# Selection box border color (R,G,B) +#selectionbox_color = (0,0,0) +# Crosshair color (R,G,B) +#crosshair_color = (255,255,255) +# Cross alpha (opaqueness, between 0 and 255) +#crosshair_alpha = 255 # Sound settings #enable_sound = true #sound_volume = 0.7 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 38410f7d2..5e1bfd65d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,7 +12,9 @@ if (NOT ENABLE_CURL) mark_as_advanced(CLEAR CURL_LIBRARY CURL_INCLUDE_DIR) endif(NOT ENABLE_CURL) -find_package(CURL) +if( ENABLE_CURL ) + find_package(CURL) +endif( ENABLE_CURL ) set(USE_CURL 0) if (CURL_FOUND AND ENABLE_CURL) message(STATUS "cURL support enabled") @@ -186,6 +188,7 @@ set(common_SRCS log.cpp content_sao.cpp mapgen.cpp + treegen.cpp content_nodemeta.cpp content_mapnode.cpp collision.cpp @@ -436,6 +439,9 @@ if(WIN32) if(VORBISFILE_DLL) install(FILES ${VORBISFILE_DLL} DESTINATION ${BINDIR}) endif() + if(CURL_DLL) + install(FILES ${CURL_DLL} DESTINATION ${BINDIR}) + endif() endif() endif() diff --git a/src/client.cpp b/src/client.cpp index c5d3b91c8..cb7afe29f 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -236,6 +236,7 @@ void * MediaFetchThread::Thread() i != m_file_requests.end(); i++) { curl = curl_easy_init(); assert(curl); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_URL, (m_remote_url + i->name).c_str()); curl_easy_setopt(curl, CURLOPT_FAILONERROR, true); std::ostringstream stream; diff --git a/src/content_abm.cpp b/src/content_abm.cpp index 12dbeea8e..0d0f0dedb 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_sao.h" #include "settings.h" #include "mapblock.h" // For getNodeBlockPos -#include "mapgen.h" // For mapgen::make_tree +#include "treegen.h" // For treegen::make_tree #include "map.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -118,7 +118,7 @@ public: v3s16 tree_blockp = getNodeBlockPos(tree_p); vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1)); bool is_apple_tree = myrand()%4 == 0; - mapgen::make_tree(vmanip, tree_p, is_apple_tree, ndef); + treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef); vmanip.blitBackAll(&modified_blocks); // update lighting diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 8916b4926..196c10e61 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -356,8 +356,11 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, m_last_sent_position_timer(0), m_last_sent_move_precision(0), m_armor_groups_sent(false), + m_animation_speed(0), + m_animation_blend(0), m_animation_sent(false), m_bone_position_sent(false), + m_attachment_parent_id(0), m_attachment_sent(false) { // Only register type if no environment supplied diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 7cb781276..f9c942590 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -108,6 +108,9 @@ void set_default_settings(Settings *settings) settings->setDefault("opaque_water", "false"); settings->setDefault("console_color", "(0,0,0)"); settings->setDefault("console_alpha", "200"); + settings->setDefault("selectionbox_color", "(0,0,0)"); + settings->setDefault("crosshair_color", "(255,255,255)"); + settings->setDefault("crosshair_alpha", "255"); settings->setDefault("enable_sound", "true"); settings->setDefault("sound_volume", "0.8"); settings->setDefault("desynchronize_mapblock_texture_animation", "true"); diff --git a/src/game.cpp b/src/game.cpp index dbb71369f..541127f5d 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2920,6 +2920,11 @@ void the_game( if(show_hud) { + v3f selectionbox_color = g_settings->getV3F("selectionbox_color"); + u32 selectionbox_color_r = rangelim(myround(selectionbox_color.X), 0, 255); + u32 selectionbox_color_g = rangelim(myround(selectionbox_color.Y), 0, 255); + u32 selectionbox_color_b = rangelim(myround(selectionbox_color.Z), 0, 255); + for(std::vector::const_iterator i = hilightboxes.begin(); i != hilightboxes.end(); i++) @@ -2929,7 +2934,7 @@ void the_game( <<" max=" <<"("<MaxEdge.X<<","<MaxEdge.Y<<","<MaxEdge.Z<<")" <draw3DBox(*i, video::SColor(255,0,0,0)); + driver->draw3DBox(*i, video::SColor(255,selectionbox_color_r,selectionbox_color_g,selectionbox_color_b)); } } @@ -2962,12 +2967,18 @@ void the_game( */ if(show_hud) { + v3f crosshair_color = g_settings->getV3F("crosshair_color"); + u32 crosshair_color_r = rangelim(myround(crosshair_color.X), 0, 255); + u32 crosshair_color_g = rangelim(myround(crosshair_color.Y), 0, 255); + u32 crosshair_color_b = rangelim(myround(crosshair_color.Z), 0, 255); + u32 crosshair_alpha = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255); + driver->draw2DLine(displaycenter - core::vector2d(10,0), displaycenter + core::vector2d(10,0), - video::SColor(255,255,255,255)); + video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b)); driver->draw2DLine(displaycenter - core::vector2d(0,10), displaycenter + core::vector2d(0,10), - video::SColor(255,255,255,255)); + video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b)); } } // timer diff --git a/src/irrlichttypes.h b/src/irrlichttypes.h index 82177299e..998992e05 100644 --- a/src/irrlichttypes.h +++ b/src/irrlichttypes.h @@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc., using namespace irr; +// Irrlicht 1.8+ defines 64bit unsigned symbol in irrTypes.h +#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) #ifdef _MSC_VER // Windows typedef unsigned long long u64; @@ -33,6 +35,7 @@ using namespace irr; typedef uint64_t u64; //typedef unsigned long long u64; #endif +#endif #endif diff --git a/src/keycode.cpp b/src/keycode.cpp index cdf3c6062..9aa9d300d 100644 --- a/src/keycode.cpp +++ b/src/keycode.cpp @@ -260,7 +260,7 @@ KeyPress::KeyPress(const char *name) try { Key = keyname_to_keycode(name); m_name = name; - if (strlen(name) > 8) { + if (strlen(name) > 8 && strncmp(name, "KEY_KEY_", 8) == 0) { int chars_read = mbtowc(&Char, name + 8, 1); assert (chars_read == 1 && "unexpected multibyte character"); } else diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 2a83ba956..751478213 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -399,13 +399,13 @@ void LocalPlayer::applyControl(float dtime) // Whether superspeed mode is used or not bool superspeed = false; - // If free movement and fast movement, always move fast - if(free_move && fast_move) - superspeed = true; - // Old descend control if(g_settings->getBool("aux1_descends")) { + // If free movement and fast movement, always move fast + if(free_move && fast_move) + superspeed = true; + // Auxiliary button 1 (E) if(control.aux1) { @@ -440,10 +440,9 @@ void LocalPlayer::applyControl(float dtime) // Auxiliary button 1 (E) if(control.aux1) { - if(!free_move && !is_climbing) + if(!is_climbing) { - // If not free movement but fast is allowed, aux1 is - // "Turbo button" + // aux1 is "Turbo button" if(fast_move) superspeed = true; } @@ -455,7 +454,7 @@ void LocalPlayer::applyControl(float dtime) { // In free movement mode, sneak descends v3f speed = getSpeed(); - if(fast_move) + if(fast_move && control.aux1) speed.Y = -20*BS; else speed.Y = -walkspeed_max; @@ -497,10 +496,20 @@ void LocalPlayer::applyControl(float dtime) if(free_move) { v3f speed = getSpeed(); - if(fast_move) - speed.Y = 20*BS; - else - speed.Y = walkspeed_max; + + if(g_settings->getBool("aux1_descends")) + { + if(fast_move) + speed.Y = 20*BS; + else + speed.Y = walkspeed_max; + } else { + if(fast_move && control.aux1) + speed.Y = 20*BS; + else + speed.Y = walkspeed_max; + } + setSpeed(speed); } else if(m_can_jump) @@ -548,7 +557,7 @@ void LocalPlayer::applyControl(float dtime) f32 inc = walk_acceleration * BS * dtime; // Faster acceleration if fast and free movement - if(free_move && fast_move) + if(free_move && fast_move && superspeed) inc = walk_acceleration * BS * dtime * 10; // Accelerate to target speed with maximum increment diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 782f00b62..ae0c551cb 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "voxelalgorithms.h" #include "profiler.h" #include "main.h" // For g_profiler +#include "treegen.h" namespace mapgen { @@ -120,174 +121,7 @@ static s16 find_stone_level(VoxelManipulator &vmanip, v2s16 p2d, } #endif -void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0, - bool is_apple_tree, INodeDefManager *ndef) -{ - MapNode treenode(ndef->getId("mapgen_tree")); - MapNode leavesnode(ndef->getId("mapgen_leaves")); - MapNode applenode(ndef->getId("mapgen_apple")); - - s16 trunk_h = myrand_range(4, 5); - v3s16 p1 = p0; - for(s16 ii=0; ii leaves_d(new u8[leaves_a.getVolume()]); - Buffer leaves_d(leaves_a.getVolume()); - for(s32 i=0; igetId("mapgen_jungletree")); - MapNode leavesnode(ndef->getId("mapgen_leaves")); - - for(s16 x=-1; x<=1; x++) - for(s16 z=-1; z<=1; z++) - { - if(myrand_range(0, 2) == 0) - continue; - v3s16 p1 = p0 + v3s16(x,0,z); - v3s16 p2 = p0 + v3s16(x,-1,z); - if(vmanip.m_area.contains(p2) - && vmanip.m_data[vmanip.m_area.index(p2)] == CONTENT_AIR) - vmanip.m_data[vmanip.m_area.index(p2)] = treenode; - else if(vmanip.m_area.contains(p1)) - vmanip.m_data[vmanip.m_area.index(p1)] = treenode; - } - - s16 trunk_h = myrand_range(8, 12); - v3s16 p1 = p0; - for(s16 ii=0; ii leaves_d(new u8[leaves_a.getVolume()]); - Buffer leaves_d(leaves_a.getVolume()); - for(s32 i=0; im_env; + if(env == NULL) return 0; + v3s16 p0 = read_v3s16(L, 2); + + treegen::TreeDef tree_def; + std::string trunk,leaves,fruit; + INodeDefManager *ndef = env->getGameDef()->ndef(); + + if(lua_istable(L, 3)) + { + getstringfield(L, 3, "axiom", tree_def.initial_axiom); + getstringfield(L, 3, "rules_a", tree_def.rules_a); + getstringfield(L, 3, "rules_b", tree_def.rules_b); + getstringfield(L, 3, "rules_c", tree_def.rules_a); + getstringfield(L, 3, "rules_d", tree_def.rules_b); + getstringfield(L, 3, "trunk", trunk); + tree_def.trunknode=ndef->getId(trunk); + getstringfield(L, 3, "leaves", leaves); + tree_def.leavesnode=ndef->getId(leaves); + getintfield(L, 3, "angle", tree_def.angle); + getintfield(L, 3, "iterations", tree_def.iterations); + getintfield(L, 3, "random_level", tree_def.iterations_random_level); + getboolfield(L, 3, "thin_trunks", tree_def.thin_trunks); + getboolfield(L, 3, "fruit_tree", tree_def.fruit_tree); + if (tree_def.fruit_tree) + { + getstringfield(L, 3, "fruit", fruit); + tree_def.fruitnode=ndef->getId(fruit); + } + } + else + return 0; + treegen::spawn_ltree (env, p0, ndef, tree_def); + return 1; + } + public: EnvRef(ServerEnvironment *env): m_env(env) @@ -4086,6 +4126,7 @@ const luaL_reg EnvRef::methods[] = { method(EnvRef, find_nodes_in_area), method(EnvRef, get_perlin), method(EnvRef, clear_objects), + method(EnvRef, spawn_tree), {0,0} }; diff --git a/src/treegen.cpp b/src/treegen.cpp new file mode 100644 index 000000000..54cee0fef --- /dev/null +++ b/src/treegen.cpp @@ -0,0 +1,520 @@ +/* +Minetest-c55 +Copyright (C) 2010-2012 celeron55, Perttu Ahola , + 2012 RealBadAngel, Maciej Kasatkin +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "irr_v3d.h" +#include +#include "util/numeric.h" +#include "util/mathconstants.h" +#include "noise.h" +#include "map.h" +#include "environment.h" +#include "nodedef.h" +#include "treegen.h" + +namespace treegen +{ + +void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0, + bool is_apple_tree, INodeDefManager *ndef) +{ + MapNode treenode(ndef->getId("mapgen_tree")); + MapNode leavesnode(ndef->getId("mapgen_leaves")); + MapNode applenode(ndef->getId("mapgen_apple")); + + s16 trunk_h = myrand_range(4, 5); + v3s16 p1 = p0; + for(s16 ii=0; ii leaves_d(new u8[leaves_a.getVolume()]); + Buffer leaves_d(leaves_a.getVolume()); + for(s32 i=0; igetServerMap(); + core::map modified_blocks; + ManualMapVoxelManipulator vmanip(map); + v3s16 tree_blockp = getNodeBlockPos(p0); + vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1)); + make_ltree (vmanip, p0, ndef, tree_definition); + vmanip.blitBackAll(&modified_blocks); + + // update lighting + core::map lighting_modified_blocks; + for(core::map::Iterator + i = modified_blocks.getIterator(); + i.atEnd() == false; i++) + { + lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue()); + } + map->updateLighting(lighting_modified_blocks, modified_blocks); + // Send a MEET_OTHER event + MapEditEvent event; + event.type = MEET_OTHER; + for(core::map::Iterator + i = modified_blocks.getIterator(); + i.atEnd() == false; i++) + { + v3s16 p = i.getNode()->getKey(); + event.modified_blocks.insert(p, true); + } + map->dispatchEvent(&event); +} + +//L-System tree generator +void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef, + TreeDef tree_definition) +{ + MapNode dirtnode(ndef->getId("mapgen_dirt")); + + // chance of inserting abcd rules + double prop_a = 9; + double prop_b = 8; + double prop_c = 7; + double prop_d = 6; + + //randomize tree growth level, minimum=2 + s16 iterations = tree_definition.iterations; + if (tree_definition.iterations_random_level>0) + iterations -= myrand_range(0,tree_definition.iterations_random_level); + if (iterations<2) + iterations=2; + + s16 MAX_ANGLE_OFFSET = 5; + double angle_in_radians = (double)tree_definition.angle*M_PI/180; + double angleOffset_in_radians = (s16)(myrand_range(0,1)%MAX_ANGLE_OFFSET)*M_PI/180; + + //initialize rotation matrix, position and stacks for branches + core::matrix4 rotation; + rotation=setRotationAxisRadians(rotation, M_PI/2,v3f(0,0,1)); + v3f position = v3f(0,0,0); + std::stack stack_orientation; + std::stack stack_position; + + //generate axiom + std::string axiom = tree_definition.initial_axiom; + for(s16 i=0; i= myrand_range(1,10)) + temp+=tree_definition.rules_a; + break; + case 'b': + if (prop_b >= myrand_range(1,10)) + temp+=tree_definition.rules_b; + break; + case 'c': + if (prop_c >= myrand_range(1,10)) + temp+=tree_definition.rules_c; + break; + case 'd': + if (prop_d >= myrand_range(1,10)) + temp+=tree_definition.rules_d; + break; + default: + temp+=axiom_char; + break; + } + } + axiom=temp; + } + + //make sure tree is not floating in the air + if (tree_definition.thin_trunks == false) + { + make_tree_node_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y-1,p0.Z+position.Z),dirtnode); + make_tree_node_placement(vmanip,v3f(p0.X+position.X-1,p0.Y+position.Y-1,p0.Z+position.Z),dirtnode); + make_tree_node_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y-1,p0.Z+position.Z+1),dirtnode); + make_tree_node_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y-1,p0.Z+position.Z-1),dirtnode); + } + + /* build tree out of generated axiom + + Key for Special L-System Symbols used in Axioms + + G - move forward one unit with the pin down + F - move forward one unit with the pin up + A - replace with rules set A + B - replace with rules set B + C - replace with rules set C + D - replace with rules set D + a - replace with rules set A, chance 90% + b - replace with rules set B, chance 80% + c - replace with rules set C, chance 70% + d - replace with rules set D, chance 60% + + - yaw the turtle right by angle degrees + - - yaw the turtle left by angle degrees + & - pitch the turtle down by angle degrees + ^ - pitch the turtle up by angle degrees + / - roll the turtle to the right by angle degrees + * - roll the turtle to the left by angle degrees + [ - save in stack current state info + ] - recover from stack state info + + */ + + s16 x,y,z; + for(s16 i=0; i<(s16)axiom.size(); i++) + { + char axiom_char = axiom.at(i); + core::matrix4 temp_rotation; + temp_rotation.makeIdentity(); + v3f dir; + switch (axiom_char) + { + case 'G': + dir = v3f(-1,0,0); + dir = transposeMatrix(rotation,dir); + position+=dir; + break; + case 'F': + make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z),tree_definition); + if (tree_definition.thin_trunks == false) + { + make_tree_trunk_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y,p0.Z+position.Z),tree_definition); + make_tree_trunk_placement(vmanip,v3f(p0.X+position.X-1,p0.Y+position.Y,p0.Z+position.Z),tree_definition); + make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z+1),tree_definition); + make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z-1),tree_definition); + } + if (stack_orientation.empty() == false) + { + s16 size = 1; + for(x=-size; x 90+tree_definition.iterations) + vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode; + else + vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.leavesnode; + } + else if (myrand_range(1,100) > 20) + vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.leavesnode; +} + +irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis) +{ + double c = cos(angle); + double s = sin(angle); + double t = 1.0 - c; + + double tx = t * axis.X; + double ty = t * axis.Y; + double tz = t * axis.Z; + double sx = s * axis.X; + double sy = s * axis.Y; + double sz = s * axis.Z; + + M[0] = tx * axis.X + c; + M[1] = tx * axis.Y + sz; + M[2] = tx * axis.Z - sy; + + M[4] = ty * axis.X - sz; + M[5] = ty * axis.Y + c; + M[6] = ty * axis.Z + sx; + + M[8] = tz * axis.X + sy; + M[9] = tz * axis.Y - sx; + M[10] = tz * axis.Z + c; + return M; +} + +v3f transposeMatrix(irr::core::matrix4 M, v3f v) +{ + v3f translated; + double x = M[0] * v.X + M[4] * v.Y + M[8] * v.Z +M[12]; + double y = M[1] * v.X + M[5] * v.Y + M[9] * v.Z +M[13]; + double z = M[2] * v.X + M[6] * v.Y + M[10] * v.Z +M[14]; + translated.X=x; + translated.Y=y; + translated.Z=z; + return translated; +} + +#if 0 +static void make_jungletree(VoxelManipulator &vmanip, v3s16 p0, + INodeDefManager *ndef) +{ + MapNode treenode(ndef->getId("mapgen_jungletree")); + MapNode leavesnode(ndef->getId("mapgen_leaves")); + + for(s16 x=-1; x<=1; x++) + for(s16 z=-1; z<=1; z++) + { + if(myrand_range(0, 2) == 0) + continue; + v3s16 p1 = p0 + v3s16(x,0,z); + v3s16 p2 = p0 + v3s16(x,-1,z); + if(vmanip.m_area.contains(p2) + && vmanip.m_data[vmanip.m_area.index(p2)] == CONTENT_AIR) + vmanip.m_data[vmanip.m_area.index(p2)] = treenode; + else if(vmanip.m_area.contains(p1)) + vmanip.m_data[vmanip.m_area.index(p1)] = treenode; + } + + s16 trunk_h = myrand_range(8, 12); + v3s16 p1 = p0; + for(s16 ii=0; ii leaves_d(new u8[leaves_a.getVolume()]); + Buffer leaves_d(leaves_a.getVolume()); + for(s32 i=0; i, + 2012 RealBadAngel, Maciej Kasatkin +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef TREEGEN_HEADER +#define TREEGEN_HEADER + +#include + +class ManualMapVoxelManipulator; +class INodeDefManager; + + +namespace treegen +{ + +struct TreeDef +{ +std::string initial_axiom; +std::string rules_a; +std::string rules_b; +std::string rules_c; +std::string rules_d; +MapNode trunknode; +MapNode leavesnode; +int angle; +int iterations; +int iterations_random_level; +bool thin_trunks; +bool fruit_tree; +MapNode fruitnode; +}; + + // Add default tree + void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0, + bool is_apple_tree, INodeDefManager *ndef); + + // Add L-Systems tree (used by engine) + void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *ndef, + TreeDef tree_definition); + // Spawn L-systems tree from LUA + void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeDef tree_definition); + + // L-System tree gen helper functions + void make_tree_node_placement(ManualMapVoxelManipulator &vmanip, v3f p0, + MapNode node); + void make_tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0, + TreeDef &tree_definition); + void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0, + TreeDef &tree_definition); + irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle,v3f axis); + + v3f transposeMatrix(irr::core::matrix4 M ,v3f v); + +}; // namespace treegen +#endif diff --git a/util/wireshark/minetest.lua b/util/wireshark/minetest.lua index de3e842a0..acc95e5f4 100644 --- a/util/wireshark/minetest.lua +++ b/util/wireshark/minetest.lua @@ -117,7 +117,7 @@ end do local f_count = ProtoField.uint8("minetest.client.gotblocks_count", "Count", base.DEC) - local f_block = ProtoField.bytes("minetset.client.gotblocks_block", "Block", base.DEC) + local f_block = ProtoField.bytes("minetest.client.gotblocks_block", "Block", base.DEC) local f_x = ProtoField.int16("minetest.client.gotblocks_x", "Block position X", base.DEC) local f_y = ProtoField.int16("minetest.client.gotblocks_y", "Block position Y", base.DEC) local f_z = ProtoField.int16("minetest.client.gotblocks_z", "Block position Z", base.DEC) @@ -151,7 +151,7 @@ end do local f_count = ProtoField.uint8("minetest.client.deletedblocks_count", "Count", base.DEC) - local f_block = ProtoField.bytes("minetset.client.deletedblocks_block", "Block", base.DEC) + local f_block = ProtoField.bytes("minetest.client.deletedblocks_block", "Block", base.DEC) local f_x = ProtoField.int16("minetest.client.deletedblocks_x", "Block position X", base.DEC) local f_y = ProtoField.int16("minetest.client.deletedblocks_y", "Block position Y", base.DEC) local f_z = ProtoField.int16("minetest.client.deletedblocks_z", "Block position Z", base.DEC)