From 6a1670dbc31cc0e44178bbd9ad34ff0d5981a060 Mon Sep 17 00:00:00 2001 From: Ilya Zhuravlev Date: Thu, 20 Dec 2012 21:19:49 +0400 Subject: Migrate to STL containers/algorithms. --- src/content_sao.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/content_sao.cpp') diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 718a42dff..1e02ea5a5 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "genericobject.h" #include "util/serialize.h" -core::map ServerActiveObject::m_types; +std::map ServerActiveObject::m_types; /* DummyLoadSAO -- cgit v1.2.3 From 7f51b2da28e004b82fc6835e5257e619da4666b2 Mon Sep 17 00:00:00 2001 From: RealBadAngel Date: Sun, 17 Mar 2013 12:16:57 +0100 Subject: lua methods set_look_pitch and set_look_yaw --- doc/lua_api.txt | 2 ++ src/content_sao.cpp | 14 ++++++++++++++ src/content_sao.h | 2 ++ src/scriptapi_object.cpp | 27 ++++++++++++++++++++++++++- src/scriptapi_object.h | 8 +++++++- 5 files changed, 51 insertions(+), 2 deletions(-) (limited to 'src/content_sao.cpp') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index eb05d117e..7d8fa149f 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1228,6 +1228,8 @@ Player-only: (no-op for other objects) - get_look_dir(): get camera direction as a unit vector - get_look_pitch(): pitch in radians - get_look_yaw(): yaw in radians (wraps around pretty randomly as of now) +- set_look_pitch(radians): sets look pitch +- set_look_yaw(radians): sets look yaw - set_inventory_formspec(formspec) ^ Redefine player's inventory form ^ Should usually be called in on_joinplayer diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 1e02ea5a5..d7afc31d8 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -1230,6 +1230,20 @@ void PlayerSAO::moveTo(v3f pos, bool continuous) m_moved = true; } +void PlayerSAO::setYaw(float yaw) +{ + m_player->setYaw(yaw); + // Force change on client + m_moved = true; +} + +void PlayerSAO::setPitch(float pitch) +{ + m_player->setPitch(pitch); + // Force change on client + m_moved = true; +} + int PlayerSAO::punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher, diff --git a/src/content_sao.h b/src/content_sao.h index 2fd1034eb..e5b89d447 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -147,6 +147,8 @@ public: void setBasePosition(const v3f &position); void setPos(v3f pos); void moveTo(v3f pos, bool continuous); + void setYaw(float); + void setPitch(float); /* Interaction interface diff --git a/src/scriptapi_object.cpp b/src/scriptapi_object.cpp index ba72840c0..a0f93cbba 100644 --- a/src/scriptapi_object.cpp +++ b/src/scriptapi_object.cpp @@ -27,7 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "scriptapi_entity.h" #include "scriptapi_common.h" - /* ObjectRef */ @@ -582,6 +581,30 @@ int ObjectRef::l_get_look_yaw(lua_State *L) return 1; } +// set_look_pitch(self, radians) +int ObjectRef::l_set_look_pitch(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + PlayerSAO* co = getplayersao(ref); + if(co == NULL) return 0; + float pitch = luaL_checknumber(L, 2) * core::RADTODEG; + // Do it + co->setPitch(pitch); + return 1; +} + +// set_look_yaw(self, radians) +int ObjectRef::l_set_look_yaw(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + PlayerSAO* co = getplayersao(ref); + if(co == NULL) return 0; + float yaw = luaL_checknumber(L, 2) * core::RADTODEG; + // Do it + co->setYaw(yaw); + return 1; +} + // set_inventory_formspec(self, formspec) int ObjectRef::l_set_inventory_formspec(lua_State *L) { @@ -755,6 +778,8 @@ const luaL_reg ObjectRef::methods[] = { luamethod(ObjectRef, get_look_dir), luamethod(ObjectRef, get_look_pitch), luamethod(ObjectRef, get_look_yaw), + luamethod(ObjectRef, set_look_yaw), + luamethod(ObjectRef, set_look_pitch), luamethod(ObjectRef, set_inventory_formspec), luamethod(ObjectRef, get_inventory_formspec), luamethod(ObjectRef, get_player_control), diff --git a/src/scriptapi_object.h b/src/scriptapi_object.h index ba1e7db39..a37abbb78 100644 --- a/src/scriptapi_object.h +++ b/src/scriptapi_object.h @@ -1,5 +1,5 @@ /* -Minetest-c55 +Minetest Copyright (C) 2013 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify @@ -169,6 +169,12 @@ private: // get_look_yaw(self) static int l_get_look_yaw(lua_State *L); + // set_look_pitch(self, radians) + static int l_set_look_pitch(lua_State *L); + + // set_look_yaw(self, radians) + static int l_set_look_yaw(lua_State *L); + // set_inventory_formspec(self, formspec) static int l_set_inventory_formspec(lua_State *L); -- cgit v1.2.3 From 8800896824d609c754eee38d3720a112f4216e57 Mon Sep 17 00:00:00 2001 From: sapier Date: Sat, 12 Jan 2013 17:59:19 +0000 Subject: Closed add object <-> object collision handling --- src/activeobject.h | 2 +- src/collision.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++-- src/collision.h | 6 +++-- src/content_cao.cpp | 21 ++++++++++++++-- src/content_sao.cpp | 38 +++++++++++++++++++++++++--- src/content_sao.h | 3 +++ src/environment.cpp | 2 +- src/localplayer.cpp | 38 ++++++++++++++-------------- src/localplayer.h | 6 +++-- src/particles.cpp | 2 +- 10 files changed, 157 insertions(+), 33 deletions(-) (limited to 'src/content_sao.cpp') diff --git a/src/activeobject.h b/src/activeobject.h index e454f2c8c..1a75fba2e 100644 --- a/src/activeobject.h +++ b/src/activeobject.h @@ -61,7 +61,7 @@ public: } virtual u8 getType() const = 0; - + virtual bool getCollisionBox(aabb3f *toset) = 0; protected: u16 m_id; // 0 is invalid, "no id" }; diff --git a/src/collision.cpp b/src/collision.cpp index 58517b779..806a3b720 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -23,7 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include "gamedef.h" #include "log.h" +#include "environment.h" +#include "serverobject.h" #include +#include #include "util/timetaker.h" #include "main.h" // g_profiler #include "profiler.h" @@ -186,11 +189,12 @@ bool wouldCollideWithCeiling( } -collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, +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) { + Map *map = &env->getMap(); //TimeTaker tt("collisionMoveSimple"); ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG); @@ -215,6 +219,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, std::vector cboxes; std::vector is_unloaded; std::vector is_step_up; + std::vector is_object; std::vector bouncy_values; std::vector node_positions; { @@ -256,6 +261,7 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, is_step_up.push_back(false); bouncy_values.push_back(n_bouncy_value); node_positions.push_back(p); + is_object.push_back(false); } } catch(InvalidPositionException &e) @@ -267,14 +273,72 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, is_step_up.push_back(false); bouncy_values.push_back(0); node_positions.push_back(p); + is_object.push_back(false); } } } // tt2 + { + ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG); + //TimeTaker tt3("collisionMoveSimple collect object boxes"); + + /* add object boxes to cboxes */ + + + std::list objects; +#ifndef SERVER + ClientEnvironment *c_env = dynamic_cast(env); + if (c_env != 0) + { + f32 distance = speed_f.getLength(); + std::vector clientobjects; + c_env->getActiveObjects(pos_f,distance * 1.5,clientobjects); + for (int i=0; i < clientobjects.size(); i++) + { + objects.push_back((ActiveObject*)clientobjects[i].obj); + } + } + else +#endif + { + ServerEnvironment *s_env = dynamic_cast(env); + if (s_env != 0) + { + f32 distance = speed_f.getLength(); + std::set s_objects = s_env->getObjectsInsideRadius(pos_f,distance * 1.5); + for (std::set::iterator iter = s_objects.begin(); iter != s_objects.end(); iter++) + { + ServerActiveObject *current = s_env->getActiveObject(*iter); + objects.push_back((ActiveObject*)current); + } + } + } + + for (std::list::const_iterator iter = objects.begin();iter != objects.end(); ++iter) + { + ActiveObject *object = *iter; + + if (object != NULL) + { + aabb3f object_collisionbox; + if (object->getCollisionBox(&object_collisionbox)) + { + 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()); assert(cboxes.size() == is_step_up.size()); assert(cboxes.size() == bouncy_values.size()); assert(cboxes.size() == node_positions.size()); + assert(cboxes.size() == is_object.size()); /* Collision detection @@ -386,7 +450,11 @@ collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, is_collision = false; CollisionInfo info; - info.type = COLLISION_NODE; + 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; diff --git a/src/collision.h b/src/collision.h index 38cc3efb3..117818456 100644 --- a/src/collision.h +++ b/src/collision.h @@ -25,10 +25,12 @@ with this program; if not, write to the Free Software Foundation, Inc., class Map; class IGameDef; +class Environment; enum CollisionType { - COLLISION_NODE + COLLISION_NODE, + COLLISION_OBJECT, }; struct CollisionInfo @@ -65,7 +67,7 @@ struct collisionMoveResult }; // Moves using a single iteration; speed should not exceed pos_max_d/dtime -collisionMoveResult collisionMoveSimple(Map *map, IGameDef *gamedef, +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); diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 269667fe5..ee1009b6c 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -174,6 +174,7 @@ public: void processMessage(const std::string &data); + bool getCollisionBox(aabb3f *toset) { return false; } private: scene::IMeshSceneNode *m_node; v3f m_position; @@ -329,6 +330,7 @@ public: std::string infoText() {return m_infotext;} + bool getCollisionBox(aabb3f *toset) { return false; } private: core::aabbox3d m_selection_box; scene::IMeshSceneNode *m_node; @@ -643,6 +645,22 @@ public: ClientActiveObject::registerType(getType(), create); } + bool getCollisionBox(aabb3f *toset) { + if (m_prop.physical) { + aabb3f retval; + //update collision box + toset->MinEdge = m_prop.collisionbox.MinEdge * BS; + toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS; + + toset->MinEdge += m_position; + toset->MaxEdge += m_position; + + return true; + } + + return false; + } + void initialize(const std::string &data) { infostream<<"GenericCAO: Got init data"<getGameDef(); - moveresult = collisionMoveSimple(&env->getMap(), gamedef, + moveresult = collisionMoveSimple(env,env->getGameDef(), pos_max_d, box, stepheight, dtime, p_pos, p_velocity, p_acceleration); // Apply results diff --git a/src/content_sao.cpp b/src/content_sao.cpp index d7afc31d8..468dfd218 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -64,6 +64,10 @@ public: infostream<<"DummyLoadSAO step"<getGameDef(); - moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, + moveresult = collisionMoveSimple(m_env,m_env->getGameDef(), pos_max_d, box, stepheight, dtime, pos_f, m_speed_f, accel_f); @@ -314,6 +321,10 @@ public: return 0; } + bool getCollisionBox(aabb3f *toset) { + return false; + } + private: std::string m_itemstring; @@ -490,8 +501,7 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) v3f p_pos = m_base_position; v3f p_velocity = m_velocity; v3f p_acceleration = m_acceleration; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, + moveresult = collisionMoveSimple(m_env,m_env->getGameDef(), pos_max_d, box, stepheight, dtime, p_pos, p_velocity, p_acceleration); // Apply results @@ -880,6 +890,22 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) m_messages_out.push_back(aom); } +bool LuaEntitySAO::getCollisionBox(aabb3f *toset) { + if (m_prop.physical) + { + //update collision box + toset->MinEdge = m_prop.collisionbox.MinEdge * BS; + toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS; + + toset->MinEdge += m_base_position; + toset->MaxEdge += m_base_position; + + return true; + } + + return false; +} + /* PlayerSAO */ @@ -1434,3 +1460,7 @@ std::string PlayerSAO::getPropertyPacket() return gob_cmd_set_properties(m_prop); } +bool PlayerSAO::getCollisionBox(aabb3f *toset) { + //player collision handling is already done clientside no need to do it twice + return false; +} diff --git a/src/content_sao.h b/src/content_sao.h index e5b89d447..60ca8f319 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -78,6 +78,7 @@ public: void setSprite(v2s16 p, int num_frames, float framelength, bool select_horiz_by_yawpitch); std::string getName(); + bool getCollisionBox(aabb3f *toset); private: std::string getPropertyPacket(); void sendPosition(bool do_interpolate, bool is_movement_end); @@ -235,6 +236,8 @@ public: m_is_singleplayer = is_singleplayer; } + bool getCollisionBox(aabb3f *toset); + private: std::string getPropertyPacket(); diff --git a/src/environment.cpp b/src/environment.cpp index 7c93090b6..07cdb24d1 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -2096,7 +2096,7 @@ void ClientEnvironment::step(float dtime) Move the lplayer. This also does collision detection. */ - lplayer->move(dtime_part, *m_map, position_max_increment, + lplayer->move(dtime_part, this, position_max_increment, &player_collisions); } } diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 9c36e75e6..ee9b41c58 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gamedef.h" #include "nodedef.h" #include "settings.h" +#include "environment.h" #include "map.h" #include "util/numeric.h" @@ -57,9 +58,10 @@ LocalPlayer::~LocalPlayer() { } -void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, +void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, std::list *collision_info) { + Map *map = &env->getMap(); INodeDefManager *nodemgr = m_gamedef->ndef(); v3f position = getPosition(); @@ -97,15 +99,15 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, if(in_liquid) { v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS); - in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); - liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity; + in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid(); + liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity; } // If not in liquid, the threshold of going in is at lower y else { v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS); - in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); - liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity; + in_liquid = nodemgr->get(map->getNode(pp).getContent()).isLiquid(); + liquid_viscosity = nodemgr->get(map->getNode(pp).getContent()).liquid_viscosity; } } catch(InvalidPositionException &e) @@ -118,7 +120,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, */ try{ v3s16 pp = floatToInt(position + v3f(0,0,0), BS); - in_liquid_stable = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); + in_liquid_stable = nodemgr->get(map->getNode(pp).getContent()).isLiquid(); } catch(InvalidPositionException &e) { @@ -132,8 +134,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, try { v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS); v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS); - is_climbing = ((nodemgr->get(map.getNode(pp).getContent()).climbable || - nodemgr->get(map.getNode(pp2).getContent()).climbable) && !free_move); + is_climbing = ((nodemgr->get(map->getNode(pp).getContent()).climbable || + nodemgr->get(map->getNode(pp2).getContent()).climbable) && !free_move); } catch(InvalidPositionException &e) { @@ -197,7 +199,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, v3f accel_f = v3f(0,0,0); - collisionMoveResult result = collisionMoveSimple(&map, m_gamedef, + collisionMoveResult result = collisionMoveSimple(env, m_gamedef, pos_max_d, playerbox, player_stepheight, dtime, position, m_speed, accel_f); @@ -219,7 +221,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, */ v3s16 current_node = floatToInt(position - v3f(0,BS/2,0), BS); if(m_sneak_node_exists && - nodemgr->get(map.getNodeNoEx(m_old_node_below)).name == "air" && + nodemgr->get(map->getNodeNoEx(m_old_node_below)).name == "air" && m_old_node_below_type != "air") { // Old node appears to have been removed; that is, @@ -227,7 +229,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, m_need_to_get_new_sneak_node = false; m_sneak_node_exists = false; } - else if(nodemgr->get(map.getNodeNoEx(current_node)).name != "air") + else if(nodemgr->get(map->getNodeNoEx(current_node)).name != "air") { // We are on something, so make sure to recalculate the sneak // node. @@ -267,10 +269,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, try{ // The node to be sneaked on has to be walkable - if(nodemgr->get(map.getNode(p)).walkable == false) + if(nodemgr->get(map->getNode(p)).walkable == false) continue; // And the node above it has to be nonwalkable - if(nodemgr->get(map.getNode(p+v3s16(0,1,0))).walkable == true) + if(nodemgr->get(map->getNode(p+v3s16(0,1,0))).walkable == true) continue; } catch(InvalidPositionException &e) @@ -331,7 +333,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, { camera_barely_in_ceiling = false; v3s16 camera_np = floatToInt(getEyePosition(), BS); - MapNode n = map.getNodeNoEx(camera_np); + MapNode n = map->getNodeNoEx(camera_np); if(n.getContent() != CONTENT_IGNORE){ if(nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2){ camera_barely_in_ceiling = true; @@ -343,21 +345,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, Update the node last under the player */ m_old_node_below = floatToInt(position - v3f(0,BS/2,0), BS); - m_old_node_below_type = nodemgr->get(map.getNodeNoEx(m_old_node_below)).name; + m_old_node_below_type = nodemgr->get(map->getNodeNoEx(m_old_node_below)).name; /* Check properties of the node on which the player is standing */ - const ContentFeatures &f = nodemgr->get(map.getNodeNoEx(getStandingNodePos())); + const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos())); // Determine if jumping is possible m_can_jump = touching_ground && !in_liquid; if(itemgroup_get(f.groups, "disable_jump")) m_can_jump = false; } -void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d) +void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d) { - move(dtime, map, pos_max_d, NULL); + move(dtime, env, pos_max_d, NULL); } void LocalPlayer::applyControl(float dtime) diff --git a/src/localplayer.h b/src/localplayer.h index e46ca6147..17434d379 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "player.h" #include +class ClientEnvironment; + class LocalPlayer : public Player { public: @@ -38,9 +40,9 @@ public: v3f overridePosition; - void move(f32 dtime, Map &map, f32 pos_max_d, + void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d, std::list *collision_info); - void move(f32 dtime, Map &map, f32 pos_max_d); + void move(f32 dtime, ClientEnvironment *env, f32 pos_max_d); void applyControl(float dtime); diff --git a/src/particles.cpp b/src/particles.cpp index 0445d7726..1d814f619 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -138,7 +138,7 @@ void Particle::step(float dtime, ClientEnvironment &env) v3f p_pos = m_pos*BS; v3f p_velocity = m_velocity*BS; v3f p_acceleration = m_acceleration*BS; - collisionMoveSimple(&env.getClientMap(), m_gamedef, + collisionMoveSimple(&env, m_gamedef, BS*0.5, box, 0, dtime, p_pos, p_velocity, p_acceleration); -- cgit v1.2.3 From 7d9329ecfe84733cdefa34eab25ee3d124c94c59 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Thu, 28 Mar 2013 21:40:44 +0100 Subject: New damage system, add damageGroups to ToolCapabilities, bump protocol version --- doc/lua_api.txt | 28 ++++++++++++++---------- src/clientserver.h | 4 +++- src/content_sao.cpp | 6 ++--- src/itemdef.cpp | 8 +++---- src/itemdef.h | 6 ++--- src/scriptapi_common.cpp | 24 ++++++++++++++++++++ src/server.cpp | 6 ++--- src/server.h | 2 +- src/tool.cpp | 57 +++++++++++++++++++++++++++++++----------------- src/tool.h | 21 +++++++++--------- 10 files changed, 105 insertions(+), 57 deletions(-) (limited to 'src/content_sao.cpp') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8ef92bdf3..42ca58239 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -471,9 +471,11 @@ a node is destroyable and how long it takes to destroy by a tool. Groups of entities ------------------- For entities, groups are, as of now, used only for calculating damage. +The rating is the percentage of damage caused by tools with this damage group. +See "Entity damage mechanism". -object.get_armor_groups() -> a group-rating table (eg. {fleshy=3}) -object.set_armor_groups({level=2, fleshy=2, cracky=2}) +object.get_armor_groups() -> a group-rating table (eg. {fleshy=100}) +object.set_armor_groups({fleshy=30, cracky=80}) Groups of tools ---------------- @@ -522,7 +524,6 @@ Special groups Known damage and digging time defining groups ---------------------------------------------- -Valid ratings for these are 0, 1, 2 and 3, unless otherwise stated. - crumbly: dirt, sand - cracky: tough but crackable stuff like stone. - snappy: something that can be cut using fine tools; eg. leaves, small @@ -575,6 +576,7 @@ groups to enable interaction with tools. * Uses (until the tool breaks) * Maximum level (usually 0, 1, 2 or 3) * Digging times + * Damage groups **Full punch interval**: When used as a weapon, the tool will do full damage if this time is spent @@ -606,8 +608,9 @@ maximum level. result in the tool to be able to dig nodes that have a rating of 2 or 3 for this group, and unable to dig the rating 1, which is the toughest. Unless there is a matching group that enables digging otherwise. - * For entities, damage equals the amount of nodes dug in the time spent - between hits, with a maximum time of ''full_punch_interval''. + +**Damage groups** +List of damage for groups of entities. See "Entity damage mechanism". Example definition of the capabilities of a tool ------------------------------------------------- @@ -617,6 +620,7 @@ tool_capabilities = { groupcaps={ crumbly={maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80}} } + damage_groups = {fleshy=2}, } This makes the tool be able to dig nodes that fullfill both of these: @@ -647,10 +651,12 @@ Notes: Entity damage mechanism ------------------------ Damage calculation: -- Take the time spent after the last hit -- Limit time to full_punch_interval -- Take the damage groups and imagine a bunch of nodes that have them -- Damage in HP is the amount of nodes destroyed in this time. +damage = 0 +foreach group in cap.damage_groups: + damage += cap.damage_groups[group] * limit(actual_interval / cap.full_punch_interval, 0.0, 1.0) + * (object.armor_groups[group] / 100.0) + -- Where object.armor_groups[group] is 0 for inexisting values +return damage Client predicts damage based on damage groups. Because of this, it is able to give an immediate response when an entity is damaged or dies; the response is @@ -1496,10 +1502,10 @@ Item definition (register_node, register_craftitem, register_tool) max_drop_level=0, groupcaps={ -- For example: - fleshy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1}, snappy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1}, choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0} - } + }, + damage_groups = {groupname=damage}, } node_placement_prediction = nil, ^ If nil and item is node, prediction is made automatically diff --git a/src/clientserver.h b/src/clientserver.h index 535fc04d8..aba84fb31 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -85,9 +85,11 @@ SharedBuffer makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed); TOCLIENT_SPAWN_PARTICLE TOCLIENT_ADD_PARTICLESPAWNER TOCLIENT_DELETE_PARTICLESPAWNER + PROTOCOL_VERSION 18: + damageGroups added to ToolCapabilities */ -#define LATEST_PROTOCOL_VERSION 17 +#define LATEST_PROTOCOL_VERSION 18 // Server's supported network protocol range #define SERVER_PROTOCOL_VERSION_MIN 13 diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 468dfd218..ae08b4260 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -381,8 +381,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, } // Initialize something to armor groups - m_armor_groups["fleshy"] = 3; - m_armor_groups["snappy"] = 2; + m_armor_groups["fleshy"] = 100; } LuaEntitySAO::~LuaEntitySAO() @@ -942,8 +941,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_, assert(m_peer_id != 0); setBasePosition(m_player->getPosition()); m_inventory = &m_player->inventory; - m_armor_groups["choppy"] = 2; - m_armor_groups["fleshy"] = 3; + m_armor_groups["fleshy"] = 100; m_prop.hp_max = PLAYER_MAX_HP; m_prop.physical = false; diff --git a/src/itemdef.cpp b/src/itemdef.cpp index 4bd4181f9..98d7ce0a8 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -111,7 +111,7 @@ void ItemDefinition::reset() node_placement_prediction = ""; } -void ItemDefinition::serialize(std::ostream &os) const +void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const { writeU8(os, 1); // version writeU8(os, type); @@ -126,7 +126,7 @@ void ItemDefinition::serialize(std::ostream &os) const std::string tool_capabilities_s = ""; if(tool_capabilities){ std::ostringstream tmp_os(std::ios::binary); - tool_capabilities->serialize(tmp_os); + tool_capabilities->serialize(tmp_os, protocol_version); tool_capabilities_s = tmp_os.str(); } os<second; // Serialize ItemDefinition and write wrapped in a string std::ostringstream tmp_os(std::ios::binary); - def->serialize(tmp_os); + def->serialize(tmp_os, protocol_version); os<::const_iterator + i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){ + // Create damage group table + lua_pushinteger(L, i->second); + lua_setfield(L, -2, i->first.c_str()); + } + lua_setfield(L, -2, "damage_groups"); } void push_tool_capabilities(lua_State *L, diff --git a/src/server.cpp b/src/server.cpp index db05b95cc..6bdebcec4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2080,7 +2080,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) SendMovement(m_con, peer_id); // Send item definitions - SendItemDef(m_con, peer_id, m_itemdef); + SendItemDef(m_con, peer_id, m_itemdef, client->net_proto_version); // Send node definitions SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version); @@ -3342,7 +3342,7 @@ void Server::SendDeathscreen(con::Connection &con, u16 peer_id, } void Server::SendItemDef(con::Connection &con, u16 peer_id, - IItemDefManager *itemdef) + IItemDefManager *itemdef, u16 protocol_version) { DSTACK(__FUNCTION_NAME); std::ostringstream os(std::ios_base::binary); @@ -3354,7 +3354,7 @@ void Server::SendItemDef(con::Connection &con, u16 peer_id, */ writeU16(os, TOCLIENT_ITEMDEF); std::ostringstream tmp_os(std::ios::binary); - itemdef->serialize(tmp_os); + itemdef->serialize(tmp_os, protocol_version); std::ostringstream tmp_os2(std::ios::binary); compressZlib(tmp_os.str(), tmp_os2); os<second); } } + if(protocol_version > 17){ + writeU32(os, damageGroups.size()); + for(std::map::const_iterator + i = damageGroups.begin(); i != damageGroups.end(); i++){ + os<first); + writeS16(os, i->second); + } + } } void ToolCapabilities::deSerialize(std::istream &is) { int version = readU8(is); - if(version != 1) throw SerializationError( + if(version != 1 && version != 2) throw SerializationError( "unsupported ToolCapabilities version"); full_punch_interval = readF1000(is); max_drop_level = readS16(is); @@ -68,6 +79,15 @@ void ToolCapabilities::deSerialize(std::istream &is) } groupcaps[name] = cap; } + if(version == 2) + { + u32 damage_groups_size = readU32(is); + for(u32 i=0; i tp->full_punch_interval) - time_from_last_punch = tp->full_punch_interval; - // Damage in hp is equivalent to nodes dug in time_from_last_punch - s16 hp = 0; - if(digprop.diggable) - hp = time_from_last_punch / digprop.time; - // Wear is the same as for digging a single node - s16 wear = (float)digprop.wear; - - return HitParams(hp, wear, digprop.main_group); + s16 damage = 0; + float full_punch_interval = tp->full_punch_interval; + + for(std::map::const_iterator + i = tp->damageGroups.begin(); i != tp->damageGroups.end(); i++){ + s16 armor = itemgroup_get(armor_groups, i->first); + damage += i->second * rangelim(time_from_last_punch * full_punch_interval, 0.0, 1.0) + * armor / 100.0; + } + + return HitParams(damage, 0); } -HitParams getHitParams(const ItemGroupList &groups, +HitParams getHitParams(const ItemGroupList &armor_groups, const ToolCapabilities *tp) { - return getHitParams(groups, tp, 1000000); + return getHitParams(armor_groups, tp, 1000000); } PunchDamageResult getPunchDamage( @@ -187,7 +205,6 @@ PunchDamageResult getPunchDamage( result.did_punch = true; result.wear = hitparams.wear; result.damage = hitparams.hp; - result.main_group = hitparams.main_group; } return result; diff --git a/src/tool.h b/src/tool.h index e812a9e36..509561a16 100644 --- a/src/tool.h +++ b/src/tool.h @@ -52,6 +52,7 @@ struct ToolGroupCap // CLANG SUCKS DONKEY BALLS typedef std::map ToolGCMap; +typedef std::map DamageGroup; struct ToolCapabilities { @@ -59,19 +60,22 @@ struct ToolCapabilities int max_drop_level; // CLANG SUCKS DONKEY BALLS ToolGCMap groupcaps; + DamageGroup damageGroups; ToolCapabilities( float full_punch_interval_=1.4, int max_drop_level_=1, // CLANG SUCKS DONKEY BALLS - ToolGCMap groupcaps_=ToolGCMap() + ToolGCMap groupcaps_=ToolGCMap(), + DamageGroup damageGroups_=DamageGroup() ): full_punch_interval(full_punch_interval_), max_drop_level(max_drop_level_), - groupcaps(groupcaps_) + groupcaps(groupcaps_), + damageGroups(damageGroups_) {} - void serialize(std::ostream &os) const; + void serialize(std::ostream &os, u16 version) const; void deSerialize(std::istream &is); }; @@ -103,19 +107,17 @@ struct HitParams { s16 hp; s16 wear; - std::string main_group; - HitParams(s16 hp_=0, s16 wear_=0, std::string main_group_=""): + HitParams(s16 hp_=0, s16 wear_=0): hp(hp_), - wear(wear_), - main_group(main_group_) + wear(wear_) {} }; -HitParams getHitParams(const ItemGroupList &groups, +HitParams getHitParams(const ItemGroupList &armor_groups, const ToolCapabilities *tp, float time_from_last_punch); -HitParams getHitParams(const ItemGroupList &groups, +HitParams getHitParams(const ItemGroupList &armor_groups, const ToolCapabilities *tp); struct PunchDamageResult @@ -123,7 +125,6 @@ struct PunchDamageResult bool did_punch; int damage; int wear; - std::string main_group; PunchDamageResult(): did_punch(false), -- cgit v1.2.3