Add AsyncPortalCreateEvent

This commit is contained in:
Jake Potrebic 2024-05-06 19:24:27 +02:00
parent 506f1651e5
commit 5d2085c986
No known key found for this signature in database
GPG key ID: ECE0B3C133C016C5
2 changed files with 497 additions and 0 deletions

View file

@ -0,0 +1,181 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 16 May 2021 13:40:23 -0700
Subject: [PATCH] Add AsyncPortalCreateEvent
calls AsyncPortalCreateEvent in more places than
PortalCreateEvent and with more reasons
diff --git a/src/main/java/io/papermc/paper/event/world/AsyncPortalCreateEvent.java b/src/main/java/io/papermc/paper/event/world/AsyncPortalCreateEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..140e914626855d39376088761aaab6194f09bc3d
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/world/AsyncPortalCreateEvent.java
@@ -0,0 +1,145 @@
+package io.papermc.paper.event.world;
+
+import java.util.List;
+import org.bukkit.RegionAccessor;
+import org.bukkit.block.BlockState;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.server.ServerEvent;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.jetbrains.annotations.ApiStatus;
+
+/**
+ * Called when a portal is created.
+ * <p>
+ * May be triggered asynchronously. Use {@link Event#isAsynchronous()} to check.
+ * </p>
+ */
+public class AsyncPortalCreateEvent extends ServerEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final RegionAccessor regionAccessor;
+ private final List<BlockState> blocks;
+ private final Entity entity;
+ private final CreateReason reason;
+ private boolean cancel;
+
+ @ApiStatus.Internal
+ public AsyncPortalCreateEvent(final boolean isAsync, final @NonNull RegionAccessor regionAccessor, final @NonNull List<BlockState> blocks, final @Nullable Entity entity, final @NonNull CreateReason reason) {
+ super(isAsync);
+ this.regionAccessor = regionAccessor;
+ this.blocks = blocks;
+ this.entity = entity;
+ this.reason = reason;
+ }
+
+ /**
+ * Get the region accessor which may be a {@link org.bukkit.World} or
+ * a {@link org.bukkit.generator.LimitedRegion}.
+ *
+ * @return the region accessor
+ */
+ public @NonNull RegionAccessor getRegionAccessor() {
+ return this.regionAccessor;
+ }
+
+ /**
+ * Gets an array list of all the blocks associated with the created portal
+ *
+ * @return array list of all the blocks associated with the created portal
+ */
+ public @NonNull List<BlockState> getBlocks() {
+ return this.blocks;
+ }
+
+ /**
+ * Returns the Entity that triggered this portal creation (if available)
+ *
+ * @return Entity involved in this event
+ */
+ public @Nullable Entity getEntity() {
+ return this.entity;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancel;
+ }
+
+ @Override
+ public void setCancelled(final boolean cancel) {
+ this.cancel = cancel;
+ }
+
+ /**
+ * Gets the reason for the portal's creation
+ *
+ * @return CreateReason for the portal's creation
+ */
+ public @NonNull CreateReason getReason() {
+ return this.reason;
+ }
+
+ @Override
+ public @NonNull HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public static @NonNull HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+
+ /**
+ * An enum to specify the various reasons for a portal's creation
+ */
+ public enum CreateReason {
+ /**
+ * When the blocks inside a portal are created due to a portal frame
+ * being set on fire.
+ */
+ FIRE,
+ /**
+ * When a nether portal frame and portal is created at the exit of an
+ * entered nether portal.
+ */
+ NETHER_PAIR,
+ /**
+ * When the target end platform is created as a result of a player
+ * entering an end portal.
+ */
+ END_PLATFORM,
+ /**
+ * When the ender dragon is defeated and a new end gateway
+ * is generated on the main end island.
+ */
+ END_GATEWAY_DRAGON_DEFEAT,
+
+ /**
+ * When an entity causes the generation of an end gateway
+ * by going through one that does not have a linked gateway.
+ */
+ END_GATEWAY_PAIR,
+
+ /**
+ * When an inactive end portal is generated on the main end
+ * island in the end dimension. This can happen in normal world generation or
+ * when a new dragon is spawned, replacing the active portal with a inactive one.
+ */
+ END_PORTAL,
+
+ /**
+ * When an active end portal is generated on the main end
+ * island in the end dimension.
+ */
+ ACTIVE_END_PORTAL,
+
+ /**
+ * Fallback reason
+ */
+ UNKNOWN,
+ }
+}
diff --git a/src/main/java/org/bukkit/event/world/PortalCreateEvent.java b/src/main/java/org/bukkit/event/world/PortalCreateEvent.java
index 579f017474ff22f0991ca884c35cdde7e14a94dc..8e6450d14a6ad16a22f8725f623944b83ebc4580 100644
--- a/src/main/java/org/bukkit/event/world/PortalCreateEvent.java
+++ b/src/main/java/org/bukkit/event/world/PortalCreateEvent.java
@@ -11,7 +11,9 @@ import org.jetbrains.annotations.Nullable;
/**
* Called when a portal is created
+ * @deprecated use {@link io.papermc.paper.event.world.AsyncPortalCreateEvent}
*/
+@Deprecated(since = "1.21")
public class PortalCreateEvent extends WorldEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel = false;
@@ -26,7 +28,6 @@ public class PortalCreateEvent extends WorldEvent implements Cancellable {
public PortalCreateEvent(@NotNull final List<BlockState> blocks, @NotNull final World world, @Nullable Entity entity, @NotNull CreateReason reason) {
super(world);
-
this.blocks = blocks;
this.entity = entity;
this.reason = reason;

View file

@ -0,0 +1,316 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 16 May 2021 13:40:35 -0700
Subject: [PATCH] Add AsyncPortalCreateEvent
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
index 89df488afeffd0c060d2d0e7fae16daf978bd192..2075364594746bca4d06df3aa2089b7263226b0f 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java
@@ -142,17 +142,23 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity {
@Nullable
public Vec3 getPortalPosition(ServerLevel world, BlockPos pos) {
+ // Paper start - add entity param
+ return this.getPortalPosition(world, pos, null);
+ }
+ @Nullable
+ public Vec3 getPortalPosition(ServerLevel world, BlockPos pos, @Nullable net.minecraft.world.entity.Entity entity) {
+ // Paper end - add entity param
BlockPos blockposition1;
if (this.exitPortal == null && world.getTypeKey() == LevelStem.END) { // CraftBukkit - work in alternate worlds
blockposition1 = TheEndGatewayBlockEntity.findOrCreateValidTeleportPos(world, pos);
blockposition1 = blockposition1.above(10);
TheEndGatewayBlockEntity.LOGGER.debug("Creating portal at {}", blockposition1);
- TheEndGatewayBlockEntity.spawnGatewayPortal(world, blockposition1, EndGatewayConfiguration.knownExit(pos, false));
+ TheEndGatewayBlockEntity.spawnGatewayPortal(world, blockposition1, EndGatewayConfiguration.knownExit(pos, false), entity); // Paper
this.setExitPosition(blockposition1, this.exactTeleport);
}
- if (this.exitPortal != null) {
+ if (this.exitPortal != null && this.getLevel().getBlockEntity(this.exitPortal) instanceof TheEndGatewayBlockEntity) { // Paper - confirm gateway was created
blockposition1 = this.exactTeleport ? this.exitPortal : TheEndGatewayBlockEntity.findExitPosition(world, this.exitPortal);
return blockposition1.getBottomCenter();
} else {
@@ -267,8 +273,12 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity {
return blockposition2;
}
- private static void spawnGatewayPortal(ServerLevel world, BlockPos pos, EndGatewayConfiguration config) {
- Feature.END_GATEWAY.place(config, world, world.getChunkSource().getGenerator(), RandomSource.create(), pos);
+ // Paper start
+ private static void spawnGatewayPortal(ServerLevel world, BlockPos pos, EndGatewayConfiguration config, @Nullable net.minecraft.world.entity.Entity entity) {
+ if (world.ensureCanWrite(pos)) {
+ ((net.minecraft.world.level.levelgen.feature.EndGatewayFeature)Feature.END_GATEWAY).place(new net.minecraft.world.level.levelgen.feature.FeaturePlaceContext<>(java.util.Optional.empty(), world, world.getChunkSource().getGenerator(), RandomSource.create(), pos, config), io.papermc.paper.event.world.AsyncPortalCreateEvent.CreateReason.END_GATEWAY_PAIR, entity);
+ }
+ // Paper end
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 18a1b4325cac81b040596071dab99ef9bf6f3142..6cbcc11de6901e4ef716f65407bec6a31e790265 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -406,8 +406,8 @@ public class EndDragonFight {
if (dragon.getUUID().equals(this.dragonUUID)) {
this.dragonEvent.setProgress(0.0F);
this.dragonEvent.setVisible(false);
- this.spawnExitPortal(true);
- this.spawnNewGateway();
+ this.spawnExitPortal(true, dragon); // Paper
+ this.spawnNewGateway(dragon); // Paper
// Paper start - Add DragonEggFormEvent
BlockPos eggPosition = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(this.origin));
org.bukkit.craftbukkit.block.CraftBlockState eggState = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(this.level, eggPosition);
@@ -442,7 +442,7 @@ public class EndDragonFight {
// Paper start - More DragonBattle API
public boolean spawnNewGatewayIfPossible() {
if (!this.gateways.isEmpty()) {
- this.spawnNewGateway();
+ this.spawnNewGateway(null); // Paper
return true;
}
return false;
@@ -457,26 +457,39 @@ public class EndDragonFight {
}
// Paper end - More DragonBattle API
- private void spawnNewGateway() {
+ private void spawnNewGateway(@Nullable EnderDragon entityEnderDragon) { // Paper
if (!this.gateways.isEmpty()) {
int i = (Integer) this.gateways.remove(this.gateways.size() - 1);
int j = Mth.floor(96.0D * Math.cos(2.0D * (-3.141592653589793D + 0.15707963267948966D * (double) i)));
int k = Mth.floor(96.0D * Math.sin(2.0D * (-3.141592653589793D + 0.15707963267948966D * (double) i)));
- this.spawnNewGateway(new BlockPos(j, 75, k));
+ this.spawnNewGateway(new BlockPos(j, 75, k), entityEnderDragon);
}
}
- public void spawnNewGateway(BlockPos pos) {
+ public void spawnNewGateway(BlockPos pos, @Nullable EnderDragon entityEnderDragon) { // Paper
this.level.levelEvent(3000, pos, 0);
this.level.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> {
return iregistry.getHolder(EndFeatures.END_GATEWAY_DELAYED);
}).ifPresent((holder_c) -> {
- ((ConfiguredFeature) holder_c.value()).place(this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), pos);
+ // Paper start
+ if (holder_c.value().feature() instanceof net.minecraft.world.level.levelgen.feature.EndGatewayFeature endGatewayFeature && holder_c.value().config() instanceof net.minecraft.world.level.levelgen.feature.configurations.EndGatewayConfiguration endGatewayConfiguration) {
+ if (this.level.ensureCanWrite(pos)) {
+ endGatewayFeature.place(new net.minecraft.world.level.levelgen.feature.FeaturePlaceContext<>(java.util.Optional.empty(), this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), pos, endGatewayConfiguration), io.papermc.paper.event.world.AsyncPortalCreateEvent.CreateReason.END_GATEWAY_DRAGON_DEFEAT, entityEnderDragon); // Paper
+ }
+ } else {
+ // Paper end
+ holder_c.value().place(this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), pos);
+ } // Paper
});
}
public void spawnExitPortal(boolean previouslyKilled) {
+ // Paper start
+ this.spawnExitPortal(previouslyKilled, null);
+ }
+ public void spawnExitPortal(boolean previouslyKilled, @Nullable Entity entity) {
+ // Paper end
EndPodiumFeature worldgenendtrophy = new EndPodiumFeature(previouslyKilled);
if (this.portalLocation == null) {
@@ -490,7 +503,7 @@ public class EndDragonFight {
this.portalLocation = this.portalLocation.atY(this.level.getMinBuildHeight() + 1);
}
// Paper end - Prevent "softlocked" exit portal generation
- if (worldgenendtrophy.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation)) {
+ if (worldgenendtrophy.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation, entity)) { // Paper - add entity context
int i = Mth.positiveCeilDiv(4, 16);
this.level.getChunkSource().chunkMap.waitForLightBeforeSending(new ChunkPos(this.portalLocation), i);
@@ -541,7 +554,7 @@ public class EndDragonFight {
this.respawnStage = null;
this.respawnTime = 0;
this.resetSpikeCrystals();
- this.spawnExitPortal(true);
+ this.spawnExitPortal(true, enderCrystal); // Paper
} else {
this.updateCrystalCount();
Entity entity = this.level.getEntity(this.dragonUUID);
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/EndGatewayFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/EndGatewayFeature.java
index b76facd940f911aa069e919d7db1ca3a7b849608..da0361bd3c9521dc4538b02ae5a32ca818062fb1 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/EndGatewayFeature.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/EndGatewayFeature.java
@@ -14,8 +14,13 @@ public class EndGatewayFeature extends Feature<EndGatewayConfiguration> {
@Override
public boolean place(FeaturePlaceContext<EndGatewayConfiguration> context) {
+ // Paper start
+ return this.place(context, io.papermc.paper.event.world.AsyncPortalCreateEvent.CreateReason.UNKNOWN, null);
+ }
+ public boolean place(FeaturePlaceContext<EndGatewayConfiguration> context, io.papermc.paper.event.world.AsyncPortalCreateEvent.CreateReason createReason, @javax.annotation.Nullable net.minecraft.world.entity.Entity entity) {
+ // Paper end
BlockPos blockPos = context.origin();
- WorldGenLevel worldGenLevel = context.level();
+ org.bukkit.craftbukkit.util.BlockStateListPopulator worldGenLevel = new org.bukkit.craftbukkit.util.BlockStateListPopulator(context.level()); // Paper
EndGatewayConfiguration endGatewayConfiguration = context.config();
for (BlockPos blockPos2 : BlockPos.betweenClosed(blockPos.offset(-1, -2, -1), blockPos.offset(1, 2, 1))) {
@@ -26,7 +31,7 @@ public class EndGatewayFeature extends Feature<EndGatewayConfiguration> {
if (bl && bl2 && bl3) {
BlockPos blockPos3 = blockPos2.immutable();
this.setBlock(worldGenLevel, blockPos3, Blocks.END_GATEWAY.defaultBlockState());
- endGatewayConfiguration.getExit().ifPresent(pos -> {
+ endGatewayConfiguration.getExit().ifPresent(pos -> { // Paper - moved to below after tile entity has been created
if (worldGenLevel.getBlockEntity(blockPos3) instanceof TheEndGatewayBlockEntity theEndGatewayBlockEntity) {
theEndGatewayBlockEntity.setExitPosition(pos, endGatewayConfiguration.isExitExact());
}
@@ -42,6 +47,13 @@ public class EndGatewayFeature extends Feature<EndGatewayConfiguration> {
}
}
- return true;
+ // Paper start
+ worldGenLevel.refreshTiles(); // Update TheEndGatewayBlockEntity
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPortalCreateEvent(worldGenLevel, context.level(), entity, createReason)) {
+ worldGenLevel.updateList();
+ return true;
+ }
+ return false;
+ // Paper end
}
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java
index 0bc659a8427b89b5e3211220c55b52eec6a20494..947b443103fee1543075393918220868b0b4c5b3 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java
@@ -60,11 +60,7 @@ public class EndPlatformFeature extends Feature<NoneFeatureConfiguration> {
return;
}
- org.bukkit.World bworld = worldaccess.getLevel().getWorld();
- PortalCreateEvent portalEvent = new PortalCreateEvent((List<BlockState>) (List) blockList.getList(), bworld, entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM);
-
- worldaccess.getLevel().getCraftServer().getPluginManager().callEvent(portalEvent);
- if (!portalEvent.isCancelled()) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPortalCreateEvent(blockList, worldaccess, entity, io.papermc.paper.event.world.AsyncPortalCreateEvent.CreateReason.END_PLATFORM)) {
blockList.updateList();
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java
index 9d3b765c764a6c5711f264bb74d04de2b1cf1232..9463ce6262b14940e1b4c422ce5e535f88d308ea 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPodiumFeature.java
@@ -27,7 +27,7 @@ public class EndPodiumFeature extends Feature<NoneFeatureConfiguration> {
@Override
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
BlockPos blockPos = context.origin();
- WorldGenLevel worldGenLevel = context.level();
+ org.bukkit.craftbukkit.util.BlockStateListPopulator worldGenLevel = new org.bukkit.craftbukkit.util.BlockStateListPopulator(context.level()); // Paper
for (BlockPos blockPos2 : BlockPos.betweenClosed(
new BlockPos(blockPos.getX() - 4, blockPos.getY() - 1, blockPos.getZ() - 4),
@@ -63,6 +63,13 @@ public class EndPodiumFeature extends Feature<NoneFeatureConfiguration> {
this.setBlock(worldGenLevel, blockPos3.relative(direction), Blocks.WALL_TORCH.defaultBlockState().setValue(WallTorchBlock.FACING, direction));
}
- return true;
+ // Paper start
+ worldGenLevel.refreshTiles();
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPortalCreateEvent(worldGenLevel, context.level(), context.entitySource, this.active ? io.papermc.paper.event.world.AsyncPortalCreateEvent.CreateReason.ACTIVE_END_PORTAL : io.papermc.paper.event.world.AsyncPortalCreateEvent.CreateReason.END_PORTAL)) {
+ worldGenLevel.updateList();
+ return true;
+ }
+ return false;
+ // Paper end
}
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/Feature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/Feature.java
index d69bac79e99639abf5598edf7b865d7b3444cca1..5412574561bed4db6e86537a5c3f238a8150478c 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/Feature.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/Feature.java
@@ -187,7 +187,12 @@ public abstract class Feature<FC extends FeatureConfiguration> {
public abstract boolean place(FeaturePlaceContext<FC> context);
public boolean place(FC config, WorldGenLevel world, ChunkGenerator chunkGenerator, RandomSource random, BlockPos pos) {
- return world.ensureCanWrite(pos) && this.place(new FeaturePlaceContext<>(Optional.empty(), world, chunkGenerator, random, pos, config));
+ // Paper start - add entity context
+ return this.place(config, world, chunkGenerator, random, pos, null);
+ }
+ public boolean place(FC config, WorldGenLevel world, ChunkGenerator chunkGenerator, RandomSource random, BlockPos pos, @org.jetbrains.annotations.Nullable net.minecraft.world.entity.Entity entitySource) {
+ return world.ensureCanWrite(pos) && this.place(new FeaturePlaceContext<>(Optional.empty(), world, chunkGenerator, random, pos, config, entitySource));
+ // Paper end - add entity context
}
protected static boolean isStone(BlockState state) {
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/FeaturePlaceContext.java b/src/main/java/net/minecraft/world/level/levelgen/feature/FeaturePlaceContext.java
index c2f54b2c4f26ff3289ad226ccadf01a9f4e31c16..d0de7f93572d8c1e534303c7426cd5981ca2c1b7 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/FeaturePlaceContext.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/FeaturePlaceContext.java
@@ -14,10 +14,17 @@ public class FeaturePlaceContext<FC extends FeatureConfiguration> {
private final RandomSource random;
private final BlockPos origin;
private final FC config;
+ public final @org.jetbrains.annotations.Nullable net.minecraft.world.entity.Entity entitySource; // Paper - add entity context
public FeaturePlaceContext(
Optional<ConfiguredFeature<?, ?>> feature, WorldGenLevel world, ChunkGenerator generator, RandomSource random, BlockPos origin, FC config
) {
+ // Paper start - add entity context
+ this(feature, world, generator, random, origin, config, null);
+ }
+ public FeaturePlaceContext(Optional<ConfiguredFeature<?, ?>> feature, WorldGenLevel world, ChunkGenerator generator, RandomSource random, BlockPos origin, FC config, @org.jetbrains.annotations.Nullable net.minecraft.world.entity.Entity entitySource) {
+ this.entitySource = entitySource;
+ // Paper end - add entity context
this.topFeature = feature;
this.level = world;
this.chunkGenerator = generator;
diff --git a/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java
index 6bfabb38b51115beb2a65a165f235347838b6006..ce9a88d7355d8a928928a47469965dbe5c70c899 100644
--- a/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java
+++ b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java
@@ -150,7 +150,7 @@ public class CraftDragonBattle implements DragonBattle {
@Override
public void spawnNewGateway(final io.papermc.paper.math.Position position) {
- this.handle.spawnNewGateway(io.papermc.paper.util.MCUtil.toBlockPos(position));
+ this.handle.spawnNewGateway(io.papermc.paper.util.MCUtil.toBlockPos(position), null); // Paper
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 9c7cd9387f90d061aec76f7f0451a1da8b42ea3d..a3854711776bf737e209d20b4d280185f282c7dd 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -2223,4 +2223,33 @@ public class CraftEventFactory {
return event;
}
// Paper end - add EntityFertilizeEggEvent
+
+ // Paper start - add AsyncPortalCreateEvent
+ public static boolean callPortalCreateEvent(final org.bukkit.craftbukkit.util.BlockStateListPopulator blockList, final net.minecraft.world.level.ServerLevelAccessor world, @Nullable final Entity entity, final io.papermc.paper.event.world.AsyncPortalCreateEvent.CreateReason reason) {
+ final org.bukkit.event.world.PortalCreateEvent.CreateReason legacyReason = switch (reason) {
+ case FIRE -> org.bukkit.event.world.PortalCreateEvent.CreateReason.FIRE;
+ case NETHER_PAIR -> org.bukkit.event.world.PortalCreateEvent.CreateReason.NETHER_PAIR;
+ case END_PLATFORM -> org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM;
+ default -> null;
+ };
+ boolean cancelled = false;
+ if (Bukkit.isPrimaryThread() && legacyReason != null) {
+ cancelled = !new org.bukkit.event.world.PortalCreateEvent((List<BlockState>) (List) blockList.getList(), world.getLevel().getWorld(), entity.getBukkitEntity(), legacyReason).callEvent();
+ }
+ final org.bukkit.RegionAccessor regionAccessor;
+ if (world instanceof ServerLevel serverLevel) {
+ regionAccessor = serverLevel.getWorld();
+ } else if (world instanceof final net.minecraft.server.level.WorldGenRegion worldGenRegion) {
+ regionAccessor = new org.bukkit.craftbukkit.generator.CraftLimitedRegion(worldGenRegion, worldGenRegion.getCenter());
+ } else {
+ return true;
+ }
+ final boolean result = new io.papermc.paper.event.world.AsyncPortalCreateEvent(!Bukkit.isPrimaryThread(), regionAccessor, (List<BlockState>) (List) blockList.getList(), entity.getBukkitEntity(), reason).callEvent();
+ if (regionAccessor instanceof final org.bukkit.craftbukkit.generator.CraftLimitedRegion craftLimitedRegion) {
+ craftLimitedRegion.saveEntities();
+ craftLimitedRegion.breakLink();
+ }
+ return result;
+ }
+ // Paper end - add AsyncPortalCreateEvent
}