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