-
-
Notifications
You must be signed in to change notification settings - Fork 406
Fixes vehicle register #8092
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
Open
TheLimeGlass
wants to merge
23
commits into
SkriptLang:dev/patch
Choose a base branch
from
TheLimeGlass:fix/vehicle-register
base: dev/patch
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Fixes vehicle register #8092
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
07025a1
Fix vehicle
TheLimeGlass 5f9001e
Update src/main/java/ch/njol/skript/expressions/ExprVehicle.java
TheLimeGlass 728cb8f
Re-add delays
TheLimeGlass 0873fce
Merge branch 'fix/vehicle-register' of https://github.com/TheLimeGlas…
TheLimeGlass 6949abd
Fix suggestion commit
TheLimeGlass 2e00061
Merge branch 'dev/patch' into fix/vehicle-register
Moderocky a99038d
Time state changes
TheLimeGlass d84617b
Merge branch 'fix/vehicle-register' of https://github.com/TheLimeGlas…
TheLimeGlass a39e1b8
Avoid infinite mounting
TheLimeGlass e8999ec
Avoid infinite mounting
TheLimeGlass c404493
Better examples
TheLimeGlass 9935ed1
Merge branch 'dev/feature' into fix/vehicle-register
Moderocky 47b2a99
Update src/main/java/ch/njol/skript/expressions/ExprVehicle.java
TheLimeGlass 306e3b9
Use Java 17
TheLimeGlass b4a49ee
Update to latest
TheLimeGlass 07111a1
git conflicts
TheLimeGlass 756381e
Update src/main/java/ch/njol/skript/expressions/ExprVehicle.java
TheLimeGlass aa6679a
Update src/main/java/ch/njol/skript/expressions/ExprVehicle.java
TheLimeGlass baad7e5
Requested changes
TheLimeGlass e10e431
Update src/main/java/ch/njol/skript/expressions/ExprVehicle.java
TheLimeGlass 5131dc4
Update src/main/java/ch/njol/skript/expressions/ExprVehicle.java
TheLimeGlass c9a2355
requested changes
TheLimeGlass ecefec5
Merge branch 'fix/vehicle-register' of https://github.com/TheLimeGlas…
TheLimeGlass File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
package ch.njol.skript.expressions; | ||
|
||
import java.util.function.Predicate; | ||
|
||
import org.bukkit.entity.Entity; | ||
import org.bukkit.event.Event; | ||
import org.bukkit.event.entity.EntityDismountEvent; | ||
import org.bukkit.event.entity.EntityEvent; | ||
import org.bukkit.event.entity.EntityMountEvent; | ||
import org.bukkit.event.vehicle.VehicleEnterEvent; | ||
import org.bukkit.event.vehicle.VehicleExitEvent; | ||
|
@@ -12,175 +13,139 @@ | |
import ch.njol.skript.Skript; | ||
import ch.njol.skript.classes.Changer.ChangeMode; | ||
import ch.njol.skript.doc.Description; | ||
import ch.njol.skript.doc.Examples; | ||
import ch.njol.skript.doc.Example; | ||
import ch.njol.skript.doc.Name; | ||
import ch.njol.skript.doc.Since; | ||
import ch.njol.skript.effects.Delay; | ||
import ch.njol.skript.entity.EntityData; | ||
import ch.njol.skript.expressions.base.SimplePropertyExpression; | ||
import ch.njol.util.coll.CollectionUtils; | ||
import ch.njol.skript.expressions.base.PropertyExpression; | ||
import ch.njol.skript.lang.Expression; | ||
import ch.njol.skript.lang.SkriptParser.ParseResult; | ||
import ch.njol.skript.registrations.EventValues; | ||
import ch.njol.util.Kleenean; | ||
|
||
import java.lang.invoke.MethodHandle; | ||
import java.lang.invoke.MethodHandles; | ||
import java.lang.invoke.MethodType; | ||
import org.bukkit.entity.Player; | ||
|
||
/** | ||
* @author Peter Güttinger | ||
*/ | ||
@Name("Vehicle") | ||
@Description({"The vehicle an entity is in, if any. This can actually be any entity, e.g. spider jockeys are skeletons that ride on a spider, so the spider is the 'vehicle' of the skeleton.", | ||
"See also: <a href='#ExprPassenger'>passenger</a>"}) | ||
@Examples({"vehicle of the player is a minecart"}) | ||
@Description({ | ||
"The vehicle an entity is in, if any.", | ||
"This can actually be any entity, e.g. spider jockeys are skeletons that ride on a spider, so the spider is the 'vehicle' of the skeleton.", | ||
"See also: <a href='#ExprPassenger'>passenger</a>" | ||
}) | ||
@Example(""" | ||
set the vehicle of {game::players::*} to a saddled pig | ||
give {game::players::*} a carrot on a stick | ||
""") | ||
@Example(""" | ||
on vehicle enter: | ||
vehicle is a horse | ||
add 1 to {statistics::horseMounting::%uuid of player%} | ||
""") | ||
TheLimeGlass marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@Since("2.0") | ||
public class ExprVehicle extends SimplePropertyExpression<Entity, Entity> { | ||
|
||
private static final boolean HAS_NEW_MOUNT_EVENTS = Skript.classExists("org.bukkit.event.entity.EntityMountEvent"); | ||
|
||
private static final boolean HAS_OLD_MOUNT_EVENTS; | ||
@Nullable | ||
private static final Class<?> OLD_MOUNT_EVENT_CLASS; | ||
@Nullable | ||
private static final MethodHandle OLD_GETMOUNT_HANDLE; | ||
@Nullable | ||
private static final Class<?> OLD_DISMOUNT_EVENT_CLASS; | ||
@Nullable | ||
private static final MethodHandle OLD_GETDISMOUNTED_HANDLE; | ||
public class ExprVehicle extends PropertyExpression<Entity, Entity> { | ||
|
||
static { | ||
register(ExprVehicle.class, Entity.class, "vehicle[s]", "entities"); | ||
|
||
// legacy support | ||
boolean hasOldMountEvents = !HAS_NEW_MOUNT_EVENTS && | ||
Skript.classExists("org.spigotmc.event.entity.EntityMountEvent"); | ||
Class<?> oldMountEventClass = null; | ||
TheLimeGlass marked this conversation as resolved.
Show resolved
Hide resolved
|
||
MethodHandle oldGetMountHandle = null; | ||
Class<?> oldDismountEventClass = null; | ||
MethodHandle oldGetDismountedHandle = null; | ||
if (hasOldMountEvents) { | ||
try { | ||
MethodHandles.Lookup lookup = MethodHandles.lookup(); | ||
MethodType entityReturnType = MethodType.methodType(Entity.class); | ||
// mount event | ||
oldMountEventClass = Class.forName("org.spigotmc.event.entity.EntityMountEvent"); | ||
oldGetMountHandle = lookup.findVirtual(oldMountEventClass, "getMount", entityReturnType); | ||
// dismount event | ||
oldDismountEventClass = Class.forName("org.spigotmc.event.entity.EntityDismountEvent"); | ||
oldGetDismountedHandle = lookup.findVirtual(oldDismountEventClass, "getDismounted", entityReturnType); | ||
} catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException e) { | ||
hasOldMountEvents = false; | ||
oldMountEventClass = null; | ||
oldGetMountHandle = null; | ||
oldDismountEventClass = null; | ||
oldGetDismountedHandle = null; | ||
Skript.exception(e, "Failed to load old mount event support."); | ||
} | ||
} | ||
HAS_OLD_MOUNT_EVENTS = hasOldMountEvents; | ||
OLD_MOUNT_EVENT_CLASS = oldMountEventClass; | ||
OLD_GETMOUNT_HANDLE = oldGetMountHandle; | ||
OLD_DISMOUNT_EVENT_CLASS = oldDismountEventClass; | ||
OLD_GETDISMOUNTED_HANDLE = oldGetDismountedHandle; | ||
} | ||
|
||
@Override | ||
protected Entity[] get(final Event e, final Entity[] source) { | ||
return get(source, entity -> { | ||
if (getTime() >= 0 && e instanceof VehicleEnterEvent && entity.equals(((VehicleEnterEvent) e).getEntered()) && !Delay.isDelayed(e)) { | ||
return ((VehicleEnterEvent) e).getVehicle(); | ||
} | ||
if (getTime() >= 0 && e instanceof VehicleExitEvent && entity.equals(((VehicleExitEvent) e).getExited()) && !Delay.isDelayed(e)) { | ||
return ((VehicleExitEvent) e).getVehicle(); | ||
} | ||
if ( | ||
(HAS_OLD_MOUNT_EVENTS || HAS_NEW_MOUNT_EVENTS) | ||
&& getTime() >= 0 && !Delay.isDelayed(e) | ||
&& e instanceof EntityEvent && entity.equals(((EntityEvent) e).getEntity()) | ||
) { | ||
if (HAS_NEW_MOUNT_EVENTS) { | ||
if (e instanceof EntityMountEvent) | ||
return ((EntityMountEvent) e).getMount(); | ||
if (e instanceof EntityDismountEvent) | ||
return ((EntityDismountEvent) e).getDismounted(); | ||
} else { // legacy mount event support | ||
try { | ||
assert OLD_MOUNT_EVENT_CLASS != null; | ||
if (OLD_MOUNT_EVENT_CLASS.isInstance(e)) { | ||
assert OLD_GETMOUNT_HANDLE != null; | ||
return (Entity) OLD_GETMOUNT_HANDLE.invoke(e); | ||
} | ||
assert OLD_DISMOUNT_EVENT_CLASS != null; | ||
if (OLD_DISMOUNT_EVENT_CLASS.isInstance(e)) { | ||
assert OLD_GETDISMOUNTED_HANDLE != null; | ||
return (Entity) OLD_GETDISMOUNTED_HANDLE.invoke(e); | ||
} | ||
} catch (Throwable ex) { | ||
Skript.exception(ex, "An error occurred while trying to invoke legacy mount event support."); | ||
} | ||
} | ||
} | ||
return entity.getVehicle(); | ||
}); | ||
if (Skript.classExists("org.bukkit.event.entity.EntityMountEvent")) | ||
registerDefault(ExprVehicle.class, Entity.class, "vehicle[s]", "entities"); | ||
TheLimeGlass marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
@Override | ||
@Nullable | ||
public Entity convert(final Entity e) { | ||
assert false; | ||
return e.getVehicle(); | ||
} | ||
|
||
|
||
@Override | ||
public Class<? extends Entity> getReturnType() { | ||
return Entity.class; | ||
@SuppressWarnings("unchecked") | ||
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { | ||
setExpr((Expression<Entity>) expressions[0]); | ||
return true; | ||
} | ||
|
||
@Override | ||
protected String getPropertyName() { | ||
return "vehicle"; | ||
protected Entity[] get(Event event, Entity[] source) { | ||
if (event instanceof EntityDismountEvent entityDismountEvent && getTime() != EventValues.TIME_FUTURE) { | ||
return get(source, e -> e.equals(entityDismountEvent.getEntity()) ? entityDismountEvent.getDismounted() : e.getVehicle()); | ||
} else if (event instanceof VehicleEnterEvent vehicleEnterEvent && getTime() != EventValues.TIME_PAST) { | ||
return get(source, e -> e.equals(vehicleEnterEvent.getEntered()) ? vehicleEnterEvent.getVehicle() : e.getVehicle()); | ||
} else if (event instanceof VehicleExitEvent vehicleExitEvent && getTime() != EventValues.TIME_FUTURE) { | ||
return get(source, e -> e.equals(vehicleExitEvent.getExited()) ? vehicleExitEvent.getVehicle() : e.getVehicle()); | ||
} else if (event instanceof EntityMountEvent entityMountEvent && getTime() != EventValues.TIME_PAST) { | ||
return get(source, e -> e.equals(entityMountEvent.getEntity()) ? entityMountEvent.getMount() : e.getVehicle()); | ||
} else { | ||
return get(source, Entity::getVehicle); | ||
} | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public Class<?>[] acceptChange(final ChangeMode mode) { | ||
public Class<?> @Nullable [] acceptChange(ChangeMode mode) { | ||
if (mode == ChangeMode.SET) { | ||
if (isDefault() && getParser().isCurrentEvent(VehicleExitEvent.class, EntityDismountEvent.class)) { | ||
Skript.error("Setting the vehicle during a dismount/exit vehicle event will create an infinite mounting loop."); | ||
return null; | ||
} | ||
return new Class[] {Entity.class, EntityData.class}; | ||
} | ||
return super.acceptChange(mode); | ||
} | ||
|
||
@Override | ||
public void change(final Event e, final @Nullable Object[] delta, final ChangeMode mode) { | ||
public void change(Event event, @Nullable Object[] delta, ChangeMode mode) { | ||
if (mode == ChangeMode.SET) { | ||
assert delta != null; | ||
final Entity[] ps = getExpr().getArray(e); | ||
if (ps.length == 0) | ||
// The player can desync if setting an entity as it's currently mounting it. | ||
// Remember that there can be other entity types aside from players, so only cancel this for players. | ||
Predicate<Entity> predicate = Player.class::isInstance; | ||
if (event instanceof EntityMountEvent entityMountEvent && predicate.test(entityMountEvent.getEntity())) { | ||
return; | ||
} | ||
if (event instanceof VehicleEnterEvent vehicleEnterEvent && predicate.test(vehicleEnterEvent.getEntered())) { | ||
return; | ||
} | ||
Entity[] passengers = getExpr().getArray(event); | ||
if (passengers.length == 0) | ||
return; | ||
final Object o = delta[0]; | ||
if (o instanceof Entity) { | ||
((Entity) o).eject(); | ||
final Entity p = CollectionUtils.getRandom(ps); | ||
assert p != null; | ||
p.leaveVehicle(); | ||
((Entity) o).setPassenger(p); | ||
} else if (o instanceof EntityData) { | ||
for (final Entity p : ps) { | ||
final Entity v = ((EntityData<?>) o).spawn(p.getLocation()); | ||
if (v == null) | ||
assert delta != null; | ||
Object object = delta[0]; | ||
if (object instanceof Entity entity) { | ||
entity.eject(); | ||
for (Entity passenger : passengers) { | ||
// Avoid infinity mounting | ||
if (event instanceof VehicleExitEvent && predicate.test(passenger) && passenger.equals(((VehicleExitEvent) event).getExited())) | ||
continue; | ||
if (event instanceof EntityDismountEvent && predicate.test(passenger) && passenger.equals(((EntityDismountEvent) event).getEntity())) | ||
continue; | ||
assert passenger != null; | ||
passenger.leaveVehicle(); | ||
entity.addPassenger(passenger); | ||
} | ||
} else if (object instanceof EntityData entityData) { | ||
VehicleExitEvent vehicleExitEvent = event instanceof VehicleExitEvent ? (VehicleExitEvent) event : null; | ||
EntityDismountEvent entityDismountEvent = event instanceof EntityDismountEvent ? (EntityDismountEvent) event : null; | ||
for (Entity passenger : passengers) { | ||
// Avoid infinity mounting | ||
if (vehicleExitEvent != null && predicate.test(passenger) && passenger.equals(vehicleExitEvent.getExited())) | ||
continue; | ||
if (entityDismountEvent != null && predicate.test(passenger) && passenger.equals(entityDismountEvent.getEntity())) | ||
continue; | ||
Entity vehicle = entityData.spawn(passenger.getLocation()); | ||
Comment on lines
+102
to
+123
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not entirely sure about these checks within the loops, same reasoning as with |
||
if (vehicle == null) | ||
continue; | ||
v.setPassenger(p); | ||
vehicle.addPassenger(passenger); | ||
} | ||
} else { | ||
assert false; | ||
} | ||
} else { | ||
super.change(e, delta, mode); | ||
super.change(event, delta, mode); | ||
} | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
|
||
@Override | ||
public boolean setTime(final int time) { | ||
return super.setTime(time, getExpr(), VehicleEnterEvent.class, VehicleExitEvent.class); | ||
public boolean setTime(int time) { | ||
return super.setTime(time, getExpr(), VehicleEnterEvent.class, VehicleExitEvent.class, EntityMountEvent.class, EntityDismountEvent.class); | ||
} | ||
|
||
|
||
@Override | ||
public Class<? extends Entity> getReturnType() { | ||
return Entity.class; | ||
} | ||
|
||
@Override | ||
public String toString(@Nullable Event event, boolean debug) { | ||
return "vehicle of " + getExpr().toString(event, debug); | ||
} | ||
|
||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is not proper Java standards. Avoids the addition of a blank line.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation of the block string is determined by the location of the left-most non-space character, OR the ending """. If you put the """ all the way to the left like that, you cause the example string to be indented by a tab. We don't want that, so the """ needs to be on the same column as the example text.
See https://www.baeldung.com/java-text-blocks#indentation for examples
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would you randomly put a new line break at the end. The existing annotations don't do this. This would essentially force a documentation page to check if the example ended with a new line break or not to differ between the annotations. Just keep it standardized and don't include a random new line break at the end of the returned string so the documentation page doesn't have to worry about varation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This formatting still contains a line break at the end. If you wanted no line break, you would write:
which is pretty ugly.
The difference between
and
is simply indentation, and the second is what we want. The first causes the lines to have a tab at the front, the second doesn't have tabs.