Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.

this is pure insanity

Lera a61cacc2 6e2b1c42

+144 -70
+12
common/src/main/java/net/lerariemann/infinity/access/BlockEntityTypeAccess.java
··· 1 + package net.lerariemann.infinity.access; 2 + 3 + import net.minecraft.block.Block; 4 + import net.minecraft.block.entity.BlockEntity; 5 + import net.minecraft.block.entity.BlockEntityType; 6 + 7 + import java.util.Set; 8 + 9 + public interface BlockEntityTypeAccess<T extends BlockEntity> { 10 + BlockEntityType.BlockEntityFactory<? extends T> infinity$getFactory(); 11 + Set<Block> infinity$getBlocks(); 12 + }
+8 -3
common/src/main/java/net/lerariemann/infinity/dimensions/RandomFeaturesList.java
··· 6 6 import net.lerariemann.infinity.dimensions.features.local_modifications.RandomGeode; 7 7 import net.lerariemann.infinity.dimensions.features.local_modifications.RandomIceberg; 8 8 import net.lerariemann.infinity.dimensions.features.local_modifications.RandomRock; 9 - import net.lerariemann.infinity.dimensions.features.raw_generation.RandomBonusChest; 9 + import net.lerariemann.infinity.dimensions.features.top_layer.RandomBonusChest; 10 10 import net.lerariemann.infinity.dimensions.features.raw_generation.RandomEndIsland; 11 11 import net.lerariemann.infinity.dimensions.features.raw_generation.RandomShape; 12 12 import net.lerariemann.infinity.dimensions.features.surface_structures.*; ··· 54 54 data.add(undergroundDecoration()); 55 55 data.add(fluidSprings()); 56 56 data.add(vegetation()); 57 - data.add(getAllElements(ConfigType.TOP_LAYER)); 57 + data.add(topLayer()); 58 58 } 59 59 60 60 NbtList getAllElements(ConfigType name) { ··· 82 82 NbtList rawGeneration() { 83 83 NbtList res = new NbtList(); 84 84 addRandomFeature("end_island", res, RandomEndIsland::new); 85 - addRandomFeature("bonus_chest", res, RandomBonusChest::new); 86 85 if (roll("shape")) addRandomFeature(res, new RandomShape(this, PROVIDER.randomName(random, ConfigType.SHAPE_TYPES))); 87 86 return res; 88 87 } ··· 158 157 addRandomFeature("water_plants", res, RandomPickle::new); 159 158 addRandomFeature("water_plants", res, RandomKelp::new); 160 159 } 160 + return res; 161 + } 162 + 163 + NbtList topLayer() { 164 + NbtList res = getAllElements(ConfigType.TOP_LAYER); 165 + addRandomFeature("bonus_chest", res, RandomBonusChest::new); 161 166 return res; 162 167 } 163 168
-31
common/src/main/java/net/lerariemann/infinity/dimensions/features/raw_generation/RandomBonusChest.java
··· 1 - package net.lerariemann.infinity.dimensions.features.raw_generation; 2 - 3 - import net.lerariemann.infinity.dimensions.RandomFeaturesList; 4 - import net.lerariemann.infinity.dimensions.features.Placement; 5 - import net.lerariemann.infinity.dimensions.features.RandomisedFeature; 6 - import net.lerariemann.infinity.util.core.ConfigType; 7 - import net.minecraft.nbt.NbtCompound; 8 - import net.minecraft.nbt.NbtList; 9 - 10 - public class RandomBonusChest extends RandomisedFeature { 11 - public RandomBonusChest(RandomFeaturesList lst) { 12 - super(lst, "chest"); 13 - id = "infinity:bonus_chest"; 14 - savePlacement(); 15 - } 16 - 17 - @Override 18 - public NbtCompound feature() { 19 - NbtCompound config = new NbtCompound(); 20 - config.putString("loot", PROVIDER.randomName(random, ConfigType.LOOT_TABLES)); 21 - return feature(config); 22 - } 23 - 24 - @Override 25 - public NbtList placement() { 26 - Placement res = new Placement(); 27 - res.addCount(random.nextInt(1, 16)); 28 - res.addBiome(); 29 - return res.data; 30 - } 31 - }
+44
common/src/main/java/net/lerariemann/infinity/dimensions/features/top_layer/RandomBonusChest.java
··· 1 + package net.lerariemann.infinity.dimensions.features.top_layer; 2 + 3 + import net.lerariemann.infinity.dimensions.RandomFeaturesList; 4 + import net.lerariemann.infinity.dimensions.features.Placement; 5 + import net.lerariemann.infinity.dimensions.features.RandomisedFeature; 6 + import net.lerariemann.infinity.util.core.ConfigType; 7 + import net.lerariemann.infinity.util.core.NbtUtils; 8 + import net.minecraft.loot.LootTables; 9 + import net.minecraft.nbt.NbtCompound; 10 + import net.minecraft.nbt.NbtList; 11 + 12 + public class RandomBonusChest extends RandomisedFeature { 13 + boolean isFrequent; 14 + 15 + public RandomBonusChest(RandomFeaturesList lst) { 16 + super(lst, "chest"); 17 + id = "infinity:bonus_chest"; 18 + isFrequent = random.nextBoolean(); 19 + savePlacement(); 20 + } 21 + 22 + @Override 23 + public NbtCompound feature() { 24 + NbtCompound config = new NbtCompound(); 25 + config.putString("loot", random.nextBoolean() ? LootTables.SPAWN_BONUS_CHEST.getValue().toString() : 26 + random.nextBoolean() ? "infinity:random" : PROVIDER.randomName(random, ConfigType.LOOT_TABLES)); 27 + config.put("block", NbtUtils.nameToElement(random.nextBoolean() ? "minecraft:chest" : 28 + isFrequent ? "minecraft:barrel" : PROVIDER.randomName(random, ConfigType.CHESTS))); 29 + return feature(config); 30 + } 31 + 32 + @Override 33 + public NbtList placement() { 34 + Placement res = new Placement(); 35 + if (isFrequent) { 36 + res.addCountEveryLayer(random.nextInt(1, 8)); 37 + } else { 38 + res.addCountEveryLayer(1); 39 + res.addRarityFilter(random.nextInt(1, 8)); 40 + } 41 + res.addBiome(); 42 + return res.data; 43 + } 44 + }
+20 -27
common/src/main/java/net/lerariemann/infinity/features/RandomBonusChestFeature.java
··· 2 2 3 3 import com.mojang.serialization.Codec; 4 4 import com.mojang.serialization.codecs.RecordCodecBuilder; 5 - import it.unimi.dsi.fastutil.ints.IntArrayList; 5 + import net.lerariemann.infinity.InfinityMod; 6 + import net.lerariemann.infinity.util.core.ConfigType; 6 7 import net.minecraft.block.BlockState; 7 8 import net.minecraft.block.Blocks; 8 9 import net.minecraft.inventory.LootableInventory; 9 10 import net.minecraft.registry.RegistryKey; 10 11 import net.minecraft.registry.RegistryKeys; 11 12 import net.minecraft.util.Identifier; 12 - import net.minecraft.util.Util; 13 13 import net.minecraft.util.math.BlockPos; 14 - import net.minecraft.util.math.ChunkPos; 15 14 import net.minecraft.util.math.Direction; 16 15 import net.minecraft.util.math.random.Random; 17 - import net.minecraft.world.Heightmap; 18 16 import net.minecraft.world.StructureWorldAccess; 19 17 import net.minecraft.world.gen.feature.Feature; 20 18 import net.minecraft.world.gen.feature.FeatureConfig; 21 19 import net.minecraft.world.gen.feature.util.FeatureContext; 22 20 23 - import java.util.stream.IntStream; 21 + import java.util.Optional; 24 22 25 23 public class RandomBonusChestFeature extends Feature<RandomBonusChestFeature.Config> { 26 24 public RandomBonusChestFeature(Codec<Config> codec) { ··· 31 29 public boolean generate(FeatureContext<Config> context) { 32 30 Random random = context.getRandom(); 33 31 StructureWorldAccess structureWorldAccess = context.getWorld(); 34 - ChunkPos chunkPos = new ChunkPos(context.getOrigin()); 35 - IntArrayList intArrayList = Util.shuffle(IntStream.rangeClosed(chunkPos.getStartX(), chunkPos.getEndX()), random); 36 - IntArrayList intArrayList2 = Util.shuffle(IntStream.rangeClosed(chunkPos.getStartZ(), chunkPos.getEndZ()), random); 37 - BlockPos.Mutable mutable = new BlockPos.Mutable(); 38 32 39 - for (Integer integer : intArrayList) { 40 - for (Integer integer2 : intArrayList2) { 41 - mutable.set(integer, 0, integer2); 42 - BlockPos blockPos = structureWorldAccess.getTopPosition(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, mutable); 43 - if (structureWorldAccess.isAir(blockPos) || structureWorldAccess.getBlockState(blockPos).getCollisionShape(structureWorldAccess, blockPos).isEmpty()) { 44 - structureWorldAccess.setBlockState(blockPos, Blocks.CHEST.getDefaultState(), 2); 45 - LootableInventory.setLootTable(structureWorldAccess, random, blockPos, RegistryKey.of(RegistryKeys.LOOT_TABLE, context.getConfig().loot)); 46 - BlockState blockState = Blocks.TORCH.getDefaultState(); 33 + BlockPos blockPos = context.getOrigin(); 34 + if (structureWorldAccess.isAir(blockPos) || structureWorldAccess.getBlockState(blockPos).getCollisionShape(structureWorldAccess, blockPos).isEmpty()) { 35 + BlockState state = context.getConfig().block.orElseGet(Blocks.CHEST::getDefaultState); 36 + structureWorldAccess.setBlockState(blockPos, state, 2); 37 + Identifier id = context.getConfig().loot; 38 + if (id.toString().equals("infinity:random")) id = Identifier.of(InfinityMod.provider.randomName(context.getRandom(), ConfigType.LOOT_TABLES)); 39 + LootableInventory.setLootTable(structureWorldAccess, random, blockPos, RegistryKey.of(RegistryKeys.LOOT_TABLE, id)); 40 + BlockState blockState = Blocks.TORCH.getDefaultState(); 47 41 48 - for (Direction direction : Direction.Type.HORIZONTAL) { 49 - BlockPos blockPos2 = blockPos.offset(direction); 50 - if (blockState.canPlaceAt(structureWorldAccess, blockPos2)) { 51 - structureWorldAccess.setBlockState(blockPos2, blockState, 2); 52 - } 53 - } 54 - 55 - return true; 42 + for (Direction direction : Direction.Type.HORIZONTAL) { 43 + BlockPos blockPos2 = blockPos.offset(direction); 44 + if (blockState.canPlaceAt(structureWorldAccess, blockPos2)) { 45 + structureWorldAccess.setBlockState(blockPos2, blockState, 2); 56 46 } 57 47 } 48 + 49 + return true; 58 50 } 59 51 return false; 60 52 } 61 53 62 - public record Config(Identifier loot) implements FeatureConfig { 54 + public record Config(Identifier loot, Optional<BlockState> block) implements FeatureConfig { 63 55 public static final Codec<Config> CODEC = RecordCodecBuilder.create(instance -> instance.group( 64 - (Identifier.CODEC.fieldOf("loot")).forGetter(a -> a.loot)).apply( 56 + (Identifier.CODEC.fieldOf("loot")).forGetter(a -> a.loot), 57 + (BlockState.CODEC.optionalFieldOf("block")).forGetter(a -> a.block)).apply( 65 58 instance, Config::new)); 66 59 } 67 60 }
+28
common/src/main/java/net/lerariemann/infinity/mixin/qol/BlockEntityTypeMixin.java
··· 1 + package net.lerariemann.infinity.mixin.qol; 2 + 3 + import net.lerariemann.infinity.access.BlockEntityTypeAccess; 4 + import net.minecraft.block.Block; 5 + import net.minecraft.block.entity.BlockEntity; 6 + import net.minecraft.block.entity.BlockEntityType; 7 + import org.spongepowered.asm.mixin.Final; 8 + import org.spongepowered.asm.mixin.Mixin; 9 + import org.spongepowered.asm.mixin.Shadow; 10 + 11 + import java.util.Set; 12 + 13 + @Mixin(BlockEntityType.class) 14 + public class BlockEntityTypeMixin<T extends BlockEntity> implements BlockEntityTypeAccess<T> { 15 + @Shadow @Final private BlockEntityType.BlockEntityFactory<? extends T> factory; 16 + 17 + @Shadow @Final private Set<Block> blocks; 18 + 19 + @Override 20 + public BlockEntityType.BlockEntityFactory<? extends T> infinity$getFactory() { 21 + return factory; 22 + } 23 + 24 + @Override 25 + public Set<Block> infinity$getBlocks() { 26 + return blocks; 27 + } 28 + }
+29 -5
common/src/main/java/net/lerariemann/infinity/util/config/ConfigGenerator.java
··· 1 1 package net.lerariemann.infinity.util.config; 2 2 3 3 import net.lerariemann.infinity.InfinityMod; 4 + import net.lerariemann.infinity.access.BlockEntityTypeAccess; 4 5 import net.lerariemann.infinity.block.entity.CosmicAltarBlockEntity; 5 6 import net.lerariemann.infinity.util.core.ConfigType; 6 7 import net.lerariemann.infinity.util.var.ColorLogic; 7 8 import net.minecraft.block.Block; 8 9 import net.minecraft.block.BlockState; 9 10 import net.minecraft.block.FallingBlock; 11 + import net.minecraft.block.entity.BlockEntity; 12 + import net.minecraft.block.entity.BlockEntityType; 13 + import net.minecraft.block.entity.LootableContainerBlockEntity; 14 + import net.minecraft.block.entity.ShulkerBoxBlockEntity; 10 15 import net.minecraft.block.enums.BlockFace; 11 16 import net.minecraft.entity.EntityType; 12 17 import net.minecraft.entity.SpawnGroup; ··· 54 59 ConfigFactory.of(Registries.STATUS_EFFECT, ConfigGenerator::extractEffect).generate(ConfigType.EFFECTS); 55 60 generateSounds(); 56 61 generateBlockTags(); 62 + generateBEs(); 57 63 SurfaceRuleScanner.scan(server); 58 64 DynamicRegistryManager manager = server.getRegistryManager(); 59 65 ConfigFactory.of(manager.get(RegistryKeys.JUKEBOX_SONG)).generate(ConfigType.JUKEBOXES); ··· 66 72 67 73 static void generateSounds() { 68 74 Registry<SoundEvent> r = Registries.SOUND_EVENT; 69 - DataCollection.Logged music = new DataCollection.Logged(ConfigType.MUSIC, "music tracks"); 70 - DataCollection.Logged sounds = new DataCollection.Logged(ConfigType.SOUNDS); 75 + DataCollection music = new DataCollection.Logged(ConfigType.MUSIC, "music tracks"); 76 + DataCollection sounds = new DataCollection.Logged(ConfigType.SOUNDS); 71 77 r.getKeys().forEach(a -> { 72 78 Identifier id = a.getValue(); 73 79 if (id.toString().contains("music")) music.addIdentifier(id); ··· 78 84 } 79 85 80 86 static void generateBlockTags() { 81 - DataCollection.Logged tagMap = new DataCollection.Logged(ConfigType.TAGS, "block tags"); 87 + DataCollection tagMap = new DataCollection.Logged(ConfigType.TAGS, "block tags"); 82 88 Registries.BLOCK.streamTags().forEach(tagKey -> tagMap.addIdentifier(tagKey.id())); 83 89 tagMap.save(); 84 90 } 85 91 86 92 static Set<String> generateFluids() { 87 - DataCollection.Logged fluidMap = new DataCollection.Logged(ConfigType.FLUIDS); 93 + DataCollection fluidMap = new DataCollection.Logged(ConfigType.FLUIDS); 88 94 Registry<Fluid> r = Registries.FLUID; 89 95 Set<String> fluidBlockNames = new HashSet<>(); 90 96 r.getKeys().forEach(key -> { ··· 105 111 } 106 112 107 113 static void generateBlocks(ServerWorld serverWorld, BlockPos inAir, BlockPos onAltar, Set<String> excludedBlockNames) { 108 - DataCollection.Logged blockMap = new DataCollection.Logged(ConfigType.BLOCKS); 114 + DataCollection blockMap = new DataCollection.Logged(ConfigType.BLOCKS); 109 115 DataCollection colorPresetMap = new DataCollection(ConfigType.COLOR_PRESETS); 110 116 DataCollection flowerMap = new DataCollection(ConfigType.FLOWERS); 111 117 Registry<Block> r = Registries.BLOCK; ··· 124 130 blockMap.save(); 125 131 colorPresetMap.save(); 126 132 flowerMap.save(); 133 + } 134 + 135 + static void generateBEs() { 136 + Registry<BlockEntityType<?>> r = Registries.BLOCK_ENTITY_TYPE; 137 + DataCollection chests = new DataCollection.Logged(ConfigType.CHESTS); 138 + Set<Identifier> allBlocks = new HashSet<>(); 139 + r.getKeys().forEach(key -> { 140 + BlockEntityTypeAccess<? extends BlockEntity> bet = (BlockEntityTypeAccess<?>)(r.get(key)); 141 + assert bet != null; 142 + Set<Block> blocks = bet.infinity$getBlocks(); 143 + 144 + BlockEntity be = bet.infinity$getFactory().create(BlockPos.ORIGIN, ((Block)blocks.toArray()[0]).getDefaultState()); 145 + if (be instanceof LootableContainerBlockEntity && !(be instanceof ShulkerBoxBlockEntity)) { 146 + for (Block b : blocks) allBlocks.add(Registries.BLOCK.getId(b)); 147 + } 148 + }); 149 + allBlocks.forEach(chests::addIdentifier); 150 + chests.save(); 127 151 } 128 152 129 153 static boolean checkColorSet(String block) {
+1
common/src/main/java/net/lerariemann/infinity/util/core/ConfigType.java
··· 14 14 FULL_BLOCKS("full_blocks", "minecraft:stone"), 15 15 FULL_BLOCKS_WG("full_blocks_worldgen", "minecraft:stone"), 16 16 FLOWERS("flowers", "minecraft:poppy"), 17 + CHESTS("chests", "minecraft:chest"), 17 18 FLUIDS("fluids", "minecraft:water", NbtUtils::nameToFluid), 18 19 ITEMS("items", "minecraft:stick"), 19 20 SOUNDS("sounds", "minecraft:block.stone.step"),
+1 -4
common/src/main/resources/config/hardcoded/features/toplayermodification.json
··· 1 1 { 2 + "infinity_version": 2004006, 2 3 "elements": [ 3 4 { 4 5 "key": "minecraft:freeze_top_layer", ··· 7 8 { 8 9 "key": "minecraft:void_start_platform", 9 10 "weight": 0.5 10 - }, 11 - { 12 - "key": "infinity:bonus_chest", 13 - "weight": 0.2 14 11 } 15 12 ] 16 13 }
+1
common/src/main/resources/infinity.mixins.json
··· 47 47 "options.EntityMixin", 48 48 "options.PlayerManagerMixin", 49 49 "options.ServerWorldMixin", 50 + "qol.BlockEntityTypeMixin", 50 51 "qol.EnderDragonEntityMixin", 51 52 "qol.FireBlockMixin", 52 53 "qol.LavaFluidMixin"