the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 293 lines 8.3 kB view raw
1#include "stdafx.h" 2#include "StructureFeature.h" 3#include "StructureStart.h" 4#include "StructurePiece.h" 5#include "ChunkPos.h" 6#include "BoundingBox.h" 7#include "net.minecraft.world.level.h" 8#include "LevelData.h" 9 10StructureFeature::StructureFeature() 11{ 12#ifdef ENABLE_STRUCTURE_SAVING 13 savedData = nullptr; 14#endif 15} 16 17StructureFeature::~StructureFeature() 18{ 19 for( AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); it++ ) 20 { 21 delete it->second; 22 } 23} 24 25void StructureFeature::addFeature(Level *level, int x, int z, int xOffs, int zOffs, byteArray blocks) 26{ 27 // this method is called for each chunk within 8 chunk's distance from 28 // the chunk being generated, but not all chunks are the sources of 29 // structures 30 31 restoreSavedData(level); 32 33 if (cachedStructures.find(ChunkPos::hashCode(x, z)) != cachedStructures.end()) 34 { 35 return; 36 } 37 38 // clear random key 39 random->nextInt(); 40 // 4J-PB - want to know if it's a superflat land, so we don't generate so many villages - we've changed the distance required between villages on the xbox 41 if (isFeatureChunk(x, z,level->getLevelData()->getGenerator() == LevelType::lvl_flat)) 42 { 43 StructureStart *start = createStructureStart(x, z); 44 cachedStructures[ChunkPos::hashCode(x, z)] = start; 45 saveFeature(x, z, start); 46 } 47} 48 49bool StructureFeature::postProcess(Level *level, Random *random, int chunkX, int chunkZ) 50{ 51 restoreSavedData(level); 52 53 // 4J Stu - The x and z used to be offset by (+8) here, but that means we can miss out half structures on the edge of the world 54 // Normal feature generation offsets generation by half a chunk to ensure that it can generate the entire feature in chunks already created 55 // Structure features don't need this, as the PlaceBlock function only places blocks inside the BoundingBox specified, and parts 56 // of a struture piece can be added in more than one post-process call 57 int cx = (chunkX << 4); // + 8; 58 int cz = (chunkZ << 4); // + 8; 59 60 bool intersection = false; 61 for( AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); it++ ) 62 { 63 StructureStart *structureStart = it->second; 64 65 if (structureStart->isValid()) 66 { 67 if (structureStart->getBoundingBox()->intersects(cx, cz, cx + 15, cz + 15)) 68 { 69 BoundingBox *bb = new BoundingBox(cx, cz, cx + 15, cz + 15); 70 structureStart->postProcess(level, random, bb); 71 delete bb; 72 intersection = true; 73 74 // because some feature pieces are modified in the postProcess step, we need to save them again 75 saveFeature(structureStart->getChunkX(), structureStart->getChunkZ(), structureStart); 76 } 77 } 78 } 79 80 return intersection; 81} 82 83bool StructureFeature::isIntersection(int cellX, int cellZ) 84{ 85 restoreSavedData(level); 86 87 for( AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); it++ ) 88 { 89 StructureStart *structureStart = it->second; 90 if (structureStart->isValid()) 91 { 92 if (structureStart->getBoundingBox()->intersects(cellX, cellZ, cellX, cellZ)) 93 { 94 AUTO_VAR(it2, structureStart->getPieces()->begin()); 95 while( it2 != structureStart->getPieces()->end() ) 96 { 97 StructurePiece *next = *it2++; 98 if (next->getBoundingBox()->intersects(cellX, cellZ, cellX, cellZ)) 99 { 100 return true; 101 } 102 } 103 } 104 } 105 } 106 return false; 107} 108 109bool StructureFeature::isInsideFeature(int cellX, int cellY, int cellZ) 110{ 111 restoreSavedData(level); 112 return getStructureAt(cellX, cellY, cellZ) != NULL; 113} 114 115StructureStart *StructureFeature::getStructureAt(int cellX, int cellY, int cellZ) 116{ 117 //for (StructureStart structureStart : cachedStructures.values()) 118 for(AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); ++it) 119 { 120 StructureStart *pStructureStart = it->second; 121 122 if (pStructureStart->isValid()) 123 { 124 if (pStructureStart->getBoundingBox()->intersects(cellX, cellZ, cellX, cellZ)) 125 { 126 /* 127 Iterator<StructurePiece> it = structureStart.getPieces().iterator(); 128 while (it.hasNext()) { 129 StructurePiece next = it.next(); 130 if (next.getBoundingBox().isInside(cellX, cellY, cellZ)) { 131 return true; 132 } 133 */ 134 list<StructurePiece *> *pieces=pStructureStart->getPieces(); 135 136 for ( AUTO_VAR(it2, pieces->begin()); it2 != pieces->end(); it2++ ) 137 { 138 StructurePiece* piece = *it2; 139 if ( piece->getBoundingBox()->isInside(cellX, cellY, cellZ) ) 140 { 141 return pStructureStart; 142 } 143 } 144 } 145 } 146 } 147 return NULL; 148} 149 150bool StructureFeature::isInsideBoundingFeature(int cellX, int cellY, int cellZ) 151{ 152 restoreSavedData(level); 153 154 for(AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); ++it) 155 { 156 StructureStart *structureStart = it->second; 157 if (structureStart->isValid()) 158 { 159 return (structureStart->getBoundingBox()->intersects(cellX, cellZ, cellX, cellZ)); 160 } 161 } 162 return false; 163} 164 165TilePos *StructureFeature::getNearestGeneratedFeature(Level *level, int cellX, int cellY, int cellZ) 166{ 167 // this is a hack that will "force" the feature to generate positions 168 // even if the player hasn't generated new chunks yet 169 this->level = level; 170 171 restoreSavedData(level); 172 173 random->setSeed(level->getSeed()); 174 __int64 xScale = random->nextLong(); 175 __int64 zScale = random->nextLong(); 176 __int64 xx = (cellX >> 4) * xScale; 177 __int64 zz = (cellZ >> 4) * zScale; 178 random->setSeed(xx ^ zz ^ level->getSeed()); 179 180 addFeature(level, cellX >> 4, cellZ >> 4, 0, 0, byteArray()); 181 182 double minDistance = DBL_MAX; 183 TilePos *selected = NULL; 184 185 for(AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); ++it) 186 { 187 StructureStart *pStructureStart = it->second; 188 189 if (pStructureStart->isValid()) 190 { 191 192 //StructurePiece *pStructurePiece = pStructureStart->getPieces().get(0); 193 StructurePiece* pStructurePiece = * pStructureStart->getPieces()->begin(); 194 TilePos *locatorPosition = pStructurePiece->getLocatorPosition(); 195 196 int dx = locatorPosition->x - cellX; 197 int dy = locatorPosition->y - cellY; 198 int dz = locatorPosition->z - cellZ; 199 double dist = dx * dx + dy * dy + dz * dz; 200 201 if (dist < minDistance) 202 { 203 minDistance = dist; 204 selected = locatorPosition; 205 } 206 } 207 } 208 if (selected != NULL) 209 { 210 return selected; 211 } 212 else 213 { 214 vector<TilePos> *guesstimatedFeaturePositions = getGuesstimatedFeaturePositions(); 215 if (guesstimatedFeaturePositions != NULL) 216 { 217 TilePos *pSelectedPos = new TilePos(0,0,0); 218 219 for(AUTO_VAR(it, guesstimatedFeaturePositions->begin()); it != guesstimatedFeaturePositions->end(); ++it) 220 { 221 int dx = (*it).x - cellX; 222 int dy = (*it).y - cellY; 223 int dz = (*it).z - cellZ; 224 double dist = dx * dx + dy * dy + dz * dz; 225 226 if (dist < minDistance) 227 { 228 minDistance = dist; 229 pSelectedPos->x = (*it).x; 230 pSelectedPos->y = (*it).y; 231 pSelectedPos->z = (*it).z; 232 } 233 } 234 delete guesstimatedFeaturePositions; 235 return pSelectedPos; 236 } 237 } 238 return NULL; 239} 240 241vector<TilePos> *StructureFeature::getGuesstimatedFeaturePositions() 242{ 243 return NULL; 244} 245 246void StructureFeature::restoreSavedData(Level *level) 247{ 248#ifdef ENABLE_STRUCTURE_SAVING 249 if (savedData == NULL) 250 { 251 savedData = dynamic_pointer_cast<StructureFeatureSavedData>( level->getSavedData(typeid(StructureFeatureSavedData), getFeatureName()) ); 252 253 if (savedData == NULL) 254 { 255 savedData = shared_ptr<StructureFeatureSavedData>( new StructureFeatureSavedData(getFeatureName()) ); 256 level->setSavedData(getFeatureName(), savedData); 257 } 258 else 259 { 260 CompoundTag *fullTag = savedData->getFullTag(); 261 262 vector<Tag *> *allTags = fullTag->getAllTags(); 263 for (AUTO_VAR(it,allTags->begin()); it != allTags->end(); ++it) 264 { 265 Tag *featureTag = *it; 266 if (featureTag->getId() == Tag::TAG_Compound) 267 { 268 CompoundTag *ct = (CompoundTag *) featureTag; 269 270 if (ct->contains(L"ChunkX") && ct->contains(L"ChunkZ")) 271 { 272 int cx = ct->getInt(L"ChunkX"); 273 int cz = ct->getInt(L"ChunkZ"); 274 275 StructureStart *start = StructureFeatureIO::loadStaticStart(ct, level); 276 // System.out.println("Loaded " + start.getClass().getSimpleName() + " from file"); 277 cachedStructures[ChunkPos::hashCode(cx, cz)] = start; 278 } 279 } 280 } 281 delete allTags; 282 } 283 } 284#endif 285} 286 287void StructureFeature::saveFeature(int chunkX, int chunkZ, StructureStart *feature) 288{ 289#ifdef ENABLE_STRUCTURE_SAVING 290 savedData->putFeatureTag(feature->createTag(chunkX, chunkZ), chunkX, chunkZ); 291 savedData->setDirty(); 292#endif 293}