the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
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}