diff options
Diffstat (limited to 'Minecraft.World/PortalForcer.cpp')
| -rw-r--r-- | Minecraft.World/PortalForcer.cpp | 263 |
1 files changed, 205 insertions, 58 deletions
diff --git a/Minecraft.World/PortalForcer.cpp b/Minecraft.World/PortalForcer.cpp index 7c9b7a86..8880399e 100644 --- a/Minecraft.World/PortalForcer.cpp +++ b/Minecraft.World/PortalForcer.cpp @@ -3,58 +3,72 @@ #include "net.minecraft.world.level.h" #include "net.minecraft.world.level.tile.h" #include "net.minecraft.world.level.dimension.h" +#include "..\Minecraft.Client\ServerLevel.h" #include "PortalForcer.h" -PortalForcer::PortalForcer() +PortalForcer::PortalPosition::PortalPosition(int x, int y, int z, __int64 time) : Pos(x, y, z) { - random = new Random(); + lastUsed = time; } +PortalForcer::PortalForcer(ServerLevel *level) +{ + this->level = level; + random = new Random(level->getSeed()); +} + +PortalForcer::~PortalForcer() +{ + for(AUTO_VAR(it,cachedPortals.begin()); it != cachedPortals.end(); ++it) + { + delete it->second; + } +} -void PortalForcer::force(Level *level, shared_ptr<Entity> e) +void PortalForcer::force(shared_ptr<Entity> e, double xOriginal, double yOriginal, double zOriginal, float yRotOriginal) { - if (level->dimension->id == 1) + if (level->dimension->id == 1) { - int x = Mth::floor(e->x); - int y = Mth::floor(e->y) - 1; - int z = Mth::floor(e->z); + int x = Mth::floor(e->x); + int y = Mth::floor(e->y) - 1; + int z = Mth::floor(e->z); - int xa = 1; - int za = 0; - for (int b = -2; b <= 2; b++) + int xa = 1; + int za = 0; + for (int b = -2; b <= 2; b++) { - for (int s = -2; s <= 2; s++) + for (int s = -2; s <= 2; s++) { - for (int h = -1; h < 3; h++) + for (int h = -1; h < 3; h++) { - int xt = x + s * xa + b * za; - int yt = y + h; - int zt = z + s * za - b * xa; + int xt = x + s * xa + b * za; + int yt = y + h; + int zt = z + s * za - b * xa; - bool border = h < 0; + bool border = h < 0; - level->setTile(xt, yt, zt, border ? Tile::obsidian_Id : 0); - } - } - } + level->setTileAndUpdate(xt, yt, zt, border ? Tile::obsidian_Id : 0); + } + } + } - e->moveTo(x, y, z, e->yRot, 0); - e->xd = e->yd = e->zd = 0; + e->moveTo(x, y, z, e->yRot, 0); + e->xd = e->yd = e->zd = 0; - return; - } + return; + } - if (findPortal(level, e)) + if (findPortal(e, xOriginal, yOriginal, zOriginal, yRotOriginal)) { return; } - createPortal(level, e); - findPortal(level, e); + createPortal(e); + findPortal(e, xOriginal, yOriginal, zOriginal, yRotOriginal); } -bool PortalForcer::findPortal(Level *level, shared_ptr<Entity> e) +bool PortalForcer::findPortal(shared_ptr<Entity> e, double xOriginal, double yOriginal, double zOriginal, float yRotOriginal) { // 4J Stu - Decrease the range at which we search for a portal in the nether given our smaller nether int r = 16;//* 8; @@ -79,29 +93,47 @@ bool PortalForcer::findPortal(Level *level, shared_ptr<Entity> e) int xc = Mth::floor(e->x); int zc = Mth::floor(e->z); - for (int x = xc - r; x <= xc + r; x++) + long hash = ChunkPos::hashCode(xc, zc); + bool updateCache = true; + + AUTO_VAR(it, cachedPortals.find(hash)); + if (it != cachedPortals.end()) + { + PortalPosition *pos = it->second; + + closest = 0; + xTarget = pos->x; + yTarget = pos->y; + zTarget = pos->z; + pos->lastUsed = level->getGameTime(); + updateCache = false; + } + else { - double xd = (x + 0.5) - e->x; - for (int z = zc - r; z <= zc + r; z++) + for (int x = xc - r; x <= xc + r; x++) { - double zd = (z + 0.5) - e->z; - for (int y = level->getHeight() - 1; y >= 0; y--) + double xd = (x + 0.5) - e->x; + for (int z = zc - r; z <= zc + r; z++) { - if (level->getTile(x, y, z) == Tile::portalTile_Id) + double zd = (z + 0.5) - e->z; + for (int y = level->getHeight() - 1; y >= 0; y--) { - while (level->getTile(x, y - 1, z) == Tile::portalTile_Id) + if (level->getTile(x, y, z) == Tile::portalTile_Id) { - y--; - } + while (level->getTile(x, y - 1, z) == Tile::portalTile_Id) + { + y--; + } - double yd = (y + 0.5) - e->y; - double dist = xd * xd + yd * yd + zd * zd; - if (closest < 0 || dist < closest) - { - closest = dist; - xTarget = x; - yTarget = y; - zTarget = z; + double yd = (y + 0.5) - e->y; + double dist = xd * xd + yd * yd + zd * zd; + if (closest < 0 || dist < closest) + { + closest = dist; + xTarget = x; + yTarget = y; + zTarget = z; + } } } } @@ -114,18 +146,110 @@ bool PortalForcer::findPortal(Level *level, shared_ptr<Entity> e) int y = yTarget; int z = zTarget; + if (updateCache) + { + cachedPortals[hash] = new PortalPosition(x, y, z, level->getGameTime()); + cachedPortalKeys.push_back(hash); + } + double xt = x + 0.5; double yt = y + 0.5; double zt = z + 0.5; + int dir = Direction::UNDEFINED; - if (level->getTile(x - 1, y, z) == Tile::portalTile_Id) xt -= 0.5; - if (level->getTile(x + 1, y, z) == Tile::portalTile_Id) xt += 0.5; + if (level->getTile(x - 1, y, z) == Tile::portalTile_Id) dir = Direction::NORTH; + if (level->getTile(x + 1, y, z) == Tile::portalTile_Id) dir = Direction::SOUTH; + if (level->getTile(x, y, z - 1) == Tile::portalTile_Id) dir = Direction::EAST; + if (level->getTile(x, y, z + 1) == Tile::portalTile_Id) dir = Direction::WEST; - if (level->getTile(x, y, z - 1) == Tile::portalTile_Id) zt -= 0.5; - if (level->getTile(x, y, z + 1) == Tile::portalTile_Id) zt += 0.5; + int originalDir = e->getPortalEntranceDir(); - e->moveTo(xt, yt, zt, e->yRot, 0); - e->xd = e->yd = e->zd = 0; + if (dir > Direction::UNDEFINED) + { + int leftDir = Direction::DIRECTION_COUNTER_CLOCKWISE[dir]; + int forwardsx = Direction::STEP_X[dir]; + int forwardsz = Direction::STEP_Z[dir]; + int leftx = Direction::STEP_X[leftDir]; + int leftz = Direction::STEP_Z[leftDir]; + + bool leftBlocked = !level->isEmptyTile(x + forwardsx + leftx, y, z + forwardsz + leftz) || !level->isEmptyTile(x + forwardsx + leftx, y + 1, z + forwardsz + leftz); + bool rightBlocked = !level->isEmptyTile(x + forwardsx, y, z + forwardsz) || !level->isEmptyTile(x + forwardsx, y + 1, z + forwardsz); + + if (leftBlocked && rightBlocked) + { + dir = Direction::DIRECTION_OPPOSITE[dir]; + leftDir = Direction::DIRECTION_OPPOSITE[leftDir]; + forwardsx = Direction::STEP_X[dir]; + forwardsz = Direction::STEP_Z[dir]; + leftx = Direction::STEP_X[leftDir]; + leftz = Direction::STEP_Z[leftDir]; + + x -= leftx; + xt -= leftx; + z -= leftz; + zt -= leftz; + leftBlocked = !level->isEmptyTile(x + forwardsx + leftx, y, z + forwardsz + leftz) || !level->isEmptyTile(x + forwardsx + leftx, y + 1, z + forwardsz + leftz); + rightBlocked = !level->isEmptyTile(x + forwardsx, y, z + forwardsz) || !level->isEmptyTile(x + forwardsx, y + 1, z + forwardsz); + } + + float offsetLeft = 0.5f; + float offsetForwards = 0.5f; + + if (!leftBlocked && rightBlocked) + { + offsetLeft = 1; + } + else if (leftBlocked && !rightBlocked) + { + offsetLeft = 0; + } + else if (leftBlocked && rightBlocked) + { + offsetForwards = 0; + } + + // Center them in the frame and push them out forwards + xt += (leftx * offsetLeft) + (offsetForwards * forwardsx); + zt += (leftz * offsetLeft) + (offsetForwards * forwardsz); + + float xx = 0; + float zz = 0; + float xz = 0; + float zx = 0; + + if (dir == originalDir) + { + xx = 1; + zz = 1; + } + else if (dir == Direction::DIRECTION_OPPOSITE[originalDir]) + { + xx = -1; + zz = -1; + } + else if (dir == Direction::DIRECTION_CLOCKWISE[originalDir]) + { + xz = 1; + zx = -1; + } + else + { + xz = -1; + zx = 1; + } + + double xd = e->xd; + double zd = e->zd; + e->xd = xd * xx + zd * zx; + e->zd = xd * xz + zd * zz; + e->yRot = (yRotOriginal - originalDir * 90) + (dir * 90); + } + else + { + e->xd = e->yd = e->zd = 0; + } + + e->moveTo(xt, yt, zt, e->yRot, e->xRot); return true; } @@ -133,7 +257,7 @@ bool PortalForcer::findPortal(Level *level, shared_ptr<Entity> e) } -bool PortalForcer::createPortal(Level *level, shared_ptr<Entity> e) +bool PortalForcer::createPortal(shared_ptr<Entity> e) { // 4J Stu - Increase the range at which we try and create a portal to stop creating them floating in mid air over lava int r = 16 * 3; @@ -240,7 +364,7 @@ bool PortalForcer::createPortal(Level *level, shared_ptr<Entity> e) } } } - next_first: continue; +next_first: continue; } } } @@ -299,7 +423,7 @@ bool PortalForcer::createPortal(Level *level, shared_ptr<Entity> e) } } } - next_second: continue; +next_second: continue; } } } @@ -341,7 +465,7 @@ bool PortalForcer::createPortal(Level *level, shared_ptr<Entity> e) bool border = h < 0; - level->setTile(xt, yt, zt, border ? Tile::obsidian_Id : 0); + level->setTileAndUpdate(xt, yt, zt, border ? Tile::obsidian_Id : 0); } } } @@ -349,7 +473,6 @@ bool PortalForcer::createPortal(Level *level, shared_ptr<Entity> e) for (int pass = 0; pass < 4; pass++) { - level->noNeighborUpdate = true; for (int s = 0; s < 4; s++) { for (int h = -1; h < 4; h++) @@ -359,10 +482,9 @@ bool PortalForcer::createPortal(Level *level, shared_ptr<Entity> e) int zt = z + (s - 1) * za; bool border = s == 0 || s == 3 || h == -1 || h == 3; - level->setTile(xt, yt, zt, border ? Tile::obsidian_Id : Tile::portalTile_Id); + level->setTileAndData(xt, yt, zt, border ? Tile::obsidian_Id : Tile::portalTile_Id, 0, Tile::UPDATE_CLIENTS); } } - level->noNeighborUpdate = false; for (int s = 0; s < 4; s++) { @@ -379,3 +501,28 @@ bool PortalForcer::createPortal(Level *level, shared_ptr<Entity> e) return true; } + +void PortalForcer::tick(__int64 time) +{ + if (time % (SharedConstants::TICKS_PER_SECOND * 5) == 0) + { + __int64 cutoff = time - SharedConstants::TICKS_PER_SECOND * 30; + + for(AUTO_VAR(it,cachedPortalKeys.begin()); it != cachedPortalKeys.end();) + { + __int64 key = *it; + PortalPosition *pos = cachedPortals[key]; + + if (pos == NULL || pos->lastUsed < cutoff) + { + delete pos; + it = cachedPortalKeys.erase(it); + cachedPortals.erase(key); + } + else + { + ++it; + } + } + } +}
\ No newline at end of file |
