Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to estimate world in teleport when it's not specified. #6611

Merged
merged 8 commits into from
Jul 1, 2024
26 changes: 22 additions & 4 deletions src/main/java/ch/njol/skript/effects/EffTeleport.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package ch.njol.skript.effects;

import ch.njol.skript.Skript;
import ch.njol.skript.sections.EffSecSpawn;
import ch.njol.skript.sections.EffSecSpawn.SpawnEvent;
import ch.njol.skript.bukkitutil.EntityUtils;
import ch.njol.skript.doc.Description;
Expand All @@ -31,7 +30,6 @@
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.Trigger;
import ch.njol.skript.lang.TriggerItem;
import ch.njol.skript.lang.TriggerSection;
import ch.njol.skript.timings.SkriptTimings;
import ch.njol.skript.util.Direction;
import ch.njol.skript.variables.Variables;
Expand All @@ -53,7 +51,7 @@
"which may cause lag spikes or server crashes when using this effect to teleport entities to unloaded chunks."
})
@Examples({
"teleport the player to {homes.%player%}",
"teleport the player to {homes::%player%}",
"teleport the attacker to the victim"
})
@Since("1.0")
Expand Down Expand Up @@ -101,18 +99,25 @@ protected TriggerItem walk(Event e) {
Location loc = location.getSingle(e);
if (loc == null)
return next;
boolean unknownWorld = !loc.isWorldLoaded();

Entity[] entityArray = entities.getArray(e); // We have to fetch this before possible async execution to avoid async local variable access.
if (entityArray.length == 0)
return next;

if (!delayed) {
if (e instanceof PlayerRespawnEvent && entityArray.length == 1 && entityArray[0].equals(((PlayerRespawnEvent) e).getPlayer())) {
if (unknownWorld)
return next;
APickledWalrus marked this conversation as resolved.
Show resolved Hide resolved
((PlayerRespawnEvent) e).setRespawnLocation(loc);
return next;
}

if (e instanceof PlayerMoveEvent && entityArray.length == 1 && entityArray[0].equals(((PlayerMoveEvent) e).getPlayer())) {
if (unknownWorld) { // we can approximate the world
loc = loc.clone();
loc.setWorld(((PlayerMoveEvent) e).getFrom().getWorld());
}
((PlayerMoveEvent) e).setTo(loc);
return next;
}
Expand All @@ -125,14 +130,27 @@ protected TriggerItem walk(Event e) {
return next;
}

if (unknownWorld) { // we can't fetch the chunk without a world
if (entityArray.length == 1) { // if there's 1 thing we can borrow its world
Entity entity = entityArray[0];
if (entity == null)
return next;
// assume it's a local teleport, use the first entity we find as a reference
loc = loc.clone();
loc.setWorld(entity.getWorld());
} else {
return next; // no entities = no chunk = nobody teleporting
}
}
final Location fixed = loc;
Delay.addDelayedEvent(e);
Object localVars = Variables.removeLocals(e);

// This will either fetch the chunk instantly if on Spigot or already loaded or fetch it async if on Paper.
PaperLib.getChunkAtAsync(loc).thenAccept(chunk -> {
// The following is now on the main thread
for (Entity entity : entityArray) {
EntityUtils.teleport(entity, loc);
EntityUtils.teleport(entity, fixed);
}

// Re-set local variables
Expand Down