Something went wrong. Try again.
the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
Something went wrong. Try again.
17 kB · 641 lines
C++
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641#include "stdafx.h"#include "net.minecraft.world.level.h"#include "net.minecraft.world.level.storage.h"#include "net.minecraft.world.level.biome.h"#include "net.minecraft.world.level.newbiome.layer.h"#include "System.h"#include "BiomeSource.h"#include "..\Minecraft.Client\Minecraft.h"#include "..\Minecraft.Client\ProgressRenderer.h"
// 4J - removal of separate temperature & downfall layers brought forward from 1.2.3void BiomeSource::_init(){ layer = nullptr; zoomedLayer = nullptr;
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::forestHills); playerSpawnBiomes.push_back(Biome::jungle); playerSpawnBiomes.push_back(Biome::jungleHills);}
void BiomeSource::_init(__int64 seed, LevelType *generator){ _init();
LayerArray layers = Layer::getDefaultLayers(seed, generator); layer = layers[0]; zoomedLayer = layers[1];
delete [] layers.data;}
BiomeSource::BiomeSource(){ _init();}
// 4J addedBiomeSource::BiomeSource(__int64 seed, LevelType *generator){ _init(seed, generator);}
// 4J - removal of separate temperature & downfall layers brought forward from 1.2.3BiomeSource::BiomeSource(Level *level){ _init(level->getSeed(), level->getLevelData()->getGenerator());}
BiomeSource::~BiomeSource(){ delete cache;}
Biome *BiomeSource::getBiome(ChunkPos *cp){ return getBiome(cp->x << 4, cp->z << 4);}
Biome *BiomeSource::getBiome(int x, int z){ return cache->getBiome(x, z);}
float BiomeSource::getDownfall(int x, int z) const{ return cache->getDownfall(x, z);}
// 4J - note that caller is responsible for deleting returned array. temperatures array is for output only.floatArray BiomeSource::getDownfallBlock(int x, int z, int w, int h) const{ floatArray downfalls; getDownfallBlock(downfalls, x, z, w, h); return downfalls;}
// 4J - note that caller is responsible for deleting returned array. temperatures array is for output only.// 4J - removal of separate temperature & downfall layers brought forward from 1.2.3void BiomeSource::getDownfallBlock(floatArray &downfalls, int x, int z, int w, int h) const{ IntCache::releaseAll(); //if (downfalls == NULL || downfalls->length < w * h) if (downfalls.data == NULL || downfalls.length < w * h) { if(downfalls.data != NULL) delete [] downfalls.data; downfalls = floatArray(w * h); }
intArray result = zoomedLayer->getArea(x, z, w, h); for (int i = 0; i < w * h; i++) { float d = (float) Biome::biomes[result[i]]->getDownfallInt() / 65536.0f; if (d > 1) d = 1; downfalls[i] = d; }}
BiomeCache::Block *BiomeSource::getBlockAt(int x, int y){ return cache->getBlockAt(x, y);}
float BiomeSource::getTemperature(int x, int y, int z) const{ return scaleTemp(cache->getTemperature(x, z), y);}
// 4J - brought forward from 1.2.3float BiomeSource::scaleTemp(float temp, int y ) const{ return temp;}
floatArray BiomeSource::getTemperatureBlock(int x, int z, int w, int h) const{ floatArray temperatures; getTemperatureBlock(temperatures, x, z, w, h); return temperatures;}
// 4J - note that caller is responsible for deleting returned array. temperatures array is for output only.// 4J - removal of separate temperature & downfall layers brought forward from 1.2.3void BiomeSource::getTemperatureBlock(floatArray& temperatures, int x, int z, int w, int h) const{ IntCache::releaseAll(); //if (temperatures == null || temperatures.length < w * h) { if (temperatures.data == NULL || temperatures.length < w * h) { if( temperatures.data != NULL ) delete [] temperatures.data; temperatures = floatArray(w * h); }
intArray result = zoomedLayer->getArea(x, z, w, h); for (int i = 0; i < w * h; i++) { float t = (float) Biome::biomes[result[i]]->getTemperatureInt() / 65536.0f; if (t > 1) t = 1; temperatures[i] = t; }}
BiomeArray BiomeSource::getRawBiomeBlock(int x, int z, int w, int h) const{ BiomeArray biomes; getRawBiomeBlock(biomes, x, z, w, h); return biomes;}
// 4J addedvoid BiomeSource::getRawBiomeIndices(intArray &biomes, int x, int z, int w, int h) const{ IntCache::releaseAll();
intArray result = layer->getArea(x, z, w, h); for (int i = 0; i < w * h; i++) { biomes[i] = result[i]; }}
void BiomeSource::getRawBiomeBlock(BiomeArray &biomes, int x, int z, int w, int h) const{ IntCache::releaseAll(); //if (biomes == null || biomes.length < w * h) if (biomes.data == NULL || biomes.length < w * h) { if(biomes.data != NULL) delete [] biomes.data; biomes = BiomeArray(w * h); }
intArray result = layer->getArea(x, z, w, h); for (int i = 0; i < w * h; i++) { biomes[i] = Biome::biomes[result[i]];#ifndef _CONTENT_PACKAGE if(biomes[i] == NULL) { app.DebugPrintf("Tried to assign null biome %d\n", result[i]); __debugbreak(); }#endif }}
BiomeArray BiomeSource::getBiomeBlock(int x, int z, int w, int h) const{ if (w == 16 && h == 16 && (x & 0xf) == 0 && (z & 0xf) == 0) { return cache->getBiomeBlockAt(x, z); } BiomeArray biomes; getBiomeBlock(biomes, x, z, w, h, true); return biomes;}
// 4J - caller is responsible for deleting biomes arrayvoid BiomeSource::getBiomeBlock(BiomeArray& biomes, int x, int z, int w, int h, bool useCache) const{ IntCache::releaseAll(); //if (biomes == null || biomes.length < w * h) if (biomes.data == NULL || biomes.length < w * h) { if(biomes.data != NULL) delete [] biomes.data; biomes = BiomeArray(w * h); }
if (useCache && w == 16 && h == 16 && (x & 0xf) == 0 && (z & 0xf) == 0) { BiomeArray tmp = cache->getBiomeBlockAt(x, z); System::arraycopy(tmp, 0, &biomes, 0, w * h); delete tmp.data; // MGH - added, the caching creates this array from the indices now. //return biomes; }
intArray result = zoomedLayer->getArea(x, z, w, h); for (int i = 0; i < w * h; i++) { biomes[i] = Biome::biomes[result[i]]; }}
byteArray BiomeSource::getBiomeIndexBlock(int x, int z, int w, int h) const{ if (w == 16 && h == 16 && (x & 0xf) == 0 && (z & 0xf) == 0) { return cache->getBiomeIndexBlockAt(x, z); } byteArray biomeIndices; getBiomeIndexBlock(biomeIndices, x, z, w, h, true); return biomeIndices;}
// 4J - caller is responsible for deleting biomes arrayvoid BiomeSource::getBiomeIndexBlock(byteArray& biomeIndices, int x, int z, int w, int h, bool useCache) const{ IntCache::releaseAll(); //if (biomes == null || biomes.length < w * h) if (biomeIndices.data == NULL || biomeIndices.length < w * h) { if(biomeIndices.data != NULL) delete [] biomeIndices.data; biomeIndices = byteArray(w * h); }
if (useCache && w == 16 && h == 16 && (x & 0xf) == 0 && (z & 0xf) == 0) { byteArray tmp = cache->getBiomeIndexBlockAt(x, z); System::arraycopy(tmp, 0, &biomeIndices, 0, w * h); //return biomes; }
intArray result = zoomedLayer->getArea(x, z, w, h); for (int i = 0; i < w * h; i++) { biomeIndices[i] = (byte)result[i]; }}
/*** Checks if an area around a block contains only the specified biomes.* Useful for placing elements like towns.* * This is a bit of a rough check, to make it as fast as possible. To ensure* NO other biomes, add a margin of at least four blocks to the radius*/bool BiomeSource::containsOnly(int x, int z, int r, vector<Biome *> allowed){ IntCache::releaseAll(); int x0 = ((x - r) >> 2); int z0 = ((z - r) >> 2); int x1 = ((x + r) >> 2); int z1 = ((z + r) >> 2);
int w = x1 - x0 + 1; int h = z1 - z0 + 1;
intArray biomes = layer->getArea(x0, z0, w, h); for (int i = 0; i < w * h; i++) { Biome *b = Biome::biomes[biomes[i]]; if (find(allowed.begin(), allowed.end(), b) == allowed.end()) return false; }
return true;}
/*** Checks if an area around a block contains only the specified biome.* Useful for placing elements like towns.* * This is a bit of a rough check, to make it as fast as possible. To ensure* NO other biomes, add a margin of at least four blocks to the radius*/bool BiomeSource::containsOnly(int x, int z, int r, Biome *allowed){ IntCache::releaseAll(); int x0 = ((x - r) >> 2); int z0 = ((z - r) >> 2); int x1 = ((x + r) >> 2); int z1 = ((z + r) >> 2);
int w = x1 - x0; int h = z1 - z0; int biomesCount = w*h; intArray biomes = layer->getArea(x0, z0, w, h); for (unsigned int i = 0; i < biomesCount; i++) { Biome *b = Biome::biomes[biomes[i]]; if (allowed != b) return false; }
return true;}
/*** Finds the specified biome within the radius. This will return a random* position if several are found. This test is fairly rough.* * Returns null if the biome wasn't found*/TilePos *BiomeSource::findBiome(int x, int z, int r, Biome *toFind, Random *random){ IntCache::releaseAll(); int x0 = ((x - r) >> 2); int z0 = ((z - r) >> 2); int x1 = ((x + r) >> 2); int z1 = ((z + r) >> 2);
int w = x1 - x0 + 1; int h = z1 - z0 + 1; intArray biomes = layer->getArea(x0, z0, w, h); TilePos *res = NULL; int found = 0; int biomesCount = w*h; for (unsigned int i = 0; i < biomesCount; i++) { int xx = x0 + i % w; int zz = z0 + i / w; Biome *b = Biome::biomes[biomes[i]]; if (b == toFind) { if (res == NULL || random->nextInt(found + 1) == 0) { res = new TilePos(xx, 0, zz); found++; } } }
return res;}
/*** Finds one of the specified biomes within the radius. This will return a* random position if several are found. This test is fairly rough.* * Returns null if the biome wasn't found*/TilePos *BiomeSource::findBiome(int x, int z, int r, vector<Biome *> allowed, Random *random){ IntCache::releaseAll(); int x0 = ((x - r) >> 2); int z0 = ((z - r) >> 2); int x1 = ((x + r) >> 2); int z1 = ((z + r) >> 2);
int w = x1 - x0 + 1; int h = z1 - z0 + 1; MemSect(50); intArray biomes = layer->getArea(x0, z0, w, h); TilePos *res = NULL; int found = 0; for (unsigned int i = 0; i < w * h; i++) { int xx = (x0 + i % w) << 2; int zz = (z0 + i / w) << 2; Biome *b = Biome::biomes[biomes[i]]; if (find(allowed.begin(), allowed.end(), b) != allowed.end()) { if (res == NULL || random->nextInt(found + 1) == 0) { delete res; res = new TilePos(xx, 0, zz); found++; } } } MemSect(0);
return res;}
void BiomeSource::update(){ cache->update();}
//#define DEBUG_SEEDS 50
// 4J added - find a seed for this biomesource that matches certain criteria#ifdef __PSVITA____int64 BiomeSource::findSeed(LevelType *generator, bool* pServerRunning) // MGH - added pRunning, so we can early out of this on Vita as it can take up to 60 secs#else__int64 BiomeSource::findSeed(LevelType *generator) #endif{
__int64 bestSeed = 0;
ProgressRenderer *mcprogress = Minecraft::GetInstance()->progressRenderer; mcprogress->progressStage(IDS_PROGRESS_NEW_WORLD_SEED);
#ifndef _CONTENT_PACKAGE if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_EnableBiomeOverride)) { // Do nothing } else#endif {#ifdef DEBUG_SEEDS for( int k = 0; k < DEBUG_SEEDS; k++ )#endif { // Try and genuinely random this search up Random *pr = new Random(System::nanoTime());
// Raw biome data has one result per 4x4 group of tiles. // Removing a border of 8 from each side since we'll be doing special things at the edge to turn our world into an island, and so don't want to count things // in the edge region in case they later get removed static const int biomeWidth = ( 54 * 4 ) - 16; // Should be even so we can offset evenly static const int biomeOffset = -( biomeWidth / 2 );
// Storage for our biome indices intArray indices = intArray( biomeWidth * biomeWidth );
// Storage for the fractional amounts of each biome that will be calculated float toCompare[Biome::BIOME_COUNT];
bool matchFound = false; int tryCount = 0;
// Just keeping trying to generate seeds until we find one that matches our criteria do { __int64 seed = pr->nextLong(); BiomeSource *biomeSource = new BiomeSource(seed,generator);
biomeSource->getRawBiomeIndices(indices, biomeOffset, biomeOffset, biomeWidth, biomeWidth); getFracs(indices, toCompare);
matchFound = getIsMatch( toCompare );
if( matchFound ) bestSeed = seed;
delete biomeSource; tryCount++;
mcprogress->progressStagePercentage( tryCount % 100 );#ifdef __PSVITA__ } while (!matchFound && *pServerRunning);#else } while (!matchFound);#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);
BiomeSource *biomeSource = new BiomeSource(bestSeed); BiomeArray biomes = biomeSource->getBiomeBlock(-27 * 16, -27 * 16, 54 * 16, 54 * 16);
unsigned int *pixels = new unsigned int[54 * 16 * 54 * 16]; for(int i = 0; i < 54 * 16 * 54 * 16; i++ ) { int id = biomes[i]->id;
// Create following colours: // 0 ocean 0000 black // 1 plains 0001 pastel cyan // 2 desert 0010 green // 3 extreme hills 0011 yellow // 4 forest 0100 blue // 5 taiga 0101 magenta // 6 swamps 0110 cyan // 7 river 0111 white // 8 hell 1000 grey // 9 end biome 1001 white // 10 frozen ocean 1010 pastel green // 11 frozen river 1011 pastel yellow // 12 ice flats 1100 pastel blue // 13 ice mountains 1101 pastel magenta // 14 mushroom island 1110 red // 15 mushroom shore 1111 pastel red
if( id == 1 ) id = 14; else if ( id == 14 ) id = 1; else if( id == 9 ) id = 15; else if( id == 15 ) id = 9; pixels[i] = 0xff000000; if( id & 1 ) pixels[i] |= 0x00ff0000; if( id & 2 ) pixels[i] |= 0x0000ff00; if( id & 4 ) pixels[i] |= 0x000000ff; 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;
char buf[256]; sprintf(buf,"GAME:\\BiomeTest%d.bmp",k); RenderManager.SaveTextureData(buf, &srcInfo, (int *)pixels);
delete [] pixels; delete biomes.data; delete biomeSource;#endif } }
return bestSeed;}
// 4J added - get the fractional amounts of each biome type in the given indicesvoid BiomeSource::getFracs(intArray indices, float *fracs){ for( int i = 0; i < Biome::BIOME_COUNT; i++ ) { fracs[i] = 0.0f; }
for( int i = 0; i < indices.length; i++ ) { fracs[indices[i]] += 1.0f; }
for( int i = 0; i < Biome::BIOME_COUNT; i++ ) { fracs[i] /= (float)(indices.length); }}
// 4J added - determine if this particular set of fractional amounts of biome types matches are requirementsbool BiomeSource::getIsMatch(float *frac){ // A true for a particular biome type here marks it as one that *has* to be present static const bool critical[Biome::BIOME_COUNT] = { true, // ocean true, // plains true, // desert false, // extreme hills true, // forest true, // taiga true, // swamps false, // river false, // hell false, // end biome false, // frozen ocean false, // frozen river false, // ice flats false, // ice mountains true, // mushroom island / shore false, // mushroom shore (combined with above) false, // beach false, // desert hills (combined with desert) false, // forest hills (combined with forest) false, // taiga hills (combined with taga) false, // small extreme hills true, // jungle false, // jungle hills (combined with jungle) };
// Don't want more than 15% ocean if( frac[0] > 0.15f ) { return false; }
// Consider mushroom shore & islands as the same by finding max frac[14] = ( ( frac[15] > frac[14] ) ? frac[15] : frac[14] );
// Merge desert and desert hills frac[2] = ( ( frac[17] > frac[2] ) ? frac[17] : frac[2] );
// Merge forest and forest hills frac[4] = ( ( frac[18] > frac[4] ) ? frac[18] : frac[4] );
// Merge taiga and taiga hills frac[5] = ( ( frac[19] > frac[5] ) ? frac[19] : frac[5] );
// Merge jungle and jungle hills frac[21] = ( ( frac[22] > frac[21] ) ? frac[22] : frac[21] );
// Loop through all biome types, and: // (1) count them // (2) give up if one of the critical ones is missing
int typeCount = 0; for( int i = 0; i < Biome::BIOME_COUNT; i++ ) { // We want to skip some where we have merged with another type if(i == 15 || i == 17 || i == 18 || i == 19 || i == 22) continue;
// Consider 0.1% as being "present" - this equates an area of about 3 chunks if( frac[i] > 0.001f ) { typeCount++; } else { // If a critical biome is missing, just give up if( critical[i] ) { return false; } } }
// Consider as suitable if we've got all the critical ones, and in total 9 or more - currently there's 8 critical so this just forces at least 1 more others return ( typeCount >= 9 );}