const path = require('path'); const fs = require('fs'); const { execSync } = require('child_process'); const { jigsawConversion } = require('./src/worldgen/structure/index.js'); const { TemplatePool, JigsawStartHeight } = require('./src/enum.js'); const mcmetaPath = path.resolve(__dirname, 'mcmeta'); execSync(`cd ${mcmetaPath} && git checkout 1.21-data`); function getMetaData(dataPath) { return JSON.parse( fs.readFileSync( path.resolve(mcmetaPath, `data/minecraft/${dataPath}.json`), 'utf8' ) ); } function getData(namespace, dataPath) { let encoding = ''; if (dataPath.endsWith('json')) { encoding = 'utf8'; } return fs.readFileSync( path.resolve(__dirname, `data/${namespace}/${dataPath}`), encoding ); } function getJsonData(namespace, dataPath) { return JSON.parse( getData(namespace, `${dataPath}.json`) ); } function writeData(namespace, dataPath, data) { return fs.writeFileSync( path.resolve(__dirname, `data/${namespace}/${dataPath}`), data ); } function overwriteData(dataPath, data) { return writeData('minecraft', dataPath, data); } function writeJson(namespace, dataPath, data) { // sort keys const allKeys = new Set(); JSON.stringify(data, (key, value) => (allKeys.add(key), value)); const sortedKeys = Array.from(allKeys).sort(); // write file return writeData( namespace, `${dataPath}.json`, JSON.stringify(data, sortedKeys, 2) ); } function overwriteJson(dataPath, data) { return writeJson('minecraft', dataPath, data); } function replaceData(source, destination) { const destinationDirectory = path.resolve(__dirname, `data/minecraft/${path.dirname(destination)}`); if (!fs.existsSync(destinationDirectory)) { fs.mkdirSync(destinationDirectory, { recursive: true }); } return fs.copyFileSync( path.resolve(__dirname, `data/vanilla_skyblock/${source}`), path.resolve(__dirname, `data/minecraft/${destination}`) ); } /* * worldgen/noise_settings */ function getWorldgenNoiseSettingsMeta(name) { return getMetaData(`worldgen/noise_settings/${name}`); } function overwriteWorldgenNoiseSettings(name, data) { return overwriteJson(`worldgen/noise_settings/${name}`, data); } // overworld const overworld = getWorldgenNoiseSettingsMeta('overworld'); Object.assign(overworld, { aquifers_enabled: false, ore_veins_enabled: false, default_block: { ...overworld.default_block, Name: 'minecraft:air', }, default_fluid: { ...overworld.default_fluid, Name: 'minecraft:air', }, noise: { ...overworld.noise, min_y: 0, height: 320, }, }); overwriteWorldgenNoiseSettings('overworld', overworld); // nether const nether = getWorldgenNoiseSettingsMeta('nether'); Object.assign(nether, { default_block: { ...nether.default_block, Name: 'minecraft:air', }, default_fluid: { ...nether.default_fluid, Name: 'minecraft:air', }, }); overwriteWorldgenNoiseSettings('nether', nether); // end const end = getWorldgenNoiseSettingsMeta('end'); Object.assign(end, { default_block: { ...end.default_block, Name: 'minecraft:air', }, }); overwriteWorldgenNoiseSettings('end', end); /* * worldgen/structure */ function getWorldgenStructureMeta(name) { return getMetaData(`worldgen/structure/${name}`); } function overwriteWorldgenStructure(name, data) { return overwriteJson(`worldgen/structure/${name}`, data); } // ancient city const ancientCity = getWorldgenStructureMeta('ancient_city'); delete ancientCity['start_jigsaw_name']; overwriteWorldgenStructure('ancient_city', ancientCity); // desert pyramid let desertPyramid = getWorldgenStructureMeta('desert_pyramid'); desertPyramid = jigsawConversion(desertPyramid, { start_pool: 'vanilla_skyblock:desert_pyramid', start_height: JigsawStartHeight.VERY_BIASED_TO_BOTTOM, }); overwriteWorldgenStructure('desert_pyramid', desertPyramid); // end city let endCity = getWorldgenStructureMeta('end_city'); endCity = jigsawConversion(endCity, { start_pool: 'vanilla_skyblock:end_city', start_height: JigsawStartHeight.UNIFORM, }); overwriteWorldgenStructure('end_city', endCity); // fortress let fortress = getWorldgenStructureMeta('fortress'); fortress = jigsawConversion(fortress, { start_pool: TemplatePool.EMPTY_FULL, start_height: JigsawStartHeight.BIASED_TO_BOTTOM, }); overwriteWorldgenStructure('fortress', fortress); // igloo let igloo = getWorldgenStructureMeta('igloo'); igloo = jigsawConversion(igloo, { start_pool: TemplatePool.EMPTY_16, start_height: JigsawStartHeight.UNIFORM, }); overwriteWorldgenStructure('igloo', igloo); // ocean monument let monument = getWorldgenStructureMeta('monument'); monument = jigsawConversion(monument, { start_pool: TemplatePool.EMPTY_FULL, start_height: JigsawStartHeight.BIASED_TO_BOTTOM, }); overwriteWorldgenStructure('monument', monument); // ocean ruin cold let oceanRuinCold = getWorldgenStructureMeta('ocean_ruin_cold'); oceanRuinCold = jigsawConversion(oceanRuinCold, { start_pool: 'vanilla_skyblock:ocean_ruin_cold', start_height: JigsawStartHeight.VERY_BIASED_TO_BOTTOM, }); overwriteWorldgenStructure('ocean_ruin_cold', oceanRuinCold); // ocean ruin cold let oceanRuinWarm = getWorldgenStructureMeta('ocean_ruin_warm'); oceanRuinWarm = jigsawConversion(oceanRuinWarm, { start_pool: 'vanilla_skyblock:ocean_ruin_warm', start_height: JigsawStartHeight.VERY_BIASED_TO_BOTTOM, }); overwriteWorldgenStructure('ocean_ruin_warm', oceanRuinWarm); // ruined portal let ruinedPortal = getWorldgenStructureMeta('ruined_portal'); ruinedPortal = jigsawConversion(ruinedPortal, { start_pool: TemplatePool.EMPTY_16, start_height: JigsawStartHeight.UNIFORM, }); overwriteWorldgenStructure('ruined_portal', ruinedPortal); // ruined portal const ruinedPortals = [ 'ruined_portal', 'ruined_portal_desert', 'ruined_portal_jungle', 'ruined_portal_mountain', 'ruined_portal_nether', 'ruined_portal_ocean', 'ruined_portal_swamp', ]; for (const structure of ruinedPortals) { let ruinedPortal = getWorldgenStructureMeta(structure); ruinedPortal = jigsawConversion(ruinedPortal, { start_pool: TemplatePool.EMPTY_16, start_height: JigsawStartHeight.UNIFORM, }); overwriteWorldgenStructure(structure, ruinedPortal); } // shipwreck const shipwrecks = [ 'shipwreck', 'shipwreck_beached', ]; for (const structure of shipwrecks) { let shipwreck = getWorldgenStructureMeta(structure); shipwreck = jigsawConversion(shipwreck, { start_pool: TemplatePool.EMPTY_16, start_height: JigsawStartHeight.UNIFORM, }); overwriteWorldgenStructure(structure, shipwreck); } // stronhold let stronghold = getWorldgenStructureMeta('stronghold'); stronghold = jigsawConversion(stronghold, { start_pool: 'vanilla_skyblock:stronghold', start_height: JigsawStartHeight.VERY_BIASED_TO_BOTTOM, }); overwriteWorldgenStructure('stronghold', stronghold); // trail ruins const trailRuins = getWorldgenStructureMeta('trail_ruins'); delete trailRuins['project_start_to_heightmap']; overwriteWorldgenStructure('trail_ruins', trailRuins); /* * worldgen/noise */ const noisesToSilence = [ 'iceberg_pillar', 'iceberg_pillar_roof', 'iceberg_surface', ]; for (const noise of noisesToSilence) { const noiseData = getMetaData(`worldgen/noise/${noise}`); Object.assign(noiseData, { firstOctave: 0, amplitudes: [], }); overwriteJson(`worldgen/noise/${noise}`, noiseData); } /* * worldgen/configured_feature */ const featuresToRemove = [ 'end_island', 'iceberg_blue', 'iceberg_packed', ]; for (const feature of featuresToRemove) { const featureData = getMetaData(`worldgen/configured_feature/${feature}`); Object.assign(featureData, { type: 'minecraft:fill_layer', config: { state: { Name: 'minecraft:air' }, height: 0, }, }); overwriteJson(`worldgen/configured_feature/${feature}`, featureData); } /* * structure/*.nbt */ // TODO if applicable check worldgen/structure.json for pool_start and get location of nbt files. // write to nbt files accordingly // ancient city const ancientCityStartPool = ancientCity.start_pool.replace('minecraft:', ''); const ancientCityTemplatePool = getMetaData(`worldgen/template_pool/${ancientCityStartPool}`); for (const templatePoolElement of ancientCityTemplatePool.elements) { const location = templatePoolElement.element.location.replace('minecraft:', ''); replaceData('structure/ancient_city.nbt', `structure/${location}.nbt`); } // bastion const bastionStartPool = getWorldgenStructureMeta('bastion_remnant').start_pool.replace('minecraft:', ''); const bastionTemplatePool = getMetaData(`worldgen/template_pool/${bastionStartPool}`); for (const templatePoolElement of bastionTemplatePool.elements) { const location = templatePoolElement.element.location.replace('minecraft:', ''); if (location.includes('/units/')) { replaceData('structure/bastion/bastion_other.nbt', `structure/${location}.nbt`); } else if (location.includes('/hoglin_stable/')) { replaceData('structure/bastion/bastion_hoglin_stable.nbt', `structure/${location}.nbt`); } else if (location.includes('/treasure/')) { replaceData('structure/bastion/bastion_treasure.nbt', `structure/${location}.nbt`); } else if (location.includes('/bridge/')) { replaceData('structure/bastion/bastion_bridge.nbt', `structure/${location}.nbt`); } } // pillager outpost const pillagerOutpostStartPool = getWorldgenStructureMeta('pillager_outpost').start_pool.replace('minecraft:', ''); const pillagerOutpostTemplatePool = getMetaData(`worldgen/template_pool/${pillagerOutpostStartPool}`); for (const templatePoolElement of pillagerOutpostTemplatePool.elements) { const location = templatePoolElement.element.location.replace('minecraft:', ''); replaceData('structure/empty_16.nbt', `structure/${location}.nbt`); } // trail ruins const trailRuinsStartPool = getWorldgenStructureMeta('trail_ruins').start_pool.replace('minecraft:', ''); const trailRuinsTemplatePool = getMetaData(`worldgen/template_pool/${trailRuinsStartPool}`); const trailRuinsRareChancePercent = 25; const trailRuinsRareMaxIndex = Math.ceil(trailRuinsTemplatePool.elements.length / (100 / trailRuinsRareChancePercent)); for (const idx in trailRuinsTemplatePool.elements) { const templatePoolElement = trailRuinsTemplatePool.elements[idx]; const location = templatePoolElement.element.location.replace('minecraft:', ''); if (idx >= trailRuinsRareMaxIndex) { replaceData('structure/archaeology/trail_ruins_common.nbt', `structure/${location}.nbt`); } else { replaceData('structure/archaeology/trail_ruins_rare.nbt', `structure/${location}.nbt`); } } // trial chambers const trialChambersStartPool = getWorldgenStructureMeta('trial_chambers').start_pool.replace('minecraft:', ''); const trialChambersTemplatePool = getMetaData(`worldgen/template_pool/${trialChambersStartPool}`); for (const templatePoolElement of trialChambersTemplatePool.elements) { const location = templatePoolElement.element.location.replace('minecraft:', ''); replaceData('structure/trial_chamber.nbt', `structure/${location}.nbt`); } // villages const villages = [ 'village_desert', 'village_plains', 'village_savanna', 'village_snowy', 'village_taiga', ]; for (const village of villages) { const villageStartPool = getWorldgenStructureMeta(village).start_pool.replace('minecraft:', ''); const villageTemplatePool = getMetaData(`worldgen/template_pool/${villageStartPool}`); for (const templatePoolElement of villageTemplatePool.elements) { const location = templatePoolElement.element.location.replace('minecraft:', ''); replaceData('structure/empty_16.nbt', `structure/${location}.nbt`); } }