- Trains can now travel through Aether Portals
This commit is contained in:
simibubi 2023-09-20 14:34:01 +02:00
parent 3bafe6fe40
commit 1439a52a37
9 changed files with 139 additions and 49 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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",

View file

@ -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();

View file

@ -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);
} }

View file

@ -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()));
}
}

View file

@ -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();
} }

View file

@ -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)),