mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-12 13:25:01 +01:00
3D
- Trains can now travel through Aether Portals
This commit is contained in:
parent
3bafe6fe40
commit
1439a52a37
9 changed files with 139 additions and 49 deletions
|
@ -203,6 +203,7 @@ dependencies {
|
||||||
// runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252")
|
// runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252")
|
||||||
// runtimeOnly fg.deobf("maven.modrinth:rubidium:0.5.3")
|
// runtimeOnly fg.deobf("maven.modrinth:rubidium:0.5.3")
|
||||||
// implementation fg.deobf("com.railwayteam.railways:railways-1.18.2-1.1.1:all") { transitive = false }
|
// implementation fg.deobf("com.railwayteam.railways:railways-1.18.2-1.1.1:all") { transitive = false }
|
||||||
|
// runtimeOnly fg.deobf("maven.modrinth:aether:1.19.2-1.0.0-beta.1.1-forge")
|
||||||
|
|
||||||
// https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497
|
// https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497
|
||||||
// Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings
|
// Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings
|
||||||
|
|
|
@ -27,7 +27,7 @@ flywheel_version = 0.6.10-20
|
||||||
jei_minecraft_version = 1.19.2
|
jei_minecraft_version = 1.19.2
|
||||||
jei_version = 11.2.0.254
|
jei_version = 11.2.0.254
|
||||||
curios_minecraft_version = 1.19.2
|
curios_minecraft_version = 1.19.2
|
||||||
curios_version = 5.1.1.0
|
curios_version = 5.1.4.1
|
||||||
|
|
||||||
cc_tweaked_enable = true
|
cc_tweaked_enable = true
|
||||||
cc_tweaked_minecraft_version = 1.19.2
|
cc_tweaked_minecraft_version = 1.19.2
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.19.2 2023-05-24T18:02:06.5252419 Create's lang merger
|
// 1.19.2 2023-09-20T14:31:50.8818458 Create's lang merger
|
||||||
12da996b104ab0e5ce956c963fbdae7e59e72f79 assets/create/lang/en_us.json
|
532d323119782de6b62f1fe52672941cc9209a40 assets/create/lang/en_us.json
|
||||||
|
|
|
@ -868,7 +868,7 @@
|
||||||
"advancement.create.train_whistle": "Choo Choo!",
|
"advancement.create.train_whistle": "Choo Choo!",
|
||||||
"advancement.create.train_whistle.desc": "Assemble a Steam Whistle to your Train and activate it while driving",
|
"advancement.create.train_whistle.desc": "Assemble a Steam Whistle to your Train and activate it while driving",
|
||||||
"advancement.create.train_portal": "Dimensional Commuter",
|
"advancement.create.train_portal": "Dimensional Commuter",
|
||||||
"advancement.create.train_portal.desc": "Ride a Train through a Nether portal",
|
"advancement.create.train_portal.desc": "Ride a Train through a portal",
|
||||||
"advancement.create.track_crafting_factory": "Track Factory",
|
"advancement.create.track_crafting_factory": "Track Factory",
|
||||||
"advancement.create.track_crafting_factory.desc": "Produce more than 1000 Train Tracks with the same Mechanical Press",
|
"advancement.create.track_crafting_factory.desc": "Produce more than 1000 Train Tracks with the same Mechanical Press",
|
||||||
"advancement.create.long_train": "Ambitious Endeavours",
|
"advancement.create.long_train": "Ambitious Endeavours",
|
||||||
|
|
|
@ -23,6 +23,7 @@ import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler;
|
||||||
import com.simibubi.create.content.schematics.ServerSchematicLoader;
|
import com.simibubi.create.content.schematics.ServerSchematicLoader;
|
||||||
import com.simibubi.create.content.trains.GlobalRailwayManager;
|
import com.simibubi.create.content.trains.GlobalRailwayManager;
|
||||||
import com.simibubi.create.content.trains.bogey.BogeySizes;
|
import com.simibubi.create.content.trains.bogey.BogeySizes;
|
||||||
|
import com.simibubi.create.content.trains.track.AllPortalTracks;
|
||||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||||
import com.simibubi.create.foundation.advancement.AllTriggers;
|
import com.simibubi.create.foundation.advancement.AllTriggers;
|
||||||
import com.simibubi.create.foundation.block.CopperRegistries;
|
import com.simibubi.create.foundation.block.CopperRegistries;
|
||||||
|
@ -134,6 +135,7 @@ public class Create {
|
||||||
// FIXME: some of these registrations are not thread-safe
|
// FIXME: some of these registrations are not thread-safe
|
||||||
AllMovementBehaviours.registerDefaults();
|
AllMovementBehaviours.registerDefaults();
|
||||||
AllInteractionBehaviours.registerDefaults();
|
AllInteractionBehaviours.registerDefaults();
|
||||||
|
AllPortalTracks.registerDefaults();
|
||||||
AllDisplayBehaviours.registerDefaults();
|
AllDisplayBehaviours.registerDefaults();
|
||||||
ContraptionMovementSetting.registerDefaults();
|
ContraptionMovementSetting.registerDefaults();
|
||||||
AllArmInteractionPointTypes.register();
|
AllArmInteractionPointTypes.register();
|
||||||
|
|
|
@ -295,9 +295,12 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
|
||||||
return PushReaction.IGNORE;
|
return PushReaction.IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPortalEntrancePos() {
|
||||||
|
portalEntrancePos = blockPosition();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PortalInfo findDimensionEntryPoint(ServerLevel pDestination) {
|
public PortalInfo findDimensionEntryPoint(ServerLevel pDestination) {
|
||||||
portalEntrancePos = blockPosition();
|
|
||||||
return super.findDimensionEntryPoint(pDestination);
|
return super.findDimensionEntryPoint(pDestination);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
package com.simibubi.create.content.trains.track;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.glue.SuperGlueEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.AttachedRegistry;
|
||||||
|
import com.simibubi.create.foundation.utility.BlockFace;
|
||||||
|
import com.simibubi.create.foundation.utility.Pair;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.world.level.portal.PortalInfo;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraftforge.common.util.ITeleporter;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
|
public class AllPortalTracks {
|
||||||
|
|
||||||
|
// Portals must be entered from the side and must lead to a different dimension
|
||||||
|
// than the one entered from
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface PortalTrackProvider extends UnaryOperator<Pair<ServerLevel, BlockFace>> {
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final AttachedRegistry<Block, PortalTrackProvider> PORTAL_BEHAVIOURS =
|
||||||
|
new AttachedRegistry<>(ForgeRegistries.BLOCKS);
|
||||||
|
|
||||||
|
public static void registerIntegration(ResourceLocation block, PortalTrackProvider provider) {
|
||||||
|
PORTAL_BEHAVIOURS.register(block, provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerIntegration(Block block, PortalTrackProvider provider) {
|
||||||
|
PORTAL_BEHAVIOURS.register(block, provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSupportedPortal(BlockState state) {
|
||||||
|
return PORTAL_BEHAVIOURS.get(state.getBlock()) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<ServerLevel, BlockFace> getOtherSide(ServerLevel level, BlockFace inboundTrack) {
|
||||||
|
BlockPos portalPos = inboundTrack.getConnectedPos();
|
||||||
|
BlockState portalState = level.getBlockState(portalPos);
|
||||||
|
PortalTrackProvider provider = PORTAL_BEHAVIOURS.get(portalState.getBlock());
|
||||||
|
return provider == null ? null : provider.apply(Pair.of(level, inboundTrack));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builtin handlers
|
||||||
|
|
||||||
|
public static void registerDefaults() {
|
||||||
|
registerIntegration(Blocks.NETHER_PORTAL, AllPortalTracks::nether);
|
||||||
|
registerIntegration(new ResourceLocation("aether", "aether_portal"), AllPortalTracks::aether);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pair<ServerLevel, BlockFace> nether(Pair<ServerLevel, BlockFace> inbound) {
|
||||||
|
return standardPortalProvider(inbound, Level.OVERWORLD, Level.NETHER, ServerLevel::getPortalForcer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pair<ServerLevel, BlockFace> aether(Pair<ServerLevel, BlockFace> inbound) {
|
||||||
|
ResourceKey<Level> aetherLevelKey =
|
||||||
|
ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation("aether", "the_aether"));
|
||||||
|
return standardPortalProvider(inbound, Level.OVERWORLD, aetherLevelKey, level -> {
|
||||||
|
try {
|
||||||
|
return (ITeleporter) Class.forName("com.aetherteam.aether.block.portal.AetherPortalForcer")
|
||||||
|
.getDeclaredConstructor(ServerLevel.class, boolean.class)
|
||||||
|
.newInstance(level, true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return level.getPortalForcer();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<ServerLevel, BlockFace> standardPortalProvider(Pair<ServerLevel, BlockFace> inbound,
|
||||||
|
ResourceKey<Level> firstDimension, ResourceKey<Level> secondDimension,
|
||||||
|
Function<ServerLevel, ITeleporter> customPortalForcer) {
|
||||||
|
ServerLevel level = inbound.getFirst();
|
||||||
|
ResourceKey<Level> resourcekey = level.dimension() == secondDimension ? firstDimension : secondDimension;
|
||||||
|
MinecraftServer minecraftserver = level.getServer();
|
||||||
|
ServerLevel otherLevel = minecraftserver.getLevel(resourcekey);
|
||||||
|
|
||||||
|
if (otherLevel == null || !minecraftserver.isNetherEnabled())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
BlockFace inboundTrack = inbound.getSecond();
|
||||||
|
BlockPos portalPos = inboundTrack.getConnectedPos();
|
||||||
|
BlockState portalState = level.getBlockState(portalPos);
|
||||||
|
ITeleporter teleporter = customPortalForcer.apply(otherLevel);
|
||||||
|
|
||||||
|
SuperGlueEntity probe = new SuperGlueEntity(level, new AABB(portalPos));
|
||||||
|
probe.setYRot(inboundTrack.getFace()
|
||||||
|
.toYRot());
|
||||||
|
probe.setPortalEntrancePos();
|
||||||
|
|
||||||
|
PortalInfo portalinfo = teleporter.getPortalInfo(probe, otherLevel, probe::findDimensionEntryPoint);
|
||||||
|
if (portalinfo == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
BlockPos otherPortalPos = new BlockPos(portalinfo.pos);
|
||||||
|
BlockState otherPortalState = otherLevel.getBlockState(otherPortalPos);
|
||||||
|
if (otherPortalState.getBlock() != portalState.getBlock())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Direction targetDirection = inboundTrack.getFace();
|
||||||
|
if (targetDirection.getAxis() == otherPortalState.getValue(BlockStateProperties.HORIZONTAL_AXIS))
|
||||||
|
targetDirection = targetDirection.getClockWise();
|
||||||
|
BlockPos otherPos = otherPortalPos.relative(targetDirection);
|
||||||
|
return Pair.of(otherLevel, new BlockFace(otherPos, targetDirection.getOpposite()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -30,7 +30,6 @@ import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllPartialModels;
|
import com.simibubi.create.AllPartialModels;
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
import com.simibubi.create.AllTags;
|
import com.simibubi.create.AllTags;
|
||||||
import com.simibubi.create.content.contraptions.glue.SuperGlueEntity;
|
|
||||||
import com.simibubi.create.content.decoration.girder.GirderBlock;
|
import com.simibubi.create.content.decoration.girder.GirderBlock;
|
||||||
import com.simibubi.create.content.equipment.wrench.IWrenchable;
|
import com.simibubi.create.content.equipment.wrench.IWrenchable;
|
||||||
import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement;
|
import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement;
|
||||||
|
@ -63,7 +62,6 @@ import net.minecraft.core.Direction.Axis;
|
||||||
import net.minecraft.core.Direction.AxisDirection;
|
import net.minecraft.core.Direction.AxisDirection;
|
||||||
import net.minecraft.network.chat.MutableComponent;
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.util.RandomSource;
|
import net.minecraft.util.RandomSource;
|
||||||
|
@ -82,7 +80,6 @@ import net.minecraft.world.level.LevelReader;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.Mirror;
|
import net.minecraft.world.level.block.Mirror;
|
||||||
import net.minecraft.world.level.block.NetherPortalBlock;
|
|
||||||
import net.minecraft.world.level.block.Rotation;
|
import net.minecraft.world.level.block.Rotation;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
@ -95,9 +92,6 @@ import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import net.minecraft.world.level.material.PushReaction;
|
import net.minecraft.world.level.material.PushReaction;
|
||||||
import net.minecraft.world.level.pathfinder.BlockPathTypes;
|
import net.minecraft.world.level.pathfinder.BlockPathTypes;
|
||||||
import net.minecraft.world.level.portal.PortalForcer;
|
|
||||||
import net.minecraft.world.level.portal.PortalInfo;
|
|
||||||
import net.minecraft.world.phys.AABB;
|
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||||
|
@ -241,10 +235,10 @@ public class TrackBlock extends Block
|
||||||
withBlockEntityDo(level, pos, tbe -> tbe.tilt.undoSmoothing());
|
withBlockEntityDo(level, pos, tbe -> tbe.tilt.undoSmoothing());
|
||||||
if (!state.getValue(SHAPE)
|
if (!state.getValue(SHAPE)
|
||||||
.isPortal())
|
.isPortal())
|
||||||
connectToNether(level, pos, state);
|
connectToPortal(level, pos, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void connectToNether(ServerLevel level, BlockPos pos, BlockState state) {
|
protected void connectToPortal(ServerLevel level, BlockPos pos, BlockState state) {
|
||||||
TrackShape shape = state.getValue(TrackBlock.SHAPE);
|
TrackShape shape = state.getValue(TrackBlock.SHAPE);
|
||||||
Axis portalTest = shape == TrackShape.XO ? Axis.X : shape == TrackShape.ZO ? Axis.Z : null;
|
Axis portalTest = shape == TrackShape.XO ? Axis.X : shape == TrackShape.ZO ? Axis.Z : null;
|
||||||
if (portalTest == null)
|
if (portalTest == null)
|
||||||
|
@ -257,11 +251,11 @@ public class TrackBlock extends Block
|
||||||
for (Direction d : Iterate.directionsInAxis(portalTest)) {
|
for (Direction d : Iterate.directionsInAxis(portalTest)) {
|
||||||
BlockPos portalPos = pos.relative(d);
|
BlockPos portalPos = pos.relative(d);
|
||||||
BlockState portalState = level.getBlockState(portalPos);
|
BlockState portalState = level.getBlockState(portalPos);
|
||||||
if (!(portalState.getBlock() instanceof NetherPortalBlock))
|
if (!AllPortalTracks.isSupportedPortal(portalState))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pop = true;
|
pop = true;
|
||||||
Pair<ServerLevel, BlockFace> otherSide = getOtherSide(level, new BlockFace(pos, d));
|
Pair<ServerLevel, BlockFace> otherSide = AllPortalTracks.getOtherSide(level, new BlockFace(pos, d));
|
||||||
if (otherSide == null) {
|
if (otherSide == null) {
|
||||||
fail = "missing";
|
fail = "missing";
|
||||||
continue;
|
continue;
|
||||||
|
@ -314,38 +308,6 @@ public class TrackBlock extends Block
|
||||||
.append(component.withStyle(st -> st.withColor(0xFFD3B4))), false);
|
.append(component.withStyle(st -> st.withColor(0xFFD3B4))), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Pair<ServerLevel, BlockFace> getOtherSide(ServerLevel level, BlockFace inboundTrack) {
|
|
||||||
BlockPos portalPos = inboundTrack.getConnectedPos();
|
|
||||||
BlockState portalState = level.getBlockState(portalPos);
|
|
||||||
if (!(portalState.getBlock() instanceof NetherPortalBlock))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
MinecraftServer minecraftserver = level.getServer();
|
|
||||||
ResourceKey<Level> resourcekey = level.dimension() == Level.NETHER ? Level.OVERWORLD : Level.NETHER;
|
|
||||||
ServerLevel otherLevel = minecraftserver.getLevel(resourcekey);
|
|
||||||
if (otherLevel == null || !minecraftserver.isNetherEnabled())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
PortalForcer teleporter = otherLevel.getPortalForcer();
|
|
||||||
SuperGlueEntity probe = new SuperGlueEntity(level, new AABB(portalPos));
|
|
||||||
probe.setYRot(inboundTrack.getFace()
|
|
||||||
.toYRot());
|
|
||||||
PortalInfo portalinfo = teleporter.getPortalInfo(probe, otherLevel, probe::findDimensionEntryPoint);
|
|
||||||
if (portalinfo == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
BlockPos otherPortalPos = new BlockPos(portalinfo.pos);
|
|
||||||
BlockState otherPortalState = otherLevel.getBlockState(otherPortalPos);
|
|
||||||
if (!(otherPortalState.getBlock() instanceof NetherPortalBlock))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Direction targetDirection = inboundTrack.getFace();
|
|
||||||
if (targetDirection.getAxis() == otherPortalState.getValue(NetherPortalBlock.AXIS))
|
|
||||||
targetDirection = targetDirection.getClockWise();
|
|
||||||
BlockPos otherPos = otherPortalPos.relative(targetDirection);
|
|
||||||
return Pair.of(otherLevel, new BlockFace(otherPos, targetDirection.getOpposite()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState updateShape(BlockState state, Direction pDirection, BlockState pNeighborState,
|
public BlockState updateShape(BlockState state, Direction pDirection, BlockState pNeighborState,
|
||||||
LevelAccessor level, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
LevelAccessor level, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||||
|
@ -362,7 +324,7 @@ public class TrackBlock extends Block
|
||||||
|
|
||||||
BlockPos portalPos = pCurrentPos.relative(d);
|
BlockPos portalPos = pCurrentPos.relative(d);
|
||||||
BlockState portalState = level.getBlockState(portalPos);
|
BlockState portalState = level.getBlockState(portalPos);
|
||||||
if (!(portalState.getBlock() instanceof NetherPortalBlock))
|
if (!AllPortalTracks.isSupportedPortal(portalState))
|
||||||
return Blocks.AIR.defaultBlockState();
|
return Blocks.AIR.defaultBlockState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -551,7 +551,7 @@ public class AllAdvancements implements DataProvider {
|
||||||
|
|
||||||
TRAIN_PORTAL = create("train_portal", b -> b.icon(Blocks.AMETHYST_BLOCK)
|
TRAIN_PORTAL = create("train_portal", b -> b.icon(Blocks.AMETHYST_BLOCK)
|
||||||
.title("Dimensional Commuter")
|
.title("Dimensional Commuter")
|
||||||
.description("Ride a Train through a Nether portal")
|
.description("Ride a Train through a portal")
|
||||||
.after(TRAIN_WHISTLE)
|
.after(TRAIN_WHISTLE)
|
||||||
.special(NOISY)),
|
.special(NOISY)),
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue