mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/4jcraft.git
synced 2026-07-15 19:38:19 +00:00
chore: format Minecraft.World
This commit is contained in:
@@ -9,74 +9,75 @@
|
||||
#include "Path.h"
|
||||
#include "PathFinder.h"
|
||||
|
||||
PathFinder::PathFinder(LevelSource *level, bool canPassDoors, bool canOpenDoors, bool avoidWater, bool canFloat)
|
||||
{
|
||||
neighbors = new NodeArray(32);
|
||||
PathFinder::PathFinder(LevelSource* level, bool canPassDoors, bool canOpenDoors,
|
||||
bool avoidWater, bool canFloat) {
|
||||
neighbors = new NodeArray(32);
|
||||
|
||||
this->canPassDoors = canPassDoors;
|
||||
this->canOpenDoors = canOpenDoors;
|
||||
this->avoidWater = avoidWater;
|
||||
this->canFloat = canFloat;
|
||||
this->canPassDoors = canPassDoors;
|
||||
this->canOpenDoors = canOpenDoors;
|
||||
this->avoidWater = avoidWater;
|
||||
this->canFloat = canFloat;
|
||||
this->level = level;
|
||||
}
|
||||
|
||||
PathFinder::~PathFinder()
|
||||
{
|
||||
// All the nodes should be uniquely referenced in the nodes map, and everything else should just be duplicate
|
||||
// references to the same things, so just need to destroy their containers
|
||||
delete [] neighbors->data;
|
||||
delete neighbors;
|
||||
AUTO_VAR(itEnd, nodes.end());
|
||||
for( AUTO_VAR(it, nodes.begin()); it != itEnd; it++ )
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
PathFinder::~PathFinder() {
|
||||
// All the nodes should be uniquely referenced in the nodes map, and
|
||||
// everything else should just be duplicate references to the same things,
|
||||
// so just need to destroy their containers
|
||||
delete[] neighbors->data;
|
||||
delete neighbors;
|
||||
AUTO_VAR(itEnd, nodes.end());
|
||||
for (AUTO_VAR(it, nodes.begin()); it != itEnd; it++) {
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
Path *PathFinder::findPath(Entity *from, Entity *to, float maxDist)
|
||||
{
|
||||
Path* PathFinder::findPath(Entity* from, Entity* to, float maxDist) {
|
||||
return findPath(from, to->x, to->bb->y0, to->z, maxDist);
|
||||
}
|
||||
|
||||
Path *PathFinder::findPath(Entity *from, int x, int y, int z, float maxDist)
|
||||
{
|
||||
Path* PathFinder::findPath(Entity* from, int x, int y, int z, float maxDist) {
|
||||
return findPath(from, x + 0.5f, y + 0.5f, z + 0.5f, maxDist);
|
||||
}
|
||||
|
||||
Path *PathFinder::findPath(Entity *e, double xt, double yt, double zt, float maxDist)
|
||||
{
|
||||
Path* PathFinder::findPath(Entity* e, double xt, double yt, double zt,
|
||||
float maxDist) {
|
||||
openSet.clear();
|
||||
nodes.clear();
|
||||
nodes.clear();
|
||||
|
||||
bool resetAvoidWater = avoidWater;
|
||||
int startY = Mth::floor(e->bb->y0 + 0.5f);
|
||||
if (canFloat && e->isInWater())
|
||||
{
|
||||
startY = (int) (e->bb->y0);
|
||||
int tileId = level->getTile((int) Mth::floor(e->x), startY, (int) Mth::floor(e->z));
|
||||
while (tileId == Tile::water_Id || tileId == Tile::calmWater_Id)
|
||||
{
|
||||
++startY;
|
||||
tileId = level->getTile((int) Mth::floor(e->x), startY, (int) Mth::floor(e->z));
|
||||
}
|
||||
resetAvoidWater = avoidWater;
|
||||
avoidWater = false;
|
||||
} else startY = Mth::floor(e->bb->y0 + 0.5f);
|
||||
bool resetAvoidWater = avoidWater;
|
||||
int startY = Mth::floor(e->bb->y0 + 0.5f);
|
||||
if (canFloat && e->isInWater()) {
|
||||
startY = (int)(e->bb->y0);
|
||||
int tileId = level->getTile((int)Mth::floor(e->x), startY,
|
||||
(int)Mth::floor(e->z));
|
||||
while (tileId == Tile::water_Id || tileId == Tile::calmWater_Id) {
|
||||
++startY;
|
||||
tileId = level->getTile((int)Mth::floor(e->x), startY,
|
||||
(int)Mth::floor(e->z));
|
||||
}
|
||||
resetAvoidWater = avoidWater;
|
||||
avoidWater = false;
|
||||
} else
|
||||
startY = Mth::floor(e->bb->y0 + 0.5f);
|
||||
|
||||
Node *from = getNode((int) floor(e->bb->x0), startY, (int) floor(e->bb->z0));
|
||||
Node *to = getNode((int) floor(xt - e->bbWidth / 2), (int) floor(yt), (int) floor(zt - e->bbWidth / 2));
|
||||
Node* from = getNode((int)floor(e->bb->x0), startY, (int)floor(e->bb->z0));
|
||||
Node* to = getNode((int)floor(xt - e->bbWidth / 2), (int)floor(yt),
|
||||
(int)floor(zt - e->bbWidth / 2));
|
||||
|
||||
Node *size = new Node((int) floor(e->bbWidth + 1), (int) floor(e->bbHeight + 1), (int) floor(e->bbWidth + 1));
|
||||
Path *path = findPath(e, from, to, size, maxDist);
|
||||
delete size;
|
||||
Node* size =
|
||||
new Node((int)floor(e->bbWidth + 1), (int)floor(e->bbHeight + 1),
|
||||
(int)floor(e->bbWidth + 1));
|
||||
Path* path = findPath(e, from, to, size, maxDist);
|
||||
delete size;
|
||||
|
||||
avoidWater = resetAvoidWater;
|
||||
avoidWater = resetAvoidWater;
|
||||
return path;
|
||||
}
|
||||
|
||||
// function A*(start,goal)
|
||||
Path *PathFinder::findPath(Entity *e, Node *from, Node *to, Node *size, float maxDist)
|
||||
{
|
||||
Path* PathFinder::findPath(Entity* e, Node* from, Node* to, Node* size,
|
||||
float maxDist) {
|
||||
from->g = 0;
|
||||
from->h = from->distanceToSqr(to);
|
||||
from->f = from->h;
|
||||
@@ -84,40 +85,32 @@ Path *PathFinder::findPath(Entity *e, Node *from, Node *to, Node *size, float ma
|
||||
openSet.clear();
|
||||
openSet.insert(from);
|
||||
|
||||
Node *closest = from;
|
||||
Node* closest = from;
|
||||
|
||||
while (!openSet.isEmpty())
|
||||
{
|
||||
Node *x = openSet.pop();
|
||||
while (!openSet.isEmpty()) {
|
||||
Node* x = openSet.pop();
|
||||
|
||||
if (x->equals(to))
|
||||
{
|
||||
if (x->equals(to)) {
|
||||
return reconstruct_path(from, to);
|
||||
}
|
||||
|
||||
if (x->distanceToSqr(to) < closest->distanceToSqr(to))
|
||||
{
|
||||
if (x->distanceToSqr(to) < closest->distanceToSqr(to)) {
|
||||
closest = x;
|
||||
}
|
||||
x->closed = true;
|
||||
|
||||
int neighborCount = getNeighbors(e, x, size, to, maxDist);
|
||||
for (int i = 0; i < neighborCount; i++)
|
||||
{
|
||||
Node *y = neighbors->data[i];
|
||||
for (int i = 0; i < neighborCount; i++) {
|
||||
Node* y = neighbors->data[i];
|
||||
|
||||
float tentative_g_score = x->g + x->distanceToSqr(y);
|
||||
if (!y->inOpenSet() || tentative_g_score < y->g)
|
||||
{
|
||||
if (!y->inOpenSet() || tentative_g_score < y->g) {
|
||||
y->cameFrom = x;
|
||||
y->g = tentative_g_score;
|
||||
y->h = y->distanceToSqr(to);
|
||||
if (y->inOpenSet())
|
||||
{
|
||||
if (y->inOpenSet()) {
|
||||
openSet.changeCost(y, y->g + y->h);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
y->f = y->g + y->h;
|
||||
openSet.insert(y);
|
||||
}
|
||||
@@ -129,47 +122,51 @@ Path *PathFinder::findPath(Entity *e, Node *from, Node *to, Node *size, float ma
|
||||
return reconstruct_path(from, closest);
|
||||
}
|
||||
|
||||
int PathFinder::getNeighbors(Entity *entity, Node *pos, Node *size, Node *target, float maxDist)
|
||||
{
|
||||
int PathFinder::getNeighbors(Entity* entity, Node* pos, Node* size,
|
||||
Node* target, float maxDist) {
|
||||
int p = 0;
|
||||
|
||||
int jumpSize = 0;
|
||||
if (isFree(entity, pos->x, pos->y + 1, pos->z, size) == TYPE_OPEN) jumpSize = 1;
|
||||
if (isFree(entity, pos->x, pos->y + 1, pos->z, size) == TYPE_OPEN)
|
||||
jumpSize = 1;
|
||||
|
||||
Node *n = getNode(entity, pos->x, pos->y, pos->z + 1, size, jumpSize);
|
||||
Node *w = getNode(entity, pos->x - 1, pos->y, pos->z, size, jumpSize);
|
||||
Node *e = getNode(entity, pos->x + 1, pos->y, pos->z, size, jumpSize);
|
||||
Node *s = getNode(entity, pos->x, pos->y, pos->z - 1, size, jumpSize);
|
||||
Node* n = getNode(entity, pos->x, pos->y, pos->z + 1, size, jumpSize);
|
||||
Node* w = getNode(entity, pos->x - 1, pos->y, pos->z, size, jumpSize);
|
||||
Node* e = getNode(entity, pos->x + 1, pos->y, pos->z, size, jumpSize);
|
||||
Node* s = getNode(entity, pos->x, pos->y, pos->z - 1, size, jumpSize);
|
||||
|
||||
if (n != NULL && !n->closed && n->distanceTo(target) < maxDist) neighbors->data[p++] = n;
|
||||
if (w != NULL && !w->closed && w->distanceTo(target) < maxDist) neighbors->data[p++] = w;
|
||||
if (e != NULL && !e->closed && e->distanceTo(target) < maxDist) neighbors->data[p++] = e;
|
||||
if (s != NULL && !s->closed && s->distanceTo(target) < maxDist) neighbors->data[p++] = s;
|
||||
if (n != NULL && !n->closed && n->distanceTo(target) < maxDist)
|
||||
neighbors->data[p++] = n;
|
||||
if (w != NULL && !w->closed && w->distanceTo(target) < maxDist)
|
||||
neighbors->data[p++] = w;
|
||||
if (e != NULL && !e->closed && e->distanceTo(target) < maxDist)
|
||||
neighbors->data[p++] = e;
|
||||
if (s != NULL && !s->closed && s->distanceTo(target) < maxDist)
|
||||
neighbors->data[p++] = s;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
Node *PathFinder::getNode(Entity *entity, int x, int y, int z, Node *size, int jumpSize)
|
||||
{
|
||||
Node *best = NULL;
|
||||
int pathType = isFree(entity, x, y, z, size);
|
||||
if (pathType == TYPE_WALKABLE) return getNode(x, y, z);
|
||||
Node* PathFinder::getNode(Entity* entity, int x, int y, int z, Node* size,
|
||||
int jumpSize) {
|
||||
Node* best = NULL;
|
||||
int pathType = isFree(entity, x, y, z, size);
|
||||
if (pathType == TYPE_WALKABLE) return getNode(x, y, z);
|
||||
if (pathType == TYPE_OPEN) best = getNode(x, y, z);
|
||||
if (best == NULL && jumpSize > 0 && pathType != TYPE_FENCE && pathType != TYPE_TRAP && isFree(entity, x, y + jumpSize, z, size) == TYPE_OPEN)
|
||||
{
|
||||
if (best == NULL && jumpSize > 0 && pathType != TYPE_FENCE &&
|
||||
pathType != TYPE_TRAP &&
|
||||
isFree(entity, x, y + jumpSize, z, size) == TYPE_OPEN) {
|
||||
best = getNode(x, y + jumpSize, z);
|
||||
y += jumpSize;
|
||||
}
|
||||
|
||||
if (best != NULL)
|
||||
{
|
||||
if (best != NULL) {
|
||||
int drop = 0;
|
||||
int cost = 0;
|
||||
while (y > 0)
|
||||
{
|
||||
cost = isFree(entity, x, y - 1, z, size);
|
||||
if (avoidWater && cost == TYPE_WATER) return NULL;
|
||||
if (cost != TYPE_OPEN) break;
|
||||
while (y > 0) {
|
||||
cost = isFree(entity, x, y - 1, z, size);
|
||||
if (avoidWater && cost == TYPE_WATER) return NULL;
|
||||
if (cost != TYPE_OPEN) break;
|
||||
// fell too far?
|
||||
if (++drop >= 4) return NULL;
|
||||
y--;
|
||||
@@ -183,76 +180,72 @@ Node *PathFinder::getNode(Entity *entity, int x, int y, int z, Node *size, int j
|
||||
return best;
|
||||
}
|
||||
|
||||
/*final*/ Node *PathFinder::getNode(int x, int y, int z)
|
||||
{
|
||||
/*final*/ Node* PathFinder::getNode(int x, int y, int z) {
|
||||
int i = Node::createHash(x, y, z);
|
||||
Node *node;
|
||||
AUTO_VAR(it, nodes.find(i));
|
||||
if ( it == nodes.end() )
|
||||
{
|
||||
MemSect(54);
|
||||
Node* node;
|
||||
AUTO_VAR(it, nodes.find(i));
|
||||
if (it == nodes.end()) {
|
||||
MemSect(54);
|
||||
node = new Node(x, y, z);
|
||||
MemSect(0);
|
||||
nodes.insert( std::unordered_map<int, Node *>::value_type(i, node) );
|
||||
MemSect(0);
|
||||
nodes.insert(std::unordered_map<int, Node*>::value_type(i, node));
|
||||
} else {
|
||||
node = (*it).second;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = (*it).second;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
int PathFinder::isFree(Entity *entity, int x, int y, int z, Node *size)
|
||||
{
|
||||
return isFree(entity, x, y, z, size, avoidWater, canOpenDoors, canPassDoors);
|
||||
int PathFinder::isFree(Entity* entity, int x, int y, int z, Node* size) {
|
||||
return isFree(entity, x, y, z, size, avoidWater, canOpenDoors,
|
||||
canPassDoors);
|
||||
}
|
||||
|
||||
int PathFinder::isFree(Entity *entity, int x, int y, int z, Node *size, bool avoidWater, bool canOpenDoors, bool canPassDoors)
|
||||
{
|
||||
bool walkable = false;
|
||||
for (int xx = x; xx < x + size->x; xx++)
|
||||
for (int yy = y; yy < y + size->y; yy++)
|
||||
for (int zz = z; zz < z + size->z; zz++)
|
||||
{
|
||||
int tileId = entity->level->getTile(xx, yy, zz);
|
||||
if(tileId <= 0) continue;
|
||||
if (tileId == Tile::trapdoor_Id) walkable = true;
|
||||
else if (tileId == Tile::water_Id || tileId == Tile::calmWater_Id)
|
||||
{
|
||||
if (avoidWater) return TYPE_WATER;
|
||||
else walkable = true;
|
||||
}
|
||||
else if (!canPassDoors && tileId == Tile::door_wood_Id)
|
||||
{
|
||||
return TYPE_BLOCKED;
|
||||
}
|
||||
int PathFinder::isFree(Entity* entity, int x, int y, int z, Node* size,
|
||||
bool avoidWater, bool canOpenDoors, bool canPassDoors) {
|
||||
bool walkable = false;
|
||||
for (int xx = x; xx < x + size->x; xx++)
|
||||
for (int yy = y; yy < y + size->y; yy++)
|
||||
for (int zz = z; zz < z + size->z; zz++) {
|
||||
int tileId = entity->level->getTile(xx, yy, zz);
|
||||
if (tileId <= 0) continue;
|
||||
if (tileId == Tile::trapdoor_Id)
|
||||
walkable = true;
|
||||
else if (tileId == Tile::water_Id ||
|
||||
tileId == Tile::calmWater_Id) {
|
||||
if (avoidWater)
|
||||
return TYPE_WATER;
|
||||
else
|
||||
walkable = true;
|
||||
} else if (!canPassDoors && tileId == Tile::door_wood_Id) {
|
||||
return TYPE_BLOCKED;
|
||||
}
|
||||
|
||||
Tile *tile = Tile::tiles[tileId];
|
||||
if (tile->isPathfindable(entity->level, xx, yy, zz)) continue;
|
||||
if (canOpenDoors && tileId == Tile::door_wood_Id) continue;
|
||||
Tile* tile = Tile::tiles[tileId];
|
||||
if (tile->isPathfindable(entity->level, xx, yy, zz)) continue;
|
||||
if (canOpenDoors && tileId == Tile::door_wood_Id) continue;
|
||||
|
||||
int renderShape = tile->getRenderShape();
|
||||
if (renderShape == Tile::SHAPE_FENCE || tileId == Tile::fenceGate_Id || renderShape == Tile::SHAPE_WALL) return TYPE_FENCE;
|
||||
if (tileId == Tile::trapdoor_Id) return TYPE_TRAP;
|
||||
Material *m = tile->material;
|
||||
if (m == Material::lava)
|
||||
{
|
||||
if (entity->isInLava()) continue;
|
||||
return TYPE_LAVA;
|
||||
}
|
||||
return TYPE_BLOCKED;
|
||||
}
|
||||
int renderShape = tile->getRenderShape();
|
||||
if (renderShape == Tile::SHAPE_FENCE ||
|
||||
tileId == Tile::fenceGate_Id ||
|
||||
renderShape == Tile::SHAPE_WALL)
|
||||
return TYPE_FENCE;
|
||||
if (tileId == Tile::trapdoor_Id) return TYPE_TRAP;
|
||||
Material* m = tile->material;
|
||||
if (m == Material::lava) {
|
||||
if (entity->isInLava()) continue;
|
||||
return TYPE_LAVA;
|
||||
}
|
||||
return TYPE_BLOCKED;
|
||||
}
|
||||
|
||||
return walkable ? TYPE_WALKABLE : TYPE_OPEN;
|
||||
}
|
||||
|
||||
// function reconstruct_path(came_from,current_node)
|
||||
Path *PathFinder::reconstruct_path(Node *from, Node *to)
|
||||
{
|
||||
Path* PathFinder::reconstruct_path(Node* from, Node* to) {
|
||||
int count = 1;
|
||||
Node *n = to;
|
||||
while (n->cameFrom != NULL)
|
||||
{
|
||||
Node* n = to;
|
||||
while (n->cameFrom != NULL) {
|
||||
count++;
|
||||
n = n->cameFrom;
|
||||
}
|
||||
@@ -260,12 +253,11 @@ Path *PathFinder::reconstruct_path(Node *from, Node *to)
|
||||
NodeArray nodes = NodeArray(count);
|
||||
n = to;
|
||||
nodes.data[--count] = n;
|
||||
while (n->cameFrom != NULL)
|
||||
{
|
||||
while (n->cameFrom != NULL) {
|
||||
n = n->cameFrom;
|
||||
nodes.data[--count] = n;
|
||||
}
|
||||
Path *ret = new Path(nodes);
|
||||
delete [] nodes.data;
|
||||
Path* ret = new Path(nodes);
|
||||
delete[] nodes.data;
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user