first version of naming system for teleports
This commit is contained in:
parent
6944fd5c19
commit
060888c0cc
@ -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}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
28
src/game.cpp
28
src/game.cpp
@ -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)
|
||||
|
33
src/map.cpp
33
src/map.cpp
@ -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)
|
||||
|
@ -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
|
||||
|
163
src/server.cpp
163
src/server.cpp
@ -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 "
|
||||
|
49
src/strfnd.h
49
src/strfnd.h
@ -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
218
src/teleports.cpp
Normal 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
99
src/teleports.h
Normal 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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user