first version of naming system for teleports

master
jachoo 2011-11-14 07:00:29 +01:00
parent 6944fd5c19
commit 060888c0cc
11 changed files with 597 additions and 123 deletions

View File

@ -128,6 +128,7 @@ set(common_SRCS
base64.cpp
ban.cpp
clans.cpp
teleports.cpp
)
# This gives us the icon
@ -175,6 +176,81 @@ set(minetestserver_SRCS
servermain.cpp
)
# Want to see header files in solution explorer
if(MSVC)
set(common_HDRS
log.h
content_sao.h
mapgen.h
content_inventory.h
content_nodemeta.h
content_craft.h
content_mapnode.h
auth.h
collision.h
nodemetadata.h
serverobject.h
noise.h
mineral.h
porting.h
materials.h
defaultsettings.h
mapnode.h
voxel.h
inventory.h
debug.h
serialization.h
light.h
filesys.h
connection.h
environment.h
server.h
servercommand.h
socket.h
mapblock.h
mapsector.h
map.h
player.h
utility.h
test.h
sha1.h
base64.h
ban.h
clans.h
teleports.h
)
set(minetest_HDRS
${common_HDRS}
MyBillboardSceneNode.h
content_mapblock.h
content_cao.h
mapblock_mesh.h
farmesh.h
keycode.h
camera.h
clouds.h
clientobject.h
guiMainMenu.h
guiKeyChangeMenu.h
guiMessageMenu.h
guiTextInputMenu.h
guiInventoryMenu.h
guiPauseMenu.h
guiPasswordChange.h
guiDeathScreen.h
client.h
tile.h
game.h
main.h
)
set(minetestserver_HDRS
${common_HDRS}
)
set(common_SRCS ${common_SRCS} ${common_HDRS})
set(minetest_SRCS ${minetest_SRCS} ${minetest_HDRS})
set(minetestserver_SRCS ${minetestserver_SRCS} ${minetestserver_HDRS})
endif()
include_directories(
${PROJECT_BINARY_DIR}
${IRRLICHT_INCLUDE_DIR}

View File

@ -111,5 +111,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("enable_experimental", "false");
settings->setDefault("crafted_teleports", "4");
settings->setDefault("build_on_borders", "false");
settings->setDefault("teleport_allow_coords", "false");
settings->setDefault("teleport_allow_oneway", "true");
}

View File

@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "utility.h"
#include "activeobject.h"
#include "clans.h"
#include "teleports.h"
class Server;
class ActiveBlockModifier;
@ -86,6 +87,7 @@ public:
//j
ClansManager clansManager;
protected:
// peer_ids in here should be unique, except that there may be many 0s
core::list<Player*> m_players;

View File

@ -1809,24 +1809,24 @@ void the_game(
{
// meta/infotext contains text inside "" quotes.
// find 3rd comma
int icomma=infotext.find(L',');
/*int icomma=infotext.find(L',');
if(icomma>0)
icomma=infotext.find(L',',icomma+1);
if(icomma>0)
icomma=infotext.find(L',',icomma+1);
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\"";
}
//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\"";
//}
}
else
if(content == CONTENT_BORDERSTONE)

View File

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h"
#include "mapgen.h"
#include "nodemetadata.h"
#include "content_nodemeta.h"
#include "content_mapnode.h"
#ifndef SERVER
#include <IMaterialRenderer.h>
@ -1177,6 +1178,19 @@ void Map::removeNodeAndUpdate(v3s16 p,
light_sources, modified_blocks);
}
//j
//If removing a teleport -> remove its name from manager
try{
ServerMap& smap = dynamic_cast<ServerMap&>(*this);
if(getNode(p).getContent() == CONTENT_TELEPORT){
SignNodeMetadata* meta = (SignNodeMetadata*)getNodeMetadata(p);
TeleportInfo ti;
if(meta && getTeleportInfo(ti,meta->getText(),true,true,true) && !ti.thisName.empty())
smap.teleportsManager.removeNoEx(ti.thisName,p);
}
}catch(std::bad_cast&){}
/*
Remove node metadata
*/
@ -1923,7 +1937,7 @@ void Map::nodeMetadataStep(float dtime,
ServerMap::ServerMap(std::string savedir):
Map(dout_server),
m_seed(0),
m_map_metadata_changed(true),
/*m_map_metadata_changed(true),*/
m_database(NULL),
m_database_read(NULL),
m_database_write(NULL)
@ -2853,10 +2867,10 @@ void ServerMap::save(bool only_changed)
infostream<<"ServerMap: Saving whole map, this can take time."
<<std::endl;
if(only_changed == false || m_map_metadata_changed)
{
/*if(only_changed == false || m_map_metadata_changed)
{*/
saveMapMeta();
}
/*}*/
u32 sector_meta_count = 0;
u32 block_count = 0;
@ -2984,11 +2998,13 @@ void ServerMap::saveMapMeta()
Settings params;
params.setU64("seed", m_seed);
teleportsManager.save(params);
params.writeLines(os);
os<<"[end_of_params]\n";
m_map_metadata_changed = false;
/*m_map_metadata_changed = false;*/
}
void ServerMap::loadMapMeta()
@ -3023,8 +3039,13 @@ void ServerMap::loadMapMeta()
}
m_seed = params.getU64("seed");
infostream<<"ServerMap::loadMapMeta(): "<<"seed="<<m_seed<<std::endl;
try{
teleportsManager.load(params);
}catch(SettingNotFoundException &e){
// This is not as important
}
}
void ServerMap::saveSectorMeta(ServerMapSector *sector)

View File

@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapblock_nodemod.h"
#include "constants.h"
#include "voxel.h"
#include "teleports.h"
extern "C" {
#include "sqlite3.h"
@ -435,6 +436,9 @@ public:
u64 getSeed(){ return m_seed; }
//j
TeleportsManager teleportsManager;
private:
// Seed used for all kinds of randomness
u64 m_seed;
@ -454,7 +458,7 @@ private:
Metadata is re-written on disk only if this is true.
This is reset to false when written on disk.
*/
bool m_map_metadata_changed;
//bool m_map_metadata_changed;
/*
SQLite database and statements

View File

@ -1816,43 +1816,73 @@ void Server::Receive()
}
}
//TODO: move this to some map class?
// throws InvalidPositionException (where = that wrong position)
bool getTeleportTarget(/*const*/ ServerEnvironment *m_env,/*in+out*/ v3s16 &where,/*out*/v3f &tgt)
bool getTeleportTarget(/*const*/ ServerEnvironment& env,/*in+out*/ v3s16 &where,/*out*/v3f &tgt)
{
// actionstream<<"Is Teleport at: "<<"("<<where.X<<","<<where.Y<<","<<where.Z<<") "<<std::endl;
ServerMap& map = env.getServerMap();
SignNodeMetadata* meta=NULL;
// check player "foot block"
if(m_env->getMap().getNode(where).getContent() == CONTENT_TELEPORT)
meta = (SignNodeMetadata*)m_env->getMap().getNodeMetadata(where);
if(map.getNode(where).getContent() == CONTENT_TELEPORT)
meta = (SignNodeMetadata*)map.getNodeMetadata(where);
else {
// check player "head block"
where.Y++;
if(where.Y<MAP_GENERATION_LIMIT-1)
if(m_env->getMap().getNode(where).getContent() == CONTENT_TELEPORT)
meta = (SignNodeMetadata*)m_env->getMap().getNodeMetadata(where);
if(map.getNode(where).getContent() == CONTENT_TELEPORT)
meta = (SignNodeMetadata*)map.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: "<<"("<<tgt.X<<","<<tgt.Y<<","<<tgt.Z<<") "<<std::endl;
static const bool allowCoords = g_settings->getBool("teleport_allow_coords");
static const bool allowOneWay = g_settings->getBool("teleport_allow_oneway");
tgt.X = core::round_(tgt.X);
tgt.Y = core::round_(tgt.Y);
tgt.Z = core::round_(tgt.Z);
TeleportInfo ti;
if( !getTeleportInfo(ti, text, allowCoords, true, true) ) return false;
try{
//first, check if teleport has coords target (if allowed)
if(allowCoords && ti.targetLocation.X != TELEPORT_IGNORE){
tgt.X = ti.targetLocation.X;
tgt.Y = ti.targetLocation.Y;
tgt.Z = ti.targetLocation.Z;
return true;
}
//next, check if it is one-way teleport (if allowed)
if(allowOneWay && !ti.targetName.empty()){
//one way teleport
v3s16 target = map.teleportsManager.getTarget(ti.targetName,where);
tgt.X = target.X;
tgt.Y = target.Y;
tgt.Z = target.Z;
return true;
}
return true;
//last, check if it is two-way teleport
if(!ti.thisName.empty()){
//one way teleport
v3s16 target = map.teleportsManager.getTarget(ti.thisName,where);
tgt.X = target.X;
tgt.Y = target.Y;
tgt.Z = target.Z;
return true;
}
//if we are here, that's bad...
return false;
}catch(TeleportManagerException&){
return false;
}
}
return false;
}
@ -1860,13 +1890,6 @@ bool getTeleportTarget(/*const*/ ServerEnvironment *m_env,/*in+out*/ v3s16 &wher
static void getTeleportDirection(const MapNode& in, const MapNode& out, Player& player)
{
#if 1
#define JLOG(x) std::cout << x << std::endl
#define JV3(x) '[' << x.X << ',' << x.Y << ',' << x.Z << ']'
#else
#define JLOG(x)
#endif
JLOG("---------------");
JLOG("old pitch: " << player.getPitch());
@ -2330,7 +2353,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
v3s16 posi_temp = tele_posi;
try{
v3f tgtf;
if(getTeleportTarget(&m_env,posi_temp,tgtf)){
if(getTeleportTarget(m_env,posi_temp,tgtf)){
if(player->lastTeleportPos == tgtf*BS)
return; //already checked... and failed, so skip checks.
player->lastTeleportPos=tgtf*BS;
@ -2352,27 +2375,37 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if(content_features(c1).walkable || content_features(c2).walkable)
return;
if(teleport_option > 1){
posi_temp=floatToInt(tgtf, 1);
bool loop=false, first=true;
while(!loop && teleport_option>1)
{ //check if there is teleport at primary teleport target, and it loops back.
v3f tgtfnext;
if(getTeleportTarget(&m_env,posi_temp,tgtfnext)){
if(first){
JLOG("wyjscie: " << JV3(posi_temp));
getTeleportDirection(entry,m_env.getMap().getNode(posi_temp),*player);
}
posi_temp=floatToInt(tgtfnext, 1);
loop=(tele_posi.getDistanceFrom(posi_temp)<=1); // tile away
//actionstream<<" D:"<<tele_posi.getDistanceFrom(posi_temp)<<" from="<<"("<<tgtf.X<<","<<tgtf.Y<<","<<tgtf.Z<<")"<<
//" to="<<"("<<tgtfnext.X<<","<<tgtfnext.Y<<","<<tgtfnext.Z<<") "<< std::endl;
} else return; //no teleport at destination
teleport_option--;
first = false;
}
if(!loop)
return;
//if(teleport_option > 1){
// posi_temp=floatToInt(tgtf, 1);
// bool loop=false, first=true;
// while(!loop && teleport_option>1)
// { //check if there is teleport at primary teleport target, and it loops back.
// v3f tgtfnext;
// if(getTeleportTarget(m_env,posi_temp,tgtfnext)){
// if(first){
// JLOG("wyjscie: " << JV3(posi_temp));
// getTeleportDirection(entry,m_env.getMap().getNode(posi_temp),*player);
// }
// posi_temp=floatToInt(tgtfnext, 1);
// loop=(tele_posi.getDistanceFrom(posi_temp)<=1); // tile away
// //actionstream<<" D:"<<tele_posi.getDistanceFrom(posi_temp)<<" from="<<"("<<tgtf.X<<","<<tgtf.Y<<","<<tgtf.Z<<")"<<
// //" to="<<"("<<tgtfnext.X<<","<<tgtfnext.Y<<","<<tgtfnext.Z<<") "<< std::endl;
// } else return; //no teleport at destination
// teleport_option--;
// first = false;
// }
// if(!loop)
// return;
//}
posi_temp = floatToInt(tgtf,1);
MapNode outNode = m_env.getMap().getNode(posi_temp);
if(outNode.getContent() != CONTENT_TELEPORT){
posi_temp.Y+=1;
outNode = m_env.getMap().getNode(posi_temp);
}
if(outNode.getContent() == CONTENT_TELEPORT){
JLOG("wyjscie: " << JV3(posi_temp));
getTeleportDirection(entry,outNode,*player);
}
dout_server << "Teleporting: " << tgtf.X << " " << tgtf.Y << " " << tgtf.Z << std::endl;
@ -3224,6 +3257,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
MapNode node = m_env.getMap().getNodeNoEx(p);
SignNodeMetadata *signmeta = (SignNodeMetadata*)meta;
//if(text.length()>1 && text[0]=='#'){
if( node.getContent() == CONTENT_BORDERSTONE ){
@ -3267,20 +3301,35 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
//j teleport
//std::string st = text;
//str_replace_char(st,',',' ');
//float f[3];
//std::istringstream is(st);
//is >> f[0] >> f[1] >> f[2];
static const bool allowCoords = g_settings->getBool("teleport_allow_coords");
static const bool allowOneWay = g_settings->getBool("teleport_allow_oneway");
////TODO: map limits!
//for(int i=0; i<3; i++)
// if(f[i]>32000 || f[i]<-32000) f[i]=0;
//delete old name if exists
TeleportInfo tl;
if(getTeleportInfo(tl,signmeta->getText(),false,false,true) && !tl.thisName.empty()){
m_env.getServerMap().teleportsManager.removeNoEx(tl.thisName,p);
}
//text = ftos(f[0]) + "," + ftos(f[1]) + "," + ftos(f[2]);
//add new name if possible
TeleportInfo ti;
if(getTeleportInfo(ti,text,allowCoords,allowOneWay,true)){
//if(allowCoords && ti.targetLocation.X != TELEPORT_IGNORE){
// //target = coordinates
// //don't add anything
//}
//if(allowOneWay && !ti.targetName.empty()){
// //target = name (one-way)
// //don't add anything too
//}
if(!ti.thisName.empty()){
//this node will have a name
//add this
m_env.getServerMap().teleportsManager.addNoEx(ti.thisName,p);
}
}
}
SignNodeMetadata *signmeta = (SignNodeMetadata*)meta;
signmeta->setText(text);
actionstream<<player->getName()<<" writes \""<<text<<"\" to sign "

View File

@ -22,7 +22,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string>
std::string trim(const std::string &str);
inline std::string trim(const std::string& source, const char* delims = " \t\r\n", const int delims_cnt = 4) {
std::string::size_type first = source.find_first_not_of(delims,0,delims_cnt);
if(first==std::string::npos) return "";
std::string::size_type last = source.find_last_not_of(delims,std::string::npos,delims_cnt);
return source.substr(first,last-first+1);
}
class Strfnd{
std::string tek;
@ -124,43 +133,5 @@ public:
}
};
inline std::string trim(const std::string &s)
{
std::string str = s;
while(
str.length()>0
&&
(
str.substr(0, 1)==" " ||
str.substr(0, 1)=="\t" ||
str.substr(0, 1)=="\r" ||
str.substr(0, 1)=="\n" ||
str.substr(str.length()-1, 1)==" " ||
str.substr(str.length()-1, 1)=="\t" ||
str.substr(str.length()-1, 1)=="\r" ||
str.substr(str.length()-1, 1)=="\n"
)
)
{
if (str.substr(0, 1)==" ")
str = str.substr(1,str.length()-1);
else if (str.substr(0, 1)=="\t")
str = str.substr(1,str.length()-1);
else if (str.substr(0, 1)=="\r")
str = str.substr(1,str.length()-1);
else if (str.substr(0, 1)=="\n")
str = str.substr(1,str.length()-1);
else if (str.substr(str.length()-1, 1)==" ")
str = str.substr(0,str.length()-1);
else if (str.substr(str.length()-1, 1)=="\t")
str = str.substr(0,str.length()-1);
else if (str.substr(str.length()-1, 1)=="\r")
str = str.substr(0,str.length()-1);
else if (str.substr(str.length()-1, 1)=="\n")
str = str.substr(0,str.length()-1);
}
return str;
}
#endif

218
src/teleports.cpp Normal file
View File

@ -0,0 +1,218 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU 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.
Author: Jan Cychnerski
*/
#include "teleports.h"
#include "settings.h"
bool TeleportsManager::addNoEx(const std::string& name, const v3s16& coords)
{
JLOG("Probuje dodac nazwe " << name << " na " << JV3(coords) );
if(coords.X == TELEPORT_IGNORE) return false;
TeleportLink& link = m_links[name];
int i;
for(i=0;link.coords[i].X != TELEPORT_IGNORE;i++); //find first empty slot for coords
if(i>=2) return false;
for(int j=0;j<2;j++) //if already exists -> report success
if(link.coords[j] == coords) return true;
JLOG("Dodaje nazwe " << name << " na " << JV3(coords) );
link.coords[i] = coords;
return true;
}
bool TeleportsManager::removeNoEx(const std::string& name, const v3s16& coords)
{
JLOG("Usuwam " << name << " z " << JV3(coords) << "...");
links_t::iterator it = m_links.find(name);
if(it==m_links.end()) return false;
TeleportLink& link = it->second;
if(link.coords[0] == coords){
if(link.coords[1].X == TELEPORT_IGNORE){
//remove entire link
m_links.erase(name);
return true;
}
link.coords[0] = link.coords[1];
link.coords[1].X = TELEPORT_IGNORE;
}else if(link.coords[1] == coords){
link.coords[1].X = TELEPORT_IGNORE;
}else if(link.coords[0].X == TELEPORT_IGNORE && link.coords[1].X == TELEPORT_IGNORE){
m_links.erase(name);
}else return false;
return true;
}
bool TeleportsManager::renameNoEx(const std::string& oldName, const v3s16& coords, const std::string& newName)
{
JLOG("Zmieniam nazwe " << oldName << " na " << newName);
removeNoEx(oldName,coords);
if(!addNoEx(newName,coords)) return false;
return true;
}
const v3s16& TeleportsManager::getTarget(const std::string& name, const v3s16& not_this) const
{
JLOG("Odczytuje cel " << name);
links_t::const_iterator it = m_links.find(name);
if(it==m_links.end()) throw TeleportManagerException();
const TeleportLink& link = it->second;
for(int i=0; i<2; i++)
if( link.coords[i].X != TELEPORT_IGNORE && link.coords[i] != not_this)
return link.coords[i];
throw TeleportManagerException();
}
const v3s16& TeleportsManager::getTarget(const std::string& name) const
{
static const v3s16 nowhere(-32768,-32768,-32768);
return getTarget(name,nowhere);
}
void TeleportsManager::save(Settings& args) const
{
std::ostringstream os;
for(links_t::const_iterator it=m_links.begin(); it!=m_links.end(); it++){
const TeleportLink& t = it->second;
os << it->first << ' '; //name
for(int i=0; i<2; i++) //coords
if(t.coords[i].X == TELEPORT_IGNORE) //if coord ignored - don't save Y and Z
os << TELEPORT_IGNORE << ' ';
else os << t.coords[i].X << ' ' << t.coords[i].Y << ' ' << t.coords[i].Z << ' ';
}
args.set("teleports",os.str());
}
void TeleportsManager::load(Settings& args)
{
try{
std::string s = args.get("teleports");
std::istringstream is(s);
while(is.good() && !is.eof()){
std::string name;
is >> name;
if(name.length() == 0) continue;
if(is.bad() || is.eof()) break;
for(int i=0; i<2; i++){
v3s16 v;
is >> v.X;
if(v.X != TELEPORT_IGNORE){
is >> v.Y >> v.Z;
addNoEx(name,v);
}
}
}
}catch(...){
//TODO: what to do?
}
}
bool getTeleportInfo(TeleportInfo& ti, const std::string& text, bool allowCoords, bool allowUnnamed, bool ignoreDescription)
{
//possible values:
//a. X,Y,Z
//b. X,Y,Z,description
//c. name
//d. name,description
//e. name->targetname
//f. name->targetname,description
//g. ->targetname
//h. ->targetname,description
//SPACES allowed EVERYWHERE! (but first char maybe)
//COMMAS allowed in DESCRIPTION
//(so may be "myhouse->mine,Some very, very, very strange description")
//a,b correct only if allowCoords=true
//g,h correct only if allowUnnamed=true
JLOG("getTeleportInfo(" << text << ")");
#define JLOGTI(x) JLOG( "ti: " << x.thisName << " -> " << x.targetName << " " << JV3(x.targetLocation) << " - " << x.description)
if(text.empty())return false;
const int maxCnt = allowCoords ? 4 : 2;
std::vector<std::string> parts = str_split(text,',',maxCnt);
//if(parts.size()==0) return false; //impossible?
if(!allowUnnamed && parts[0].empty()) return false;
if(allowCoords && parts.size() >= 3){ //possibly coords (a or b)
try{
v3s16 tgt;
tgt.X = core::round_( stof_ex(parts[0]) );
tgt.Y = core::round_( stof_ex(parts[1]) );
tgt.Z = core::round_( stof_ex(parts[2]) );
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
) return false; //bad coords!
ti.targetLocation = tgt; //good coords
if(!ignoreDescription && parts.size()==4) //description is given?
ti.description = parts[3];
JLOG("Koordynaty: " << JV3(tgt));
JLOGTI(ti);
return true;
}catch(std::ios::failure&){ //bad number format
JLOG("Bad number format");
}
}
//find if parts[0] has target name
int pos = parts[0].find("->");
if(!allowUnnamed && pos==0) JLOGAND("no 'thisname'", return false;) //no 'thisname' specified
if(pos != std::string::npos){ //yes, split it to 'thisname' and 'targetname'
if(pos>0) ti.thisName = trim(parts[0].substr(0,pos));
if(pos+2<parts[0].length()) ti.targetName = trim(parts[0].substr(pos+2));
}else ti.thisName = parts[0]; //no, it's just 'thisname'
//do we have description?
if(!ignoreDescription && parts.size()>1){
//yes, desc is the rest of 'parts'
for(unsigned i=1; i<parts.size(); i++)
ti.description += parts[i];
}
JLOGTI(ti);
return true;
}

99
src/teleports.h Normal file
View File

@ -0,0 +1,99 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU 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.
*/
/*
teleports.h - author: Jan Cychnerski
*/
#ifndef TELEPORTS_HEADER
#define TELEPORTS_HEADER
#include "common_irrlicht.h"
#include "utility.h"
#include <map>
#include <vector>
#include <string>
#define TELEPORT_IGNORE -32768
class Settings;
class TeleportManagerException : public BaseException {
public:
TeleportManagerException():BaseException("Teleport manager exception"){}
};
struct TeleportLink {
v3s16 coords[2]; //if X == TELEPORT_IGNORE then ignore it!
//std::string name;
TeleportLink(){
coords[0].X = TELEPORT_IGNORE;
coords[1].X = TELEPORT_IGNORE;
}
};
class TeleportsManager {
public:
//NOTE: all methods (except *NoEx) throw if name is not defined!
//returns false if error
bool addNoEx(const std::string& name, const v3s16& coords);
bool removeNoEx(const std::string& name, const v3s16& coords);
bool renameNoEx(const std::string& oldName, const v3s16& coords, const std::string& newName);
//returns coords of teleport, but not equal to not_this (if many, returns first)
const v3s16& getTarget(const std::string& name, const v3s16& not_this) const;
//returns coords of this name
const v3s16& getTarget(const std::string& name) const;
void save(Settings& args) const;
void load(Settings& args);
private:
typedef std::map<std::string,TeleportLink> links_t;
links_t m_links;
};
#if 1
#define JLOG(x) std::cout << x << std::endl
#define JV3(x) '[' << x.X << ',' << x.Y << ',' << x.Z << ']'
#define JLOGAND(x,y) { JLOG(x); y }
#else
#define JLOG(x)
#define JLOGAND(x,y) y
#endif
struct TeleportInfo {
std::string thisName, targetName, description;
v3s16 /*thisLocation,*/ targetLocation;
TeleportInfo(): targetLocation(TELEPORT_IGNORE,TELEPORT_IGNORE,TELEPORT_IGNORE) {}
};
bool getTeleportInfo(TeleportInfo& ti, const std::string& text, bool allowCoords, bool allowUnnamed, bool ignoreDescription);
#endif

View File

@ -775,17 +775,28 @@ inline std::string wide_to_narrow(const std::wstring& wcs)
// Split a string using the given delimiter. Returns a vector containing
// the component parts.
inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
// Optionally limits output strings (0 = unlimited)
template<class T, class D>
inline std::vector<T> str_split(const T& str, const D& delimiter, int limit = 0)
{
std::vector<std::wstring> parts;
std::wstringstream sstr(str);
std::wstring part;
while(std::getline(sstr, part, delimiter))
parts.push_back(part);
std::vector<T> parts;
int pos = 0, lpos = 0;
while( --limit && pos != T::npos ){
pos = str.find(delimiter,lpos);
parts.push_back( str.substr(lpos, pos-lpos) );
lpos = pos+1;
}
if(limit==0 && pos != T::npos)
parts.push_back( str.substr(lpos) );
return parts;
}
/*
See test.cpp for example cases.
wraps degrees to the range of -360...360
@ -894,6 +905,27 @@ inline float stof(std::string s)
#endif
//throws if error
template<class T, class Str>
inline T stonum_ex(const typename Str& s)
{
typedef typename Str::value_type char_t;
T f;
std::basic_istringstream<char_t> ss(s);
ss.exceptions(std::ios::failbit);
ss>>f;
return f;
}
template<class Str>
inline float stof_ex(const typename Str& s) { return stonum_ex<float>(s); }
template<class Str>
inline double stod_ex(const typename Str& s) { return stonum_ex<double>(s); }
template<class Str>
inline double stoi_ex(const typename Str& s) { return stonum_ex<int>(s); }
inline std::string itos(s32 i)
{
std::ostringstream o;