mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
Simple climate based biome scattering
This commit is contained in:
parent
0f3738c320
commit
6f725b8355
|
|
@ -5,6 +5,7 @@
|
|||
#include "net.minecraft.world.level.newbiome.layer.h"
|
||||
#include "System.h"
|
||||
#include "BiomeSource.h"
|
||||
#include "ClimateLayer.h"
|
||||
#include "..\Minecraft.Client\Minecraft.h"
|
||||
#include "..\Minecraft.Client\ProgressRenderer.h"
|
||||
|
||||
|
|
@ -16,12 +17,12 @@ void BiomeSource::_init()
|
|||
|
||||
cache = new BiomeCache(this);
|
||||
|
||||
playerSpawnBiomes.push_back(Biome::forest);
|
||||
playerSpawnBiomes.push_back(Biome::taiga);
|
||||
// 4J-PB - Moving forward plains as a spawnable biome (mainly for the Superflat world)
|
||||
playerSpawnBiomes.push_back(Biome::plains);
|
||||
playerSpawnBiomes.push_back(Biome::taigaHills);
|
||||
playerSpawnBiomes.push_back(Biome::forest);
|
||||
playerSpawnBiomes.push_back(Biome::forestHills);
|
||||
playerSpawnBiomes.push_back(Biome::taiga);
|
||||
playerSpawnBiomes.push_back(Biome::taigaHills);
|
||||
playerSpawnBiomes.push_back(Biome::jungle);
|
||||
playerSpawnBiomes.push_back(Biome::jungleHills);
|
||||
}
|
||||
|
|
@ -30,7 +31,8 @@ void BiomeSource::_init(int64_t seed, LevelType *generator)
|
|||
{
|
||||
_init();
|
||||
|
||||
LayerArray layers = Layer::getDefaultLayers(seed, generator);
|
||||
// LayerArray layers = Layer::getDefaultLayers(seed, generator);
|
||||
LayerArray layers = getClimateLayers(seed, generator);
|
||||
layer = layers[0];
|
||||
zoomedLayer = layers[1];
|
||||
|
||||
|
|
@ -147,6 +149,16 @@ void BiomeSource::getTemperatureBlock(floatArray& temperatures, int x, int z, in
|
|||
}
|
||||
}
|
||||
|
||||
LayerArray BiomeSource::getClimateLayers(int64_t seed, LevelType* generator)
|
||||
{
|
||||
LayerArray layers(2);
|
||||
// Ãðóáûé ñëîé (ìàñøòàá 0.04) — äëÿ ïðåäâàðèòåëüíûõ ïðîâåðîê, åñëè íóæåí
|
||||
layers[0] = std::make_shared<ClimateLayer>(seed, 4, 0.04);
|
||||
// Äåòàëüíûé ñëîé (ìàñøòàá 0.01) — äëÿ ôèíàëüíîé êàðòû áèîìîâ
|
||||
layers[1] = std::make_shared<ClimateLayer>(seed, 4, 0.01);
|
||||
return layers;
|
||||
}
|
||||
|
||||
BiomeArray BiomeSource::getRawBiomeBlock(int x, int z, int w, int h) const
|
||||
{
|
||||
BiomeArray biomes;
|
||||
|
|
@ -408,6 +420,7 @@ void BiomeSource::update()
|
|||
}
|
||||
|
||||
//#define DEBUG_SEEDS 50
|
||||
const int MAX_SEED_ATTEMPTS = 100;
|
||||
|
||||
// 4J added - find a seed for this biomesource that matches certain criteria
|
||||
#ifdef __PSVITA__
|
||||
|
|
@ -422,7 +435,7 @@ int64_t BiomeSource::findSeed(LevelType *generator)
|
|||
ProgressRenderer *mcprogress = Minecraft::GetInstance()->progressRenderer;
|
||||
mcprogress->progressStage(IDS_PROGRESS_NEW_WORLD_SEED);
|
||||
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
#if 0//ndef _CONTENT_PACKAGE
|
||||
if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_EnableBiomeOverride))
|
||||
{
|
||||
// Do nothing
|
||||
|
|
@ -470,23 +483,25 @@ int64_t BiomeSource::findSeed(LevelType *generator)
|
|||
|
||||
mcprogress->progressStagePercentage( tryCount % 100 );
|
||||
#ifdef __PSVITA__
|
||||
} while (!matchFound && *pServerRunning);
|
||||
} while (!matchFound && *pServerRunning && tryCount < MAX_SEED_ATTEMPTS);
|
||||
#else
|
||||
} while (!matchFound);
|
||||
} while (!matchFound && tryCount < MAX_SEED_ATTEMPTS);
|
||||
#endif
|
||||
|
||||
// Clean up
|
||||
delete pr;
|
||||
delete indices.data;
|
||||
|
||||
#ifdef DEBUG_SEEDS
|
||||
app.DebugPrintf("%d: %d tries taken, seed used is %lld\n", k, tryCount, bestSeed);
|
||||
#if 1//def DEBUG_SEEDS
|
||||
//app.DebugPrintf("%d: %d tries taken, seed used is %lld\n", k, tryCount, bestSeed);
|
||||
|
||||
BiomeSource *biomeSource = new BiomeSource(bestSeed);
|
||||
BiomeArray biomes = biomeSource->getBiomeBlock(-27 * 16, -27 * 16, 54 * 16, 54 * 16);
|
||||
int size = 64 * 16;
|
||||
|
||||
unsigned int *pixels = new unsigned int[54 * 16 * 54 * 16];
|
||||
for(int i = 0; i < 54 * 16 * 54 * 16; i++ )
|
||||
BiomeSource *biomeSource = new BiomeSource(bestSeed, generator);
|
||||
BiomeArray biomes = biomeSource->getBiomeBlock(-27 * 16, -27 * 16, size, size);
|
||||
|
||||
unsigned int *pixels = new unsigned int[size * size];
|
||||
for(int i = 0; i < size * size; i++ )
|
||||
{
|
||||
int id = biomes[i]->id;
|
||||
|
||||
|
|
@ -519,13 +534,13 @@ int64_t BiomeSource::findSeed(LevelType *generator)
|
|||
if( id & 8 ) pixels[i] |= 0x00808080;
|
||||
}
|
||||
D3DXIMAGE_INFO srcInfo;
|
||||
srcInfo.Format = D3DFMT_LIN_A8R8G8B8;
|
||||
srcInfo.ImageFileFormat = D3DXIFF_BMP;
|
||||
srcInfo.Width = 54 * 16;
|
||||
srcInfo.Height = 54 * 16;
|
||||
//srcInfo.Format = D3DFMT_LIN_A8R8G8B8;
|
||||
//srcInfo.ImageFileFormat = D3DXIFF_BMP;
|
||||
srcInfo.Width = size;
|
||||
srcInfo.Height = size;
|
||||
|
||||
char buf[256];
|
||||
sprintf(buf,"GAME:\\BiomeTest%d.bmp",k);
|
||||
sprintf(buf,"GAME:\\BiomeTest%d.bmp", bestSeed);
|
||||
RenderManager.SaveTextureData(buf, &srcInfo, (int *)pixels);
|
||||
|
||||
delete [] pixels;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ public:
|
|||
virtual Biome *getBiome(ChunkPos *cp);
|
||||
virtual Biome *getBiome(int x, int z);
|
||||
|
||||
static LayerArray getClimateLayers(int64_t seed, LevelType* generator);
|
||||
|
||||
// 4J - changed the interface for these methods, mainly for thread safety
|
||||
virtual float getDownfall(int x, int z) const;
|
||||
virtual floatArray getDownfallBlock(int x, int z, int w, int h) const;
|
||||
|
|
|
|||
81
Minecraft.World/ClimateLayer.cpp
Normal file
81
Minecraft.World/ClimateLayer.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#include "stdafx.h"
|
||||
#include "ClimateLayer.h"
|
||||
#include "Random.h"
|
||||
#include "Mth.h"
|
||||
#include "IntCache.h"
|
||||
|
||||
ClimateLayer::ClimateLayer(int64_t seed, int octaves, double scale)
|
||||
: Layer(seed), scale(scale)
|
||||
{
|
||||
Random random(seed);
|
||||
temperatureNoise = new PerlinNoise(&random, octaves);
|
||||
humidityNoise = new PerlinNoise(&random, octaves);
|
||||
initBiomeCenters();
|
||||
}
|
||||
|
||||
ClimateLayer::~ClimateLayer()
|
||||
{
|
||||
delete temperatureNoise;
|
||||
delete humidityNoise;
|
||||
}
|
||||
|
||||
void ClimateLayer::initBiomeCenters()
|
||||
{
|
||||
// Çàäà¸ì öåíòðû îñíîâíûõ áèîìîâ â ïðîñòðàíñòâå (òåìïåðàòóðà, âëàæíîñòü)
|
||||
// Çíà÷åíèÿ ïîäîáðàíû íà îñíîâå setTemperatureAndDownfall() èç Biome.cpp
|
||||
centers.push_back({ 0.00f, 0.25f, Biome::iceFlats }); // õîëîäíûå ðàâíèíû
|
||||
centers.push_back({ 0.10f, 0.80f, Biome::taiga }); // òàéãà
|
||||
centers.push_back({ 0.30f, 0.30f, Biome::extremeHills }); // ýêñòðåìàëüíûå õîëìû
|
||||
centers.push_back({ 0.70f, 0.40f, Biome::plains }); // ðàâíèíû
|
||||
centers.push_back({ 0.70f, 0.70f, Biome::forest }); // ëåñ
|
||||
centers.push_back({ 0.80f, 0.95f, Biome::swampland }); // áîëîòî
|
||||
centers.push_back({ 0.95f, 0.05f, Biome::desert }); // ïóñòûíÿ
|
||||
centers.push_back({ 0.95f, 0.85f, Biome::jungle }); // äæóíãëè
|
||||
|
||||
// Ïðèìå÷àíèå: îêåàíè÷åñêèå áèîìû íå âêëþ÷åíû — îíè áóäóò îïðåäåëÿòüñÿ ïî âûñîòå îòäåëüíî.
|
||||
// Õîëìèñòûå âàðèàíòû (desertHills, forestHills è ò.ä.) ìîæíî äîáàâèòü ïîçæå,
|
||||
// èñïîëüçóÿ äîïîëíèòåëüíûé øóì âûñîòû èëè âòîðîé ïðîõîä.
|
||||
}
|
||||
|
||||
Biome* ClimateLayer::getBiomeForClimate(float temp, float hum) const
|
||||
{
|
||||
float bestDist = 1e9f;
|
||||
Biome* bestBiome = Biome::plains; // çàïàñíîé âàðèàíò
|
||||
|
||||
for (const auto& c : centers) {
|
||||
float dx = temp - c.temp;
|
||||
float dy = hum - c.hum;
|
||||
float dist = dx * dx + dy * dy; // êâàäðàò åâêëèäîâà ðàññòîÿíèÿ
|
||||
if (dist < bestDist) {
|
||||
bestDist = dist;
|
||||
bestBiome = c.biome;
|
||||
}
|
||||
}
|
||||
return bestBiome;
|
||||
}
|
||||
|
||||
intArray ClimateLayer::getArea(int xo, int yo, int w, int h)
|
||||
{
|
||||
IntCache::releaseAll();
|
||||
intArray result = IntCache::allocate(w * h);
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
int worldX = xo + x;
|
||||
int worldY = yo + y;
|
||||
|
||||
// Ïîëó÷àåì çíà÷åíèÿ øóìà â äèàïàçîíå ïðèìåðíî [-1, 1]
|
||||
double tempNoise = temperatureNoise->getValue(worldX * scale, worldY * scale);
|
||||
double humNoise = humidityNoise->getValue(worldX * scale, worldY * scale);
|
||||
|
||||
// Íîðìàëèçóåì â [0, 1] (ëîãèñòè÷åñêàÿ ôóíêöèÿ èëè ïðîñòî clamp)
|
||||
float normTemp = Mth::clamp((float)((tempNoise + 1.0) * 0.5), 0.0f, 1.0f);
|
||||
float normHum = Mth::clamp((float)((humNoise + 1.0) * 0.5), 0.0f, 1.0f);
|
||||
|
||||
Biome* biome = getBiomeForClimate(normTemp, normHum);
|
||||
result[x + y * w] = biome->id;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
29
Minecraft.World/ClimateLayer.h
Normal file
29
Minecraft.World/ClimateLayer.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
#include "Layer.h"
|
||||
#include "PerlinNoise.h"
|
||||
#include "Biome.h"
|
||||
#include <vector>
|
||||
|
||||
class ClimateLayer : public Layer
|
||||
{
|
||||
private:
|
||||
PerlinNoise* temperatureNoise;
|
||||
PerlinNoise* humidityNoise;
|
||||
double scale; // ìàñøòàá øóìà (÷åì ìåíüøå, òåì êðóïíåå áèîìû)
|
||||
|
||||
struct BiomeCenter {
|
||||
float temp;
|
||||
float hum;
|
||||
Biome* biome;
|
||||
};
|
||||
std::vector<BiomeCenter> centers;
|
||||
|
||||
void initBiomeCenters(); // çàïîëíèòü öåíòðû áèîìîâ
|
||||
Biome* getBiomeForClimate(float temp, float hum) const;
|
||||
|
||||
public:
|
||||
ClimateLayer(int64_t seed, int octaves = 4, double scale = 0.01);
|
||||
virtual ~ClimateLayer();
|
||||
|
||||
virtual intArray getArea(int xo, int yo, int w, int h) override;
|
||||
};
|
||||
Loading…
Reference in a new issue