From 1439a52a3752e197f597b7afd3b07ca152f321dc Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:34:01 +0200 Subject: [PATCH] 3D - Trains can now travel through Aether Portals --- build.gradle | 1 + gradle.properties | 2 +- .../9b718366ce2ebddbc65bf65c103939e2cf56b4af | 4 +- .../resources/assets/create/lang/en_us.json | 2 +- src/main/java/com/simibubi/create/Create.java | 2 + .../contraptions/glue/SuperGlueEntity.java | 5 +- .../content/trains/track/AllPortalTracks.java | 122 ++++++++++++++++++ .../content/trains/track/TrackBlock.java | 48 +------ .../advancement/AllAdvancements.java | 2 +- 9 files changed, 139 insertions(+), 49 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java diff --git a/build.gradle b/build.gradle index ba8971476..f574f9ffd 100644 --- a/build.gradle +++ b/build.gradle @@ -203,6 +203,7 @@ dependencies { // runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252") // 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 } + // runtimeOnly fg.deobf("maven.modrinth:aether:1.19.2-1.0.0-beta.1.1-forge") // https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497 // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings diff --git a/gradle.properties b/gradle.properties index eafe87c0f..5c6d8a2cd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,7 +27,7 @@ flywheel_version = 0.6.10-20 jei_minecraft_version = 1.19.2 jei_version = 11.2.0.254 curios_minecraft_version = 1.19.2 -curios_version = 5.1.1.0 +curios_version = 5.1.4.1 cc_tweaked_enable = true cc_tweaked_minecraft_version = 1.19.2 diff --git a/src/generated/resources/.cache/9b718366ce2ebddbc65bf65c103939e2cf56b4af b/src/generated/resources/.cache/9b718366ce2ebddbc65bf65c103939e2cf56b4af index 0a218373e..d39f222d0 100644 --- a/src/generated/resources/.cache/9b718366ce2ebddbc65bf65c103939e2cf56b4af +++ b/src/generated/resources/.cache/9b718366ce2ebddbc65bf65c103939e2cf56b4af @@ -1,2 +1,2 @@ -// 1.19.2 2023-05-24T18:02:06.5252419 Create's lang merger -12da996b104ab0e5ce956c963fbdae7e59e72f79 assets/create/lang/en_us.json +// 1.19.2 2023-09-20T14:31:50.8818458 Create's lang merger +532d323119782de6b62f1fe52672941cc9209a40 assets/create/lang/en_us.json diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 6d5b564e2..d5657d531 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -868,7 +868,7 @@ "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_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.desc": "Produce more than 1000 Train Tracks with the same Mechanical Press", "advancement.create.long_train": "Ambitious Endeavours", diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 98e1f6462..4a008c30a 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -23,6 +23,7 @@ import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler; import com.simibubi.create.content.schematics.ServerSchematicLoader; import com.simibubi.create.content.trains.GlobalRailwayManager; 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.AllTriggers; import com.simibubi.create.foundation.block.CopperRegistries; @@ -134,6 +135,7 @@ public class Create { // FIXME: some of these registrations are not thread-safe AllMovementBehaviours.registerDefaults(); AllInteractionBehaviours.registerDefaults(); + AllPortalTracks.registerDefaults(); AllDisplayBehaviours.registerDefaults(); ContraptionMovementSetting.registerDefaults(); AllArmInteractionPointTypes.register(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueEntity.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueEntity.java index 0efe74944..a47a9e43f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueEntity.java @@ -295,9 +295,12 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat return PushReaction.IGNORE; } + public void setPortalEntrancePos() { + portalEntrancePos = blockPosition(); + } + @Override public PortalInfo findDimensionEntryPoint(ServerLevel pDestination) { - portalEntrancePos = blockPosition(); return super.findDimensionEntryPoint(pDestination); } diff --git a/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java b/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java new file mode 100644 index 000000000..ce6f64a52 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/AllPortalTracks.java @@ -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> { + }; + + private static final AttachedRegistry 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 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 nether(Pair inbound) { + return standardPortalProvider(inbound, Level.OVERWORLD, Level.NETHER, ServerLevel::getPortalForcer); + } + + private static Pair aether(Pair inbound) { + ResourceKey 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 standardPortalProvider(Pair inbound, + ResourceKey firstDimension, ResourceKey secondDimension, + Function customPortalForcer) { + ServerLevel level = inbound.getFirst(); + ResourceKey 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())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackBlock.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlock.java index 0c58a3b83..0b447f1b3 100644 --- a/src/main/java/com/simibubi/create/content/trains/track/TrackBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlock.java @@ -30,7 +30,6 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllPartialModels; import com.simibubi.create.AllShapes; 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.equipment.wrench.IWrenchable; 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.network.chat.MutableComponent; import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; 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.Blocks; 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.entity.BlockEntity; 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.PushReaction; 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.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; @@ -241,10 +235,10 @@ public class TrackBlock extends Block withBlockEntityDo(level, pos, tbe -> tbe.tilt.undoSmoothing()); if (!state.getValue(SHAPE) .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); Axis portalTest = shape == TrackShape.XO ? Axis.X : shape == TrackShape.ZO ? Axis.Z : null; if (portalTest == null) @@ -257,11 +251,11 @@ public class TrackBlock extends Block for (Direction d : Iterate.directionsInAxis(portalTest)) { BlockPos portalPos = pos.relative(d); BlockState portalState = level.getBlockState(portalPos); - if (!(portalState.getBlock() instanceof NetherPortalBlock)) + if (!AllPortalTracks.isSupportedPortal(portalState)) continue; pop = true; - Pair otherSide = getOtherSide(level, new BlockFace(pos, d)); + Pair otherSide = AllPortalTracks.getOtherSide(level, new BlockFace(pos, d)); if (otherSide == null) { fail = "missing"; continue; @@ -314,38 +308,6 @@ public class TrackBlock extends Block .append(component.withStyle(st -> st.withColor(0xFFD3B4))), false); } - protected Pair 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 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 public BlockState updateShape(BlockState state, Direction pDirection, BlockState pNeighborState, LevelAccessor level, BlockPos pCurrentPos, BlockPos pNeighborPos) { @@ -362,7 +324,7 @@ public class TrackBlock extends Block BlockPos portalPos = pCurrentPos.relative(d); BlockState portalState = level.getBlockState(portalPos); - if (!(portalState.getBlock() instanceof NetherPortalBlock)) + if (!AllPortalTracks.isSupportedPortal(portalState)) return Blocks.AIR.defaultBlockState(); } diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java index 036f4591e..ead320f9a 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java @@ -551,7 +551,7 @@ public class AllAdvancements implements DataProvider { TRAIN_PORTAL = create("train_portal", b -> b.icon(Blocks.AMETHYST_BLOCK) .title("Dimensional Commuter") - .description("Ride a Train through a Nether portal") + .description("Ride a Train through a portal") .after(TRAIN_WHISTLE) .special(NOISY)),