From d264de084cde43ee84816a036457b08d6bcbba67 Mon Sep 17 00:00:00 2001 From: placki Date: Sat, 29 Oct 2011 00:14:40 +0200 Subject: [PATCH] crafted_teleports, teleport pairs/loops, working "0,0,0" --- minetest.conf.example | 4 ++ src/defaultsettings.cpp | 1 + src/player.cpp | 5 +- src/player.h | 2 + src/server.cpp | 104 +++++++++++++++++++++++++++++++--------- 5 files changed, 92 insertions(+), 24 deletions(-) diff --git a/minetest.conf.example b/minetest.conf.example index 30adc5e..2cf4c6c 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -154,4 +154,8 @@ # Set to true to enable experimental features or stuff that is tested # (varies from version to version, usually not useful at all) #enable_experimental = false +# 0 - disables crafted teleports. 1 - teleport work if target area exists and there are 2 air/water (clear) tiles +# 2 - teleport A works iff it points to clear area containing teleport B, and teleport B points back to teleport A +# 3 or more - just like 2 but there can be 3 of more teleports in loop (warning - high value is bad for server performance) +#crafted_teleports = 4 diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 7f0d46a..ccacd37 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -109,5 +109,6 @@ void set_default_settings(Settings *settings) settings->setDefault("server_map_save_interval", "10"); settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); settings->setDefault("enable_experimental", "false"); + settings->setDefault("crafted_teleports", "4"); } diff --git a/src/player.cpp b/src/player.cpp index e2d1f49..c104a8d 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -40,13 +40,14 @@ Player::Player(): craftresult_is_preview(true), hp(20), peer_id(PEER_ID_INEXISTENT), + clanOwner(0), m_selected_item(0), m_pitch(0), m_yaw(0), m_speed(0,0,0), - m_position(0,0,0), - clanOwner(0) + m_position(0,0,0) { + lastTeleportPos.X=FLT_MAX; updateName(""); resetInventory(); } diff --git a/src/player.h b/src/player.h index 7818853..ad89487 100644 --- a/src/player.h +++ b/src/player.h @@ -171,6 +171,8 @@ public: std::set clans; u16 clanOwner; bool canModify(const ClansManager* clansManager, Map* map, MapBlock* block, MapNode* node, v3s16* nodepos) const; + v3f lastTeleportPos; //server: remember position player teleported to, to let him move away. + protected: char m_name[PLAYERNAME_SIZE]; diff --git a/src/server.cpp b/src/server.cpp index 2239341..03b7161 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1816,6 +1816,38 @@ void Server::Receive() } } +bool getTeleportTarget(/*const*/ ServerEnvironment *m_env,/*in+out*/ v3s16 &where,/*out*/v3f &tgt) +{ + // actionstream<<"Is Teleport at: "<<"("<getMap().getNodeNoEx(where).getContent() == CONTENT_TELEPORT) + meta = (SignNodeMetadata*)m_env->getMap().getNodeMetadata(where); + else { + where.Y++; + if(where.YgetMap().getNodeNoEx(where).getContent() == CONTENT_TELEPORT) + meta = (SignNodeMetadata*)m_env->getMap().getNodeMetadata(where); + } + + if(meta){ + std::string text = meta->getText(); + if(text == "") + return false; + str_replace_char(text,',',' '); + std::istringstream is(text); + is >> tgt.X >> tgt.Y >> tgt.Z; + + if( tgt.X >= MAP_GENERATION_LIMIT || tgt.X <= -MAP_GENERATION_LIMIT || + tgt.Y >= MAP_GENERATION_LIMIT || tgt.Y <= -MAP_GENERATION_LIMIT || + tgt.Z >= MAP_GENERATION_LIMIT || tgt.Z <= -MAP_GENERATION_LIMIT || + ( tgt.X == 0 && tgt.Y == 0 && tgt.Z == 0 && text.substr(0,5) != "0 0 0" ) + ) return false; + // actionstream<<"It points to: "<<"("< 32000 || t.X < -32000 || - t.Y > 32000 || t.Y < -32000 || - t.Z > 32000 || t.Z < -32000 || - (t.X == 0 && t.Y == 0 && t.Z == 0) - ) return; - - dout_server << "Teleporting: " << text << std::endl; - player->setPosition(t*BS); - SendMovePlayer(player); + if(player->lastTeleportPos.X != FLT_MAX){ + if(player->getPosition().getDistanceFrom(player->lastTeleportPos) <= BS*3/2) //1 tile away + return; //allow player to leave teleport destination + else + player->lastTeleportPos.X=FLT_MAX; //player left previous teleport destination } - } + + v3f tgtf; + if(getTeleportTarget(&m_env,tele_posi,tgtf)){ + if(player->lastTeleportPos == tgtf*BS) + return; //already checked... and failed, so skip checks. + player->lastTeleportPos=tgtf*BS; + + // check: is there known and empty place to teleport to? + v3s16 tgti=floatToInt(tgtf, 1); + content_t c1,c2; + c1=m_env.getMap().getNodeNoEx(tgti).getContent(); + tgti.Y++; + c2=m_env.getMap().getNodeNoEx(tgti).getContent(); + if((c1==CONTENT_IGNORE)||(c2==CONTENT_IGNORE)) //teleporting to unknown space? + return; + if(content_features(c1).walkable || content_features(c2).walkable) + return; + + if(teleport_option > 1){ + tgti=floatToInt(tgtf, 1); + bool loop=false; + while(!loop && teleport_option>1) + { //check if there is teleport at primary teleport target, and it loops back. + v3f tgtfnext; + if(getTeleportTarget(&m_env,tgti,tgtfnext)){ + tgti=floatToInt(tgtfnext, 1); + loop=(tele_posi.getDistanceFrom(tgti)<=1); // tile away + //actionstream<<" D:"<setPosition(tgtf*BS); + SendMovePlayer(player); + } //teleport exists + } //teleport_option } else if(command == TOSERVER_GOTBLOCKS) {