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 "StrongholdFeature.h"
3#include "StrongholdPieces.h"
4#include "net.minecraft.world.level.h"
5#include "net.minecraft.world.level.biome.h"
6#include "net.minecraft.world.level.dimension.h"
7#include "Mth.h"
8#include "FileHeader.h"
9#include "JavaMath.h"
10
11const wstring StrongholdFeature::OPTION_DISTANCE = L"distance";
12const wstring StrongholdFeature::OPTION_COUNT = L"count";
13const wstring StrongholdFeature::OPTION_SPREAD = L"spread";
14
15vector<Biome *> StrongholdFeature::allowedBiomes;
16
17void StrongholdFeature::staticCtor()
18{
19 allowedBiomes.push_back(Biome::desert);
20 allowedBiomes.push_back(Biome::forest);
21 allowedBiomes.push_back(Biome::extremeHills);
22 allowedBiomes.push_back(Biome::swampland);
23 allowedBiomes.push_back(Biome::taiga);
24 allowedBiomes.push_back(Biome::iceFlats);
25 allowedBiomes.push_back(Biome::iceMountains);
26 allowedBiomes.push_back(Biome::desertHills);
27 allowedBiomes.push_back(Biome::forestHills);
28 allowedBiomes.push_back(Biome::smallerExtremeHills);
29 allowedBiomes.push_back(Biome::taigaHills);
30 allowedBiomes.push_back(Biome::jungle);
31 allowedBiomes.push_back(Biome::jungleHills);
32};
33
34void StrongholdFeature::_init()
35{
36 distance = 32;
37 spread = 3;
38
39 // 4J added initialisers
40 for (int i = 0; i < strongholdPos_length; i++)
41 {
42 strongholdPos[i] = NULL;
43 }
44 isSpotSelected = false;
45}
46
47StrongholdFeature::StrongholdFeature() : StructureFeature()
48{
49 _init();
50}
51
52StrongholdFeature::StrongholdFeature(unordered_map<wstring, wstring> options)
53{
54 _init();
55
56 for (AUTO_VAR(it, options.begin()); it != options.end(); ++it)
57 {
58 if (it->first.compare(OPTION_DISTANCE) == 0)
59 {
60 distance = Mth::getDouble(it->second, distance, 1);
61 }
62 else if (it->first.compare(OPTION_COUNT) == 0)
63 {
64 // 4J-JEV: Removed, we only have the one stronghold.
65 //strongholdPos = new ChunkPos[ Mth::getInt(it->second, strongholdPos_length, 1) ];
66 assert(false);
67 }
68 else if (it->first.compare(OPTION_SPREAD) == 0)
69 {
70 spread = Mth::getInt(it->second, spread, 1);
71 }
72 }
73}
74
75StrongholdFeature::~StrongholdFeature()
76{
77 for (int i = 0; i < strongholdPos_length; i++)
78 {
79 delete strongholdPos[i];
80 }
81}
82
83wstring StrongholdFeature::getFeatureName()
84{
85 return LargeFeature::STRONGHOLD;
86}
87
88bool StrongholdFeature::isFeatureChunk(int x, int z,bool bIsSuperflat)
89{
90 if (!isSpotSelected)
91 {
92 Random random;
93
94 random.setSeed(level->getSeed());
95 double angle = random.nextDouble() * PI * 2.0;
96 int circle = 1;
97
98 // 4J Stu - Changed so that we keep trying more until we have found somewhere in the world to place a stronghold
99 bool hasFoundValidPos = false;
100 int findAttempts = 0;
101 do
102 {
103 for (int i = 0; i < strongholdPos_length; i++)
104 {
105 double dist = 0.0;
106#ifdef _LARGE_WORLDS
107 if(level->dimension->getXZSize() < (2.25f * 32.0f) )
108 {
109 // Xbox360/PS3 distances
110 dist = (1.25 + random.nextDouble()) * (3 + random.nextInt(4));
111 }
112 else
113 {
114 // Original Java
115 dist = (1.25 * circle + random.nextDouble()) * (distance * circle);
116 }
117#else
118 // 4J Stu - Design change: Original spawns at *32 chunks rather than *10 chunks from (0,0) but that is outside our world
119 // double dist = (1.25 + random->nextDouble()) * 32.0;
120 // The max of the first part is 2.25, and we have 27 chunks in each direction
121 // Therefore 27/2.25 = 12, which should be the max of the second part
122 // The constant part and random part can be tuned to move the strongholds further from the spawn
123 // 4J Stu - The original (pre-TU9) calculation for selecting a start point could put the stronghold very close to the edge
124 // of the world, causing some parts to fail to generate. If the save is a newer save then we bring that generation in
125 if(level->getOriginalSaveVersion() >= SAVE_FILE_VERSION_MOVED_STRONGHOLD)
126 {
127 // Post TU9
128 // The stronghold cannot extend more than 7 chunks in any direction from the start position
129 // Therefore as long as the the start x/z are less than 20 it will be fully contained
130 dist = (1.25 + random.nextDouble()) * (3 + random.nextInt(4));
131 }
132 else
133 {
134 // Pre TU9
135 dist = (1.25 + random.nextDouble()) * (5.0 + random.nextInt(7));
136 }
137#endif
138
139 int selectedX = (int) (Math::round(cos(angle) * dist));
140 int selectedZ = (int) (Math::round(sin(angle) * dist));
141
142 TilePos *position = level->getBiomeSource()->findBiome((selectedX << 4) + 8, (selectedZ << 4) + 8, 7 << 4, allowedBiomes, &random);
143 if (position != NULL)
144 {
145 selectedX = position->x >> 4;
146 selectedZ = position->z >> 4;
147
148#ifndef _CONTENT_PACKAGE
149 if(position->x > 2560 || position->x < -2560 || position->z > 2560 || position->z < -2560)
150 {
151 __debugbreak();
152 }
153#endif
154
155 app.DebugPrintf("Placed stronghold in valid biome at (%d, %d), (%d, %d)\n", selectedX, selectedZ, position->x, position->z);
156 // 4J added
157 app.AddTerrainFeaturePosition(eTerrainFeature_Stronghold,selectedX,selectedZ);
158
159 // 4J Added
160 hasFoundValidPos = true;
161 delete position;
162 }
163
164 delete strongholdPos[i];
165 strongholdPos[i] = new ChunkPos(selectedX, selectedZ);
166
167 angle += PI * 2.0 / (double) strongholdPos_length;
168 }
169
170 // 4J Stu - We want to make sure that we have at least one stronghold in this world
171 ++findAttempts;
172
173 // 4J Stu - Randomise the angles for retries as well
174#ifdef _LARGE_WORLDS
175 angle = random.nextDouble() * PI * 2.0 * circle / (double) spread;
176#endif
177 }
178 while(!hasFoundValidPos && findAttempts < MAX_STRONGHOLD_ATTEMPTS);
179
180 if(!hasFoundValidPos)
181 {
182 // Even if it's not a valid position we are still creating the last one we tried, so store it in the save so Eye of Ender works
183 // Fix for #81933 - GAMEPLAY: The Eye of Ender occasionally does not appear when used to try and locate the End Portal.
184 app.AddTerrainFeaturePosition(eTerrainFeature_Stronghold,strongholdPos[0]->x,strongholdPos[0]->z);
185 }
186
187 isSpotSelected = true;
188 }
189
190 for (int i = 0; i < strongholdPos_length; i++)
191 {
192 bool forcePlacement = false;
193 LevelGenerationOptions *levelGenOptions = app.getLevelGenerationOptions();
194 if( levelGenOptions != NULL )
195 {
196 forcePlacement = levelGenOptions->isFeatureChunk(x,z,eFeature_Stronghold);
197 }
198
199 ChunkPos *pos = strongholdPos[i];
200 if (forcePlacement || (pos && x == pos->x && z == pos->z) )
201 {
202 return true;
203 }
204 }
205 return false;
206}
207
208vector<TilePos> *StrongholdFeature::getGuesstimatedFeaturePositions()
209{
210 vector<TilePos> *positions = new vector<TilePos>();
211 for( int i = 0; i < strongholdPos_length; i++ )
212 {
213 ChunkPos *chunkPos = strongholdPos[i];
214 if (chunkPos != NULL)
215 {
216 positions->push_back(chunkPos->getMiddleBlockPosition(64));
217 }
218 }
219 return positions;
220}
221
222StructureStart *StrongholdFeature::createStructureStart(int x, int z)
223{
224
225 StrongholdStart *start = new StrongholdStart(level, random, x, z);
226
227 // 4J - front() was get(0)
228 while (start->getPieces()->empty() || ((StrongholdPieces::StartPiece *) start->getPieces()->front())->portalRoomPiece == NULL)
229 {
230 delete start;
231 // regenerate stronghold without changing seed
232 start = new StrongholdStart(level, random, x, z);
233 }
234
235 return start;
236
237 // System.out.println("Creating stronghold at (" + x + ", " + z + ")");
238 // return new StrongholdStart(level, random, x, z);
239}
240
241StrongholdFeature::StrongholdStart::StrongholdStart()
242{
243 // for reflection
244}
245
246StrongholdFeature::StrongholdStart::StrongholdStart(Level *level, Random *random, int chunkX, int chunkZ) : StructureStart(chunkX, chunkZ)
247{
248 StrongholdPieces::resetPieces();
249
250 StrongholdPieces::StartPiece *startRoom = new StrongholdPieces::StartPiece(0, random, (chunkX << 4) + 2, (chunkZ << 4) + 2, level);
251 pieces.push_back(startRoom);
252 startRoom->addChildren(startRoom, &pieces, random);
253
254 vector<StructurePiece *> *pendingChildren = &startRoom->pendingChildren;
255 while (!pendingChildren->empty())
256 {
257 int pos = random->nextInt((int)pendingChildren->size());
258 AUTO_VAR(it, pendingChildren->begin() + pos);
259 StructurePiece *structurePiece = *it;
260 pendingChildren->erase(it);
261 structurePiece->addChildren(startRoom, &pieces, random);
262 }
263
264 calculateBoundingBox();
265 moveBelowSeaLevel(level, random, 10);
266}