mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-04-24 12:23:36 +00:00
145 lines
5 KiB
C++
145 lines
5 KiB
C++
#include "../../Platform/stdafx.h"
|
|
#include "../../Headers/net.minecraft.world.level.h"
|
|
#include "../../Headers/net.minecraft.world.level.tile.h"
|
|
#include "OreFeature.h"
|
|
|
|
void OreFeature::_init(int tile, int count, int targetTile) {
|
|
this->tile = tile;
|
|
this->count = count;
|
|
this->targetTile = targetTile;
|
|
}
|
|
|
|
OreFeature::OreFeature(int tile, int count) {
|
|
_init(tile, count, Tile::stone_Id);
|
|
}
|
|
|
|
OreFeature::OreFeature(int tile, int count, int targetTile) {
|
|
_init(tile, count, targetTile);
|
|
}
|
|
|
|
bool OreFeature::place(Level* level, Random* random, int x, int y, int z) {
|
|
PIXBeginNamedEvent(0, "Place Ore Feature");
|
|
float dir = random->nextFloat() * PI;
|
|
|
|
double x0 = x + 8 + Mth::sin(dir) * count / 8;
|
|
double x1 = x + 8 - Mth::sin(dir) * count / 8;
|
|
double z0 = z + 8 + Mth::cos(dir) * count / 8;
|
|
double z1 = z + 8 - Mth::cos(dir) * count / 8;
|
|
|
|
double y0 = y + random->nextInt(3) - 2;
|
|
double y1 = y + random->nextInt(3) - 2;
|
|
|
|
bool collisionsExpected = false;
|
|
|
|
LevelGenerationOptions* levelGenOptions = NULL;
|
|
if (app.getLevelGenerationOptions() != NULL) {
|
|
levelGenOptions = app.getLevelGenerationOptions();
|
|
|
|
// 4J Stu - Optimise schematic intersection checks by first checking the
|
|
// max possible bounding box of this place call
|
|
int minX = x0 - 1;
|
|
int minY = y0 - 1;
|
|
int minZ = z0 - 1;
|
|
|
|
double maxss = count / 16;
|
|
double maxr = (Mth::sin(PI) + 1) * maxss + 1;
|
|
double maxhr = (Mth::sin(PI) + 1) * maxss + 1;
|
|
int maxX = Mth::floor(x1 + maxr / 2);
|
|
int maxY = Mth::floor(y1 + maxhr / 2);
|
|
int maxZ = Mth::floor(z1 + maxr / 2);
|
|
|
|
collisionsExpected = levelGenOptions->checkIntersects(minX, minY, minZ,
|
|
maxX, maxY, maxZ);
|
|
}
|
|
|
|
bool doEarlyRejectTest = false;
|
|
if (y0 > level->getSeaLevel()) {
|
|
doEarlyRejectTest = true;
|
|
}
|
|
|
|
for (int d = 0; d <= count; d++) {
|
|
double xx = x0 + (x1 - x0) * d / count;
|
|
double yy = y0 + (y1 - y0) * d / count;
|
|
double zz = z0 + (z1 - z0) * d / count;
|
|
|
|
double ss = random->nextDouble() * count / 16;
|
|
double r = (Mth::sin(d * PI / count) + 1) * ss + 1;
|
|
double hr = r; //(Mth::sin(d * PI / count) + 1) * ss + 1;
|
|
|
|
double halfR = r / 2;
|
|
double halfHR = halfR; // hr/2;
|
|
|
|
int xt0 = Mth::floor(xx - halfR);
|
|
int yt0 = Mth::floor(yy - halfHR);
|
|
int zt0 = Mth::floor(zz - halfR);
|
|
|
|
int xt1 = Mth::floor(xx + halfR);
|
|
int yt1 = Mth::floor(yy + halfHR);
|
|
int zt1 = Mth::floor(zz + halfR);
|
|
|
|
// 4J Stu Added to stop ore features generating areas previously place
|
|
// by game rule generation
|
|
if (collisionsExpected && levelGenOptions != NULL) {
|
|
bool intersects =
|
|
levelGenOptions->checkIntersects(xt0, yt0, zt0, xt1, yt1, zt1);
|
|
if (intersects) {
|
|
// app.DebugPrintf("Skipping ore feature generation as it
|
|
// overlaps a game rule structure\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// A large % of ore placement is entirely into the air. Attempt to
|
|
// identify some of these early, by check the corners of the area we are
|
|
// placing in to see if we are going to (very probably) be entirely
|
|
// above the height stored in the heightmap
|
|
|
|
if (doEarlyRejectTest) {
|
|
bool earlyReject = true;
|
|
if (level->getHeightmap(xt0, zt0) >= yt0)
|
|
earlyReject = false;
|
|
else if (level->getHeightmap(xt1, zt0) >= yt0)
|
|
earlyReject = false;
|
|
else if (level->getHeightmap(xt0, zt1) >= yt0)
|
|
earlyReject = false;
|
|
else if (level->getHeightmap(xt1, zt1) >= yt0)
|
|
earlyReject = false;
|
|
|
|
if (earlyReject) continue;
|
|
}
|
|
|
|
double xdxd, ydyd;
|
|
|
|
double xd0 = ((xt0 + 0.5) - xx);
|
|
double yd0 = ((yt0 + 0.5) - yy);
|
|
double zd0 = ((zt0 + 0.5) - zz);
|
|
|
|
double halfRSq = halfR * halfR;
|
|
|
|
double xd = xd0;
|
|
for (int x2 = xt0; x2 <= xt1; x2++, xd++) {
|
|
xdxd = xd * xd;
|
|
if (xdxd < halfRSq) {
|
|
double yd = yd0;
|
|
for (int y2 = yt0; y2 <= yt1; y2++, yd++) {
|
|
ydyd = yd * yd;
|
|
if (xdxd + ydyd < halfRSq) {
|
|
double zd = zd0;
|
|
for (int z2 = zt0; z2 <= zt1; z2++, zd++) {
|
|
if (xdxd + ydyd + zd * zd < halfRSq) {
|
|
if (level->getTile(x2, y2, z2) == targetTile) {
|
|
level->setTileAndData(
|
|
x2, y2, z2, tile, 0,
|
|
Tile::UPDATE_INVISIBLE_NO_LIGHT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PIXEndNamedEvent();
|
|
return true;
|
|
} |