Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions finders.c
Original file line number Diff line number Diff line change
Expand Up @@ -2129,6 +2129,97 @@ Pos3List generateVeinPart(int mc, OreConfig config, RandomSource rnd, double off
return poses;
}

//==============================================================================
// Ore vein generation
//==============================================================================

int initOreVeinNoise(OreVeinParameters *params, uint64_t ws, int mc) {
static const uint64_t md5_ore[2] = {0x9b88124de600116d, 0x2ae68055aa4a7761}; // minecraft:ore
static const uint64_t md5_ore_veininess[2] = {0x6b86c7820a307171, 0xd87fb0fefd9c1624}; // minecraft:ore_veininess
static const uint64_t md5_ore_vein_a[2] = {0x4cd8d69b9a841649, 0xcdd63f17bfe8f5ed}; // minecraft:ore_vein_a
static const uint64_t md5_ore_vein_b[2] = {0x6b26220b31f7c6c9, 0xae077edebf6aaec1}; // minecraft:ore_vein_b
static const uint64_t md5_ore_gap[2] = {0x9c4cc6b2fb0be4bb, 0xbd5964705573bb5e}; // minecraft:ore_gap

if (mc <= MC_1_17) {
return 0;
}

Xoroshiro wsx;
xSetSeed(&wsx, ws);
const uint64_t lo = xNextLong(&wsx);
const uint64_t hi = xNextLong(&wsx);

Xoroshiro ore_x = {lo ^ md5_ore[0], hi ^ md5_ore[1]};
const uint64_t a = xNextLong(&ore_x);
const uint64_t b = xNextLong(&ore_x);
ore_x = (Xoroshiro) {a, b};
params->posRandom = ore_x;

Xoroshiro ore_veininess_x = {lo ^ md5_ore_veininess[0], hi ^ md5_ore_veininess[1]};
DoublePerlinNoise ore_veininess_n;
const double ore_veininess_amp = {1.0};
xDoublePerlinInit(&ore_veininess_n, &ore_veininess_x, malloc(2 * sizeof(PerlinNoise)), &ore_veininess_amp, -8, 1, -1);
params->oreVeininess = ore_veininess_n;

Xoroshiro ore_vein_a_x = {lo ^ md5_ore_vein_a[0], hi ^ md5_ore_vein_a[1]};
DoublePerlinNoise ore_vein_a_n;
const double ore_vein_a_amp = {1.0};
xDoublePerlinInit(&ore_vein_a_n, &ore_vein_a_x, malloc(2 * sizeof(PerlinNoise)), &ore_vein_a_amp, -7, 1, -1);
params->oreVeinA = ore_vein_a_n;

Xoroshiro ore_vein_b_x = {lo ^ md5_ore_vein_b[0], hi ^ md5_ore_vein_b[1]};
DoublePerlinNoise ore_vein_b_n;
const double ore_vein_b_amp = {1.0};
xDoublePerlinInit(&ore_vein_b_n, &ore_vein_b_x, malloc(2 * sizeof(PerlinNoise)), &ore_vein_b_amp, -7, 1, -1);
params->oreVeinB = ore_vein_b_n;

Xoroshiro ore_gap_x = {lo ^ md5_ore_gap[0], hi ^ md5_ore_gap[1]};
DoublePerlinNoise ore_gap_n;
const double ore_gap_amp = {1.0};
xDoublePerlinInit(&ore_gap_n, &ore_gap_x, malloc(2 * sizeof(PerlinNoise)), &ore_gap_amp, -5, 1, -1);
params->oreGap = ore_gap_n;

return 1;
}

int32_t getOreVeinBlockAt(int x, int y, int z, OreVeinParameters* params)
{
static const OreVeinConfig
ov_copper = {COPPER_ORE, RAW_COPPER_BLOCK, GRANITE, 0, 50},
ov_iron = {IRON_ORE, RAW_IRON_BLOCK, TUFF, -60, -8};
static const int min_y = MIN(0 /*ov_copper.minY*/, -60 /*ov_iron.minY*/);
static const int max_y = MAX(50 /*ov_copper.maxY*/, -8 /*ov_iron.maxY*/);

if (y < min_y || y > max_y) {
return -1;
}
double veinRidgedSample = MAX(fabs(sampleDoublePerlin(&params->oreVeinA, 4 * x, 4 * y, 4 * z)), fabs(sampleDoublePerlin(&params->oreVeinB, 4 * x, 4 * y, 4 * z)));
if (veinRidgedSample >= 0.08F) {
return -1;
}
double veinToggleSample = sampleDoublePerlin(&params->oreVeininess, x * 1.5, y * 1.5, z * 1.5);
OreVeinConfig ovconf = veinToggleSample > 0.0 ? ov_copper : ov_iron;
double abs = fabs(veinToggleSample);
int belowTop = ovconf.maxY - y;
int aboveBottom = y - ovconf.minY;
if (aboveBottom < 0 || belowTop < 0) {
return -1;
}
int offset = MIN(belowTop, aboveBottom);
if (abs + clampedMap(offset, 0.0, 20.0, -0.2, 0.0) < 0.4F) {
return -1;
}
Xoroshiro xr = xAtPos(&params->posRandom, x, y, z);
if (xNextFloat(&xr) > 0.7F) {
return -1;
}
double veinGapSample = sampleDoublePerlin(&params->oreGap, x, y, z);
if (xNextFloat(&xr) < clampedMap(abs, 0.4F, 0.6F, 0.1F, 0.3F) && veinGapSample > -0.3F) {
return xNextFloat(&xr) < 0.02F ? ovconf.rawOreBlock : ovconf.oreBlock;
}
return ovconf.fillerBlock;
}

//==============================================================================
// Validating Structure Positions
//==============================================================================
Expand Down
29 changes: 29 additions & 0 deletions finders.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ enum Blocks {
NETHERRACK,
NETHER_GOLD_ORE,
NETHER_QUARTZ_ORE,
RAW_COPPER_BLOCK,
RAW_IRON_BLOCK,
REDSTONE_ORE,
SOUL_SAND,
STONE,
Expand Down Expand Up @@ -509,6 +511,33 @@ Pos3List generateOrePositions(const Generator *g, const SurfaceNoise *sn, OreCon

Pos3List generateVeinPart(int mc, OreConfig config, RandomSource rnd, double offsetXPos, double offsetXNeg, double offsetZPos, double offsetZNeg, double offsetYPos, double offsetYNeg, int startX, int startY, int startZ, int oreSize, int radius);

enum OreVeins {
CopperVein,
IronVein,
};

STRUCT(OreVeinConfig)
{
uint32_t oreBlock;
uint32_t rawOreBlock;
uint32_t fillerBlock;
int32_t minY;
int32_t maxY;
};

STRUCT(OreVeinParameters)
{
DoublePerlinNoise oreVeininess;
DoublePerlinNoise oreVeinA;
DoublePerlinNoise oreVeinB;
DoublePerlinNoise oreGap;
Xoroshiro posRandom;
};

int initOreVeinNoise(OreVeinParameters *params, uint64_t ws, int mc);

int32_t getOreVeinBlockAt(int x, int y, int z, OreVeinParameters* params);

/* Finds a suitable pseudo-random location in the specified area.
* This function is used to determine the positions of spawn and strongholds.
* Warning: accurate, but slow!
Expand Down
13 changes: 13 additions & 0 deletions rng.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,15 @@ static inline int xNextIntJBetween(Xoroshiro *xr, const int min, const int max)
return xNextIntJ(xr, max - min + 1) + min;
}

static inline Xoroshiro xAtPos(Xoroshiro *xr, int x, int y, int z)
{
int64_t l = (int64_t)(x * 3129871) ^ (int64_t)z * 116129781L ^ (int64_t)y;
l = l * l * 42317861L + l * 11L;
l >>= 16;

return (Xoroshiro) {(uint64_t)l ^ xr->lo, xr->hi};
}

// expand as necessary
STRUCT(RandomSource)
{
Expand Down Expand Up @@ -423,6 +432,10 @@ static inline double clampedLerp(double part, double from, double to)
return lerp(part, from, to);
}

static inline double clampedMap(double input, double inputMin, double inputMax, double ouputMin, double outputMax) {
return clampedLerp((input - inputMin) / (inputMax - inputMin), ouputMin, outputMax);
}

/* Find the modular inverse: (1/x) | mod m.
* Assumes x and m are positive (less than 2^63), co-prime.
*/
Expand Down