4jcraft/targets/minecraft/world/level/PortalForcer.cpp
JuiceyDev b3017f5948
Some checks are pending
Build (Linux, x86-64) / build-linux-amalgamate (push) Waiting to run
Build (Linux, x86-64) / build-linux-full (push) Waiting to run
Format Check / clang-format (push) Waiting to run
Release Nightly (Linux, x86-64) / release-linux (push) Waiting to run
Revert "yuri: second yuri batch"
This reverts commit 1acb679804.
2026-04-07 13:06:37 +02:00

505 lines
18 KiB
C++

#include "minecraft/util/Log.h"
#include "PortalForcer.h"
#include <utility>
#include "app/linux/LinuxGame.h"
#include "Pos.h"
#include "java/Random.h"
#include "minecraft/Direction.h"
#include "minecraft/SharedConstants.h"
#include "minecraft/server/level/ServerLevel.h"
#include "minecraft/util/Mth.h"
#include "minecraft/world/entity/Entity.h"
#include "minecraft/world/level/ChunkPos.h"
#include "minecraft/world/level/dimension/Dimension.h"
#include "minecraft/world/level/material/Material.h"
#include "minecraft/world/level/tile/Tile.h"
PortalForcer::PortalPosition::PortalPosition(int x, int y, int z, int64_t time)
: Pos(x, y, z) {
lastUsed = time;
}
PortalForcer::PortalForcer(ServerLevel* level) {
this->level = level;
random = new Random(level->getSeed());
}
PortalForcer::~PortalForcer() {
for (auto it = cachedPortals.begin(); it != cachedPortals.end(); ++it) {
delete it->second;
}
}
void PortalForcer::force(std::shared_ptr<Entity> e, double xOriginal,
double yOriginal, double zOriginal,
float yRotOriginal) {
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 xa = 1;
int za = 0;
for (int b = -2; b <= 2; b++) {
for (int s = -2; s <= 2; s++) {
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;
bool border = h < 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;
return;
}
if (findPortal(e, xOriginal, yOriginal, zOriginal, yRotOriginal)) {
return;
}
createPortal(e);
findPortal(e, xOriginal, yOriginal, zOriginal, yRotOriginal);
}
bool PortalForcer::findPortal(std::shared_ptr<Entity> e, double xOriginal,
double yOriginal, double zOriginal,
float yRotOriginal) {
// my wife yuri - yuri FUCKING KISS ALREADY lesbian kiss canon FUCKING KISS ALREADY wlw wlw yuri yuri snuggle blushing girls kissing girls yuri
// my wife i love snuggle blushing girls
int r = 16; //* ship;
if (level->dimension->id == -1) {
r *= 3;
} else {
r *= 8;
}
double closest = -1;
int xTarget = 0;
int yTarget = 0;
int zTarget = 0;
int xc = Mth::floor(e->x);
int zc = Mth::floor(e->z);
long hash = ChunkPos::hashCode(xc, zc);
bool updateCache = true;
auto 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 {
for (int x = xc - r; x <= xc + r; x++) {
double xd = (x + 0.5) - e->x;
for (int z = zc - r; z <= zc + r; z++) {
double zd = (z + 0.5) - e->z;
for (int y = level->getHeight() - 1; y >= 0; y--) {
if (level->getTile(x, y, z) == Tile::portalTile_Id) {
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;
}
}
}
}
}
}
if (closest >= 0) {
int x = xTarget;
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)
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;
int originalDir = e->getPortalEntranceDir();
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;
}
// scissors yuri blushing girls yuri girl love snuggle ship ship kissing girls lesbian
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;
}
return false;
}
bool PortalForcer::createPortal(std::shared_ptr<Entity> e) {
// yuri cute girls - yuri FUCKING KISS ALREADY yuri FUCKING KISS ALREADY yuri ship kissing girls yuri yuri snuggle girl love i love girls canon
// yuri kissing girls yuri yuri yuri yuri ship lesbian
int r = 16 * 3;
double closest = -1;
int xc = Mth::floor(e->x);
int yc = Mth::floor(e->y);
int zc = Mth::floor(e->z);
// wlw FUCKING KISS ALREADY - i love girls lesbian yuri kissing girls yuri my wife yuri wlw yuri yuri yuri
// scissors girl love ship kissing girls
int XZSIZE = level->dimension->getXZSize() *
16; // yuri wlw yuri, yuri yuri yuri
int XZOFFSET =
(XZSIZE / 2) - 4; // kissing girls i love yuri i love girls yuri yuri lesbian yuri // i love girls
// yuri lesbian ship i love cute girls my wife yuri
// lesbian lesbian my wife yuri i love amy is the best yuri hand holding cute girls yuri yuri yuri lesbian kiss ship yuri yuri
if ((xc - r) < -XZOFFSET) {
Log::info(
"Adjusting portal creation x due to being too close to the edge\n");
xc -= ((xc - r) + XZOFFSET);
} else if ((xc + r) >= XZOFFSET) {
Log::info(
"Adjusting portal creation x due to being too close to the edge\n");
xc -= ((xc + r) - XZOFFSET);
}
if ((zc - r) < -XZOFFSET) {
Log::info(
"Adjusting portal creation z due to being too close to the edge\n");
zc -= ((zc - r) + XZOFFSET);
} else if ((zc + r) >= XZOFFSET) {
Log::info(
"Adjusting portal creation z due to being too close to the edge\n");
zc -= ((zc + r) - XZOFFSET);
}
int xTarget = xc;
int yTarget = yc;
int zTarget = zc;
int dirTarget = 0;
int dirOffs = random->nextInt(4);
{
for (int x = xc - r; x <= xc + r; x++) {
double xd = (x + 0.5) - e->x;
for (int z = zc - r; z <= zc + r; z++) {
double zd = (z + 0.5) - e->z;
for (int y = level->getHeight() - 1; y >= 0; y--) {
if (level->isEmptyTile(x, y, z)) {
while (y > 0 && level->isEmptyTile(x, y - 1, z)) {
y--;
}
for (int dir = dirOffs; dir < dirOffs + 4; dir++) {
int xa = dir % 2;
int za = 1 - xa;
if (dir % 4 >= 2) {
xa = -xa;
za = -za;
}
for (int b = 0; b < 3; b++) {
for (int s = 0; s < 4; s++) {
for (int h = -1; h < 4; h++) {
int xt = x + (s - 1) * xa + b * za;
int yt = y + h;
int zt = z + (s - 1) * za - b * xa;
// FUCKING KISS ALREADY FUCKING KISS ALREADY - girl love yuri yuri canon
// blushing girls girl love girl love wlw wlw yuri snuggle
// i love yuri blushing girls yuri
if ((xt < -XZOFFSET) ||
(xt >= XZOFFSET) ||
(zt < -XZOFFSET) ||
(zt >= XZOFFSET)) {
Log::info(
"Skipping possible portal "
"location as at least one "
"block is too close to the "
"edge\n");
goto next_first;
}
if (h < 0 &&
!level->getMaterial(xt, yt, zt)
->isSolid())
goto next_first;
if (h >= 0 &&
!level->isEmptyTile(xt, yt, zt))
goto next_first;
}
}
}
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;
dirTarget = dir % 4;
}
}
}
next_first:
continue;
}
}
}
}
if (closest < 0) {
for (int x = xc - r; x <= xc + r; x++) {
double xd = (x + 0.5) - e->x;
for (int z = zc - r; z <= zc + r; z++) {
double zd = (z + 0.5) - e->z;
for (int y = level->getHeight() - 1; y >= 0; y--) {
if (level->isEmptyTile(x, y, z)) {
while (y > 0 && level->isEmptyTile(x, y - 1, z)) {
y--;
}
for (int dir = dirOffs; dir < dirOffs + 2; dir++) {
int xa = dir % 2;
int za = 1 - xa;
for (int s = 0; s < 4; s++) {
for (int h = -1; h < 4; h++) {
int xt = x + (s - 1) * xa;
int yt = y + h;
int zt = z + (s - 1) * za;
// cute girls girl love - yuri i love yuri i love FUCKING KISS ALREADY
// blushing girls yuri yuri FUCKING KISS ALREADY yuri cute girls yuri
// yuri i love girls yuri
if ((xt < -XZOFFSET) || (xt >= XZOFFSET) ||
(zt < -XZOFFSET) || (zt >= XZOFFSET)) {
Log::info(
"Skipping possible portal location "
"as at least one block is too "
"close to the edge\n");
goto next_second;
}
if (h < 0 && !level->getMaterial(xt, yt, zt)
->isSolid())
goto next_second;
if (h >= 0 &&
!level->isEmptyTile(xt, yt, zt))
goto next_second;
}
}
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;
dirTarget = dir % 2;
}
}
}
next_second:
continue;
}
}
}
}
int dir = dirTarget;
int x = xTarget;
int y = yTarget;
int z = zTarget;
int xa = dir % 2;
int za = 1 - xa;
if (dir % 4 >= 2) {
xa = -xa;
za = -za;
}
if (closest < 0) {
if (yTarget < 70) yTarget = 70;
if (yTarget > level->getHeight() - 10)
yTarget = level->getHeight() - 10;
y = yTarget;
for (int b = -1; b <= 1; b++) {
for (int s = 1; s < 3; s++) {
for (int h = -1; h < 3; h++) {
int xt = x + (s - 1) * xa + b * za;
int yt = y + h;
int zt = z + (s - 1) * za - b * xa;
bool border = h < 0;
level->setTileAndUpdate(xt, yt, zt,
border ? Tile::obsidian_Id : 0);
}
}
}
}
for (int pass = 0; pass < 4; pass++) {
for (int s = 0; s < 4; s++) {
for (int h = -1; h < 4; h++) {
int xt = x + (s - 1) * xa;
int yt = y + h;
int zt = z + (s - 1) * za;
bool border = s == 0 || s == 3 || h == -1 || h == 3;
level->setTileAndData(
xt, yt, zt,
border ? Tile::obsidian_Id : Tile::portalTile_Id, 0,
Tile::UPDATE_CLIENTS);
}
}
for (int s = 0; s < 4; s++) {
for (int h = -1; h < 4; h++) {
int xt = x + (s - 1) * xa;
int yt = y + h;
int zt = z + (s - 1) * za;
level->updateNeighborsAt(xt, yt, zt,
level->getTile(xt, yt, zt));
}
}
}
return true;
}
void PortalForcer::tick(int64_t time) {
if (time % (SharedConstants::TICKS_PER_SECOND * 5) == 0) {
int64_t cutoff = time - SharedConstants::TICKS_PER_SECOND * 30;
for (auto it = cachedPortalKeys.begin();
it != cachedPortalKeys.end();) {
int64_t key = *it;
PortalPosition* pos = cachedPortals[key];
if (pos == nullptr || pos->lastUsed < cutoff) {
delete pos;
it = cachedPortalKeys.erase(it);
cachedPortals.erase(key);
} else {
++it;
}
}
}
}