aboutsummaryrefslogtreecommitdiff
path: root/src/script
Commit message (Collapse)AuthorAge
* Send only changed node metadata to clients instead of whole mapblock (#5268)SmallJoker2018-12-04
| | | | | | | Includes newer style changes and fixes by est31 Improve the block position de-serialization Add type NodeMetadataMap
* Move client-specific files to 'src/client' (#7902)Quentin Bazin2018-11-28
| | | | | Update Android.mk Remove 'src/client' from include_directories
* Clean up stack after script_get_backtrace (#7854)Michael Muller2018-11-28
| | | | | | | | script_get_backtrace() was leaving its return value on the stack, corrupting subsequent lua operations for functions that did not immediately return. This problem can specifically be observed in the case of multiple "groupcaps" entries, each of which provides the legacy "maxwear" property. These cause a backtrace and thus pollute the stack for the following lua_next() call.
* Add Lua methods 'set_rotation()' and 'get_rotation()' (#7395)CoderForTheBetter2018-11-28
| | | | * Adds Lua methods 'set_rotation()' and 'get_rotation'. Also changed some method names to be more clear. Instead of an f32 being sent over network for yaw, now a v3f is sent for rotation on xyz axes. Perserved Lua method set_yaw/setyaw so that old mods still work, other wise to set yaw they would need to switch to set_rotation(0, yaw, 0).
* Content store: Add setting to filter non-free packages (#7766)rubenwardy2018-11-08
| | | | Defaulting to hiding in order to help with Debian/etc distribution. This could be changed at a later date.
* clear_craft: Return false if recipe not found, don't throw error (#7804)Paramat2018-10-24
|
* Add core.remove_detached_inventory (#7684)SmallJoker2018-10-10
| | | | Breaks backwards compatibility for good Bump protocol version
* markAliasDeprecated: Fix MSVC buildSmallJoker2018-09-11
|
* Particles: Make collision with objects optional (#7682)Paramat2018-09-08
| | | | | | Also set it to false for node dig particles, as they are often created and high in number. Improve particle documentation.
* Raycast: export exact pointing location (#6304)Dániel Juhász2018-08-16
| | | | | * Return intersection point in node coordinates. * Clarify 'intersection_point' documentation
* Replace auth.txt with SQLite auth database (#7279)Ben Deutsch2018-08-05
| | | | * Replace auth.txt with SQLite auth database
* LuaVoxelManip: Throw warning or error instead of silently doing nothing (#7567)HybridDog2018-08-02
| | | | Error on missing parameter. Warning when using a method on the incorrect type of LuaVoxelManip.
* Add protocol_version and supported package types to ContentDB urlsrubenwardy2018-07-29
|
* Add a MSVC / Windows compatible snprintf function (#7353)nOOb31672018-07-22
| | | Use sizeof where applicable for mt_snprintf
* Lua templating reading (part 4): s16, v2s16, v2f (#7512)Loïc Blot2018-07-08
|
* Log deprecated Lua function calls (#7491)SmallJoker2018-07-01
|
* Modernize lua read (part 2 & 3): C++ templating assurance (#7410)Loïc Blot2018-06-30
| | | | | | | | | * Modernize lua read (part 2 & 3): C++ templating assurance Implement the boolean reader Implement the string reader Also remove unused & unimplemented script_error_handler Add a reader with default value
* Fix memory leaks in mod storage (#7500)red-0012018-06-30
|
* Fix world deletion (#7494)Vitaliy2018-06-30
| | | | * Fix world deletion
* Fix a memleak before assertion in l_get_mod_storageLoic Blot2018-06-30
|
* Fix mod channels crash (#7481)red-0012018-06-27
|
* Rename CSM flavours to restrictionsSmallJoker2018-06-26
| | | | & Satisfy LINT
* Update to new ContentDB APIrubenwardy2018-06-18
|
* Fix narrow/utf8 difference in incoming/outcoming messagesnumber Zero2018-06-10
|
* CSM/SSM: Add on_mods_loaded callback (#7411)Loïc Blot2018-06-06
| | | | | * CSM/SSM: Add on_mods_loaded callback
* Modernize lua read (part 1): C++ templating insurance (#7394)Loïc Blot2018-06-04
| | | | | | | * Modernize lua read (part 1): C++ templating assurance Implement the float reader
* Fix isNan on setYaw Lua call (#7380)Loïc Blot2018-05-31
| | | | * Fix isNan on setYaw Lua call
* Fix missing ignore textures (#7326)you2018-05-20
|
* Add screenshots to online content browserrubenwardy2018-05-20
|
* Add updating to online content browserrubenwardy2018-05-16
|
* Fix segfault in player migration and crash in log_deprecatedSmallJoker2018-05-14
| | | | Makes log_deprecated work when triggered from no function
* Fix builtin inventory list crash when size = 0 (#7297)SmallJoker2018-05-05
|
* Allow damage for attached objects, add attach/detach callbacks (#6786)SmallJoker2018-04-30
| | | * Allow right-clicking on attached LuaEntities
* MetaDataRef: Add contains() and get() (#7214)rubenwardy2018-04-30
|
* Add online content repositoryrubenwardy2018-04-19
| | | | Replaces mods and texture pack tabs with a single content tab
* Biome API / dungeons: Add biome-defined dungeon nodesParamat2018-04-07
| | | | | | | | | | Add new biome fields 'node_dungeon', 'node_dungeon_alt', 'node_dungeon_stair'. If 'node_dungeon' is not defined dungeons fall back to classic behaviour. Remove messy and imprecise dungeon material code from 'generateBiomes()'. Code deciding dungeon materials is now in 'generateDungeons()' and uses the biome at mapchunk centre for more precision. Remove hardcoded 'MG_STONE' types as long intended.
* Add player:get_meta(), deprecate player attributes (#7202)rubenwardy2018-04-06
| | | | * Add player:get_meta(), deprecate player attributes
* Biome API / cavegen: Add definable cave liquid for a biome (#7192)Paramat2018-04-05
| | | | Add 'node_cave_liquid' as a new field in biome registration. If field is absent cave liquids fall back to classic behaviour.
* Fix last clang-tidy reported problems for performance-type-promotion-in-math-fnLoic Blot2018-04-03
| | | | | | Based on https://travis-ci.org/minetest/minetest/jobs/361810382 output Also fix 2 missing copyright notices
* Fix many issues reported by clang-tidy (#7189)Loïc Blot2018-04-02
| | | | | | | | | | | * Fix many issues reported by clang-tidy We have many issues in code related to some performance to float <-> double. Clang-tidy reported it in performance-type-promotion-in-math-fn I fixed many of them. It's not ready for a promote to blocking Also fix some value which should be const-ref
* Run callback in IDropAction, refactor function argumentsSmallJoker2018-04-02
|
* Add player inventory callbacksSmallJoker2018-04-02
|
* LINT: add clang-tidy step (#6295)Loïc Blot2018-04-01
| | | | | | | | | * Implement new travis clang-tidy build step * This step enable some rules and enforce one rule as error * This permits to have some C++ quality rules based on clang & clang contributor guidelines * Fix clang-tidy reported problems on push_back -> emplace_back
* ObjectRef: Add add_velocity() (#3208)you2018-03-31
| | | | Allow changing the velocity of objects relatively to their current velocity
* Optional alpha channel support for entitiesstujones112018-03-29
|
* Fix a warning reported by clangLoic Blot2018-03-29
| | | | | minetest/src/script/cpp_api/s_player.h:27:1: warning: struct 'PlayerHPChangeReason' was previously declared as a class [-Wmismatched-tags] struct PlayerHPChangeReason;
* Load dependencies and description from mod.confAndrew Ward2018-03-28
|
* Add reasons to on_dieplayer and on_hpchangeAndrew Ward2018-03-28
|
* Add formspec theming using prepended stringsAndrew Ward2018-03-28
|
* Mapgen: Remove unused mgv7 code and some unused biometypesParamat2018-03-26
|
box.MinEdge.Z + speed.Z * dtime < zsize) && (relbox.MaxEdge.Z + speed.Z * dtime > COLL_ZERO)) return 1; } else if(relbox.MinEdge.Y > ysize) { return -1; } } else if(speed.Y < 0) // Check for collision with Y+ plane { if(relbox.MinEdge.Y >= ysize - d) { dtime = (ysize - relbox.MinEdge.Y) / speed.Y; if((relbox.MinEdge.X + speed.X * dtime < xsize) && (relbox.MaxEdge.X + speed.X * dtime > COLL_ZERO) && (relbox.MinEdge.Z + speed.Z * dtime < zsize) && (relbox.MaxEdge.Z + speed.Z * dtime > COLL_ZERO)) return 1; } else if(relbox.MaxEdge.Y < 0) { return -1; } } // NO else if here if(speed.Z > 0) // Check for collision with Z- plane { if(relbox.MaxEdge.Z <= d) { dtime = - relbox.MaxEdge.Z / speed.Z; if((relbox.MinEdge.X + speed.X * dtime < xsize) && (relbox.MaxEdge.X + speed.X * dtime > COLL_ZERO) && (relbox.MinEdge.Y + speed.Y * dtime < ysize) && (relbox.MaxEdge.Y + speed.Y * dtime > COLL_ZERO)) return 2; } //else if(relbox.MinEdge.Z > zsize) //{ // return -1; //} } else if(speed.Z < 0) // Check for collision with Z+ plane { if(relbox.MinEdge.Z >= zsize - d) { dtime = (zsize - relbox.MinEdge.Z) / speed.Z; if((relbox.MinEdge.X + speed.X * dtime < xsize) && (relbox.MaxEdge.X + speed.X * dtime > COLL_ZERO) && (relbox.MinEdge.Y + speed.Y * dtime < ysize) && (relbox.MaxEdge.Y + speed.Y * dtime > COLL_ZERO)) return 2; } //else if(relbox.MaxEdge.Z < 0) //{ // return -1; //} } return -1; } // Helper function: // Checks if moving the movingbox up by the given distance would hit a ceiling. bool wouldCollideWithCeiling( const std::vector<aabb3f> &staticboxes, const aabb3f &movingbox, f32 y_increase, f32 d) { //TimeTaker tt("wouldCollideWithCeiling"); assert(y_increase >= 0); // pre-condition for(std::vector<aabb3f>::const_iterator i = staticboxes.begin(); i != staticboxes.end(); ++i) { const aabb3f& staticbox = *i; if((movingbox.MaxEdge.Y - d <= staticbox.MinEdge.Y) && (movingbox.MaxEdge.Y + y_increase > staticbox.MinEdge.Y) && (movingbox.MinEdge.X < staticbox.MaxEdge.X) && (movingbox.MaxEdge.X > staticbox.MinEdge.X) && (movingbox.MinEdge.Z < staticbox.MaxEdge.Z) && (movingbox.MaxEdge.Z > staticbox.MinEdge.Z)) return true; } return false; } collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, f32 pos_max_d, const aabb3f &box_0, f32 stepheight, f32 dtime, v3f &pos_f, v3f &speed_f, v3f &accel_f,ActiveObject* self, bool collideWithObjects) { Map *map = &env->getMap(); //TimeTaker tt("collisionMoveSimple"); ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG); collisionMoveResult result; /* Calculate new velocity */ if( dtime > 0.5 ) { warningstream<<"collisionMoveSimple: maximum step interval exceeded, lost movement details!"<<std::endl; dtime = 0.5; } speed_f += accel_f * dtime; // If there is no speed, there are no collisions if(speed_f.getLength() == 0) return result; // Limit speed for avoiding hangs speed_f.Y=rangelim(speed_f.Y,-5000,5000); speed_f.X=rangelim(speed_f.X,-5000,5000); speed_f.Z=rangelim(speed_f.Z,-5000,5000); /* Collect node boxes in movement range */ std::vector<aabb3f> cboxes; std::vector<bool> is_unloaded; std::vector<bool> is_step_up; std::vector<bool> is_object; std::vector<int> bouncy_values; std::vector<v3s16> node_positions; { //TimeTaker tt2("collisionMoveSimple collect boxes"); ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG); v3s16 oldpos_i = floatToInt(pos_f, BS); v3s16 newpos_i = floatToInt(pos_f + speed_f * dtime, BS); s16 min_x = MYMIN(oldpos_i.X, newpos_i.X) + (box_0.MinEdge.X / BS) - 1; s16 min_y = MYMIN(oldpos_i.Y, newpos_i.Y) + (box_0.MinEdge.Y / BS) - 1; s16 min_z = MYMIN(oldpos_i.Z, newpos_i.Z) + (box_0.MinEdge.Z / BS) - 1; s16 max_x = MYMAX(oldpos_i.X, newpos_i.X) + (box_0.MaxEdge.X / BS) + 1; s16 max_y = MYMAX(oldpos_i.Y, newpos_i.Y) + (box_0.MaxEdge.Y / BS) + 1; s16 max_z = MYMAX(oldpos_i.Z, newpos_i.Z) + (box_0.MaxEdge.Z / BS) + 1; bool any_position_valid = false; for(s16 x = min_x; x <= max_x; x++) for(s16 y = min_y; y <= max_y; y++) for(s16 z = min_z; z <= max_z; z++) { v3s16 p(x,y,z); bool is_position_valid; MapNode n = map->getNodeNoEx(p, &is_position_valid); if (is_position_valid) { // Object collides into walkable nodes any_position_valid = true; const ContentFeatures &f = gamedef->getNodeDefManager()->get(n); if(f.walkable == false) continue; int n_bouncy_value = itemgroup_get(f.groups, "bouncy"); std::vector<aabb3f> nodeboxes = n.getCollisionBoxes(gamedef->ndef()); for(std::vector<aabb3f>::iterator i = nodeboxes.begin(); i != nodeboxes.end(); ++i) { aabb3f box = *i; box.MinEdge += v3f(x, y, z)*BS; box.MaxEdge += v3f(x, y, z)*BS; cboxes.push_back(box); is_unloaded.push_back(false); is_step_up.push_back(false); bouncy_values.push_back(n_bouncy_value); node_positions.push_back(p); is_object.push_back(false); } } else { // Collide with unloaded nodes aabb3f box = getNodeBox(p, BS); cboxes.push_back(box); is_unloaded.push_back(true); is_step_up.push_back(false); bouncy_values.push_back(0); node_positions.push_back(p); is_object.push_back(false); } } // Do not move if world has not loaded yet, since custom node boxes // are not available for collision detection. if (!any_position_valid) return result; } // tt2 if(collideWithObjects) { ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG); //TimeTaker tt3("collisionMoveSimple collect object boxes"); /* add object boxes to cboxes */ std::vector<ActiveObject*> objects; #ifndef SERVER ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env); if (c_env != 0) { f32 distance = speed_f.getLength(); std::vector<DistanceSortedActiveObject> clientobjects; c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects); for (size_t i=0; i < clientobjects.size(); i++) { if ((self == 0) || (self != clientobjects[i].obj)) { objects.push_back((ActiveObject*)clientobjects[i].obj); } } } else #endif { ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env); if (s_env != 0) { f32 distance = speed_f.getLength(); std::vector<u16> s_objects; s_env->getObjectsInsideRadius(s_objects, pos_f, distance * 1.5); for (std::vector<u16>::iterator iter = s_objects.begin(); iter != s_objects.end(); ++iter) { ServerActiveObject *current = s_env->getActiveObject(*iter); if ((self == 0) || (self != current)) { objects.push_back((ActiveObject*)current); } } } } for (std::vector<ActiveObject*>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) { ActiveObject *object = *iter; if (object != NULL) { aabb3f object_collisionbox; if (object->getCollisionBox(&object_collisionbox) && object->collideWithObjects()) { cboxes.push_back(object_collisionbox); is_unloaded.push_back(false); is_step_up.push_back(false); bouncy_values.push_back(0); node_positions.push_back(v3s16(0,0,0)); is_object.push_back(true); } } } } //tt3 assert(cboxes.size() == is_unloaded.size()); // post-condition assert(cboxes.size() == is_step_up.size()); // post-condition assert(cboxes.size() == bouncy_values.size()); // post-condition assert(cboxes.size() == node_positions.size()); // post-condition assert(cboxes.size() == is_object.size()); // post-condition /* Collision detection */ /* Collision uncertainty radius Make it a bit larger than the maximum distance of movement */ f32 d = pos_max_d * 1.1; // A fairly large value in here makes moving smoother //f32 d = 0.15*BS; // This should always apply, otherwise there are glitches assert(d > pos_max_d); // invariant int loopcount = 0; while(dtime > BS * 1e-10) { //TimeTaker tt3("collisionMoveSimple dtime loop"); ScopeProfiler sp(g_profiler, "collisionMoveSimple dtime loop avg", SPT_AVG); // Avoid infinite loop loopcount++; if (loopcount >= 100) { warningstream << "collisionMoveSimple: Loop count exceeded, aborting to avoid infiniite loop" << std::endl; dtime = 0; break; } aabb3f movingbox = box_0; movingbox.MinEdge += pos_f; movingbox.MaxEdge += pos_f; int nearest_collided = -1; f32 nearest_dtime = dtime; u32 nearest_boxindex = -1; /* Go through every nodebox, find nearest collision */ for (u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) { // Ignore if already stepped up this nodebox. if(is_step_up[boxindex]) continue; // Find nearest collision of the two boxes (raytracing-like) f32 dtime_tmp; int collided = axisAlignedCollision( cboxes[boxindex], movingbox, speed_f, d, dtime_tmp); if (collided == -1 || dtime_tmp >= nearest_dtime) continue; nearest_dtime = dtime_tmp; nearest_collided = collided; nearest_boxindex = boxindex; } if (nearest_collided == -1) { // No collision with any collision box. pos_f += speed_f * dtime; dtime = 0; // Set to 0 to avoid "infinite" loop due to small FP numbers } else { // Otherwise, a collision occurred. const aabb3f& cbox = cboxes[nearest_boxindex]; // Check for stairs. bool step_up = (nearest_collided != 1) && // must not be Y direction (movingbox.MinEdge.Y < cbox.MaxEdge.Y) && (movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) && (!wouldCollideWithCeiling(cboxes, movingbox, cbox.MaxEdge.Y - movingbox.MinEdge.Y, d)); // Get bounce multiplier bool bouncy = (bouncy_values[nearest_boxindex] >= 1); float bounce = -(float)bouncy_values[nearest_boxindex] / 100.0; // Move to the point of collision and reduce dtime by nearest_dtime if (nearest_dtime < 0) { // Handle negative nearest_dtime (can be caused by the d allowance) if (!step_up) { if (nearest_collided == 0) pos_f.X += speed_f.X * nearest_dtime; if (nearest_collided == 1) pos_f.Y += speed_f.Y * nearest_dtime; if (nearest_collided == 2) pos_f.Z += speed_f.Z * nearest_dtime; } } else { pos_f += speed_f * nearest_dtime; dtime -= nearest_dtime; } bool is_collision = true; if (is_unloaded[nearest_boxindex]) is_collision = false; CollisionInfo info; if (is_object[nearest_boxindex]) info.type = COLLISION_OBJECT; else info.type = COLLISION_NODE; info.node_p = node_positions[nearest_boxindex]; info.bouncy = bouncy; info.old_speed = speed_f; // Set the speed component that caused the collision to zero if (step_up) { // Special case: Handle stairs is_step_up[nearest_boxindex] = true; is_collision = false; } else if(nearest_collided == 0) { // X if (fabs(speed_f.X) > BS * 3) speed_f.X *= bounce; else speed_f.X = 0; result.collides = true; result.collides_xz = true; } else if(nearest_collided == 1) { // Y if(fabs(speed_f.Y) > BS * 3) speed_f.Y *= bounce; else speed_f.Y = 0; result.collides = true; } else if(nearest_collided == 2) { // Z if (fabs(speed_f.Z) > BS * 3) speed_f.Z *= bounce; else speed_f.Z = 0; result.collides = true; result.collides_xz = true; } info.new_speed = speed_f; if (info.new_speed.getDistanceFrom(info.old_speed) < 0.1 * BS) is_collision = false; if (is_collision) { result.collisions.push_back(info); } } } /* Final touches: Check if standing on ground, step up stairs. */ aabb3f box = box_0; box.MinEdge += pos_f; box.MaxEdge += pos_f; for (u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) { const aabb3f& cbox = cboxes[boxindex]; /* See if the object is touching ground. Object touches ground if object's minimum Y is near node's maximum Y and object's X-Z-area overlaps with the node's X-Z-area. Use 0.15*BS so that it is easier to get on a node. */ if (cbox.MaxEdge.X - d > box.MinEdge.X && cbox.MinEdge.X + d < box.MaxEdge.X && cbox.MaxEdge.Z - d > box.MinEdge.Z && cbox.MinEdge.Z + d < box.MaxEdge.Z) { if (is_step_up[boxindex]) { pos_f.Y += (cbox.MaxEdge.Y - box.MinEdge.Y); box = box_0; box.MinEdge += pos_f; box.MaxEdge += pos_f; } if (fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.15 * BS) { result.touching_ground = true; if (is_object[boxindex]) result.standing_on_object = true; if (is_unloaded[boxindex]) result.standing_on_unloaded = true; } } } return result; }