mirror of
https://github.com/celisej567/mcpe.git
synced 2026-01-04 14:09:47 +03:00
* Add PathFinder and friends.
This commit is contained in:
@@ -155,6 +155,10 @@ add_library(reminecraftpe-core STATIC
|
||||
world/level/levelgen/synth/Synth.cpp
|
||||
world/level/levelgen/synth/ImprovedNoise.cpp
|
||||
world/level/levelgen/synth/PerlinNoise.cpp
|
||||
world/level/path/Node.cpp
|
||||
world/level/path/Path.cpp
|
||||
world/level/path/BinaryHeap.cpp
|
||||
world/level/path/PathFinder.cpp
|
||||
world/phys/HitResult.cpp
|
||||
world/phys/Vec3.cpp
|
||||
world/phys/AABB.cpp
|
||||
@@ -185,6 +189,9 @@ add_library(reminecraftpe-core STATIC
|
||||
world/level/storage/LevelSource.cpp
|
||||
world/level/storage/MemoryChunkStorage.cpp
|
||||
world/level/storage/ExternalFileLevelStorageSource.cpp
|
||||
world/level/path/Node.cpp
|
||||
world/level/path/Path.cpp
|
||||
world/level/path/PathFinder.cpp
|
||||
world/level/levelgen/feature/BirchFeature.cpp
|
||||
world/level/levelgen/feature/LargeFeature.cpp
|
||||
world/level/levelgen/feature/Feature.cpp
|
||||
|
||||
103
source/world/level/path/BinaryHeap.cpp
Normal file
103
source/world/level/path/BinaryHeap.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
#include <climits>
|
||||
#include "BinaryHeap.hpp"
|
||||
#include "common/Mth.hpp"
|
||||
|
||||
void BinaryHeap::insert(Node* pNode)
|
||||
{
|
||||
if (m_count == m_capacity)
|
||||
{
|
||||
m_capacity *= 2;
|
||||
Node** newItems = new Node * [m_capacity];
|
||||
|
||||
for (int i = 0; i < m_count; i++)
|
||||
{
|
||||
newItems[i] = m_items[i];
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(m_items);
|
||||
|
||||
m_items = newItems;
|
||||
}
|
||||
|
||||
m_items[m_count] = pNode;
|
||||
pNode->field_0 = m_count;
|
||||
m_count++;
|
||||
|
||||
inlined0(m_count - 1);
|
||||
}
|
||||
|
||||
void BinaryHeap::inlined0(int num)
|
||||
{
|
||||
Node* var2 = m_items[num];
|
||||
|
||||
int var4;
|
||||
for (float var3 = var2->field_C; num > 0; num = var4) {
|
||||
var4 = (num - 1) >> 1;
|
||||
Node* var5 = m_items[var4];
|
||||
if (var3 >= var5->field_C) {
|
||||
break;
|
||||
}
|
||||
|
||||
m_items[num] = var5;
|
||||
var5->field_0 = num;
|
||||
}
|
||||
|
||||
m_items[num] = var2;
|
||||
var2->field_0 = num;
|
||||
}
|
||||
|
||||
void BinaryHeap::downHeap(int num)
|
||||
{
|
||||
Node* var2 = m_items[num];
|
||||
float var3 = var2->field_C;
|
||||
|
||||
while (true) {
|
||||
int var4 = 1 + (num << 1);
|
||||
int var5 = var4 + 1;
|
||||
if (var4 >= m_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
Node* var6 = m_items[var4];
|
||||
float var7 = var6->field_C;
|
||||
Node* var8;
|
||||
float var9;
|
||||
if (var5 >= m_count) {
|
||||
var8 = nullptr;
|
||||
var9 = INFINITY;
|
||||
}
|
||||
else {
|
||||
var8 = m_items[var5];
|
||||
var9 = var8->field_C;
|
||||
}
|
||||
|
||||
if (var7 < var9) {
|
||||
if (var7 >= var3) {
|
||||
break;
|
||||
}
|
||||
|
||||
m_items[num] = var6;
|
||||
var6->field_0 = num;
|
||||
num = var4;
|
||||
}
|
||||
else {
|
||||
if (var9 >= var3) {
|
||||
break;
|
||||
}
|
||||
|
||||
m_items[num] = var8;
|
||||
var8->field_0 = num;
|
||||
num = var5;
|
||||
}
|
||||
}
|
||||
|
||||
m_items[num] = var2;
|
||||
var2->field_0 = num;
|
||||
}
|
||||
66
source/world/level/path/BinaryHeap.hpp
Normal file
66
source/world/level/path/BinaryHeap.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "Node.hpp"
|
||||
|
||||
class BinaryHeap
|
||||
{
|
||||
public:
|
||||
BinaryHeap()
|
||||
{
|
||||
m_count = 0;
|
||||
m_capacity = 1024;
|
||||
m_items = new Node*[m_capacity];
|
||||
}
|
||||
|
||||
~BinaryHeap()
|
||||
{
|
||||
if (m_items)
|
||||
delete[] m_items;
|
||||
}
|
||||
|
||||
void insert(Node* pNode);
|
||||
void inlined0(int i);
|
||||
void downHeap(int i);
|
||||
|
||||
Node* removeTop() {
|
||||
Node* pNode = m_items[0];
|
||||
m_items[0] = m_items[--m_count];
|
||||
m_items[m_count] = 0;
|
||||
|
||||
if (m_count > 0)
|
||||
downHeap(0);
|
||||
|
||||
pNode->field_0 = -1;
|
||||
return pNode;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
int size() const {
|
||||
return m_count;
|
||||
}
|
||||
|
||||
void setDistance(Node* pNode, float distance) {
|
||||
float oldDistance = pNode->field_C;
|
||||
pNode->field_C = distance;
|
||||
|
||||
if (oldDistance >= distance)
|
||||
downHeap(pNode->field_0);
|
||||
else
|
||||
inlined0(pNode->field_0);
|
||||
}
|
||||
|
||||
private:
|
||||
Node** m_items;
|
||||
int m_count;
|
||||
int m_capacity;
|
||||
};
|
||||
17
source/world/level/path/Node.cpp
Normal file
17
source/world/level/path/Node.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
#include "Node.hpp"
|
||||
#include "common/Mth.hpp"
|
||||
|
||||
float Node::distanceTo(Node* node)
|
||||
{
|
||||
float dx = node->m_x - m_x;
|
||||
float dy = node->m_y - m_y;
|
||||
float dz = node->m_z - m_z;
|
||||
return Mth::sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
60
source/world/level/path/Node.hpp
Normal file
60
source/world/level/path/Node.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
#pragma once
|
||||
|
||||
struct Node
|
||||
{
|
||||
int field_0;
|
||||
float field_4;
|
||||
float field_8;
|
||||
float field_C;
|
||||
Node* field_10;
|
||||
short m_x;
|
||||
short m_y;
|
||||
short m_z;
|
||||
bool field_1A;
|
||||
int m_hash;
|
||||
|
||||
Node()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void setPos(int x, int y, int z)
|
||||
{
|
||||
m_x = short(x);
|
||||
m_y = short(y);
|
||||
m_z = short(z);
|
||||
}
|
||||
|
||||
void setHash(int index)
|
||||
{
|
||||
m_hash = index;
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
field_0 = -1;
|
||||
field_4 = 0.0f;
|
||||
field_8 = 0.0f;
|
||||
field_C = 0.0f;
|
||||
field_10 = nullptr;
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
m_z = 0;
|
||||
field_1A = false;
|
||||
m_hash = 0;
|
||||
}
|
||||
|
||||
bool equals(Node* node)
|
||||
{
|
||||
return m_hash == node->m_hash && m_x == node->m_x && m_y == node->m_y && m_z == node->m_z;
|
||||
}
|
||||
|
||||
float distanceTo(Node* node);
|
||||
};
|
||||
36
source/world/level/path/Path.cpp
Normal file
36
source/world/level/path/Path.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
#include "Path.hpp"
|
||||
|
||||
Path::Path()
|
||||
{
|
||||
m_numNodes = 0;
|
||||
m_pNodes = nullptr;
|
||||
field_8 = 0;
|
||||
}
|
||||
|
||||
Path::~Path()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void Path::setNodes(Node** pNodes, int nodeCount)
|
||||
{
|
||||
clear();
|
||||
m_numNodes = nodeCount;
|
||||
m_pNodes = pNodes;
|
||||
|
||||
for (int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
// TODO: We are using the pNodes array for storage but duplicating the pNodes?
|
||||
// This might cause a memory leak?
|
||||
Node* oldNode = pNodes[i];
|
||||
m_pNodes[i] = new Node;
|
||||
*m_pNodes[i] = *oldNode;
|
||||
}
|
||||
}
|
||||
39
source/world/level/path/Path.hpp
Normal file
39
source/world/level/path/Path.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "Node.hpp"
|
||||
|
||||
class Path
|
||||
{
|
||||
public:
|
||||
Path();
|
||||
~Path();
|
||||
|
||||
void setNodes(Node** pNodes, int nodeCount);
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (m_pNodes)
|
||||
{
|
||||
for (int i = 0; i < m_numNodes; i++)
|
||||
delete m_pNodes[i];
|
||||
|
||||
delete[] m_pNodes;
|
||||
}
|
||||
|
||||
m_pNodes = nullptr;
|
||||
m_numNodes = 0;
|
||||
field_8 = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_numNodes;
|
||||
Node** m_pNodes;
|
||||
int field_8;
|
||||
};
|
||||
320
source/world/level/path/PathFinder.cpp
Normal file
320
source/world/level/path/PathFinder.cpp
Normal file
@@ -0,0 +1,320 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
#include "PathFinder.hpp"
|
||||
#include "world/level/Level.hpp"
|
||||
#include "world/tile/DoorTile.hpp"
|
||||
#include "world/entity/Entity.hpp"
|
||||
|
||||
static int dword_1CD868;
|
||||
static int dword_1CD86C;
|
||||
static int dword_1CD870;
|
||||
|
||||
constexpr int MakeNodeHash(int x, int y, int z)
|
||||
{
|
||||
// NOTE: Same as in Java Edition Beta 1.3_01
|
||||
return (y & 0xFF) |
|
||||
((x & 0x7FFF) << 8) |
|
||||
((z & 0x7FFF) << 24) |
|
||||
(x < 0 ? 0x80000000 : 0) |
|
||||
(z < 0 ? 0x8000 : 0);
|
||||
}
|
||||
|
||||
PathFinder::PathFinder()
|
||||
{
|
||||
m_pLevel = nullptr;
|
||||
}
|
||||
|
||||
PathFinder::~PathFinder()
|
||||
{
|
||||
// NOTE: In v0.2.0, this is it. We're going to do more:
|
||||
for (size_t i = 0; i < m_nodeSpillover.size(); i++)
|
||||
delete m_nodeSpillover[i];
|
||||
|
||||
m_nodeSpillover.clear();
|
||||
}
|
||||
|
||||
int PathFinder::isFree(Entity* pEntity, int x, int y, int z, const Node* node)
|
||||
{
|
||||
for (int x1 = x; x1 < x + node->m_x; x1++)
|
||||
{
|
||||
for (int y1 = y; y1 < y + node->m_y; y1++)
|
||||
{
|
||||
for (int z1 = z; z1 < z + node->m_z; z1++)
|
||||
{
|
||||
TileID id = m_pLevel->getTile(x1, y1, z1);
|
||||
if (id < 0)
|
||||
continue;
|
||||
|
||||
if (id == Tile::door_iron->m_ID || id == Tile::door_wood->m_ID)
|
||||
{
|
||||
if (!DoorTile::isOpen(m_pLevel->getData(x1, y1, z1)))
|
||||
return 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Material* pMtl = Tile::tiles[id]->m_pMaterial;
|
||||
if (pMtl->blocksMotion())
|
||||
return 0;
|
||||
|
||||
if (pMtl == Material::water)
|
||||
return -1;
|
||||
if (pMtl == Material::lava)
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1; // Totally free!
|
||||
}
|
||||
|
||||
Node* PathFinder::getNode(Entity* pEntity, int x, int y, int z, const Node* node, int a)
|
||||
{
|
||||
Node* pNode = nullptr;
|
||||
if (isFree(pEntity, x, y, z, node) == 1)
|
||||
pNode = getNode(x, y, z);
|
||||
|
||||
if (a > 0 && !pNode && isFree(pEntity, x, y + a, z, node) == 1)
|
||||
{
|
||||
y += a;
|
||||
pNode = getNode(x, y, z);
|
||||
}
|
||||
|
||||
if (!pNode || y < 0)
|
||||
return nullptr;
|
||||
|
||||
int limit = y - 4;
|
||||
while (true)
|
||||
{
|
||||
int is_free = isFree(pEntity, x, --y, z, node);
|
||||
|
||||
if (is_free != 1)
|
||||
{
|
||||
if (is_free == -2)
|
||||
pNode = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (y == limit)
|
||||
{
|
||||
pNode = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!y)
|
||||
break;
|
||||
|
||||
pNode = getNode(x, y, z);
|
||||
}
|
||||
|
||||
return pNode;
|
||||
}
|
||||
|
||||
Node* PathFinder::getNode(int x, int y, int z)
|
||||
{
|
||||
NodeMap::iterator iter = m_nodeMap.find(MakeNodeHash(x, y, z));
|
||||
|
||||
if (iter != m_nodeMap.end())
|
||||
return iter->second;
|
||||
|
||||
Node* pNode = new_Node(x, y, z);
|
||||
dword_1CD868++;
|
||||
m_nodeMap.insert_or_assign(MakeNodeHash(x, y, z), pNode);
|
||||
|
||||
return pNode;
|
||||
}
|
||||
|
||||
int PathFinder::getNeighbors(Entity* pEntity, Node* node1, const Node* node2, Node* node3, float maxDist)
|
||||
{
|
||||
int nr = 0;
|
||||
bool isf = isFree(pEntity, node1->m_x, node1->m_y, node1->m_z, node2) == 1;
|
||||
|
||||
Node* n1 = getNode(pEntity, node1->m_x, node1->m_y, node1->m_z + 1, node2, isf);
|
||||
Node* n2 = getNode(pEntity, node1->m_x - 1, node1->m_y, node1->m_z, node2, isf);
|
||||
Node* n3 = getNode(pEntity, node1->m_x + 1, node1->m_y, node1->m_z, node2, isf);
|
||||
Node* n4 = getNode(pEntity, node1->m_x, node1->m_y, node1->m_z - 1, node2, isf);
|
||||
|
||||
if (n1 && !n1->field_1A && n1->distanceTo(node3) < maxDist) field_10038[nr++] = n1;
|
||||
if (n2 && !n2->field_1A && n2->distanceTo(node3) < maxDist) field_10038[nr++] = n2;
|
||||
if (n3 && !n3->field_1A && n3->distanceTo(node3) < maxDist) field_10038[nr++] = n3;
|
||||
if (n4 && !n4->field_1A && n4->distanceTo(node3) < maxDist) field_10038[nr++] = n4;
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
bool PathFinder::inlined_0(Path& path, Node* nodeEnd)
|
||||
{
|
||||
if (dword_1CD870 < dword_1CD868)
|
||||
dword_1CD870 = dword_1CD868;
|
||||
|
||||
int number = 1;
|
||||
Node* temp = nodeEnd;
|
||||
while (temp->field_10)
|
||||
{
|
||||
temp = temp->field_10;
|
||||
number++;
|
||||
}
|
||||
|
||||
Node** pathNodes = new Node*[number];
|
||||
int index = number - 1;
|
||||
|
||||
pathNodes[index--] = nodeEnd;
|
||||
|
||||
while (nodeEnd->field_10)
|
||||
{
|
||||
pathNodes[index--] = nodeEnd->field_10;
|
||||
nodeEnd = nodeEnd->field_10;
|
||||
}
|
||||
|
||||
path.setNodes(pathNodes, number);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PathFinder::findPath(Path& path, Entity* pEntity, Node* nodeStart, Node* nodeEnd, const Node* node3, float fp)
|
||||
{
|
||||
dword_1CD868 = 0;
|
||||
|
||||
nodeStart->field_4 = 0;
|
||||
nodeStart->field_C = nodeStart->field_8 = nodeStart->distanceTo(nodeEnd);
|
||||
|
||||
m_binaryHeap.clear();
|
||||
m_binaryHeap.insert(nodeStart);
|
||||
|
||||
Node* nodep = nodeStart;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!m_binaryHeap.size())
|
||||
break;
|
||||
|
||||
Node* pNode = m_binaryHeap.removeTop();
|
||||
if (pNode->equals(nodeEnd))
|
||||
return inlined_0(path, nodeEnd);
|
||||
|
||||
if (nodep->distanceTo(nodeEnd) > pNode->distanceTo(nodeEnd))
|
||||
nodep = pNode;
|
||||
|
||||
pNode->field_1A = true;
|
||||
|
||||
int numNeighbors = getNeighbors(pEntity, pNode, node3, nodeEnd, fp);
|
||||
for (int i = 0; i < numNeighbors; i++)
|
||||
{
|
||||
Node* otherNode = field_10038[i];
|
||||
|
||||
if (!otherNode->field_1A)
|
||||
{
|
||||
float dist = pNode->field_4 + pNode->distanceTo(otherNode);
|
||||
if (otherNode->field_0 < 0 || otherNode->field_4 > dist)
|
||||
{
|
||||
otherNode->field_10 = pNode;
|
||||
otherNode->field_4 = dist;
|
||||
otherNode->field_8 = otherNode->distanceTo(nodeEnd);
|
||||
|
||||
if (otherNode->field_0 < 0)
|
||||
{
|
||||
otherNode->field_C = otherNode->field_4 + otherNode->field_8;
|
||||
m_binaryHeap.insert(otherNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update distance
|
||||
m_binaryHeap.setDistance(otherNode, otherNode->field_4 + otherNode->field_8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nodep != nodeStart)
|
||||
return inlined_0(path, nodeEnd);
|
||||
|
||||
return false; // no path found
|
||||
}
|
||||
|
||||
bool PathFinder::findPath(Path& path, Entity* pEntity, float x, float y, float z, float d)
|
||||
{
|
||||
// uh?
|
||||
m_nodeMap.clear();
|
||||
|
||||
m_nodeCount = 0;
|
||||
// not treating spillover btw? or what
|
||||
|
||||
int x1 = Mth::floor(pEntity->m_hitbox.min.x);
|
||||
int y1 = Mth::floor(pEntity->m_hitbox.min.y);
|
||||
int z1 = Mth::floor(pEntity->m_hitbox.min.z);
|
||||
Node* node1 = getNode(x1, y1, z1);
|
||||
|
||||
int x2 = Mth::floor(x - 0.5f * pEntity->field_88);
|
||||
int y2 = Mth::floor(y);
|
||||
int z2 = Mth::floor(z - 0.5f * pEntity->field_88);
|
||||
Node* node2 = nullptr;
|
||||
|
||||
if (!m_pLevel->getTile(x2, y2 - 1, z2))
|
||||
{
|
||||
for (int x3 = x2; x3 <= Mth::floor(x + 0.5f * pEntity->field_88); x3++)
|
||||
{
|
||||
for (int z3 = z2; z3 <= Mth::floor(y + 0.5f * pEntity->field_88); z3++)
|
||||
{
|
||||
if (m_pLevel->getTile(x3, y2 - 1, z3))
|
||||
{
|
||||
node2 = getNode(x3, y2, z3);
|
||||
break; // breaking out of the z3 loop only. Intended to break out of x3 too?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!node2)
|
||||
node2 = getNode(x2, y2, z2);
|
||||
|
||||
int x4 = Mth::floor(pEntity->field_88 + 1.0f);
|
||||
int y4 = Mth::floor(pEntity->field_8C + 1.0f);
|
||||
int z4 = Mth::floor(pEntity->field_88 + 1.0f);
|
||||
|
||||
Node node3;
|
||||
node3.setPos(x4, y4, z4);
|
||||
node3.setHash(MakeNodeHash(x4, y4, z4));
|
||||
|
||||
bool foundPath = findPath(path, pEntity, node1, node2, &node3, d);
|
||||
|
||||
if (m_nodeCount > 2048)
|
||||
{
|
||||
// huh.
|
||||
for (size_t i = 0; i < m_nodeSpillover.size(); i++)
|
||||
delete m_nodeSpillover[i];
|
||||
|
||||
m_nodeSpillover.clear();
|
||||
}
|
||||
|
||||
return foundPath;
|
||||
}
|
||||
|
||||
Node* PathFinder::new_Node(int x, int y, int z)
|
||||
{
|
||||
int nodeID = m_nodeCount++;
|
||||
|
||||
Node* pNode;
|
||||
|
||||
if (m_nodeCount < MAX_NODE_COUNT)
|
||||
{
|
||||
// Allocate from node reserve
|
||||
pNode = &m_nodeReserve[nodeID];
|
||||
pNode->init();
|
||||
pNode->setPos(x, y, z);
|
||||
pNode->setHash(MakeNodeHash(x, y, z));
|
||||
}
|
||||
else
|
||||
{
|
||||
pNode = new Node;
|
||||
pNode->setPos(x, y, z);
|
||||
pNode->setHash(MakeNodeHash(x, y, z));
|
||||
m_nodeSpillover.push_back(pNode);
|
||||
}
|
||||
|
||||
return pNode;
|
||||
}
|
||||
48
source/world/level/path/PathFinder.hpp
Normal file
48
source/world/level/path/PathFinder.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "Path.hpp"
|
||||
#include "BinaryHeap.hpp"
|
||||
|
||||
class Level;
|
||||
class Entity;
|
||||
|
||||
#define MAX_NODE_COUNT (2048)
|
||||
#define FIELD_10038_SIZE (32)
|
||||
|
||||
typedef std::map <int, Node*> NodeMap;
|
||||
|
||||
class PathFinder
|
||||
{
|
||||
public:
|
||||
PathFinder();
|
||||
~PathFinder();
|
||||
|
||||
int isFree(Entity*, int x, int y, int z, const Node* node);
|
||||
Node* getNode(Entity*, int x, int y, int z, const Node* node, int a);
|
||||
Node* getNode(int x, int y, int z);
|
||||
int getNeighbors(Entity*, Node*, const Node*, Node*, float);
|
||||
bool findPath(Path&, Entity*, Node*, Node*, const Node*, float);
|
||||
bool findPath(Path&, Entity*, float, float, float, float);
|
||||
|
||||
private:
|
||||
Node* new_Node(int x, int y, int z);
|
||||
bool inlined_0(Path& path, Node* node2);
|
||||
|
||||
private:
|
||||
Level* m_pLevel;
|
||||
BinaryHeap m_binaryHeap;
|
||||
NodeMap m_nodeMap;
|
||||
Node m_nodeReserve[MAX_NODE_COUNT];
|
||||
std::vector<Node*> m_nodeSpillover;
|
||||
int m_nodeCount;
|
||||
Node* field_10038[FIELD_10038_SIZE];
|
||||
};
|
||||
@@ -39,11 +39,11 @@ public:
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// @NOTE: These are inlined.
|
||||
inline bool isOpen(int data)
|
||||
inline static bool isOpen(int data)
|
||||
{
|
||||
return (data & 4) != 0;
|
||||
}
|
||||
inline bool isTop(int data)
|
||||
inline static bool isTop(int data)
|
||||
{
|
||||
return (data & 8) != 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user