Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.
at master 274 lines 11 kB view raw
1package net.lerariemann.infinity.dimensions; 2 3import net.lerariemann.infinity.InfinityMod; 4import net.lerariemann.infinity.util.VersionMethods; 5import net.lerariemann.infinity.util.core.*; 6import net.lerariemann.infinity.util.core.NbtUtils; 7import net.minecraft.nbt.*; 8 9import java.util.*; 10 11public class RandomBiome { 12 public RandomDimension parent; 13 public final RandomProvider PROVIDER; 14 public long id; 15 public String name; 16 public String fullname; 17 public final Random random; 18 public Set<String> mobs; 19 public CompoundTag data; 20 public CompoundTag colors; 21 22 RandomBiome(long i, RandomDimension dim) { 23 id = i; 24 parent = dim; 25 random = new Random(i); 26 PROVIDER = dim.PROVIDER; 27 name = "biome_" +i; 28 fullname = InfinityMod.MOD_ID + ":" + name; 29 mobs = new HashSet<>(); 30 data = new CompoundTag(); 31 data.putDouble("temperature", -1 + random.nextFloat()*3); 32 data.putBoolean("has_precipitation", PROVIDER.roll(random, "has_precipitation")); 33 data.putString("temperature_modifier", roll("temperature_modifier_frozen") ? "frozen" : "none"); 34 data.putDouble("downfall", random.nextDouble()); 35 data.put("effects", randomEffects()); 36 data.put("spawners", (new RandomMobsList(this)).asData()); 37 data.put("spawn_costs", spawnCosts()); 38 data.put("features", (new RandomFeaturesList(this)).data); 39 data.put("carvers", carvers()); 40 CommonIO.write(data, dim.getStoragePath() + "/worldgen/biome", name + ".json"); 41 } 42 43 boolean roll(String key) { 44 return PROVIDER.roll(random, key); 45 } 46 47 void rollAndPutSafe(CompoundTag res, String key, Tag randomSound) { 48 if (roll(key)) { 49 if (randomSound != null && !NbtUtils.getAsString(randomSound).isBlank()) 50 res.put(key, randomSound); 51 } 52 } 53 54 public IntTag randomColor() { 55 return IntTag.valueOf(random.nextInt(16777216)); 56 } 57 public ListTag randomDustColor() { 58 ListTag res = new ListTag(); 59 res.add(DoubleTag.valueOf(random.nextDouble())); 60 res.add(DoubleTag.valueOf(random.nextDouble())); 61 res.add(DoubleTag.valueOf(random.nextDouble())); 62 return res; 63 } 64 public ListTag randomEntityEffectColor() { 65 ListTag res = randomDustColor(); 66 res.add(DoubleTag.valueOf(random.nextDouble())); 67 return res; 68 } 69 70 private ListTag zeroBlockPos() { 71 ListTag nbtElements = new ListTag(); 72 nbtElements.add(FloatTag.valueOf(0)); 73 nbtElements.add(FloatTag.valueOf(0)); 74 nbtElements.add(FloatTag.valueOf(0)); 75 return nbtElements; 76 } 77 78 private Tag randomBlockState() { 79 return InfinityMod.provider.randomBlockProvider(new Random(), ConfigType.ALL_BLOCKS); 80 } 81 82 StringTag randomSound(){ 83 return StringTag.valueOf(PROVIDER.randomName(random, ConfigType.SOUNDS)); 84 } 85 86 CompoundTag randomEffects() { 87 CompoundTag res = new CompoundTag(); 88 res.put("fog_color", randomColor()); 89 res.put("sky_color", randomColor()); 90 res.put("water_color", randomColor()); 91 res.put("water_fog_color", randomColor()); 92 if (random.nextBoolean()) res.put("foliage_color", randomColor()); 93 if (random.nextBoolean()) res.put("grass_color", randomColor()); 94 colors = res.copy(); 95 if (random.nextBoolean()) res.put("grass_color_modifier", StringTag.valueOf(random.nextBoolean() ? "dark_forest" : "swamp")); 96 if (roll("use_particles")) res.put("particle", randomParticle()); 97 rollAndPutSafe(res, "ambient_sound", randomSound()); 98 rollAndPutSafe(res, "mood_sound", randomMoodSound()); 99 rollAndPutSafe(res, "additions_sound", randomAdditionSound()); 100 if (roll("music")) res.put("music", randomMusic()); 101 return res; 102 } 103 104 CompoundTag randomMoodSound() { 105 CompoundTag res = new CompoundTag(); 106 var sound = randomSound(); 107 if (NbtUtils.getAsString(sound).isEmpty()) { 108 return null; 109 } 110 res.put("sound", sound); 111 res.putInt("tick_delay", random.nextInt(6000)); 112 res.putInt("block_search_extent", random.nextInt(32)); 113 res.putDouble("offset", random.nextDouble()*8); 114 return res; 115 } 116 117 CompoundTag randomAdditionSound(){ 118 CompoundTag res = new CompoundTag(); 119 var sound = randomSound(); 120 if (NbtUtils.getAsString(sound).isEmpty()) { 121 return null; 122 } 123 res.put("sound", sound); 124 res.putDouble("tick_chance", random.nextExponential()*0.01); 125 return res; 126 } 127 128 Tag randomMusic(){ 129 CompoundTag data = new CompoundTag(); 130 data.put("sound", StringTag.valueOf(PROVIDER.randomName(random, ConfigType.MUSIC))); 131 int a = random.nextInt(0, 12000); 132 int b = random.nextInt(0, 24000); 133 data.putInt("min_delay", Math.min(a,b)); 134 data.putInt("max_delay", Math.max(a,b)); 135 data.putBoolean("replace_current_music", random.nextBoolean()); 136 // todo - multiple music entries per biome? 137 //? if >1.21.6 { 138 ListTag musicList = new ListTag(); 139 CompoundTag res = new CompoundTag(); 140 res.putInt("weight", 1); 141 res.put("data", data); 142 musicList.add(res); 143 return musicList; 144 //?} else { 145 /*return data; 146 *///?} 147 } 148 149 CompoundTag randomParticle(){ 150 CompoundTag res = new CompoundTag(); 151 res.putFloat("probability", (float)(random.nextExponential()*0.01)); 152 res.put("options", particleOptions()); 153 return res; 154 } 155 156 float randomDustScale() { 157 return random.nextBoolean() ? random.nextFloat() * 0.99f + 0.01f : random.nextFloat() * 3f + 1f; 158 } 159 160 CompoundTag particleOptions() { 161 CompoundTag res = new CompoundTag(); 162 String particle = PROVIDER.randomName(random, ConfigType.PARTICLES); 163 res.putString("type", particle); 164 switch(particle) { 165 case "minecraft:block", "minecraft:block_marker", "minecraft:dust_pillar", "minecraft:falling_dust" -> { 166 CompoundTag value = new CompoundTag(); 167 value.putString("Name", PROVIDER.randomName(random, ConfigType.ALL_BLOCKS)); 168 res.put("block_state", value); 169 return res; 170 } 171 case "minecraft:item" -> { 172 CompoundTag value = new CompoundTag(); 173 value.putString("id", PROVIDER.randomName(random, ConfigType.ITEMS)); 174 res.put("item", value); 175 return res; 176 } 177 case "minecraft:dust" -> { 178 res.put("color", randomDustColor()); 179 res.putFloat("scale", randomDustScale()); 180 return res; 181 } 182 case "minecraft:dust_color_transition" -> { 183 res.put("from_color", randomDustColor()); 184 res.put("to_color", randomDustColor()); 185 res.putFloat("scale", randomDustScale()); 186 return res; 187 } 188 case "minecraft:entity_effect" -> { 189 res.put("color", randomEntityEffectColor()); 190 return res; 191 } 192 case "minecraft:sculk_charge" -> { 193 res.putFloat("roll", (float)(random.nextFloat()*Math.PI)); 194 return res; 195 } 196 case "minecraft:shriek" -> { 197 res.putInt("delay", random.nextInt(500)); 198 return res; 199 } 200 case "minecraft:vibration" -> { 201 CompoundTag destination = new CompoundTag(); 202 destination.putString("type", "block"); 203 ListTag pos = new ListTag(); 204 for (int ii = 0; ii < 3; ii+=1) pos.add(IntTag.valueOf(random.nextInt(20000))); 205 destination.put("pos", pos); 206 res.put("destination", destination); 207 res.putInt("arrival_in_ticks", random.nextInt(20000)); 208 return res; 209 } 210 //? if >1.21.4 { 211 case "minecraft:trail" -> { 212 res.put("color", randomColor()); 213 res.put("target", zeroBlockPos()); 214 res.putInt("duration", random.nextInt(500)); 215 return res; 216 } 217 case "minecraft:block_crumble" -> { 218 res.put("block_state", randomBlockState()); 219 return res; 220 } 221 case "minecraft:tinted_leaves" -> { 222 res.put("color", randomColor()); 223 return res; 224 } 225 //?} 226 } 227 return res; 228 } 229 230 CompoundTag addMob(String category, boolean add) { 231 CompoundTag mob = new CompoundTag(); 232 String mobname = PROVIDER.randomName(random, ConfigType.byName(category)); 233 mob.putString("type", mobname); 234 if (add) mobs.add(mobname); 235 mob.putInt("weight", 1 + random.nextInt(20)); 236 int a = 1 + random.nextInt(6); 237 int b = 1 + random.nextInt(6); 238 mob.putInt("minCount", Math.min(a, b)); 239 mob.putInt("maxCount", Math.max(a, b)); 240 return mob; 241 } 242 243 CompoundTag spawnCosts() { 244 CompoundTag res = new CompoundTag(); 245 for (String mob: mobs) { 246 CompoundTag mobData = new CompoundTag(); 247 mobData.putDouble("energy_budget", random.nextDouble()*0.6); 248 mobData.putDouble("charge", 0.5 + random.nextDouble()*0.4); 249 res.put(mob, mobData); 250 } 251 return res; 252 } 253 254 //? if <1.21.5 { 255 /*CompoundTag carvers() { 256 CompoundTag res = new CompoundTag(); 257 ListTag air = new ListTag(); 258 if (PROVIDER.roll(random, "use_random_cave")) air.add(StringTag.valueOf((new RandomCarver(this, true)).fullname)); 259 if (PROVIDER.roll(random, "use_random_canyon")) air.add(StringTag.valueOf((new RandomCarver(this, false)).fullname)); 260 PROVIDER.registry.get(ConfigType.CARVERS).getAllNames(random::nextDouble).forEach(s -> air.add(StringTag.valueOf(s))); 261 res.put("air", air); 262 return res; 263 } 264 *///?} else { 265 ListTag carvers() { 266 ListTag air = new ListTag(); 267 if (PROVIDER.roll(random, "use_random_cave")) air.add(StringTag.valueOf((new RandomCarver(this, true)).fullname)); 268 if (PROVIDER.roll(random, "use_random_canyon")) air.add(StringTag.valueOf((new RandomCarver(this, false)).fullname)); 269 PROVIDER.registry.get(ConfigType.CARVERS).getAllNames(random::nextDouble).forEach(s -> air.add(StringTag.valueOf(s))); 270 return air; 271 } 272 //?} 273 274}