From ba858f17a058f2c8b82055447c5cc42bfadc7fa6 Mon Sep 17 00:00:00 2001 From: placki Date: Thu, 27 Oct 2011 23:10:43 +0200 Subject: [PATCH 1/8] fix and message for building on edge of clan territory --- src/game.cpp | 10 +++++++--- src/server.cpp | 5 +++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index b2883e6..46c7a09 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1759,8 +1759,12 @@ void the_game( u16 block_owner = block ? block->getOwner() : 0; u16 block2_owner = block2 ? block2->getOwner() : 0; - if(block_owner || block2_owner ) - ownershiptext = L"Property of clan "; + if(block_owner || block2_owner ){ + if(block_owner == block2_owner) + ownershiptext = L"Property of clan "; + else + ownershiptext = L"Border of clan "; + } if(block_owner) ownershiptext += narrow_to_wide(clansManager->clanNameNoEx(block_owner)); @@ -1929,7 +1933,7 @@ void the_game( } } - if(canModify && input->getRightClicked()) + if(canModifyNeighbour && input->getRightClicked()) { infostream<<"Ground right-clicked"<canModify(&m_env.clansManager,&m_env.getMap(),NULL,NULL,&p_under) || !player->canModify(&m_env.clansManager,&m_env.getMap(),NULL,NULL,&p_over) ) + //j,placki + if( ( action == 1 && !player->canModify(&m_env.clansManager,&m_env.getMap(),NULL,NULL,&p_over) ) + ||( action != 1 && !player->canModify(&m_env.clansManager,&m_env.getMap(),NULL,NULL,&p_under) ) ) { derr_server<<"Player isn't owner of a block"< Date: Thu, 27 Oct 2011 23:17:44 +0200 Subject: [PATCH 2/8] "die" server command added --- src/server.cpp | 4 ++++ src/server.h | 1 + src/servercommand.cpp | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/src/server.cpp b/src/server.cpp index f2ba398..2239341 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -4272,6 +4272,10 @@ void Server::SendBlocks(float dtime) /* Something random */ +void Server::KillPlayer(Player *player) +{ // to consider: in creative or if hp is disabled: just respawn, so inventory is not lost + HandlePlayerHP(player,32767); +} void Server::HandlePlayerHP(Player *player, s16 damage) { diff --git a/src/server.h b/src/server.h index cc49b22..b6f6bfe 100644 --- a/src/server.h +++ b/src/server.h @@ -432,6 +432,7 @@ public: void BroadcastPlayerClan(u16 clan, const std::string& name); //j void SendClanDeleted(u16 peer_id,u16 clan); //j void BroadcastClanDeleted(u16 clan); //j + void KillPlayer(Player *player); //p u64 getPlayerAuthPrivs(const std::string &name) { diff --git a/src/servercommand.cpp b/src/servercommand.cpp index 016a043..8a81438 100644 --- a/src/servercommand.cpp +++ b/src/servercommand.cpp @@ -339,6 +339,12 @@ void cmd_clanNew(std::wostringstream &os, else os<< L"-!- Error - clan '"<parms[1]<<"' NOT added."; } +void cmd_die(std::wostringstream &os, + ServerCommandContext *ctx) +{ + ctx->server->KillPlayer(ctx->player); +} + //j void cmd_clanDelete(std::wostringstream &os, ServerCommandContext *ctx) @@ -502,6 +508,8 @@ std::wstring processServerCommand(ServerCommandContext *ctx) cmd_me(os, ctx); else if(ctx->parms[0] == L"clearobjects") cmd_clearobjects(os, ctx); + else if(ctx->parms[0] == L"die") + cmd_die(os, ctx); else if(ctx->parms[0] == L"clan-new") { cmd_clanNew(os, ctx); From d264de084cde43ee84816a036457b08d6bcbba67 Mon Sep 17 00:00:00 2001 From: placki Date: Sat, 29 Oct 2011 00:14:40 +0200 Subject: [PATCH 3/8] 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) { From f0e9065426e72c2a17b2a8ea4ed3027e425bbbbe Mon Sep 17 00:00:00 2001 From: placki Date: Sat, 29 Oct 2011 01:09:54 +0200 Subject: [PATCH 4/8] build on borders option --- minetest.conf.example | 3 ++- src/defaultsettings.cpp | 1 + src/server.cpp | 7 +++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/minetest.conf.example b/minetest.conf.example index 2cf4c6c..b706bc3 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -158,4 +158,5 @@ # 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 - +#are players allowed to build connecting to border/edge of hostile clan territory +#build_on_borders = false diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index ccacd37..3e1c98e 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -110,5 +110,6 @@ void set_default_settings(Settings *settings) settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); settings->setDefault("enable_experimental", "false"); settings->setDefault("crafted_teleports", "4"); + settings->setDefault("build_on_borders", "false"); } diff --git a/src/server.cpp b/src/server.cpp index 03b7161..dae146b 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2470,8 +2470,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) u16 item_i = readU16(&data[15]); //j,placki - if( ( action == 1 && !player->canModify(&m_env.clansManager,&m_env.getMap(),NULL,NULL,&p_over) ) - ||( action != 1 && !player->canModify(&m_env.clansManager,&m_env.getMap(),NULL,NULL,&p_under) ) ) + bool canModifyOver=player->canModify(&m_env.clansManager,&m_env.getMap(),NULL,NULL,&p_over); + bool canModifyUnder=player->canModify(&m_env.clansManager,&m_env.getMap(),NULL,NULL,&p_under); + bool canBoB=g_settings->getBool("build_on_borders"); + if((!canBoB && (!canModifyOver || !canModifyUnder)) + ||(canBoB && ((action == 1 && !canModifyOver) || (action != 1 && !canModifyUnder))) ) { derr_server<<"Player isn't owner of a block"< Date: Wed, 2 Nov 2011 13:36:19 +0100 Subject: [PATCH 5/8] +comments for teleport --- src/server.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/server.cpp b/src/server.cpp index dae146b..0497010 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1816,13 +1816,16 @@ void Server::Receive() } } +//TODO: move this to some map class? 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 { + // check player "head block" where.Y++; if(where.YgetMap().getNodeNoEx(where).getContent() == CONTENT_TELEPORT) From 409eefb2cd4863c4defe8e4b30677db5363d58e3 Mon Sep 17 00:00:00 2001 From: placki Date: Wed, 2 Nov 2011 13:36:58 +0100 Subject: [PATCH 6/8] client display of teleport names and destination --- src/game.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/game.cpp b/src/game.cpp index 46c7a09..91714e1 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1798,7 +1798,32 @@ void the_game( NodeMetadata *meta = client.getNodeMetadata(nodepos); if(meta) { + //HACK: server should not be sending teleport info to clients at all... infotext = narrow_to_wide(meta->infoText()); + MapNode n = client.getNode(nodepos); + if(n.getContent() == CONTENT_TELEPORT) + { + // meta/infotext contains text inside "" quotes. + // find 3rd comma + int icomma=infotext.find(L','); + if(icomma>0) + icomma=infotext.find(L',',icomma+1); + if(icomma>0) + icomma=infotext.find(L',',icomma+1); + + if(!canModify) + { + if(icomma<0) + infotext = L"Unnamed teleport"; + else + infotext=L"Teleport: "+infotext.substr(icomma+1,infotext.length()-icomma-2); + } + else + { + if(icomma<0) + infotext = infotext.substr(0,infotext.length()-1)+L",Unnamed\""; + } + } } //MapNode node = client.getNode(nodepos); From 7adcebc1378d3dc94176b2a7b495aed6a25eceb4 Mon Sep 17 00:00:00 2001 From: placki Date: Wed, 2 Nov 2011 14:38:43 +0100 Subject: [PATCH 7/8] Message for borderstone protected area --- src/game.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 91714e1..768b5fa 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1798,10 +1798,10 @@ void the_game( NodeMetadata *meta = client.getNodeMetadata(nodepos); if(meta) { - //HACK: server should not be sending teleport info to clients at all... + //maybe server should not be sending teleport info to clients at all? infotext = narrow_to_wide(meta->infoText()); - MapNode n = client.getNode(nodepos); - if(n.getContent() == CONTENT_TELEPORT) + content_t content = map->getNodeNoEx(nodepos).getContent(); + if(content == CONTENT_TELEPORT) { // meta/infotext contains text inside "" quotes. // find 3rd comma @@ -1824,6 +1824,17 @@ void the_game( infotext = infotext.substr(0,infotext.length()-1)+L",Unnamed\""; } } + else + if(content == CONTENT_BORDERSTONE) + { char ts[50]; + v3s16 tp=getContainerPos(nodepos,MAP_BLOCKSIZE); + tp*=MAP_BLOCKSIZE; + snprintf(ts, 50, "Protected area: %i<=X<%i, %i<=Y<%i, %i<=Z<%i", + tp.X,tp.X+MAP_BLOCKSIZE, + tp.Y,tp.Y+MAP_BLOCKSIZE, + tp.Z,tp.Z+MAP_BLOCKSIZE); + infotext=narrow_to_wide(ts).c_str(); + } } //MapNode node = client.getNode(nodepos); From adbd11e4edb29010687abebb04019151f1505938 Mon Sep 17 00:00:00 2001 From: placki Date: Wed, 2 Nov 2011 17:51:36 +0100 Subject: [PATCH 8/8] Borderstones always have valid owners. (but what happens when clan is removed?!) --- src/map.cpp | 5 ++-- src/map.h | 3 ++- src/player.cpp | 1 + src/player.h | 1 + src/server.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 12fe9b5..a47a877 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -901,7 +901,7 @@ void Map::updateLighting(core::map & a_blocks, /* */ void Map::addNodeAndUpdate(v3s16 p, MapNode n, - core::map &modified_blocks, std::string &player_name) + core::map &modified_blocks, std::string &player_name,NodeMetadata *initial_metadata) { /*PrintInfo(m_dout); m_dout<clone(); diff --git a/src/map.h b/src/map.h index c9bc817..06859c1 100644 --- a/src/map.h +++ b/src/map.h @@ -209,7 +209,8 @@ public: These handle lighting but not faces. */ void addNodeAndUpdate(v3s16 p, MapNode n, - core::map &modified_blocks, std::string &player_name); + core::map &modified_blocks, std::string &player_name, + NodeMetadata *initial_metadata=NULL); void removeNodeAndUpdate(v3s16 p, core::map &modified_blocks); diff --git a/src/player.cpp b/src/player.cpp index c104a8d..c70da52 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -41,6 +41,7 @@ Player::Player(): hp(20), peer_id(PEER_ID_INEXISTENT), clanOwner(0), + lastClan(0), m_selected_item(0), m_pitch(0), m_yaw(0), diff --git a/src/player.h b/src/player.h index ad89487..8b909c8 100644 --- a/src/player.h +++ b/src/player.h @@ -172,6 +172,7 @@ public: 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. + u16 lastClan; //server: remember last clan put into borderstone protected: diff --git a/src/server.cpp b/src/server.cpp index 0497010..c6c9ba9 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2786,12 +2786,47 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) getNodeBlockPos(p_over), BLOCK_EMERGE_FLAG_FROMDISK); return; } + + MaterialItem *mitem = (MaterialItem*)item; + + NodeMetadata *initial_metadata=NULL; + u16 newowner=0; + // Only allow borderstone if player already belongs to some clan + if(mitem->getMaterial() == CONTENT_BORDERSTONE) + { if(player->lastClan && player->clans.find(player->lastClan) == player->clans.end()) + player->lastClan=0; // was invalid (no longer member?) + if(!player->lastClan) + { if(player->clanOwner) + player->lastClan=player->clanOwner; + else + if(!player->clans.empty()) + player->lastClan=*player->clans.begin(); + } + if(!player->lastClan) + { + actionstream<getName()<<" failed to put borderstone"<getName()<<" will put cornerstone for clan " + <lastClan + <<" ["<lastClan)<<"]"<getOwner()) return; //already has owner! + + newowner=player->lastClan; + initial_metadata=new SignNodeMetadata("Property of "+m_env.clansManager.clanNameNoEx(player->lastClan)); + } // Reset build time counter getClient(peer_id)->m_time_from_building = 0.0; // Create node data - MaterialItem *mitem = (MaterialItem*)item; MapNode n; n.setContent(mitem->getMaterial()); @@ -2855,7 +2890,22 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) MapEditEventIgnorer ign(&m_ignore_map_edit_events); std::string p_name = std::string(player->getName()); - m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name); + m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name, initial_metadata); + if(initial_metadata) delete initial_metadata; + if(newowner) + { + MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(getNodeBlockPos(p_over)); + assert(block != NULL); + block->setOwner(newowner); + // force update for all clients + for(core::map::Iterator + i = m_clients.getIterator(); + i.atEnd()==false; i++) + { + RemoteClient *client = i.getNode()->getValue(); + if(client) client->SetBlockNotSent(getNodeBlockPos(p_over)); + } + } } /* Set blocks not sent to far players @@ -3061,25 +3111,30 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } u16 clan = (u16)i_clan;*/ - bool nullclan = false; - if(clanName == "#" || clanName == "" || clanName == "nobody") nullclan = true; +// bool nullclan = false; +// if(clanName == "#" || clanName == "" || clanName == "nobody") nullclan = true; u16 clan = 0; - if(!nullclan){ +// if(!nullclan){ clan = m_env.clansManager.clanId(clanName); if(!clan){ derr_server<<"Wrong clan name"<clans.find(clan) == player->clans.end()) return; block->setOwner(clan); - if(clan) text = "Property of " + clanName; - else text = "Property of nobody"; + player->lastClan=clan; + text = "Property of " + m_env.clansManager.clanNameNoEx(clan); } else if( node.getContent() == CONTENT_TELEPORT ){ //j teleport