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

nether portals no longer overwritten

Lera 86433741 6d89ccd7

+21 -68
+5 -29
common/src/main/java/net/lerariemann/infinity/block/custom/InfinityPortalBlock.java
··· 229 229 public static void tryUpdateOpenStatus(InfinityPortalBlockEntity npbe, ServerWorld worldFrom, 230 230 ServerWorld worldTo, BlockPos pos) { 231 231 if (!npbe.isOpen() ^ worldTo == null) { 232 - PortalCreationLogic.modifyPortalRecursive(worldFrom, pos, 233 - new PortalCreationLogic.PortalModifier(e -> e.setOpen(!npbe.isOpen()))); 232 + PortalCreationLogic.modifyPortalRecursive(worldFrom, pos, e -> e.setOpen(!npbe.isOpen())); 234 233 } 235 234 } 236 235 ··· 336 335 } 337 336 338 337 /** 339 - * Filter for portal blocks except infinity portals of other destinations. 340 - */ 341 - public static boolean isValidDestinationWeak(ServerWorld worldFrom, ServerWorld worldTo, BlockPos posTo) { 342 - if (posTo == null || !InfinityMethods.dimExists(worldTo)) return false; 343 - return (worldTo.getBlockState(posTo).isOf(Blocks.NETHER_PORTAL)) 344 - || (worldTo.getBlockEntity(posTo) instanceof InfinityPortalBlockEntity ipbe 345 - && ipbe.getDimension().toString().equals(worldFrom.getRegistryKey().getValue().toString())); 346 - } 347 - 348 - /** 349 338 * Filter for infinity portals of the correct destination. 350 339 */ 351 340 public static boolean isValidDestinationStrong(ServerWorld worldFrom, ServerWorld worldTo, BlockPos posTo) { ··· 413 402 PointOfInterestStorage poiStorage = worldTo.getPointOfInterestStorage(); 414 403 poiStorage.preloadChunks(worldTo, originOfTesting, radiusOfTesting); 415 404 416 - Set<BlockPos> allPortalsInRange = poiStorage.getInSquare(poiType -> 405 + return poiStorage.getInSquare(poiType -> 417 406 poiType.matchesKey(PointOfInterestTypes.NETHER_PORTAL) || poiType.matchesKey(ModPoi.NEITHER_PORTAL_KEY), 418 407 originOfTesting, radiusOfTesting, PointOfInterestStorage.OccupationStatus.ANY) 419 408 .map(PointOfInterest::getPos) 420 409 .filter(wbTo::contains) 421 - .collect(Collectors.toSet()); 422 - 423 - Set<BlockPos> matchingPortalsInRange = allPortalsInRange 424 - .stream() 425 410 .filter(pos -> isValidDestinationStrong(worldFrom, worldTo, pos)) 426 - .collect(Collectors.toSet()); //try a stronger selector first (only infinity portals of matching dimension) 427 - 428 - if (matchingPortalsInRange.isEmpty()) 429 - matchingPortalsInRange = allPortalsInRange 430 - .stream() 431 - .filter(pos -> isValidDestinationWeak(worldFrom, worldTo, pos)) 432 - .collect(Collectors.toSet()); //try a weaker selector (which also accepts nether portals) 433 - 434 - return matchingPortalsInRange.stream() 435 411 .min(Comparator.comparingDouble(posTo -> posTo.getSquaredDistance(originOfTesting))); 436 412 } 437 413 ··· 446 422 if (ipbe.isConnectedBothSides()) return; //don't resync what's already synced 447 423 } 448 424 else { 449 - otherSideModifier = PortalCreationLogic.forInitialSetupping(worldTo, posTo, idFrom, true); //make it an infinity portal while you're at it 425 + otherSideModifier = PortalCreationLogic.forInitialSetupping(worldTo, posTo, idFrom, true); 426 + //make it an infinity portal while you're at it 450 427 } 451 428 452 429 otherSideModifier.addModifier(ipbe1 -> ipbe1.setBlockPos(posFrom)); 453 - PortalCreationLogic.modifyPortalRecursive(worldFrom, posFrom, 454 - new PortalCreationLogic.PortalModifier(ipbe -> ipbe.setBlockPos(posTo))); 430 + PortalCreationLogic.modifyPortalRecursive(worldFrom, posFrom, ipbe -> ipbe.setBlockPos(posTo)); 455 431 PortalCreationLogic.modifyPortalRecursive(worldTo, posTo, otherSideModifier); 456 432 } 457 433 }
+1
common/src/main/java/net/lerariemann/infinity/mixin/NetherPortalBlockMixin.java
··· 54 54 return (neighborState.getBlock() instanceof NetherPortalBlock); 55 55 } 56 56 57 + /* This makes sure that newly portals in infdims become infinity portals. */ 57 58 @Override 58 59 protected void injected_onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean notify, CallbackInfo ci) { 59 60 if (state.isOf(Blocks.NETHER_PORTAL) &&
-24
common/src/main/java/net/lerariemann/infinity/mixin/ServerPlayerEntityMixin.java
··· 1 1 package net.lerariemann.infinity.mixin; 2 2 3 - import com.llamalad7.mixinextras.sugar.Local; 4 3 import com.mojang.authlib.GameProfile; 5 - import net.lerariemann.infinity.InfinityMod; 6 4 import net.lerariemann.infinity.access.Timebombable; 7 5 import net.lerariemann.infinity.access.ServerPlayerEntityAccess; 8 6 import net.lerariemann.infinity.options.InfinityOptions; 9 7 import net.lerariemann.infinity.util.InfinityMethods; 10 - import net.lerariemann.infinity.util.PortalCreationLogic; 11 8 import net.lerariemann.infinity.util.WarpLogic; 12 9 import net.lerariemann.infinity.var.ModPayloads; 13 - import net.minecraft.block.Blocks; 14 10 import net.minecraft.entity.Entity; 15 11 import net.minecraft.entity.damage.DamageSource; 16 12 import net.minecraft.entity.player.PlayerEntity; 17 13 import net.minecraft.network.packet.s2c.play.PositionFlag; 18 - import net.minecraft.registry.RegistryKey; 19 14 import net.minecraft.server.network.ServerPlayerEntity; 20 15 import net.minecraft.server.world.ServerWorld; 21 16 import net.minecraft.util.Identifier; ··· 57 52 @Inject(method="findRespawnPosition", at = @At("HEAD"), cancellable = true) 58 53 private static void injected(ServerWorld world, BlockPos pos, float angle, boolean forced, boolean alive, CallbackInfoReturnable<Optional<Vec3d>> cir) { 59 54 if (((Timebombable)world).infinity$isTimebombed()) cir.setReturnValue(Optional.empty()); 60 - } 61 - 62 - /* When the player is using the Infinity portal, this modifies the portal on the other side if needed. */ 63 - @Inject(method = "teleportTo", 64 - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;setServerWorld(Lnet/minecraft/server/world/ServerWorld;)V") 65 - ) 66 - private void injected2(TeleportTarget teleportTarget, CallbackInfoReturnable<Entity> cir, @Local(ordinal = 0) ServerWorld serverWorld, @Local RegistryKey<World> registryKey) { 67 - if (InfinityMod.provider.rule("returnPortalsEnabled") && 68 - (registryKey.getValue().getNamespace().equals(InfinityMod.MOD_ID))) { 69 - BlockPos pos = BlockPos.ofFloored(teleportTarget.pos()); 70 - ServerWorld destination = teleportTarget.world(); 71 - for (BlockPos pos2: new BlockPos[] {pos, pos.add(1, 0, 0), pos.add(0, 0, 1), 72 - pos.add(-1, 0, 0), pos.add(0, 0, -1)}) if (destination.getBlockState(pos2).isOf(Blocks.NETHER_PORTAL)) { 73 - Identifier dimensionName = registryKey.getValue(); 74 - 75 - PortalCreationLogic.modifyPortalRecursive(destination, pos2, dimensionName, true); 76 - break; 77 - } 78 - } 79 55 } 80 56 81 57 @Inject(method = "teleportTo",
+14 -10
common/src/main/java/net/lerariemann/infinity/util/PortalCreationLogic.java
··· 173 173 } 174 174 175 175 /* Set the portal's open status making it usable. */ 176 - modifyPortalRecursive(world, pos, new PortalModifierUnion() 177 - .addModifier(be -> be.setOpen(true)) 178 - .addModifier(BlockEntity::markDirty)); 176 + modifyPortalRecursive(world, pos, be -> { 177 + be.setOpen(true); 178 + be.markDirty(); 179 + }); 179 180 runAfterEffects(world, pos, bl, true); 180 181 } 181 182 return bl; 182 183 } 183 184 184 185 /** 186 + * Updates this and all neighbouring portal blocks with a new dimension and open status. 187 + */ 188 + static void modifyPortalRecursive(ServerWorld world, BlockPos pos, Identifier id, boolean open) { 189 + modifyPortalRecursive(world, pos, forInitialSetupping(world, pos, id, open)); 190 + } 191 + 192 + /** 185 193 * Recursively creates a queue of neighbouring portal blocks and for each of them executes an action. 186 194 */ 195 + static void modifyPortalRecursive(ServerWorld world, BlockPos pos, Consumer<InfinityPortalBlockEntity> consumer) { 196 + modifyPortalRecursive(world, pos, new PortalModifier(consumer)); 197 + } 187 198 static void modifyPortalRecursive(ServerWorld world, BlockPos pos, BiConsumer<World, BlockPos> modifier) { 188 199 Set<BlockPos> set = Sets.newHashSet(); 189 200 Queue<BlockPos> queue = Queues.newArrayDeque(); ··· 225 236 .addModifier(npbe -> npbe.setColor(applier.apply(npbe.getPos()))) 226 237 .addModifier(npbe -> npbe.setOpen(open)) 227 238 .addModifier(BlockEntity::markDirty); 228 - } 229 - 230 - /** 231 - * Updates this and all neighbouring portal blocks with a new dimension and open status. 232 - */ 233 - static void modifyPortalRecursive(ServerWorld world, BlockPos pos, Identifier id, boolean open) { 234 - modifyPortalRecursive(world, pos, forInitialSetupping(world, pos, id, open)); 235 239 } 236 240 237 241 /**
+1 -3
common/src/main/resources/assets/infinity/lang/en_us.json
··· 132 132 "config.infinity.gameRules.iridescenceInitialDuration.description": "How long it takes for the visual aspects of the iridescent effect to start, in minutes. Set to 0 to start them immediately.", 133 133 "config.infinity.gameRules.iridescenceCooldownDuration": "Iridescence - cooldown duration", 134 134 "config.infinity.gameRules.iridescenceCooldownDuration.description": "Duration of the iridescent cooldown effect in minutes. The full cooldown is twice this, the second half limiting the player to level I of the effect. Set to 0 to disable the cooldown.", 135 - "config.infinity.gameRules.returnPortalsEnabled": "Enable Return Portals", 136 - "config.infinity.gameRules.returnPortalsEnabled.description": "If enabled, every time you go through a portal from a custom dimension and generate a new portal, it will link back to a dimension you came from. If changed to false, all portals created this way will be normal Nether Portals.", 137 - "config.infinity.gameRules.runtimeGenerationEnabled": "Enable Runtime Generation", 135 + "config.infinity.gameRules.runtimeGenerationEnabled": "Enable Runtime Generation", 138 136 "config.infinity.gameRules.runtimeGenerationEnabled.description": "If disabled, registration of dimensions and features in runtime will no longer occur, meaning you need to quit to title and enter the world again to access dimensions after tossing the book. Included for compatibility reasons.", 139 137 "config.infinity.gameRules.chaosMobsEnabled": "Enable Chaos Mobs", 140 138 "config.infinity.gameRules.chaosMobsEnabled.description": "If disabled, this mod's Chaos Mobs will no longer spawn, both in dimensions and inside your portals.",
-1
common/src/main/resources/config/infinity.json
··· 2 2 "infinity_version": 2003008, 3 3 "gameRules": { 4 4 "runtimeGenerationEnabled": true, 5 - "returnPortalsEnabled": true, 6 5 "longArithmeticEnabled": false, 7 6 "forceSolidSurface": false, 8 7 "chaosMobsEnabled": true,
-1
docs/Configuring-the-mod.mdx
··· 13 13 14 14 ### Gamerules 15 15 * `runtimeGenerationEnabled` - setting this to false will disable registration of dimensions and features in runtime, meaning you need to quit to title and enter the world again to access dimensions after tossing the book. Included for compatibility reasons. 16 - * `returnPortalsEnabled` - leaving this as true means every time you go through a portal from a custom dimension and generate a new portal, it will link back to a dimension you came from. If changed to false, all portals created this way will be normal nether portals. 17 16 * `longArithmeticEnabled` - setting this to true will expand the range in which dimension, biome and feature IDs generate from the integer limit (~2 billion) to the long limit (~9 quintillion). You know, if for some reason 2 billion dimensions is not enough for you :D 18 17 * `forceSolidSurface` - setting this to true will disallow non-full blocks from being used as material for the surface of random biomes. 19 18 * `chaosMobsEnabled` - a toggle to enable/disable custom mobs, added in the mod, from naturally spawning.