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
23 changes: 19 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,23 @@ 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 = new Location(((PlayerMoveEvent) e).getFrom().getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
Moderocky marked this conversation as resolved.
Show resolved Hide resolved
((PlayerMoveEvent) e).setTo(loc);
return next;
}
Expand All @@ -125,14 +128,26 @@ protected TriggerItem walk(Event e) {
return next;
}

find_a_world:
if (unknownWorld) { // we can't fetch the chunk without a world
for (Entity entity : entityArray) {
if (entity == null)
continue;
// assume it's a local teleport, use the first entity we find as a reference
loc = new Location(entity.getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
loc = new Location(entity.getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
loc = loc.clone();
loc.setWorld(entity.getWorld());

break find_a_world;
}
return next; // no entities = no chunk = nobody teleporting
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% convinced this is great, but it seems like a very good assumption most of the time so whatever

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
Loading