finders.h 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. #ifndef FINDERS_H_
  2. #define FINDERS_H_
  3. #include "generator.h"
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <math.h>
  8. #ifdef _WIN32
  9. #include <Windows.h>
  10. typedef HANDLE thread_id_t;
  11. #else
  12. #define USE_PTHREAD
  13. #include <pthread.h>
  14. typedef pthread_t thread_id_t;
  15. #endif
  16. #ifdef __cplusplus
  17. extern "C"
  18. {
  19. #endif
  20. #define SEED_BASE_MAX (1LL << 48)
  21. #define PI 3.141592653589793
  22. #define LARGE_STRUCT 1
  23. #define CHUNK_STRUCT 2
  24. enum StructureType
  25. {
  26. Feature, // for locations of temple generation attempts pre 1.13
  27. Desert_Pyramid,
  28. Jungle_Pyramid,
  29. Swamp_Hut,
  30. Igloo,
  31. Village,
  32. Ocean_Ruin,
  33. Shipwreck,
  34. Monument,
  35. Mansion,
  36. Outpost,
  37. Ruined_Portal,
  38. Treasure,
  39. };
  40. enum // village house types prior to 1.14
  41. {
  42. HouseSmall, Church, Library, WoodHut, Butcher, FarmLarge, FarmSmall,
  43. Blacksmith, HouseLarge, HOUSE_NUM
  44. };
  45. // only the very best constellations
  46. static const int64_t lowerBaseBitsIdeal[] =
  47. {
  48. 0x43f18,0xc751a,0xf520a,
  49. };
  50. // for the classic quad-structure constellations
  51. static const int64_t lowerBaseBitsClassic[] =
  52. {
  53. 0x43f18,0x79a0a,0xc751a,0xf520a,
  54. };
  55. // for any valid quad-structure constellation with a structure size:
  56. // (7+1,7+43+1,9+1) which corresponds to a fall-damage based quad-witch-farm,
  57. // but may require a perfect player position
  58. static const int64_t lowerBaseBitsHutNormal[] =
  59. {
  60. 0x43f18,0x65118,0x75618,0x79a0a, 0x89718,0x9371a,0xa5a08,0xb5e18,
  61. 0xc751a,0xf520a,
  62. };
  63. // for any valid quad-structure constellation with a structure size:
  64. // (7+1,7+1,9+1) which corresponds to quad-witch-farms without drop chute
  65. static const int64_t lowerBaseBitsHutBarely[] =
  66. {
  67. 0x1272d,0x17908,0x367b9,0x43f18, 0x487c9,0x487ce,0x50aa7,0x647b5,
  68. 0x65118,0x75618,0x79a0a,0x89718, 0x9371a,0x967ec,0xa3d0a,0xa5918,
  69. 0xa591d,0xa5a08,0xb5e18,0xc6749, 0xc6d9a,0xc751a,0xd7108,0xd717a,
  70. 0xe2739,0xe9918,0xee1c4,0xf520a,
  71. };
  72. STRUCT(StructureConfig)
  73. {
  74. int salt;
  75. char regionSize;
  76. char chunkRange;
  77. unsigned char structType;
  78. unsigned char properties;
  79. };
  80. /* for desert pyramids, jungle temples, witch huts and igloos prior to 1.13 */
  81. static const StructureConfig FEATURE_CONFIG = { 14357617, 32, 24, Feature, 0};
  82. static const StructureConfig DESERT_CONFIG_17 = { 14357617, 32, 24, Desert_Pyramid, 0};
  83. static const StructureConfig IGLOO_CONFIG_17 = { 14357617, 32, 24, Igloo, 0};
  84. static const StructureConfig JUNGLE_CONFIG_17 = { 14357617, 32, 24, Jungle_Pyramid, 0};
  85. static const StructureConfig SWAMP_HUT_CONFIG_17 = { 14357617, 32, 24, Swamp_Hut, 0};
  86. /* ocean features before 1.16 */
  87. static const StructureConfig OCEAN_RUIN_CONFIG_113 = { 14357621, 16, 8, Ocean_Ruin, 0};
  88. static const StructureConfig SHIPWRECK_CONFIG_113 = {165745295, 15, 7, Shipwreck, 0};
  89. /* 1.13 separated feature seeds by type */
  90. static const StructureConfig DESERT_PYRAMID_CONFIG = { 14357617, 32, 24, Desert_Pyramid, 0};
  91. static const StructureConfig IGLOO_CONFIG = { 14357618, 32, 24, Igloo, 0};
  92. static const StructureConfig JUNGLE_PYRAMID_CONFIG = { 14357619, 32, 24, Jungle_Pyramid, 0};
  93. static const StructureConfig SWAMP_HUT_CONFIG = { 14357620, 32, 24, Swamp_Hut, 0};
  94. static const StructureConfig OUTPOST_CONFIG = {165745296, 32, 24, Outpost, 0};
  95. static const StructureConfig VILLAGE_CONFIG = { 10387312, 32, 24, Village, 0};
  96. static const StructureConfig OCEAN_RUIN_CONFIG = { 14357621, 20, 12, Ocean_Ruin, 0};
  97. static const StructureConfig SHIPWRECK_CONFIG = {165745295, 24, 20, Shipwreck, 0};
  98. static const StructureConfig MONUMENT_CONFIG = { 10387313, 32, 27, Monument, LARGE_STRUCT};
  99. static const StructureConfig MANSION_CONFIG = { 10387319, 80, 60, Mansion, LARGE_STRUCT};
  100. static const StructureConfig RUINED_PORTAL_CONFIG = { 34222645, 40, 25, Ruined_Portal, 0}; // overworld variant
  101. // structures that check each chunk individually
  102. static const StructureConfig TREASURE_CONFIG = { 10387320, 1, 0, Treasure, CHUNK_STRUCT};
  103. //==============================================================================
  104. // Biome Tables
  105. //==============================================================================
  106. static const int achievementBiomes_1_7[] =
  107. {
  108. ocean, plains, desert, extremeHills, forest, taiga, swampland, river, /*hell, sky,*/ // 0-9
  109. /*frozenOcean,*/ frozenRiver, icePlains, iceMountains, mushroomIsland, mushroomIslandShore, beach, desertHills, forestHills, taigaHills, // 10-19
  110. /*extremeHillsEdge,*/ jungle, jungleHills, jungleEdge, deepOcean, stoneBeach, coldBeach, birchForest, birchForestHills, roofedForest, // 20-29
  111. coldTaiga, coldTaigaHills, megaTaiga, megaTaigaHills, extremeHillsPlus, savanna, savannaPlateau, mesa, mesaPlateau_F, mesaPlateau // 30-39
  112. };
  113. STRUCT(Pos)
  114. {
  115. int x, z;
  116. };
  117. STRUCT(BiomeFilter)
  118. {
  119. // bitfields for biomes required at their respecive layers
  120. uint64_t tempsToFind; // Special (1:1024)
  121. uint64_t otempToFind; // OceanTemp (1:256)
  122. uint64_t majorToFind; // Biome (1:256)
  123. uint64_t edgesToFind; // Edge (1:64) [mod64: as special case for bamboo]
  124. // bitfields for biomes to find at RareBiome(1:64), Shore(1:16) and Mix(1:4)
  125. // layers for (biomeID < 64) and modified (biomeID >= 128 && biomeID < 192)
  126. uint64_t raresToFind, raresToFindM;
  127. uint64_t shoreToFind, shoreToFindM;
  128. uint64_t riverToFind, riverToFindM;
  129. uint64_t oceanToFind; // all required ocean types
  130. int specialCnt; // number of special temperature categories required
  131. };
  132. /******************************** SEED FINDING *********************************
  133. *
  134. * If we want to find rare seeds that meet multiple custom criteria then we
  135. * should test each condition, starting with the one that is the cheapest
  136. * to test for, while ruling out the most seeds.
  137. *
  138. * Biome checks are quite expensive and should be applied late in the
  139. * condition chain (to avoid as many unnecessary checks as possible).
  140. * Fortunately we can often rule out vast amounts of seeds before hand.
  141. */
  142. /***************************** Structure Positions *****************************
  143. *
  144. * For most structure positions, Minecraft divides the world into a grid of
  145. * regions (usually 32x32 chunks) and performs one generation attempt
  146. * somewhere in each region. The position of this attempt is governed by the
  147. * structure type, the region coordiates and the lower 48-bits of the world
  148. * seed. The remaining top 16 bits do not influence structure positions.
  149. * The dependency on the region coordinates is linear for both the X and Z
  150. * directions, which means that the positions of most structures in a world
  151. * can be translated by applying the following transformation to a seed:
  152. *
  153. * seed2 = seed1 - dregX * 341873128712 - dregZ * 132897987541;
  154. *
  155. * Here seed1 and seed2 have the same structure positioning, but moved by a
  156. * region offset of (dregX,dregZ).
  157. *
  158. * Another property of note is that seed1 at region (0,0) is simply the world
  159. * seed plus a constant that is specific to the stucture type (its salt). This
  160. * means that some structure types share quad-bases which are just offset by
  161. * their respective salt differences.
  162. *
  163. *
  164. ** Quad-Witch-Huts
  165. *
  166. * For a quad-structure, we mainly care about relative positioning, so we can
  167. * get away with just checking the regions near the origin: (0,0),(0,1),(1,0)
  168. * and (1,1) and then move the structures to the desired position.
  169. *
  170. * Futhermore, the PRNG that determines the chunk positions inside each region,
  171. * performs some modular arithmatic on the 48-bit numbers which causes some
  172. * restrictions on the lower bits when looking for near perfect structure
  173. * positions. This is difficult to prove, but can be used to reduce the number
  174. * of free bits to 28 which can be comfortably brute-forced to get the entire
  175. * set of quad-structure candidates. Each of the seeds found this way
  176. * describes entire set of possible quad-witch-huts (with degrees of freedom
  177. * for region-transposition, as well as the top 16-bit bits).
  178. */
  179. //==============================================================================
  180. // Moving Structures
  181. //==============================================================================
  182. /* Transposes a base seed such that structures are moved by the specified region
  183. * vector, (regX, regZ).
  184. */
  185. static inline int64_t moveStructure(const int64_t baseSeed,
  186. const int regX, const int regZ)
  187. {
  188. return (baseSeed - regX*341873128712 - regZ*132897987541) & 0xffffffffffff;
  189. }
  190. //==============================================================================
  191. // Saving & Loading Seeds
  192. //==============================================================================
  193. /* Loads a list of seeds from a file. The seeds should be written as decimal
  194. * ASCII numbers separated by newlines.
  195. * @fnam: file path
  196. * @scnt: number of valid seeds found in the file, which is also the number of
  197. * elements in the returned buffer
  198. *
  199. * Return a pointer to a dynamically allocated seed list.
  200. */
  201. int64_t *loadSavedSeeds(const char *fnam, int64_t *scnt);
  202. //==============================================================================
  203. // Finding Structure Positions
  204. //==============================================================================
  205. /* Finds the block position at which the structure generation attempt will
  206. * occur within the specified region. This function is a wrapper for the more
  207. * specific inlinable functions, which can be found below. You can use
  208. * isViableStructurePos() to test if the necessary biome requirements are met
  209. * for the structure to actually generate at the returned position (much much
  210. * slower than checking attempts).
  211. *
  212. * @config : the structure configuration
  213. * @seed : world seed (only the lower 48-bits are relevant)
  214. * @regX,regZ : region coordinates
  215. * @valid : some structures, like outposts, can have invalid positions,
  216. * use NULL to ignore this options
  217. */
  218. Pos getStructurePos(StructureConfig config, int64_t seed, int regX, int regZ, int *valid);
  219. static inline __attribute__((const))
  220. Pos getFeaturePos(StructureConfig config, int64_t seed, int regX, int regZ);
  221. static inline __attribute__((const))
  222. Pos getFeatureChunkInRegion(StructureConfig config, int64_t seed, int regX, int regZ);
  223. static inline __attribute__((const))
  224. Pos getLargeStructurePos(StructureConfig config, int64_t seed, int regX, int regZ);
  225. static inline __attribute__((const))
  226. Pos getLargeStructureChunkInRegion(StructureConfig config, int64_t seed, int regX, int regZ);
  227. /* Some structures check each chunk individually for viability.
  228. * The placement and biome check within a valid chunk is at block position (9,9)
  229. * or at (2,2) with layer scale=4 from 1.16 onwards.
  230. */
  231. int isMineshaftChunk(int64_t seed, int chunkX, int chunkZ);
  232. int isTreasureChunk(int64_t seed, int chunkX, int chunkZ);
  233. //==============================================================================
  234. // Multi-Structure-Base Checks
  235. //==============================================================================
  236. /* This function determines if the lower 48-bits of a seed qualify as a
  237. * quad-base. This implies that the four structures in the adjacent regions
  238. * (0,0)-(1,1) will attempt to generate close enough together to be within the
  239. * specified block radius of a single block position. The quad-structure can be
  240. * moved to a different location by applying moveStructure() to the quad-base.
  241. * The upper 16 bits of the seed can be chosen freely, as they do not affect
  242. * structure positions.
  243. *
  244. * This function is a wrapper for more specific filtering functions which can
  245. * be found below. Using the correct quad-base finder directly can be faster as
  246. * it is more likely to avoid code branching and offers more control over the
  247. * quality of the structure positions.
  248. *
  249. * The return value is zero if the seed is not a quad-base, and equal to the
  250. * radius of the enclosing sphere if it is, and can be used as a measure of
  251. * quality for the quad-base (smaller is better).
  252. */
  253. static inline float isQuadBase(const StructureConfig sconf, int64_t seed, int radius);
  254. /* Determines if the specified seed qualifies as a quad-base, given a required
  255. * structure size. The structure size should include the actual dimensions of
  256. * the structure and any additional size requirements where despawning shall
  257. * not occur (such as fall damage drop chutes). A smaller size requirement can
  258. * yield more seeds and relax constraints for other structure positions.
  259. * (Since most structures use the same positioning algorithm with an offset,
  260. * this also affects restrictions on the placement of other structure types.)
  261. *
  262. * The function variants are:
  263. * isQuadBaseFeature24Classic() - finds only the classic constellations
  264. * isQuadBaseFeature24() - optimisation for region=32,range=24,radius=128
  265. * isQuadBaseFeature() - for small features (chunkRange not a power of 2)
  266. * isQuadBaseLarge() - for large structures (chunkRange not a power of 2)
  267. *
  268. * The function returns the actual block radius to the furthest block inside
  269. * any of the four structures or zero if the seed does not satisfy the
  270. * quad-base requirements.
  271. *
  272. * @sconf : structure configuration
  273. * @seed : world seed (only the lower 48-bits are relevant)
  274. * @ax,ay,az : required structure size
  275. * @radius : maximum radius for a sphere that encloses all four structures
  276. *
  277. * Implementation sidenote:
  278. * Inline actually matters here, as these functions are not small and compilers
  279. * generally don't want to inline them. However, these functions usually return
  280. * so quickly that the function call is a major contributor to the overall time.
  281. */
  282. static inline __attribute__((always_inline, const))
  283. float isQuadBaseFeature24Classic (const StructureConfig sconf, int64_t seed);
  284. static inline __attribute__((always_inline, const))
  285. float isQuadBaseFeature24 (const StructureConfig sconf, int64_t seed,
  286. int ax, int ay, int az);
  287. static inline __attribute__((always_inline, const))
  288. float isQuadBaseFeature (const StructureConfig sconf, int64_t seed,
  289. int ax, int ay, int az, int radius);
  290. static inline __attribute__((always_inline, const))
  291. float isQuadBaseLarge (const StructureConfig sconf, int64_t seed,
  292. int ax, int ay, int az, int radius);
  293. // Defines how the search should limit the lower bits of the seed bases.
  294. // Conveniently this also provides a way of specifying a quality category.
  295. enum LowBitSet
  296. {
  297. LBIT_ALL, // all bit configurations
  298. LBIT_HUT_BARELY, // any constellation for huts within 128 blocks
  299. LBIT_HUT_NORMAL, // sufficiently close for standard farm designs
  300. LBIT_CLASSIC, // only classic constellations
  301. LBIT_IDEAL, // only the very best constellations that exist
  302. };
  303. /* Starts a multi-threaded search for quad-bases, given a maximum block radius
  304. * for the enclosing sphere. The result is saved in a file of path 'fnam'.
  305. */
  306. void search4QuadBases(const char *fnam, int threads,
  307. const StructureConfig structureConfig, int radius, int lbitset);
  308. int countBlocksInSpawnRange(Pos p[4], int ax, int ay, int az, Pos *afk);
  309. //==============================================================================
  310. // Checking Biomes & Biome Helper Functions
  311. //==============================================================================
  312. /* Returns the biome for the specified block position.
  313. * (Alternatives should be considered first in performance critical code.)
  314. */
  315. int getBiomeAtPos(const LayerStack *g, const Pos pos);
  316. /* Finds a suitable pseudo-random location in the specified area.
  317. * This function is used to determine the positions of spawn and strongholds.
  318. * Warning: accurate, but slow!
  319. *
  320. * @mcversion : Minecraft version (changed in: 1.7, 1.13)
  321. * @l : entry layer with scale = 4
  322. * @cache : biome buffer, set to NULL for temporary allocation
  323. * @centreX, centreZ : origin for the search
  324. * @range : square 'radius' of the search
  325. * @isValid : boolean array of valid biome ids (size = 256)
  326. * @seed : seed used for the RNG
  327. * (initialise RNG using setSeed(&seed))
  328. * @passes : (output) number of valid biomes passed, NULL to ignore
  329. */
  330. Pos findBiomePosition(
  331. const int mcversion,
  332. const Layer * l,
  333. int * cache,
  334. const int centerX,
  335. const int centerZ,
  336. const int range,
  337. const char * isValid,
  338. int64_t * seed,
  339. int * passes
  340. );
  341. /* Determines if the given area contains only biomes specified by 'biomeList'.
  342. * This function is used to determine the positions of villages, ocean monuments
  343. * and mansions.
  344. * Warning: accurate, but slow!
  345. *
  346. * @l : entry layer with scale = 4: (L_RIVER_MIX_4, L13_OCEAN_MIX_4)
  347. * @cache : biome buffer, set to NULL for temporary allocation
  348. * @posX, posZ : centre for the check
  349. * @radius : 'radius' of the check area
  350. * @isValid : boolean array of valid biome ids (size = 256)
  351. */
  352. int areBiomesViable(
  353. const Layer * l,
  354. int * cache,
  355. const int posX,
  356. const int posZ,
  357. const int radius,
  358. const char * isValid
  359. );
  360. /* Finds the smallest radius (by square around the origin) at which all the
  361. * specified biomes are present. The input map is assumed to be a square of
  362. * side length 'sideLen'.
  363. *
  364. * @map : square biome map to be tested
  365. * @sideLen : side length of the square map (should be 2*radius+1)
  366. * @biomes : list of biomes to check for
  367. * @bnum : length of 'biomes'
  368. * @ignoreMutations : flag to count mutated biomes as their original form
  369. *
  370. * Return the radius on the square map that covers all biomes in the list.
  371. * If the map does not contain all the specified biomes, -1 is returned.
  372. */
  373. int getBiomeRadius(
  374. const int * map,
  375. const int mapSide,
  376. const int * biomes,
  377. const int bnum,
  378. const int ignoreMutations);
  379. //==============================================================================
  380. // Finding Strongholds and Spawn
  381. //==============================================================================
  382. /* The chunk locations of the 3 closest strongholds, from the inner ring, can
  383. * be approximated without going through the full biome check. However, the
  384. * accurate positions as well as the locations of the strongholds in the outer
  385. * rings depend on a pseudo-random-number which requires the full biome check
  386. * for all strongholds before them.
  387. *
  388. * Up to MC_1_8 this covers the approximate location for all strongholds as
  389. * there is only one ring.
  390. *
  391. * Note that this function requires only the lower 48-bits of the seed, and the
  392. * accuracy is within +/-112 blocks.
  393. */
  394. void approxInnerStrongholdRing(Pos p[3], int mcversion, int64_t s48);
  395. /* Finds the block positions of the strongholds in the world. Note that the
  396. * number of strongholds was increased from 3 to 128 in MC 1.9.
  397. * Warning: Slow!
  398. *
  399. * @mcversion : Minecraft version (changed in 1.7, 1.9, 1.13)
  400. * @g : generator layer stack [worldSeed should be applied before call!]
  401. * @cache : biome buffer, set to NULL for temporary allocation
  402. * @locations : output block positions
  403. * @worldSeed : world seed of the generator
  404. * @maxSH : Stop when this many strongholds have been found. A value of 0
  405. * defaults to 3 for mcversion <= MC_1_8, and to 128 for >= MC_1_9.
  406. * @maxRing : Stop after this many rings.
  407. *
  408. * Returned is the number of strongholds found.
  409. */
  410. int findStrongholds(
  411. const int mcversion,
  412. const LayerStack * g,
  413. int * cache,
  414. Pos * locations,
  415. int64_t worldSeed,
  416. int maxSH,
  417. int maxRing
  418. );
  419. /* Finds the spawn point in the world.
  420. * Warning: Slow, and may be inaccurate because the world spawn depends on
  421. * grass blocks!
  422. *
  423. * @mcversion : Minecraft version (changed in 1.7, 1.13)
  424. * @g : generator layer stack [worldSeed should be applied before call!]
  425. * @cache : biome buffer, set to NULL for temporary allocation
  426. * @worldSeed : world seed used for the generator
  427. */
  428. Pos getSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed);
  429. /* Finds the approximate spawn point in the world.
  430. *
  431. * @mcversion : Minecraft version (changed in 1.7, 1.13)
  432. * @g : generator layer stack [worldSeed should be applied before call!]
  433. * @cache : biome buffer, set to NULL for temporary allocation
  434. * @worldSeed : world seed used for the generator
  435. */
  436. Pos estimateSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed);
  437. //==============================================================================
  438. // Validating Structure Positions
  439. //==============================================================================
  440. /* This function performs a biome check at the specified block coordinates to
  441. * determine whether the corresponding structure would spawn there. You can get
  442. * the block positions using the appropriate getXXXPos() function.
  443. *
  444. * @structureType : structure type to be checked
  445. * @mcversion : minecraft version
  446. * @g : generator layer stack, seed will be applied to layers
  447. * @seed : world seed, will be applied to generator
  448. * @blockX, blockZ : block coordinates
  449. *
  450. * The return value is non-zero if the position is valid.
  451. */
  452. int isViableStructurePos(int structureType, int mcversion, LayerStack *g,
  453. int64_t seed, int blockX, int blockZ);
  454. /* Checks if the specified structure type could generate in the given biome.
  455. */
  456. int isViableFeatureBiome(int structureType, int biomeID);
  457. //==============================================================================
  458. // Finding Properties of Structures
  459. //==============================================================================
  460. /* Initialises and returns a random seed used in the (16x16) chunk generation.
  461. * This random object is used for recursiveGenerate() which is responsible for
  462. * generating caves, ravines, mineshafts, and virtually all other structures.
  463. */
  464. inline static int64_t chunkGenerateRnd(const int64_t worldSeed,
  465. const int chunkX, const int chunkZ)
  466. {
  467. int64_t rnd = worldSeed;
  468. setSeed(&rnd);
  469. rnd = (nextLong(&rnd) * chunkX) ^ (nextLong(&rnd) * chunkZ) ^ worldSeed;
  470. setSeed(&rnd);
  471. return rnd;
  472. }
  473. /* Checks if the village in the given region would be infested by zombies.
  474. * (Minecraft 1.10+)
  475. */
  476. int isZombieVillage(const int mcversion, const int64_t worldSeed,
  477. const int regionX, const int regionZ);
  478. /* Finds the number of each type of house that generate in a village.
  479. * @worldSeed : world seed
  480. * @chunkX, chunkZ : 16x16 chunk position of the village origin
  481. * @housesOut : output number of houses for each entry in the house type
  482. * enum (i.e this should be an array of length HOUSE_NUM)
  483. *
  484. * Returns the random object seed after finding these numbers.
  485. */
  486. int64_t getHouseList(const int64_t worldSeed, const int chunkX, const int chunkZ,
  487. int *housesOut);
  488. static inline char* getValidSpawnBiomes()
  489. {
  490. static const int biomesToSpawnIn[] = {forest, plains, taiga, taiga_hills, wooded_hills, jungle, jungle_hills};
  491. static char isValid[256];
  492. unsigned int i;
  493. if (!isValid[biomesToSpawnIn[0]])
  494. for (i = 0; i < sizeof(biomesToSpawnIn) / sizeof(int); i++)
  495. isValid[ biomesToSpawnIn[i] ] = 1;
  496. return isValid;
  497. }
  498. static inline char* getValidStrongholdBiomes()
  499. {
  500. static char validStrongholdBiomes[256];
  501. if (!validStrongholdBiomes[plains])
  502. {
  503. int id;
  504. for (id = 0; id < 256; id++)
  505. {
  506. if (biomeExists(id) && biomes[id].height > 0.0)
  507. validStrongholdBiomes[id] = 1;
  508. }
  509. }
  510. return validStrongholdBiomes;
  511. }
  512. //==============================================================================
  513. // Seed Filters
  514. //==============================================================================
  515. /* Creates a biome filter configuration from a given list of biomes.
  516. */
  517. BiomeFilter setupBiomeFilter(const int *biomeList, int listLen);
  518. /* Starts to generate the specified area and checks if all biomes in the filter
  519. * are present. If so, the area will be fully generated inside the cache
  520. * (if != NULL) up to the entry 'layerID', and the return value will be > 0.
  521. * Otherwise, the contents of 'cache' is undefined and a value <= 0 is returned.
  522. * More aggressive filtering can be enabled with 'protoCheck' which may yield
  523. * some false negatives in exchange for speed.
  524. *
  525. * @g : generator (will be modified!)
  526. * @layerID : layer enum of generation entry point
  527. * @cache : working buffer, and output (if != NULL)
  528. * @seed : world seed
  529. * @x,z,w,h : requested area
  530. * @filter : biomes to be checked for
  531. * @protoCheck : enables more aggressive filtering when non-zero
  532. */
  533. int checkForBiomes(
  534. LayerStack * g,
  535. int layerID,
  536. int * cache,
  537. int64_t seed,
  538. int x,
  539. int z,
  540. unsigned int w,
  541. unsigned int h,
  542. BiomeFilter filter,
  543. int protoCheck
  544. );
  545. int hasAllTemps(LayerStack *g, int64_t seed, int x1024, int z1024);
  546. //==============================================================================
  547. // Implementaions for Functions that Ideally Should be Inlined
  548. //==============================================================================
  549. static inline __attribute__((const))
  550. Pos getFeatureChunkInRegion(StructureConfig config, int64_t seed, int regX, int regZ)
  551. {
  552. /*
  553. // Vanilla like implementation.
  554. seed = regionX*341873128712 + regionZ*132897987541 + seed + structureSeed;
  555. setSeed(&(seed));
  556. Pos pos;
  557. pos.x = nextInt(&seed, 24);
  558. pos.z = nextInt(&seed, 24);
  559. */
  560. Pos pos;
  561. const int64_t K = 0x5deece66dLL;
  562. const int64_t M = (1ULL << 48) - 1;
  563. const int64_t b = 0xb;
  564. // set seed
  565. seed = seed + regX*341873128712 + regZ*132897987541 + config.salt;
  566. seed = (seed ^ K);
  567. seed = (seed * K + b) & M;
  568. if (config.chunkRange & (config.chunkRange-1))
  569. {
  570. pos.x = (int)(seed >> 17) % config.chunkRange;
  571. seed = (seed * K + b) & M;
  572. pos.z = (int)(seed >> 17) % config.chunkRange;
  573. }
  574. else
  575. {
  576. // Java RNG treats powers of 2 as a special case.
  577. pos.x = (config.chunkRange * (seed >> 17)) >> 31;
  578. seed = (seed * K + b) & M;
  579. pos.z = (config.chunkRange * (seed >> 17)) >> 31;
  580. }
  581. return pos;
  582. }
  583. static inline __attribute__((const))
  584. Pos getFeaturePos(StructureConfig config, int64_t seed, int regX, int regZ)
  585. {
  586. Pos pos = getFeatureChunkInRegion(config, seed, regX, regZ);
  587. // The structure is positioned at the chunk origin, but the biome check is
  588. // performed near the middle of the chunk [(9,9) in 1.13, TODO: check 1.7]
  589. // In 1.16 the biome check is always performed at (2,2) with layer scale=4.
  590. pos.x = ((regX*config.regionSize + pos.x) << 4) + 9;
  591. pos.z = ((regZ*config.regionSize + pos.z) << 4) + 9;
  592. return pos;
  593. }
  594. static inline __attribute__((const))
  595. Pos getLargeStructureChunkInRegion(StructureConfig config, int64_t seed, int regX, int regZ)
  596. {
  597. Pos pos;
  598. const int64_t K = 0x5deece66dLL;
  599. const int64_t M = (1ULL << 48) - 1;
  600. const int64_t b = 0xb;
  601. //TODO: power of two chunk ranges...
  602. // set seed
  603. seed = seed + regX*341873128712 + regZ*132897987541 + config.salt;
  604. seed = (seed ^ K);
  605. seed = (seed * K + b) & M;
  606. pos.x = (int)(seed >> 17) % config.chunkRange;
  607. seed = (seed * K + b) & M;
  608. pos.x += (int)(seed >> 17) % config.chunkRange;
  609. seed = (seed * K + b) & M;
  610. pos.z = (int)(seed >> 17) % config.chunkRange;
  611. seed = (seed * K + b) & M;
  612. pos.z += (int)(seed >> 17) % config.chunkRange;
  613. pos.x >>= 1;
  614. pos.z >>= 1;
  615. return pos;
  616. }
  617. static inline __attribute__((const))
  618. Pos getLargeStructurePos(StructureConfig config, int64_t seed, int regX, int regZ)
  619. {
  620. Pos pos = getLargeStructureChunkInRegion(config, seed, regX, regZ);
  621. pos.x = regX*config.regionSize + pos.x;
  622. pos.z = regZ*config.regionSize + pos.z;
  623. pos.x = pos.x*16 + 9;
  624. pos.z = pos.z*16 + 9;
  625. return pos;
  626. }
  627. static __attribute__((const))
  628. float getEnclosingRadius(
  629. int x0, int z0, int x1, int z1, int x2, int z2, int x3, int z3,
  630. int ax, int ay, int az, int reg, int gap)
  631. {
  632. // convert chunks to blocks
  633. x0 = (x0 << 4);
  634. z0 = (z0 << 4);
  635. x1 = ((reg+x1) << 4) + ax;
  636. z1 = ((reg+z1) << 4) + az;
  637. x2 = ((reg+x2) << 4) + ax;
  638. z2 = (z2 << 4);
  639. x3 = (x3 << 4);
  640. z3 = ((reg+z3) << 4) + az;
  641. int sqrad = 0x7fffffff;
  642. // build the inner rectangle containing the center point
  643. int cbx0 = (x1 > x2 ? x1 : x2) - gap;
  644. int cbz0 = (z1 > z3 ? z1 : z3) - gap;
  645. int cbx1 = (x0 < x3 ? x0 : x3) + gap;
  646. int cbz1 = (z0 < z2 ? z0 : z2) + gap;
  647. int x, z;
  648. // brute force the ideal center position
  649. for (z = cbz0; z <= cbz1; z++)
  650. {
  651. for (x = cbx0; x <= cbx1; x++)
  652. {
  653. int sq = 0;
  654. int s;
  655. s = (x-x0)*(x-x0) + (z-z0)*(z-z0); if (s > sq) sq = s;
  656. s = (x-x1)*(x-x1) + (z-z1)*(z-z1); if (s > sq) sq = s;
  657. s = (x-x2)*(x-x2) + (z-z2)*(z-z2); if (s > sq) sq = s;
  658. s = (x-x3)*(x-x3) + (z-z3)*(z-z3); if (s > sq) sq = s;
  659. if (sq < sqrad)
  660. sqrad = sq;
  661. }
  662. }
  663. return sqrad < 0x7fffffff ? sqrtf(sqrad + ay*ay/4.0f) : 0xffff;
  664. }
  665. static inline float isQuadBase(const StructureConfig sconf, int64_t seed, int radius)
  666. {
  667. switch(sconf.structType)
  668. {
  669. case Swamp_Hut:
  670. if (radius == 128)
  671. return isQuadBaseFeature24(sconf, seed, 7+1, 7+1, 9+1);//7+1, 7+43+1, 9+1);
  672. else
  673. return isQuadBaseFeature(sconf, seed, 7+1, 7+1, 9+1, radius);
  674. case Desert_Pyramid:
  675. case Jungle_Pyramid:
  676. case Igloo:
  677. case Village:
  678. // nothing special spawns here, why would you want these?
  679. if (radius == 128)
  680. return isQuadBaseFeature24(sconf, seed, 0, 0, 0);
  681. else
  682. return isQuadBaseFeature(sconf, seed, 0, 0, 0, radius);
  683. case Outpost:
  684. // Outposts are tricky. They require an additional 1 in 5 PRNG pass to
  685. // generate and no village nearby. Also perfect quad-outposts don't
  686. // exist as they are too large, given that the generation point will
  687. // always be 8 chunks apart. However, the watchtower can be offset to
  688. // the generation attempt by a chunk or two (TODO: investivgate this!).
  689. return isQuadBaseFeature(sconf, seed, 72, 54, 72, radius);
  690. case Monument:
  691. return isQuadBaseLarge(sconf, seed, 58, 23, 58, radius);
  692. //case Mansion:
  693. //case Ocean_Ruin:
  694. //case Shipwreck:
  695. //case Ruined_Portal:
  696. default:
  697. fprintf(stderr, "ERR isQuadBase: not implemented for structure type"
  698. " %d\n", sconf.structType);
  699. exit(-1);
  700. }
  701. return 0;
  702. }
  703. // optimised version for regionSize=32,chunkRange=24,radius=128
  704. static inline __attribute__((always_inline, const))
  705. float isQuadBaseFeature24(const StructureConfig sconf, int64_t seed,
  706. int ax, int ay, int az)
  707. {
  708. seed += sconf.salt;
  709. int64_t s00 = seed;
  710. int64_t s11 = 341873128712 + 132897987541 + seed;
  711. const int64_t K = 0x5deece66dLL;
  712. int x0, z0, x1, z1, x2, z2, x3, z3;
  713. int x, z;
  714. // check that the two structures in the opposing diagonal quadrants are
  715. // close enough together
  716. s00 ^= K;
  717. JAVA_NEXT_INT24(s00, x0); if L(x0 < 20) return 0;
  718. JAVA_NEXT_INT24(s00, z0); if L(z0 < 20) return 0;
  719. s11 ^= K;
  720. JAVA_NEXT_INT24(s11, x1); if L(x1 > x0-20) return 0;
  721. JAVA_NEXT_INT24(s11, z1); if L(z1 > z0-20) return 0;
  722. x = x1 + 32 - x0;
  723. z = z1 + 32 - z0;
  724. if (x*x + z*z > 255)
  725. return 0;
  726. int64_t s01 = 341873128712 + seed;
  727. int64_t s10 = 132897987541 + seed;
  728. s01 ^= K;
  729. JAVA_NEXT_INT24(s01, x2); if L(x2 >= 4) return 0;
  730. JAVA_NEXT_INT24(s01, z2); if L(z2 < 20) return 0;
  731. s10 ^= K;
  732. JAVA_NEXT_INT24(s10, x3); if L(x3 < 20) return 0;
  733. JAVA_NEXT_INT24(s10, z3); if L(z3 >= 4) return 0;
  734. x = x2 + 32 - x3;
  735. z = z3 + 32 - z2;
  736. if (x*x + z*z > 255)
  737. return 0;
  738. // only approx. 1 in 100M seeds makes it here, now we have to determine if
  739. // there is a sphere, centered on a block, which is in range of all four
  740. // structures
  741. float sqrad = getEnclosingRadius(x0,z0,x1,z1,x2,z2,x3,z3,ax,ay,az,32,128);
  742. return sqrad < 128 ? sqrad : 0;
  743. }
  744. // variant of isQuadBaseFeature24 which finds only the classic constellations
  745. static inline __attribute__((always_inline, const))
  746. float isQuadBaseFeature24Classic(const StructureConfig sconf, int64_t seed)
  747. {
  748. seed += sconf.salt;
  749. int64_t s00 = seed;
  750. int64_t s11 = 341873128712 + 132897987541 + seed;
  751. const int64_t K = 0x5deece66dLL;
  752. int p;
  753. // check that the two structures in the opposing diagonal quadrants are
  754. // close enough together
  755. s00 ^= K;
  756. JAVA_NEXT_INT24(s00, p); if L(p < 22) return 0;
  757. JAVA_NEXT_INT24(s00, p); if L(p < 22) return 0;
  758. s11 ^= K;
  759. JAVA_NEXT_INT24(s11, p); if L(p > 1) return 0;
  760. JAVA_NEXT_INT24(s11, p); if L(p > 1) return 0;
  761. int64_t s01 = 341873128712 + seed;
  762. int64_t s10 = 132897987541 + seed;
  763. s01 ^= K;
  764. JAVA_NEXT_INT24(s01, p); if L(p > 1) return 0;
  765. JAVA_NEXT_INT24(s01, p); if L(p < 22) return 0;
  766. s10 ^= K;
  767. JAVA_NEXT_INT24(s10, p); if L(p < 22) return 0;
  768. JAVA_NEXT_INT24(s10, p); if L(p > 1) return 0;
  769. return 1; // should actually return one of 122.781311 or 127.887650
  770. }
  771. static inline __attribute__((always_inline, const))
  772. float isQuadBaseFeature(const StructureConfig sconf, int64_t seed,
  773. int ax, int ay, int az, int radius)
  774. {
  775. seed += sconf.salt;
  776. int64_t s00 = seed;
  777. int64_t s11 = 341873128712 + 132897987541 + seed;
  778. const int64_t M = (1ULL << 48) - 1;
  779. const int64_t K = 0x5deece66dLL;
  780. const int64_t b = 0xbLL;
  781. int x0, z0, x1, z1, x2, z2, x3, z3;
  782. int x, z;
  783. const int R = sconf.regionSize;
  784. const int C = sconf.chunkRange;
  785. int cd = radius/8;
  786. int rm = R - (int)sqrtf(cd*cd - (R-C+1)*(R-C+1));
  787. int64_t s;
  788. s = s00 ^ K;
  789. s = (s * K + b) & M; x0 = (int)(s >> 17) % C; if L(x0 <= rm) return 0;
  790. s = (s * K + b) & M; z0 = (int)(s >> 17) % C; if L(z0 <= rm) return 0;
  791. s = s11 ^ K;
  792. s = (s * K + b) & M; x1 = (int)(s >> 17) % C; if L(x1 >= x0-rm) return 0;
  793. s = (s * K + b) & M; z1 = (int)(s >> 17) % C; if L(z1 >= z0-rm) return 0;
  794. // check that the two structures in the opposing diagonal quadrants are
  795. // close enough together
  796. x = x1 + R - x0;
  797. z = z1 + R - z0;
  798. if L(x*x + z*z > cd*cd)
  799. return 0;
  800. int64_t s01 = 341873128712 + seed;
  801. int64_t s10 = 132897987541 + seed;
  802. s = s01 ^ K;
  803. s = (s * K + b) & M; x2 = (int)(s >> 17) % C; if L(x2 >= C-rm) return 0;
  804. s = (s * K + b) & M; z2 = (int)(s >> 17) % C; if L(z2 <= rm) return 0;
  805. s = s10 ^ K;
  806. s = (s * K + b) & M; x3 = (int)(s >> 17) % C; if L(x3 <= rm) return 0;
  807. s = (s * K + b) & M; z3 = (int)(s >> 17) % C; if L(z3 >= C-rm) return 0;
  808. x = x2 + R - x3;
  809. z = z3 + R - z2;
  810. if L(x*x + z*z > cd*cd)
  811. return 0;
  812. float sqrad = getEnclosingRadius(
  813. x0,z0,x1,z1,x2,z2,x3,z3,ax,ay,az,sconf.regionSize,radius);
  814. return sqrad < radius ? sqrad : 0;
  815. }
  816. static inline __attribute__((always_inline, const))
  817. float isQuadBaseLarge(const StructureConfig sconf, int64_t seed,
  818. int ax, int ay, int az, int radius)
  819. {
  820. // Good quad-monument bases are very rare indeed. There are only two seeds
  821. // for a radius below 148 blocks, between seed-bases 0 and 1e13:
  822. // 775379617447 : radius=143.30 (400,384);(384,528);(528,384);(528,528)
  823. // 3752024106001 : radius=145.07 (400,384);(400,560);(544,416);(528,512)
  824. const int64_t M = (1ULL << 48) - 1;
  825. const int64_t K = 0x5deece66dLL;
  826. const int64_t b = 0xbLL;
  827. seed += sconf.salt;
  828. int64_t s00 = seed;
  829. int64_t s01 = 341873128712 + seed;
  830. int64_t s10 = 132897987541 + seed;
  831. int64_t s11 = 341873128712 + 132897987541 + seed;
  832. // p1 = nextInt(range); p2 = nextInt(range); pos = (p1+p2)>>1
  833. const int R = sconf.regionSize;
  834. const int C = sconf.chunkRange;
  835. int rm = (int)(2 * R + ((ax<az?ax:az) - 2*radius + 7) / 8);
  836. int64_t s;
  837. int p;
  838. int x0,z0,x1,z1,x2,z2,x3,z3;
  839. s = s00 ^ K;
  840. s = (s * K + b) & M; p = (int)(s >> 17) % C;
  841. s = (s * K + b) & M; p += (int)(s >> 17) % C; if L(p <= rm) return 0;
  842. x0 = p;
  843. s = (s * K + b) & M; p = (int)(s >> 17) % C;
  844. s = (s * K + b) & M; p += (int)(s >> 17) % C; if L(p <= rm) return 0;
  845. z0 = p;
  846. s = s11 ^ K;
  847. s = (s * K + b) & M; p = (int)(s >> 17) % C;
  848. s = (s * K + b) & M; p += (int)(s >> 17) % C; if L(p > x0-rm) return 0;
  849. x1 = p;
  850. s = (s * K + b) & M; p = (int)(s >> 17) % C;
  851. s = (s * K + b) & M; p += (int)(s >> 17) % C; if L(p > z0-rm) return 0;
  852. z1 = p;
  853. s = ((x1-x0)>>1)*((x1-x0)>>1) + ((z1-z0)>>1)*((z1-z0)>>1);
  854. if (s > 4*radius*radius)
  855. return 0;
  856. s = s01 ^ K;
  857. s = (s * K + b) & M; p = (int)(s >> 17) % C;
  858. s = (s * K + b) & M; p += (int)(s >> 17) % C; if L(p > x0-rm) return 0;
  859. x2 = p;
  860. s = (s * K + b) & M; p = (int)(s >> 17) % C;
  861. s = (s * K + b) & M; p += (int)(s >> 17) % C; if L(p <= rm) return 0;
  862. z2 = p;
  863. s = s10 ^ K;
  864. s = (s * K + b) & M; p = (int)(s >> 17) % C;
  865. s = (s * K + b) & M; p += (int)(s >> 17) % C; if L(p <= rm) return 0;
  866. x3 = p;
  867. s = (s * K + b) & M; p = (int)(s >> 17) % C;
  868. s = (s * K + b) & M; p += (int)(s >> 17) % C; if L(p > z0-rm) return 0;
  869. z3 = p;
  870. float sqrad = getEnclosingRadius(
  871. x0>>1,z0>>1, x1>>1,z1>>1, x2>>1,z2>>1, x3>>1,z3>>1,
  872. ax,ay,az, sconf.regionSize, radius);
  873. return sqrad < radius ? sqrad : 0;
  874. }
  875. #ifdef __cplusplus
  876. }
  877. #endif
  878. #endif /* FINDERS_H_ */