Skip to content

Add extra raytracing api#8205

Closed
PrimordialMoros wants to merge 2 commits into
PaperMC:masterfrom
PrimordialMoros:raytracing-api
Closed

Add extra raytracing api#8205
PrimordialMoros wants to merge 2 commits into
PaperMC:masterfrom
PrimordialMoros:raytracing-api

Conversation

@PrimordialMoros
Copy link
Copy Markdown
Contributor

New api allows to specify a set of blocks (or rather block positions) that will be ignored when performing a raytrace.

It also adds a builder to easily construct raytraces instead of using the world methods with a myriad args.

Should this be consolidated with previous raytrace patches?

@PrimordialMoros PrimordialMoros requested a review from a team as a code owner July 29, 2022 14:46
Copy link
Copy Markdown
Member

@Machine-Maker Machine-Maker left a comment

Choose a reason for hiding this comment

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

Thanks for you contribution!

I like the idea of using a builder pattern here.

Comment thread patches/api/0389-Add-extra-raytracing-api.patch Outdated
Comment thread patches/server/0925-Add-extra-raytracing-api.patch Outdated
Comment thread patches/server/0925-Add-extra-raytracing-api.patch Outdated
Comment thread patches/server/0925-Add-extra-raytracing-api.patch Outdated
Comment thread patches/server/0925-Add-extra-raytracing-api.patch Outdated
Comment thread patches/server/0925-Add-extra-raytracing-api.patch Outdated
Comment on lines +162 to +186
+ /**
+ * Build and cast the raytrace checking only blocks.
+ *
+ * @param world the world to cast the raytrace in
+ * @return the result
+ */
+ @Nullable
+ public RayTraceResult blocks(@NotNull World world) {
+ Preconditions.checkArgument(world != null, "World cannot be null");
+ Location start = new Location(world, origin.getX(), origin.getY(), origin.getZ());
+ return world.rayTraceBlocks(start, direction, range, mode, ignorePassable, ignoreBlocks);
+ }
+
+ /**
+ * Build and cast the raytrace checking both blocks and entities.
+ *
+ * @param world the world to cast the raytrace in
+ * @return the result
+ */
+ @Nullable
+ public RayTraceResult entities(@NotNull World world) {
+ Preconditions.checkArgument(world != null, "World cannot be null");
+ Location start = new Location(world, origin.getX(), origin.getY(), origin.getZ());
+ return world.rayTrace(start, direction, range, mode, ignorePassable, raySize, entityPredicate, ignoreBlocks);
+ }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think these methods should probably be on World, and just take a RayTraceQuery object.

Something to also do in the future (not in this PR) would be to make all the other ray trace methods utilize builders

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it's still useful to have utility methods to cast the raytrace directly from the builder.
If I add the methods with the RayTraceContext arg on World should I replace the new overload methods or simply add them. It would be rather odd to "lock" new api functionality behind the method with the context parameter. But on the other hand could be confusing to have multiple ways (and maybe implementations) to perform the same thing.

Copy link
Copy Markdown
Member

@Machine-Maker Machine-Maker Jul 30, 2022

Choose a reason for hiding this comment

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

I generally think that a "Builder" should have one job, to build some other object type. Now the Paper API isn't consistent on that, see the ParticleBuilder

EDIT: Also why wouldn't you just put those methods on the context type? What's the purpose of having them on the Builder specifically instead of the type that's being built.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Likewise, you could argue the context object has one job, storing the raytrace configuration.
I think it's fair to assume that whenever one builds a context they also want to cast a raytrace using it. Those helper methods would simply combine the build and cast in one call.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

To be honest, i disagree; simply keeping data is not a responsibility: this turns objects into C structs. I don't see any problems of having a rayTrace method here.

+ * <p>Usage of the {@link Builder} is preferred over the super long
+ * {@link World#rayTrace(Location, Vector, double, FluidCollisionMode, boolean, double, Predicate, Collection)} API.
+ */
+public class RayTraceContext {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can this be a record?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It could but you'd need to repeat validation for all the arguments and also override some methods due to vectors being mutable. Not sure if it would be worth it.

Copy link
Copy Markdown
Member

@Owen1212055 Owen1212055 left a comment

Choose a reason for hiding this comment

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

I'm curious on a couple things...

  1. I feel the max range is a bit too restrictive here, IMO if someone puts a huge number here too bad! I don't think it's great to limit it like this. Why was this range chosen?
  2. Why not use a predicate for ignoreBlocks instead? This way you could simply (in the predicate) define your own logic and possibly extend it in the future.

But in general, this makes that whole api MUCH nicer to handle. 😅

@Owen1212055
Copy link
Copy Markdown
Member

Superceeded by 23860da .

A builder is something that might be useful, but in general, would probably be better off implemented in a different way (avoid passing World, etc) So if someone wants to pickup on that, PRs welcome. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Closed

Development

Successfully merging this pull request may close these issues.

4 participants