You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1281 lines
34 KiB
1281 lines
34 KiB
|
|
#include "modelbahn.h"
|
|
#include "server.h"
|
|
#include "debug.h"
|
|
|
|
Railways::Railways() {
|
|
debug (0, "* Railways Constructor");
|
|
height = 0;
|
|
width = 0;
|
|
railways = NULL;
|
|
pthread_mutex_init(&mtx, NULL);
|
|
changed = 0;
|
|
};
|
|
|
|
|
|
Railways::~Railways() {
|
|
if (railways) free (railways);
|
|
height = 0;
|
|
width = 0;
|
|
};
|
|
|
|
|
|
//
|
|
// thread protection: lock
|
|
int Railways::Lock() {
|
|
if (pthread_mutex_lock(&mtx) == 0) return 1;
|
|
else return 0;
|
|
};
|
|
|
|
|
|
//
|
|
// thread protection: unlock
|
|
int Railways::UnLock() {
|
|
if (pthread_mutex_unlock(&mtx) == 0) return 1;
|
|
else return 0;
|
|
};
|
|
|
|
|
|
//
|
|
// data must be mutex looked before use
|
|
struct s_findway_data Railways::NextPos(struct s_findway_data pos, int dirtype) {
|
|
struct s_findway_data np = { x: -1, y: -1, enterfrom: -1, oldx: pos.x, oldy:pos.y,
|
|
oldenterfrom: pos.enterfrom,
|
|
dist: pos.dist + 1,
|
|
way: pos.way }; // newpos
|
|
|
|
if (dirtype == 1) {
|
|
if (pos.enterfrom == EF_NORTH) {
|
|
np.x = pos.x;
|
|
np.y = pos.y + 1 ;
|
|
np.enterfrom = EF_NORTH;
|
|
return np;
|
|
} else if (pos.enterfrom == EF_SOUTH) {
|
|
np.x = pos.x;
|
|
np.y = pos.y - 1;
|
|
np.enterfrom = EF_SOUTH;
|
|
return np;
|
|
}
|
|
}
|
|
else if (dirtype == 2) {
|
|
if (pos.enterfrom == EF_WEST) {
|
|
np.x = pos.x + 1;
|
|
np.y = pos.y;
|
|
np.enterfrom = EF_WEST;
|
|
return np;
|
|
} else if (pos.enterfrom == EF_EAST) {
|
|
np.x = pos.x - 1;
|
|
np.y = pos.y;
|
|
np.enterfrom = EF_EAST;
|
|
return np;
|
|
}
|
|
}
|
|
else if (dirtype == 3) {
|
|
if (pos.enterfrom == EF_WEST) {
|
|
np.x = pos.x;
|
|
np.y = pos.y - 1;
|
|
np.enterfrom = EF_SOUTH;
|
|
return np;
|
|
} else if (pos.enterfrom == EF_NORTH){
|
|
np.x = pos.x - 1;
|
|
np.y = pos.y;
|
|
np.enterfrom = EF_EAST;
|
|
return np;
|
|
}
|
|
}
|
|
else if (dirtype == 4) {
|
|
if (pos.enterfrom == EF_NORTH) {
|
|
np.x = pos.x + 1;
|
|
np.y = pos.y;
|
|
np.enterfrom = EF_WEST;
|
|
return np;
|
|
} else if (pos.enterfrom == EF_EAST){
|
|
np.x = pos.x;
|
|
np.y = pos.y - 1;
|
|
np.enterfrom = EF_SOUTH;
|
|
return np;
|
|
}
|
|
}
|
|
else if (dirtype == 5) {
|
|
if (pos.enterfrom == EF_SOUTH) {
|
|
np.x = pos.x + 1;
|
|
np.y = pos.y;
|
|
np.enterfrom = EF_WEST;
|
|
return np;
|
|
} else if (pos.enterfrom == EF_EAST){
|
|
np.x = pos.x;
|
|
np.y = pos.y + 1;
|
|
np.enterfrom = EF_NORTH;
|
|
return np;
|
|
}
|
|
}
|
|
else if (dirtype == 6) {
|
|
if (pos.enterfrom == EF_WEST) {
|
|
np.x = pos.x;
|
|
np.y = pos.y + 1;
|
|
np.enterfrom = EF_NORTH;
|
|
return np;
|
|
} else if (pos.enterfrom == EF_SOUTH){
|
|
np.x = pos.x - 1;
|
|
np.y = pos.y;
|
|
np.enterfrom = EF_EAST;
|
|
return np;
|
|
}
|
|
}
|
|
else {
|
|
debug (0, "Railways::NextPos dirtype unknown:%d", dirtype);
|
|
return np;
|
|
}
|
|
|
|
return np;
|
|
};
|
|
|
|
|
|
//
|
|
// return index inside the array (clip to boundery)
|
|
int Railways::GetRIdx(int x, int y) {
|
|
int _x, _y;
|
|
|
|
if (x < 0) _x = 0;
|
|
else if (x >= width) _x = width-1;
|
|
else _x = x;
|
|
|
|
if (y < 0) _y = 0;
|
|
else if (y >= height) _y = height-1;
|
|
else _y = y;
|
|
|
|
return (_x + _y * width);
|
|
};
|
|
|
|
|
|
//
|
|
// return JSON strign with the Railway data
|
|
// not thread safe !!!!
|
|
JSONParse Railways::_GetJSONRailway(int x, int y) {
|
|
JSONParse json;
|
|
JSONElement je;
|
|
int idx = GetRIdx(x,y);
|
|
string text = "";
|
|
|
|
json.Clear();
|
|
json.AddObject("x", x);
|
|
json.AddObject("y", y);
|
|
json.AddObject("dir", railways[idx].dir);
|
|
json.AddObject("altdir", railways[idx].altdir);
|
|
json.AddObject("type", railways[idx].type);
|
|
json.AddObject("maxspeed", railways[idx].maxspeed);
|
|
json.AddObject("flags", railways[idx].flags);
|
|
text = railways[idx].lockedby;
|
|
json.AddObject("lockedby", text);
|
|
text = railways[idx].name;
|
|
json.AddObject("name", text);
|
|
|
|
return json;
|
|
};
|
|
|
|
|
|
//
|
|
// return JSON strign with the Railway data
|
|
// thread safe.
|
|
JSONParse Railways::GetJSONRailway(int x, int y) {
|
|
JSONParse json;
|
|
|
|
Lock();
|
|
json = _GetJSONRailway(x, y);
|
|
UnLock();
|
|
|
|
return json;
|
|
};
|
|
|
|
|
|
Railway Railways::GetRailwayFromJSON(JSONParse *j) {
|
|
string text;
|
|
Railway r = {
|
|
type: RAILWAY_NOTHING,
|
|
x: 0,
|
|
y: 0,
|
|
dir: 0,
|
|
altdir: 0,
|
|
maxspeed: -1,
|
|
flags: 0,
|
|
name: { 0 }
|
|
};
|
|
r.name[0] = 0;
|
|
r.lockedby[0] = 0;
|
|
|
|
j->GetValueInt("x", &r.x);
|
|
j->GetValueInt("y", &r.y);
|
|
j->GetValueInt("dir", &r.dir);
|
|
j->GetValueInt("altdir", &r.altdir);
|
|
j->GetValueInt("type", &r.type);
|
|
j->GetValueInt("maxspeed", &r.maxspeed);
|
|
j->GetValueInt("flags", &r.flags);
|
|
j->GetValue("name", &text);
|
|
strncpy (r.name, text.c_str(), REFERENCENAME_LEN);
|
|
j->GetValue("lockedby", &text);
|
|
strncpy (r.lockedby, text.c_str(), REFERENCENAME_LEN);
|
|
|
|
return r;
|
|
};
|
|
|
|
|
|
//
|
|
// return some data about the railway/tracks
|
|
//
|
|
JSONParse Railways::GetJSONTrack() {
|
|
JSONParse json;
|
|
JSONParse jsondata;
|
|
JSONElement je;
|
|
|
|
json.Clear();
|
|
json.AddObject("height", height);
|
|
json.AddObject("width", width);
|
|
|
|
return json;
|
|
};
|
|
|
|
//
|
|
// change railway
|
|
// return 1 on change
|
|
int Railways::Change(Railway *rw) {
|
|
int result = 1;
|
|
JSONParse json;
|
|
|
|
if (rw == NULL) return 0;
|
|
Lock();
|
|
|
|
if (rw->x < 0 || rw->x >= width) result = 0;
|
|
else if (rw->y < 0 || rw->y >= height) result = 0;
|
|
else if (rw->dir < 0 || rw->dir > 6) result = 0;
|
|
else {
|
|
changed = true;
|
|
result = 1;
|
|
|
|
//
|
|
// need to delete?
|
|
if (rw->type == RAILWAY_NOTHING) {
|
|
Railway *r = &railways[GetRIdx(rw->x, rw->y)];
|
|
|
|
r->type = RAILWAY_NOTHING;
|
|
r->dir = 0;
|
|
r->altdir = 0;
|
|
r->flags = 0;
|
|
r->maxspeed = 0;
|
|
r->x = rw->x;
|
|
r->y = rw->y;
|
|
r->name[0] = 0;
|
|
r->lockedby[0] = 0;
|
|
}
|
|
|
|
//
|
|
// add normal railway
|
|
else if (rw->type == RAILWAY_NORMAL) {
|
|
railways[GetRIdx(rw->x, rw->y)] = *rw;
|
|
}
|
|
|
|
//
|
|
// add normal railway
|
|
else if (rw->type < RAILWAY_MAX) {
|
|
railways[GetRIdx(rw->x, rw->y)] = *rw;
|
|
}
|
|
|
|
else {
|
|
debug (DEBUG_INFO, "%s:%d add unknown %d,%d dir(%d) type:%d", __FILE__, __LINE__, rw->x, rw->y, rw->dir, rw->type);
|
|
}
|
|
}
|
|
|
|
UnLock();
|
|
return result;
|
|
};
|
|
|
|
//
|
|
// redefine the size of the track, keep data
|
|
void Railways::SetSize (int neww, int newh) {
|
|
Railway *rarray = railways;
|
|
int ow = width;
|
|
int oh = height;
|
|
int x, y;
|
|
|
|
debug (0, "* Railways::SetSize (%d, %d)", neww, newh);
|
|
|
|
Lock();
|
|
|
|
//
|
|
// old values saved during call up of the function, create new array for the railways data
|
|
railways = NULL;
|
|
_New (neww, newh);
|
|
|
|
//
|
|
// copy old data
|
|
for (x = 0; x < ow && x < width; x++)
|
|
for (y = 0; y < oh && x < height; y++)
|
|
railways[x + y * width] = rarray[x + y * oh];
|
|
free (rarray);
|
|
UnLock();
|
|
};
|
|
|
|
|
|
void Railways::_New (int neww, int newh) {
|
|
int x, y;
|
|
|
|
debug (0, "* Railways New");
|
|
|
|
//
|
|
// clip to minimum and maximum sizes
|
|
if (neww < RAILWAYS_MIN_WIDTH) width = RAILWAYS_MIN_WIDTH;
|
|
else if (neww > RAILWAYS_MAX_WIDTH) width = RAILWAYS_MAX_WIDTH;
|
|
else width = neww;
|
|
if (newh < RAILWAYS_MIN_HEIGHT) width = RAILWAYS_MIN_HEIGHT;
|
|
else if (newh > RAILWAYS_MAX_HEIGHT) width = RAILWAYS_MAX_HEIGHT;
|
|
else height = newh;
|
|
|
|
//
|
|
// if memory is already allocated free it first
|
|
if (railways != NULL) free (railways);
|
|
|
|
//
|
|
// allocate memory and reset memory
|
|
railways = (Railway*) malloc (sizeof (Railway) * width * height);
|
|
for (x = 0; x < width; x++) for (y = 0; y < height; y++) {
|
|
Railway *r = &railways[GetRIdx(x, y)];
|
|
r->type = RAILWAY_NOTHING;
|
|
r->dir = 0;
|
|
r->altdir = 0;
|
|
r->flags = 0;
|
|
r->maxspeed = 0;
|
|
r->x = x;
|
|
r->y = y;
|
|
r->name[0] = 0;
|
|
r->lockedby[0] = 0;
|
|
}
|
|
};
|
|
|
|
void Railways::New (int neww, int newh) {
|
|
Lock();
|
|
_New (neww, newh);
|
|
UnLock();
|
|
};
|
|
|
|
|
|
//
|
|
// append all data to the givin jasonobject
|
|
void Railways::GetJSONAll(JSONParse *json) {
|
|
int x, y;
|
|
|
|
if (json == NULL) return;
|
|
|
|
Lock();
|
|
|
|
json->AddObject("track", GetJSONTrack());
|
|
for (y = 0; y < height; y++)
|
|
for (x = 0; x < width; x++)
|
|
if (railways[GetRIdx(x, y)].type != RAILWAY_NOTHING) {
|
|
json->AddObject("railway", _GetJSONRailway(x, y));
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
//
|
|
// get railway element
|
|
// thread safe
|
|
Railway Railways::Get(int x, int y) {
|
|
Railway r;
|
|
|
|
Lock();
|
|
r = railways[GetRIdx(x, y)];
|
|
UnLock();
|
|
|
|
return r;
|
|
};
|
|
|
|
void Railways::ClearLockedby(string name) {
|
|
int x, y;
|
|
JSONParse jp;
|
|
|
|
Lock();
|
|
|
|
for (x = 0; x < width; x++)
|
|
for (y = 0; y < height; y++) {
|
|
if (name.compare(railways[GetRIdx(x,y)].lockedby) == 0) {
|
|
railways[GetRIdx(x,y)].lockedby [0] = 0;
|
|
changed = 1;
|
|
jp.AddObject("railway",_GetJSONRailway(x,y));
|
|
if(network) network->ChangeListPushToAll(jp.ToString());
|
|
}
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
|
|
int Railways::_FindReference(int *x, int *y, string name, int cnt) {
|
|
int found = 0;
|
|
int c; // counter of occurance
|
|
if (x == NULL || y == NULL) return 0;
|
|
|
|
for (c = 0, *y = 0; found == 0 && *y < height; (*y)++) {
|
|
for (*x = 0; found == 0 && *x < width; (*x)++) {
|
|
if (strncmp (railways[GetRIdx(*x, *y)].name, name.c_str(), REFERENCENAME_LEN) == 0)
|
|
if ((c++) == cnt) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (found) break;
|
|
}
|
|
|
|
if (*x < width && *y < height) return 1;
|
|
return 0;
|
|
};
|
|
|
|
|
|
int Railways::FindReference(int *x, int *y, string name, int cnt) {
|
|
int res;
|
|
|
|
Lock();
|
|
res = _FindReference (x, y, name, cnt);
|
|
UnLock();
|
|
return res;
|
|
};
|
|
|
|
|
|
void Railways::DebugPrintFindWay(struct s_findway_map *fw) {
|
|
string c;
|
|
int x, y;
|
|
int idx;
|
|
char chr;
|
|
|
|
printf (" ");
|
|
for (x = 0; x < width && x < 80; x++)
|
|
printf ("%c", (char) ((x % 10) + '0'));
|
|
printf ("\n");
|
|
for (y = 0; y < height && y < 40; y++) {
|
|
printf ("%c ", (char) ((y % 10) + '0'));
|
|
for (x = 0; x < width && x < 80; x++) {
|
|
idx = GetRIdx(x, y);
|
|
if (railways[idx].dir == 1) c = "│";
|
|
if (railways[idx].dir == 2) c = "─";
|
|
if (railways[idx].dir == 3) c = "╯";
|
|
if (railways[idx].dir == 4) c = "╰";
|
|
if (railways[idx].dir == 5) c = "╭";
|
|
if (railways[idx].dir == 6) c = "╮";
|
|
if (railways[idx].type == RAILWAY_CROSSING) c = "+";
|
|
if (railways[idx].type == RAILWAY_TURNOUT) c = "t";
|
|
if (railways[idx].type == RAILWAY_CONNECTOR) c = "◯";
|
|
if (railways[idx].type == RAILWAY_BLOCK && railways[idx].dir == 1) c = "┃";
|
|
if (railways[idx].type == RAILWAY_BLOCK && railways[idx].dir == 2) c = "━";
|
|
|
|
if (fw != NULL) {
|
|
if ((fw[idx].e & 15) > 0) {
|
|
chr = (char)('0' + (fw[idx].e & 15));
|
|
if (chr > '9') chr = chr - ('0' + 10) + 'A';
|
|
c = chr;
|
|
}
|
|
else if (fw[idx].e != 0) {
|
|
c = "?";
|
|
printf ("---%d---", fw[idx].e);
|
|
}
|
|
}
|
|
printf ("%s", c.c_str());
|
|
c = " ";
|
|
}
|
|
printf ("\n");
|
|
}
|
|
|
|
for (x = 0; x < width && x < 80; x++)
|
|
printf ("%c", (char) ((x % 10) + '0'));
|
|
printf ("\n");
|
|
|
|
printf ("Debug Finished\n");
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* GetDestBlock: check if the destination is a split block and return
|
|
* the final destination block.
|
|
*/
|
|
string Railways::GetDestBlock(int locoflags, string blockend) {
|
|
int block_f;
|
|
string block;
|
|
string blockp, blockn; // blockend[pos,neg] name
|
|
|
|
blockp = blockend.substr(2, string::npos);
|
|
block_f = server->blocks.GetFlags(blockp);
|
|
if ((block_f & BLOCK_F_SPLIT) && !(locoflags & LOCO_F_SHORTTRAIN)) {
|
|
blockn = server->blocks.GetFlags(blockp);
|
|
|
|
// direction and position
|
|
if (block_f & BLOCK_F_SPLITPOS) {
|
|
blockn = server->blocks.GetSecondBlock(blockp);
|
|
}
|
|
else {
|
|
blockn = blockp;
|
|
blockp = server->blocks.GetSecondBlock(blockn);
|
|
}
|
|
|
|
if (blockend[0] == '+') block = "+:" + blockn;
|
|
else block = "-:" + blockp;
|
|
}
|
|
else {
|
|
block = blockend;
|
|
}
|
|
|
|
debug (0, "Railway::GetDestBlock Final split:%d loco short:%d blockend:%s -> block:%s"
|
|
, (block_f & BLOCK_F_SPLIT) ? 1 : 0
|
|
, (locoflags & LOCO_F_SHORTTRAIN) ? 1: 0
|
|
, blockend.c_str()
|
|
, block.c_str());
|
|
|
|
return block;
|
|
}
|
|
|
|
/*
|
|
* insert the element in an ordered list
|
|
*/
|
|
void FDListPush (std::list<struct s_findway_data> *list, struct s_findway_data *element) {
|
|
std::list<struct s_findway_data>::iterator iter;
|
|
|
|
for (iter = list->begin(); iter != list->end(); iter++)
|
|
if (element->dist < iter->dist) {
|
|
// printf ("%s:%d Push dist list:%d dist element:%d (%d,%d E:%d)\n", __FILE__, __LINE__, iter->dist, element->dist, element->x, element->y, element->enterfrom);
|
|
list->insert(iter, *element);
|
|
return;
|
|
}
|
|
|
|
// printf ("%s:%d Push dist list:--- dist element:%d (%d,%d E:%d)\n", __FILE__, __LINE__, element->dist, element->x, element->y, element->enterfrom);
|
|
list->push_back(*element);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* FindWay: will be in two phases to decide where to go and how
|
|
* - check if endblock is valid on SPLIT and long trains.
|
|
* - check all possible ways in respect of (out of service blocks)
|
|
* and the ONLYCARGO/PASSENGER flags
|
|
* return 0 if no way found
|
|
*/
|
|
int Railways::FindWay(string org_blockstart, string org_blockend, string lockedfor, string *next) {
|
|
// direction 0 ... RIGHT and DOWN
|
|
// direction 1 ... LEFT and UP
|
|
struct s_findway_data fd_pos;
|
|
struct s_findway_data fd_tmp;
|
|
struct s_findway_data fd_start;
|
|
struct s_findway_data fd_end;
|
|
Railway *rpos, *rnext;
|
|
std::list<struct s_findway_data> fd_list;
|
|
struct s_findway_map *fd_data = NULL;
|
|
string blockstart, blockend;
|
|
string lockedby;
|
|
int x ,y;
|
|
int found = 0;
|
|
int locoflags = server->locomotives.GetFlags(lockedfor);
|
|
|
|
debug (0, "Railway::FindWay blockstart:%s blockend:%s lockedfor:%s", org_blockstart.c_str(), org_blockend.c_str(), lockedfor.c_str());
|
|
|
|
//
|
|
// check blocklen
|
|
if (org_blockstart.length() <= 3 || org_blockend.length() <= 3) return 0;
|
|
|
|
|
|
//
|
|
// setup blockstart and blockend depending on train type
|
|
// long trains need to get special attentions on the destination
|
|
blockstart = org_blockstart; // no check needed
|
|
blockend = GetDestBlock(locoflags, org_blockend);
|
|
|
|
|
|
//
|
|
// allocate and clear memory for checked data
|
|
fd_data = (struct s_findway_map *) malloc (sizeof(struct s_findway_map) * width * height);
|
|
if (fd_data == NULL) {
|
|
printf ("%s:%d (%s) FATAL ERROR: could not allocate enough memory\n", __FILE__, __LINE__, __FUNCTION__);
|
|
exit (1);
|
|
}
|
|
memset (fd_data, 0x0, sizeof(struct s_findway_map) * width*height);
|
|
|
|
|
|
//
|
|
// find start and endpoint mark on fd_data, also startpoint to fd_list
|
|
fd_end.x = fd_start.x = -1;
|
|
fd_end.y = fd_start.y = -1;
|
|
fd_end.enterfrom = fd_start.enterfrom = -1;
|
|
fd_end.dist = fd_start.dist = 0;
|
|
|
|
if (FindReference(&fd_start.x, &fd_start.y, blockstart.substr(2, string::npos),0)) {
|
|
debug (0, "Railway::FindWay found startblock (%s).", blockstart.c_str());
|
|
if (Get(fd_start.x, fd_start.y).dir == 1) {
|
|
if (blockstart[0] == '+') fd_start.enterfrom = 0;
|
|
else fd_start.enterfrom = 2;
|
|
}
|
|
else {
|
|
if (blockstart[0] == '+') fd_start.enterfrom = 3;
|
|
else fd_start.enterfrom = 1;
|
|
}
|
|
fd_start.way = "b:" + blockstart;
|
|
fd_data[GetRIdx(fd_start.x, fd_start.y)].e = (1 << fd_start.enterfrom);
|
|
fd_data[GetRIdx(fd_start.x, fd_start.y)].score = 1;
|
|
}
|
|
else {
|
|
debug (0, "Railway::FindWay could not find startblock (%s).", blockstart.c_str());
|
|
free (fd_data);
|
|
return 0;
|
|
}
|
|
|
|
if (FindReference(&fd_end.x, &fd_end.y, blockend.substr(2, string::npos), 0)) {
|
|
debug (0, "Railway::FindWay found endblock (%s).", blockend.c_str());
|
|
if (Get(fd_end.x, fd_end.y).dir == 1) {
|
|
if (blockend[0] == '+') fd_end.enterfrom = 0;
|
|
else fd_end.enterfrom = 2;
|
|
}
|
|
else {
|
|
if (blockend[0] == '+') fd_end.enterfrom = 3;
|
|
else fd_end.enterfrom = 1;
|
|
}
|
|
fd_end.way = blockend;
|
|
fd_data[GetRIdx(fd_end.x, fd_end.y)].e = (1 << fd_end.enterfrom);
|
|
}
|
|
else {
|
|
debug (0, "Railway::FindWay could not find endblock (%s).", blockend.c_str());
|
|
free (fd_data);
|
|
return 0;
|
|
}
|
|
|
|
fd_pos = NextPos(fd_start, Get(fd_start.x, fd_start.y).dir);
|
|
|
|
Lock();
|
|
|
|
//
|
|
// loop through the map to find all possible ways to the destination
|
|
// this will be done in respect of lockedby blocks and ways.
|
|
//
|
|
// DebugPrintFindWay(fd_data);
|
|
while ((fd_list.size() > 0 || fd_pos.enterfrom >= 0) && found == 0) {
|
|
// std::list<struct s_findway_data>::iterator iter;
|
|
// for (iter = fd_list.begin(); iter != fd_list.end(); iter++)
|
|
// printf ("List: Dist:%-4d Pos (%d,%d)\n", iter->dist, iter->x, iter->y);
|
|
// DebugPrintFindWay(fd_data);
|
|
|
|
if (fd_pos.enterfrom < 0) {
|
|
std::list<struct s_findway_data>::iterator iter;
|
|
|
|
iter = fd_list.begin();
|
|
if (iter != fd_list.end()) {
|
|
fd_pos = *iter;
|
|
fd_list.pop_front();
|
|
// printf ("%s:%d pop_front -> fd_pos (%d,%d e:%d) dist:%d\n", __FILE__, __LINE__, fd_pos.x, fd_pos.y, fd_pos.enterfrom, fd_pos.dist);
|
|
}
|
|
}
|
|
|
|
if (fd_pos.enterfrom < 0 && fd_pos.enterfrom > 3) {
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
else if (fd_pos.enterfrom >= 0 && fd_end.x == fd_pos.x && fd_pos.y == fd_end.y && fd_pos.enterfrom == fd_end.enterfrom) {
|
|
// destination found
|
|
found = 1;
|
|
*next = fd_pos.way + ",b:" + blockend;
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
debug (0, "Railway::FindWay %s:%d found way. [%s]", __FILE__, __LINE__, next->c_str());
|
|
}
|
|
else if (fd_pos.enterfrom >= 0 && fd_start.x == fd_pos.x && fd_start.y == fd_pos.y && fd_start.enterfrom == fd_pos.enterfrom) {
|
|
// start found
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
else if (fd_data[GetRIdx(fd_pos.x, fd_pos.y)].e & (1 << fd_pos.enterfrom)) {
|
|
// old entry found
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
else if (fd_pos.enterfrom >= 0) {
|
|
rpos = &railways[GetRIdx(fd_pos.x, fd_pos.y)];
|
|
fd_data[GetRIdx(fd_pos.x, fd_pos.y)].e |= (1 << fd_pos.enterfrom);
|
|
|
|
if (rpos->type == RAILWAY_NORMAL || rpos->type == RAILWAY_SENSOR) {
|
|
fd_pos = NextPos(fd_pos, rpos->dir);
|
|
rnext = &railways[GetRIdx(fd_pos.x, fd_pos.y)];
|
|
if (rnext->lockedby[0] != 0 || !_NextPosIsValid(lockedfor, locoflags, &fd_pos)) {
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
}
|
|
|
|
else if (rpos->type == RAILWAY_TURNOUT) {
|
|
fd_tmp = NextPos(fd_pos, rpos->altdir);
|
|
fd_tmp.way += (string)",t:" + (string)rpos->name + (string)":1";
|
|
if (fd_tmp.enterfrom != -1) FDListPush(&fd_list, &fd_tmp);
|
|
|
|
fd_tmp = NextPos(fd_pos, rpos->dir);
|
|
fd_tmp.way += (string)",t:" + (string)rpos->name + (string)":0";
|
|
if (fd_tmp.enterfrom != -1) FDListPush(&fd_list, &fd_tmp);
|
|
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
|
|
else if (rpos->type == RAILWAY_CONNECTOR) {
|
|
int conector_found = 0;
|
|
x = -1;
|
|
y = -1;
|
|
int cnt = 0;
|
|
while (conector_found == 0 && _FindReference(&x, &y, rpos->name, (cnt++)) == 1) {
|
|
if (fd_pos.x != x || fd_pos.y != y) {
|
|
fd_pos.oldx = fd_pos.x;
|
|
fd_pos.oldy = fd_pos.y;
|
|
fd_pos.oldenterfrom = fd_pos.enterfrom;
|
|
fd_pos.x = x;
|
|
fd_pos.y = y;
|
|
rpos = &railways[GetRIdx(fd_pos.x, fd_pos.y)];
|
|
fd_pos = NextPos(fd_pos, rpos->dir);
|
|
|
|
conector_found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (conector_found == 0 || !_NextPosIsValid(lockedfor, locoflags, &fd_pos)) {
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
}
|
|
else if (rpos->type == RAILWAY_BLOCK) {
|
|
int blflags = server->blocks.GetFlags(rpos->name);
|
|
debug (0, "Railways::FindWay %s:%d found block: %s", __FILE__, __LINE__, rpos->name);
|
|
|
|
//
|
|
// check if block is available for entering
|
|
if ((server->blocks.IsOff(rpos->name) ||
|
|
((blflags & BLOCK_F_ENDSTATION) && !(locoflags & LOCO_F_CANREVERSE)) ||
|
|
((blflags & BLOCK_F_SHORT) && !(locoflags & LOCO_F_SHORTTRAIN) &&
|
|
!_SplitBlockIsFreeAndAllowed(lockedfor, locoflags, rpos->name)) ||
|
|
((blflags & BLOCK_F_ONLYCARGO) && !(locoflags & LOCO_F_CARGO)) ||
|
|
((blflags & BLOCK_F_ONLYPASSENGER) && (locoflags & LOCO_F_CARGO)))) {
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
else {
|
|
// lockedby = server->blocks.GetLockedby(rpos->name);
|
|
lockedby = server->blocks.GetLockedby(rpos->name);
|
|
if (lockedby.length() == 0 || lockedby.compare(lockedfor) == 0) {
|
|
if (fd_pos.enterfrom == 0 || fd_pos.enterfrom == 3)
|
|
fd_pos.way += (string)",b:+:" + (string)rpos->name;
|
|
else fd_pos.way += (string)",b:-:" + (string)rpos->name;
|
|
|
|
fd_pos = NextPos(fd_pos, rpos->dir);
|
|
if (!_NextPosIsValid(lockedfor, locoflags, &fd_pos)) {
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
}
|
|
else {
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
}
|
|
}
|
|
|
|
else { // finished
|
|
fd_pos.enterfrom = -1;
|
|
fd_pos.x = -1;
|
|
fd_pos.y = -1;
|
|
fd_pos.way = "";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (found == 0) *next = "";
|
|
else {
|
|
//
|
|
// do final checks:
|
|
//
|
|
|
|
//
|
|
// check if way found a block.
|
|
size_t npos;
|
|
if ((npos = next->rfind(",b:")) != string::npos)
|
|
*next = next->substr(0, next->find(",", npos+1));
|
|
else // nothing found?
|
|
*next = "";
|
|
|
|
//
|
|
// check that a way is not set twice
|
|
//
|
|
if (!FindWayCheckIfNoDoubleTurnouts (next)) {
|
|
debug (0, "FindWayCheckIfNoDoubleTurnouts way [%s] is not valid.", next->c_str());
|
|
*next = "";
|
|
}
|
|
}
|
|
UnLock();
|
|
|
|
free (fd_data);
|
|
|
|
debug (0, "Railway::FindWay Result (%s) -> (%s) Found:%d Next:%s", blockstart.c_str(), blockend.c_str(), found, next->c_str());
|
|
|
|
return found;
|
|
};
|
|
|
|
|
|
int Railways::FindWayCheckIfNoDoubleTurnouts (string *way) {
|
|
size_t pos1, pos2; // block positions
|
|
size_t tp1, tp2; // turnouts
|
|
int wayset;
|
|
string s; // search string (should not been found)
|
|
|
|
for (pos1 = 0, pos2 = way->find(",b:"); pos2 != string::npos; pos1 = pos2, pos2 = way->find(",b:", pos1+1)) {
|
|
tp1 = pos1;
|
|
for (tp1 = way->find(",t:", tp1+1); tp1 != string::npos; tp1 = way->find(",t:", tp1+1)) {
|
|
if ((*way)[way->find(":", tp1+4)+1] == '0')
|
|
s = way->substr(tp1, way->find(":", tp1+4)-tp1) + ":1";
|
|
else
|
|
s = way->substr(tp1, way->find(":", tp1+4)-tp1) + ":0";
|
|
tp2 = way->find (s, tp1+4);
|
|
if (tp2 == string::npos) continue; // not found
|
|
if (tp2 < pos2) return 0; // found ... return 0
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* check if the position in fwd.x|y is valid for the loco. The check will only done on
|
|
* RAILWAY_BLOCK types. It will also check if the block is free.
|
|
*/
|
|
int Railways::_NextPosIsValid(string loconame, int locoflags, struct s_findway_data *fwd) {
|
|
int bflags = -1;
|
|
Railway *rpos = NULL;
|
|
|
|
rpos = &railways[GetRIdx(fwd->x, fwd->y)];
|
|
bflags = server->blocks.GetFlags(rpos->name);
|
|
|
|
if (rpos->type != RAILWAY_BLOCK) return 1;
|
|
|
|
if (server->blocks.IsOff(rpos->name)) return 0;
|
|
if ((bflags & BLOCK_F_ENDSTATION) && !(locoflags & LOCO_F_CANREVERSE)) return 0;
|
|
if ((bflags & BLOCK_F_SHORT) && !(locoflags & LOCO_F_SHORTTRAIN) &&
|
|
!_SplitBlockIsFreeAndAllowed(loconame, locoflags, rpos->name)) return 0;
|
|
if ((bflags & BLOCK_F_ONLYCARGO) && !(locoflags & LOCO_F_CARGO)) return 0;
|
|
if ((bflags & BLOCK_F_ONLYPASSENGER) && (locoflags & LOCO_F_CARGO)) return 0;
|
|
|
|
return 1;
|
|
};
|
|
|
|
|
|
/*
|
|
* check if this is a split block, and if it can be entered
|
|
* all needed elements must be unlocked to return 1.
|
|
* if the loco is a short train return 0
|
|
*/
|
|
int Railways::_SplitBlockIsFreeAndAllowed(string loconame, int locoflags, string block) {
|
|
string pblock;
|
|
string nblock;
|
|
Railway *rpos = NULL;
|
|
int bflags = server->blocks.GetFlags(block);
|
|
int nblockflags = 0;
|
|
int pblockflags = 0;
|
|
int x1, y1, x2, y2, x = 0, y = 0;
|
|
|
|
debug (0, "Railway::_SplitBlockIsFreeAndAllowed loconame:%s flags:%d block:%s", loconame.c_str(), locoflags, block.c_str());
|
|
|
|
if (locoflags & LOCO_F_SHORTTRAIN) return 0;
|
|
if ((locoflags & !LOCO_F_SHORTTRAIN) && (bflags & !BLOCK_F_SPLIT)) return 0;
|
|
|
|
//
|
|
// read negative and positive block flags
|
|
if (bflags & BLOCK_F_SPLITPOS) {
|
|
pblockflags = bflags;
|
|
pblock = block;
|
|
nblock = server->blocks.GetSecondBlock(block);
|
|
if (nblock.length() == 0) return 0;
|
|
nblockflags = server->blocks.GetFlags(nblock);
|
|
}
|
|
else {
|
|
nblockflags = bflags;
|
|
nblock = block;
|
|
pblock = server->blocks.GetSecondBlock(block);
|
|
if (pblock.length() == 0) return 0;
|
|
pblockflags = server->blocks.GetFlags(pblock);
|
|
}
|
|
|
|
//
|
|
// check if blockflags are setup right and the blocks are free
|
|
if (!(nblockflags & BLOCK_F_SPLIT) && (nblockflags & BLOCK_F_SPLITPOS)) return 0;
|
|
if (!(pblockflags & BLOCK_F_SPLIT) && !(pblockflags & BLOCK_F_SPLITPOS)) return 0;
|
|
if (server->blocks.GetLockedby(nblock).length() != 0) return 0;
|
|
if (server->blocks.GetLockedby(pblock).length() != 0) return 0;
|
|
|
|
// check the way between the blocks
|
|
if (_FindReference(&x1, &y1, pblock, 0) == 0) return 0;
|
|
if (_FindReference(&x2, &y2, nblock, 0) == 0) return 0;
|
|
debug (0, "Railway::_SplitBlockIsFreeAndAllowed p pos(%d,%d) n pos(%d,%d)", x1, y1, x2, y2);
|
|
|
|
x = x1; y = y1;
|
|
do {
|
|
if ( railways[GetRIdx(x,y)].lockedby[0] != 0) return 0;
|
|
if (x1 == x2) y++; // block is going from down to up
|
|
else x++; // block is going from left to right
|
|
} while (x != x2 || y != y2);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int Railways::FindRandomWay(string blockstart, string lockedfor, string *next) {
|
|
// direction 0 ... RIGHT and DOWN
|
|
// direction 1 ... LEFT and UP
|
|
struct s_findway_data fd_pos;
|
|
struct s_findway_data fd_tmp;
|
|
struct s_findway_data fd_start;
|
|
struct s_findway_data fd_end;
|
|
Railway *rpos, *rnext;
|
|
std::list<struct s_findway_data> fd_list;
|
|
struct s_findway_map *fd_data = NULL;
|
|
string lockedby;
|
|
int x ,y;
|
|
int found = 0;
|
|
int locoflags = server->locomotives.GetFlags(lockedfor);
|
|
|
|
debug (0, "Railway::FindRandomWay - disabled for now - needs to be rewritten");
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* try to lock or unlock the way for the loco(lockedby)
|
|
* this lock will only go from one to the next block.
|
|
* Will also do the check for long trains and split blocks.
|
|
*
|
|
* flags: RAILWAYS_LOCKF_* see definition
|
|
*/
|
|
int Railways::LockWay (string way, string lockedby, int lockonoff, int flags) {
|
|
int res = 0;
|
|
size_t pos1, pos2;
|
|
size_t curwaypos;
|
|
struct s_findway_data start;
|
|
struct s_findway_data end;
|
|
struct s_findway_data pos;
|
|
string startblock, startblock2, startblockfinal, endblock, endblock2,endblockfinal;
|
|
Railway *r;
|
|
int finished = 0;
|
|
JSONParse jp;
|
|
int locoflags = server->locomotives.GetFlags(lockedby);
|
|
int blockendflags = 0;
|
|
int blockstartflags = 0;
|
|
|
|
debug (0, "* LockWay Way:'%s' for '%s' lockonoff:%d", way.c_str(), lockedby.c_str(), lockonoff);
|
|
|
|
end.x = start.x = -1;
|
|
end.y = start.y = -1;
|
|
end.enterfrom = start.enterfrom = -1;
|
|
|
|
if ((pos1 = way.find("b:")) == string::npos) return 0;
|
|
if ((pos2 = way.find(",", pos1+1)) == string::npos) return 0;
|
|
startblock = way.substr (pos1+2, pos2-pos1-2);
|
|
|
|
if ((pos1 = way.find(",b:",pos2)) == string::npos) return 0;
|
|
if ((pos2 = way.find(",", pos1+1)) == string::npos) endblock = way.substr (pos1+3, pos2);
|
|
else endblock = way.substr (pos1+3, pos2-pos1-3);
|
|
|
|
//
|
|
// take care of split blocks and long trains.
|
|
// if the second block is not needed endblock2 will remain empty
|
|
blockendflags = server->blocks.GetFlags(endblock.substr(2, string::npos));
|
|
if (!(locoflags & LOCO_F_SHORTTRAIN) && (blockendflags & BLOCK_F_SPLIT))
|
|
endblock2 = server->blocks.GetSecondBlock(endblock.substr(2, string::npos));
|
|
else endblock2 = "";
|
|
blockstartflags = server->blocks.GetFlags(startblock.substr(2, string::npos));
|
|
if (!(locoflags & LOCO_F_SHORTTRAIN) && (blockstartflags & BLOCK_F_SPLIT))
|
|
startblock2 = server->blocks.GetSecondBlock(startblock.substr(2, string::npos));
|
|
else startblock2 = "";
|
|
debug (0, "%s:%d LockWay Way: '%s' Startblock: '%s' Startblock2: '%s' Endblock: '%s' Endblock2: '%s'", __FILE__, __LINE__, way.c_str(),
|
|
startblock.c_str(), startblock2.c_str(), endblock.c_str(), endblock2.c_str());
|
|
|
|
//
|
|
// find start position
|
|
//
|
|
if (startblock2.length() > 0) {
|
|
if ((startblock[0] == '+' && !(blockstartflags & BLOCK_F_SPLITPOS)) ||
|
|
(startblock[0] == '-' && (blockstartflags & BLOCK_F_SPLITPOS)) ) {
|
|
startblockfinal = startblock2;
|
|
}
|
|
else {
|
|
startblockfinal = startblock.substr(2, string::npos);
|
|
}
|
|
}
|
|
else {
|
|
startblockfinal = startblock.substr(2, string::npos);
|
|
}
|
|
|
|
|
|
//
|
|
// retrieve final start position, in case of split blocks
|
|
if (FindReference(&start.x, &start.y, startblockfinal, 0)) {
|
|
if (Get(start.x, start.y).dir == 1) {
|
|
if (startblock[0] == '+') start.enterfrom = 0;
|
|
else start.enterfrom = 2;
|
|
}
|
|
else {
|
|
if (startblock[0] == '+') start.enterfrom = 3;
|
|
else start.enterfrom = 1;
|
|
}
|
|
}
|
|
else {
|
|
debug (0, "Railway::LockWay could not find start (%s).", startblock.c_str());
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// find end position
|
|
//
|
|
|
|
//
|
|
// retrieve final end position, in case of split blocks
|
|
if (endblock2.length() > 0) {
|
|
if (lockonoff) {
|
|
if ((endblock[0] == '+' && (blockendflags & BLOCK_F_SPLITPOS)) ||
|
|
(endblock[0] == '-' && !(blockendflags & BLOCK_F_SPLITPOS)) ) {
|
|
endblockfinal = endblock2;
|
|
}
|
|
else {
|
|
endblockfinal = endblock.substr(2, string::npos);
|
|
}
|
|
}
|
|
else {
|
|
if ((endblock[0] == '-' && (blockendflags & BLOCK_F_SPLITPOS)) ||
|
|
(endblock[0] == '+' && !(blockendflags & BLOCK_F_SPLITPOS)) ) {
|
|
endblockfinal = endblock2;
|
|
}
|
|
else {
|
|
endblockfinal = endblock.substr(2, string::npos);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
endblockfinal = endblock.substr(2, string::npos);
|
|
}
|
|
|
|
// get the final end position
|
|
if (!FindReference(&end.x, &end.y, endblockfinal, 0)) {
|
|
debug (0, "Railway::FindWay could not find endblock (%s).", endblockfinal.c_str());
|
|
return 0;
|
|
}
|
|
|
|
|
|
if (Get(end.x, end.y).dir == 1) {
|
|
if (endblock[0] == '+') end.enterfrom = 0;
|
|
else end.enterfrom = 2;
|
|
}
|
|
else {
|
|
if (endblock[0] == '+') end.enterfrom = 3;
|
|
else end.enterfrom = 1;
|
|
}
|
|
|
|
printf ("%s:%d LockWay Way:'%s' start [%d,%d -> %d] to [%d,%d -> %d] LockOnOff:%d\n", __FILE__, __LINE__, way.c_str(),
|
|
start.x, start.y, start.enterfrom, end.x, end.y, end.enterfrom, lockonoff);
|
|
|
|
//
|
|
// lock way depending on Way
|
|
Lock();
|
|
|
|
pos.x = start.x;
|
|
pos.y = start.y;
|
|
pos.enterfrom = start.enterfrom;
|
|
curwaypos = 0; // position in string // find first turnout
|
|
curwaypos = way.find(",t:", curwaypos);
|
|
if (curwaypos != string::npos) curwaypos++;
|
|
|
|
finished = 0;
|
|
do {
|
|
r = &railways[GetRIdx(pos.x, pos.y)];
|
|
debug (0, "LockWay Position [%d,%d] Name:%s LockedBy:'%s'", pos.x, pos.y, r->name, r->lockedby);
|
|
|
|
// check if railway is free or locked by me
|
|
if (r->lockedby[0] != 0 && lockedby.compare(r->lockedby) != 0 && !(lockonoff == 0 && pos.x == start.x && pos.y == start.y && r->type == RAILWAY_BLOCK)) {
|
|
debug (0, "LockWay: Railway currently locked by '%s'.", r->lockedby);
|
|
UnLock();
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// lock start and endpoint... unlock only start
|
|
if (r->type == RAILWAY_BLOCK) {
|
|
// endblock
|
|
if ((strcmp(endblock.c_str()+2,r->name) == 0) || (endblock2.length() > 0 && (endblock2.compare(r->name) == 0))) {
|
|
UnLock();
|
|
if (lockonoff) {
|
|
strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
|
|
server->blocks.SetLockedby(r->name, lockedby, lockonoff);
|
|
}
|
|
Lock();
|
|
}
|
|
// startblock
|
|
else if ((strcmp(startblock.c_str()+2, r->name) == 0) || (startblock2.length() > 0 && (startblock2.compare(r->name) == 0))) {
|
|
UnLock();
|
|
if ((!flags & RAILWAYS_LOCKF_KEEPSTART) || lockonoff) server->blocks.SetLockedby(r->name, lockedby, lockonoff);
|
|
if (lockonoff) strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
|
|
else if (!flags & RAILWAYS_LOCKF_KEEPSTART) r->lockedby[0] = 0;
|
|
Lock();
|
|
}
|
|
else {
|
|
debug (0, "*** ERROR *** RailWay BLOCK not start and end (r->name:%s) startblock:%s [%s] endblock:%s [%s]"
|
|
, r->name, startblock.c_str(), startblock2.c_str(), endblock.c_str(), endblock2.c_str());
|
|
server->PowerOnOff(0);
|
|
}
|
|
jp.Clear();
|
|
jp.AddObject("railway",_GetJSONRailway(pos.x, pos.y));
|
|
if(network) network->ChangeListPushToAll(jp.ToString());
|
|
}
|
|
else {
|
|
if (lockonoff) strncpy (r->lockedby, lockedby.c_str(), REFERENCENAME_LEN);
|
|
else r->lockedby[0] = 0;
|
|
jp.Clear();
|
|
jp.AddObject("railway",_GetJSONRailway(pos.x, pos.y));
|
|
if(network) network->ChangeListPushToAll(jp.ToString());
|
|
}
|
|
|
|
if (pos.x < 0 || pos.y < 0 || pos.x >= width || pos.y >= height) {
|
|
server->interfaces.PowerOnOff(false);
|
|
debug (0, "Railway::LockWay %s:%d Error: routing out of surface [%d,%d]", __FILE__, __LINE__, pos.x, pos.y);
|
|
finished = 1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// to prevent unlocking split blocks on enter, check if the start and the end are different blocks.
|
|
// ignore this if startblock and endblock are the same split block.
|
|
if (locoflags & LOCO_F_SHORTTRAIN) {
|
|
if (pos.x == end.x && pos.y == end.y) {
|
|
finished = 1;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
// freeing way on stop: abort if block is part of the split endblock
|
|
if ((pos.x == end.x && pos.y == end.y) ||
|
|
(lockonoff == 0 && (endblock.compare(startblock.substr(0,2) + startblock2) != 0) &&
|
|
((endblock.compare(r->name) == 0) ||
|
|
(endblock2.length() > 0 && endblock2.compare(r->name) == 0)))) {
|
|
finished = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// go to next position
|
|
if (r->type == RAILWAY_TURNOUT) {
|
|
if (curwaypos == string::npos) { // we should have a turnout
|
|
debug (0, "LockWay turnout '%s' not on Way '%s'", r->name, way.c_str());
|
|
UnLock();
|
|
return 0;
|
|
}
|
|
|
|
pos1 = way.find(":", curwaypos+2);
|
|
if (pos1 == string::npos) {
|
|
debug (0, "LockWay turnout could not find parameter 'active'" );
|
|
UnLock();
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// in case this turnout is not in the way list. It is might in between the splitblocks
|
|
if (way.substr(curwaypos+2, pos1-curwaypos-2).compare(r->name) != 0) {
|
|
int d = server->turnouts.Get(r->name);
|
|
debug (0, "LockWay tournout %s in between start or endblock? Active: %d", r->name, d);
|
|
pos = NextPos(pos, d ? r->altdir : r->dir);
|
|
}
|
|
else {
|
|
if (way[pos1+1] == '0') pos = NextPos(pos, r->dir);
|
|
else pos = NextPos(pos, r->altdir);
|
|
|
|
// next turnout?
|
|
curwaypos = way.find(",t:", curwaypos);
|
|
if (curwaypos != string::npos) curwaypos++;
|
|
}
|
|
}
|
|
|
|
else if (r->type == RAILWAY_CONNECTOR) {
|
|
int found = 0;
|
|
int x = -1, y = -1, cnt = 0;
|
|
|
|
debug (0, "LockWay connector found Reference:'%s'", r->name);
|
|
while (found == 0 && _FindReference(&x, &y, r->name, (cnt++)) == 1) {
|
|
if (pos.x != x || pos.y != y) {
|
|
debug (0, "%s:%d found %d,%d", __FILE__, __LINE__, x, y);
|
|
pos.oldx = pos.x;
|
|
pos.oldy = pos.y;
|
|
pos.oldenterfrom = pos.enterfrom;
|
|
pos.x = x;
|
|
pos.y = y;
|
|
r = &railways[GetRIdx(pos.x, pos.y)];
|
|
pos = NextPos(pos, r->dir);
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found == 0) {
|
|
debug (0, "LockWay connector '%s' did not find second end.", r->name );
|
|
UnLock();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
else if (r->type == RAILWAY_BLOCK || r->type == RAILWAY_SENSOR || r->type == RAILWAY_NORMAL) {
|
|
pos = NextPos(pos, r->dir);
|
|
}
|
|
} while (finished == 0);
|
|
|
|
if (pos.x == end.x && pos.y == end.y) res = 1;
|
|
UnLock();
|
|
|
|
return res;
|
|
};
|
|
|
|
|
|
int Railways::SetLockedby (int x, int y, string name, int locked) {
|
|
int res = 1;
|
|
Railway *r;
|
|
JSONParse jp;
|
|
|
|
if (x < 0 || y < 0 || x >= width || y >= height) return 0;
|
|
|
|
Lock();
|
|
r = &railways[GetRIdx(x,y)];
|
|
if (r->lockedby[0] != 0)
|
|
if (name.compare(r->lockedby) != 0) res = 0;
|
|
|
|
if (res) {
|
|
if (locked) strncpy (r->lockedby, name.c_str(), REFERENCENAME_LEN);
|
|
else r->lockedby[0] = 0;
|
|
|
|
if (railways[GetRIdx(x, y)].type != RAILWAY_NOTHING) {
|
|
jp.AddObject("railway", _GetJSONRailway(x, y));
|
|
if(network) network->ChangeListPushToAll(jp.ToString());
|
|
}
|
|
}
|
|
|
|
UnLock();
|
|
return res;
|
|
};
|
|
|