Skip to content

Commit

Permalink
improve: handle nether portal using EntityPortalReadyEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
Siroshun09 committed Oct 10, 2022
1 parent b009209 commit 04c9036
Showing 1 changed file with 10 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.okocraft.morevanillaportals.listener;

import io.papermc.paper.event.entity.EntityInsideBlockEvent;
import io.papermc.paper.event.entity.EntityPortalReadyEvent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.Shapes;
Expand All @@ -14,26 +15,13 @@
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public class PortalListener implements Listener {

private final WorldNameMap netherMap = WorldNameMap.nether();
private final WorldNameMap endMap = WorldNameMap.end();
private final Map<Player, AtomicInteger> lastTickMap = new HashMap<>();
private final Map<Player, AtomicInteger> portalTimeMap = new HashMap<>();

@EventHandler
public void clearCache(@NotNull PlayerQuitEvent event) {
lastTickMap.remove(event.getPlayer());
portalTimeMap.remove(event.getPlayer());
}

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void handleInsideEndPortal(@NotNull EntityInsideBlockEvent event) {
Expand Down Expand Up @@ -71,69 +59,19 @@ public void handleInsideEndPortal(@NotNull EntityInsideBlockEvent event) {
}
}

public boolean handleNetherPortal(@NotNull CraftPlayer player) {
var destinationWorldName = netherMap.getWorldNameOfPortalDestination(player.getWorld());

if (destinationWorldName == null || destinationWorldName.isEmpty() ||
!(Bukkit.getWorld(destinationWorldName) instanceof CraftWorld destination)) {
return false;
}

var lastTick = lastTickMap.computeIfAbsent(player, p -> new AtomicInteger(-1));
var portalTime = portalTimeMap.computeIfAbsent(player, p -> new AtomicInteger(0));

int elapsed = Bukkit.getCurrentTick() - lastTick.get();

// prevent multiple counts on the same tick
if (elapsed == 0) {
return true;
}

if (lastTick.get() != -1 && 1 < elapsed) {
// nms - Entity#handleNetherPortal
if (portalTime.get() > 0) {
portalTime.addAndGet(elapsed * -4);
}

if (portalTime.get() < 0) {
portalTime.set(0);
}
}

int waitTime = player.isInvulnerable() ? 1 : 80; // Entity#getPortalWaitTime
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onNetherPortalReady(@NotNull EntityPortalReadyEvent event) {
var currentWorld = event.getEntity().getWorld();
var destinationWorldName = netherMap.getWorldNameOfPortalDestination(currentWorld);

if (waitTime <= portalTime.incrementAndGet()) {
player.setPortalCooldown(player.getHandle().getDimensionChangingDelay()); // Entity#setPortalCooldown
player.getHandle().changeDimension(destination.getHandle(), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL);
if (destinationWorldName == null || destinationWorldName.isEmpty()) {
return;
}

lastTick.set(Bukkit.getCurrentTick());
var destinationWorld = Bukkit.getWorld(destinationWorldName);

return true;
}

public boolean handleEndPortal(@NotNull CraftPlayer player) {
var destinationWorldName = endMap.getWorldNameOfPortalDestination(player.getWorld());

if (destinationWorldName == null || destinationWorldName.isEmpty() ||
!(Bukkit.getWorld(destinationWorldName) instanceof CraftWorld destination)) {
return false;
if (destinationWorld != null) {
event.setTargetWorld(destinationWorld);
}

// Entity#tickEndPortal
player.getHandle().changeDimension(destination.getHandle(), PlayerTeleportEvent.TeleportCause.END_PORTAL);
return true;
}

private boolean isPortal(@NotNull Block block) {
return block.getType() == Material.NETHER_PORTAL || block.getType() == Material.END_PORTAL;
}

private boolean isOverworldOrNether(@NotNull World.Environment environment) {
return environment == World.Environment.NORMAL || environment == World.Environment.NETHER;
}

private boolean isOverworldOrEnd(@NotNull World.Environment environment) {
return environment == World.Environment.NORMAL || environment == World.Environment.THE_END;
}
}

0 comments on commit 04c9036

Please sign in to comment.