Inspired by 2020's April Fools' 20w14infinite Snapshot, this mod brings endless randomly generated dimensions into Minecraft.
1package net.lerariemann.infinity.compat;
2
3//? if <1.21.2 {
4/*import com.simibubi.create.api.contraption.train.PortalTrackProvider;
5import com.simibubi.create.content.trains.track.AllPortalTracks;
6import com.simibubi.create.content.trains.track.TrackBlock;
7import com.simibubi.create.content.trains.track.TrackShape;
8import net.createmod.catnip.math.BlockFace;
9*///?} else if fabric {
10import com.zurrtum.create.api.contraption.train.PortalTrackProvider;
11import com.zurrtum.create.catnip.math.BlockFace;
12import com.zurrtum.create.content.trains.track.AllPortalTracks;
13import com.zurrtum.create.content.trains.track.TrackBlock;
14import com.zurrtum.create.content.trains.track.TrackShape;
15//?}
16//? if <1.21.2 || fabric {
17import net.lerariemann.infinity.block.custom.RailHelper;
18import net.lerariemann.infinity.block.entity.InfinityPortalBlockEntity;
19import net.lerariemann.infinity.registry.core.ModBlocks;
20import net.lerariemann.infinity.util.InfinityMethods;
21import net.minecraft.core.BlockPos;
22import net.minecraft.core.Direction;
23import net.minecraft.core.registries.BuiltInRegistries;
24import net.minecraft.server.MinecraftServer;
25import net.minecraft.server.level.ServerLevel;
26import net.minecraft.world.level.Level;
27import net.minecraft.world.level.block.Block;
28import net.minecraft.world.level.block.Blocks;
29import net.minecraft.world.level.block.NetherPortalBlock;
30import net.minecraft.world.level.block.state.BlockState;
31import net.minecraft.world.level.block.state.properties.BlockStateProperties;
32
33import java.util.Optional;
34import java.util.Set;
35//?}
36
37public class CreateCompat {
38 //? if <1.21.2 || fabric {
39 private static PortalTrackProvider.Exit infinityPortalProvider(ServerLevel worldFrom, BlockFace blockFace) {
40 MinecraftServer server = worldFrom.getServer();
41 //? if <1.21
42 /*if (!server.isNetherEnabled()) return null;*/
43 //? if >1.21.9 {
44 /*server.getGameRules().getRule(GameRules.RULE_ALLOW_NETHER);
45 *///?}
46 BlockPos posFrom = blockFace.getConnectedPos();
47 if (worldFrom.getBlockEntity(posFrom) instanceof InfinityPortalBlockEntity ipbe
48 && ipbe.isConnectedBothSides()) { //we only allow trains through if portals are in sync
49 ServerLevel worldTo = ipbe.getDimensionAsWorld();
50 BlockPos posTo = ipbe.getOtherSidePos();
51 assert worldTo != null;
52 assert posTo != null;
53
54 BlockPos correctedPos = getCorrectedPos(worldFrom, posFrom, worldTo, posTo);
55
56 Direction targetDirection = blockFace.getFace();
57 Direction.Axis axisTo = worldTo.getBlockState(posTo).getValue(BlockStateProperties.HORIZONTAL_AXIS);
58 if (targetDirection.getAxis().equals(axisTo)) {
59 targetDirection = targetDirection.getClockWise();
60 }
61 return new PortalTrackProvider.Exit(worldTo, new BlockFace(correctedPos.relative(targetDirection), targetDirection.getOpposite()));
62 }
63 return null;
64 }
65
66 public static BlockPos getCorrectedPos(ServerLevel worldFrom, BlockPos posFrom, ServerLevel worldTo, BlockPos posTo) {
67 Direction.Axis axisFrom = worldFrom.getBlockState(posFrom).getValue(BlockStateProperties.HORIZONTAL_AXIS);
68 boolean fromX = axisFrom.equals(Direction.Axis.X);
69
70 BlockPos maxHere = getBound(worldFrom, posFrom, axisFrom, true);
71 int max_here = fromX ? maxHere.getX() : maxHere.getZ();
72 BlockPos minHere = getBound(worldFrom, posFrom, axisFrom, false);
73 int min_here = fromX ? minHere.getX() : minHere.getZ();
74
75 Direction.Axis axisTo = worldTo.getBlockState(posTo).getValue(BlockStateProperties.HORIZONTAL_AXIS);
76 boolean toX = axisTo.equals(Direction.Axis.X);
77
78 BlockPos maxThere = getBound(worldTo, posTo, axisTo, true);
79 int max_there = toX ? maxThere.getX() : maxThere.getZ();
80 BlockPos minThere = getBound(worldTo, posTo, axisTo, false);
81 int min_there = toX ? minThere.getX() : minThere.getZ();
82
83 int here = fromX ? posFrom.getX() : posFrom.getZ();
84 int there;
85 if (max_there - min_there == max_here - min_here) {
86 there = min_there + (here - min_here);
87 }
88 there = min_there + (int)((here - min_here)*(max_there-min_there)/(float)(max_here-min_here)); //might not be super good but feels decent
89
90 return new BlockPos(toX ? there : posTo.getX(), posTo.getY(), toX ? posTo.getZ() : there);
91 }
92
93 public static BlockPos getBound(ServerLevel world, BlockPos pos, Direction.Axis axis, boolean positive) {
94 BlockPos bp = pos;
95 int i = positive ? 1 : -1;
96 while (world.getBlockState(bp).getBlock() instanceof NetherPortalBlock) {
97 bp = bp.relative(axis, i);
98 }
99 return bp.relative(axis, -i);
100 }
101
102 public static void register() {
103 AllPortalTracks.tryRegisterIntegration(InfinityMethods.getId("neither_portal"), CreateCompat::infinityPortalProvider);
104 }
105
106 public static void tryModifyRails(InfinityPortalBlockEntity ipbe) {
107 Level w = ipbe.getLevel();
108 if (w instanceof ServerLevel worldFrom) {
109 BlockPos posFrom = ipbe.getBlockPos();
110 BlockState state = worldFrom.getBlockState(posFrom);
111 if (!state.is(ModBlocks.PORTAL.get())) return;
112 Set<Direction> toCheck = state.getValue(BlockStateProperties.HORIZONTAL_AXIS).equals(Direction.Axis.X) ?
113 Set.of(Direction.NORTH, Direction.SOUTH) : Set.of(Direction.EAST, Direction.WEST);
114 for (Direction dir : toCheck) {
115 BlockPos posTrack = posFrom.relative(dir);
116 BlockState bs = worldFrom.getBlockState(posTrack);
117 if (bs.getBlock() instanceof TrackBlock)
118 modifyRails(ipbe, worldFrom, posTrack, bs);
119 }
120 }
121 }
122
123 public static void modifyRails(InfinityPortalBlockEntity ipbe, ServerLevel worldFrom,
124 BlockPos posTrack, BlockState bs) {
125 if (ipbe.isConnectedBothSides()) {
126 if (!bs.hasProperty(TrackBlock.SHAPE)) return;
127 worldFrom.setBlockAndUpdate(posTrack, ModBlocks.RAIL_HELPER.get().defaultBlockState());
128 RailHelper.RHBEntity e = RailHelper.getBlockEntity(worldFrom, posTrack);
129 e.trackBlock = BuiltInRegistries.BLOCK.getKey(bs.getBlock());
130 e.shape = switch (bs.getValue(TrackBlock.SHAPE)) {
131 case TN, TS -> "zo";
132 default -> "xo";
133 };
134 }
135 worldFrom.setBlockAndUpdate(posTrack, Blocks.AIR.defaultBlockState());
136 }
137 public static void reattachRails(ServerLevel world, BlockPos pos, RailHelper.RHBEntity e) {
138 BlockState bs;
139 Optional<Block> b = BuiltInRegistries.BLOCK.getOptional(e.trackBlock);
140 if (b.isEmpty() || !(b.get() instanceof TrackBlock)) bs = Blocks.AIR.defaultBlockState();
141 else bs = b.get().defaultBlockState().setValue(TrackBlock.SHAPE, e.shape.equals("zo") ? TrackShape.ZO : TrackShape.XO);
142 world.setBlockAndUpdate(pos, bs);
143 }
144 //?}
145}