2021-06-11 14:02:28 +02:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Aikar <aikar@aikar.co>
|
|
|
|
Date: Tue, 15 Aug 2017 22:29:12 -0400
|
|
|
|
Subject: [PATCH] Expand World.spawnParticle API and add Builder
|
|
|
|
|
|
|
|
Adds ability to control who receives it and who is the source/sender (vanish API)
|
|
|
|
the standard API is to send the packet to everyone in the world, which is ineffecient.
|
|
|
|
Adds an option to control the force mode of the particle.
|
|
|
|
|
|
|
|
This adds a new Builder API which is much friendlier to use.
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
Rework async chunk api implementation
Firstly, the old methods all routed to the CompletableFuture method.
However, the CF method could not guarantee that if the caller
was off-main that the future would be "completed" on-main. Since
the callback methods used the CF one, this meant that the callback
methods did not guarantee that the callbacks were to be called on
the main thread.
Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb)
so that the methods with the callback are guaranteed to invoke
the callback on the main thread. The CF behavior remains unchanged;
it may still appear to complete on main if invoked off-main.
Secondly, remove the scheduleOnMain invocation in the async
chunk completion. This unnecessarily delays the callback
by 1 tick.
Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which
will load chunks within an area. This method is provided as a helper
as keeping all chunks loaded within an area can be complicated to
implement for plugins (due to the lacking ticket API), and is
already implemented internally anyways.
Fourthly, remove the ticket addition that occured with getChunkAt
and getChunkAtAsync. The ticket addition may delay the unloading
of the chunk unnecessarily. It also fixes a very rare timing bug
where the future/callback would be completed after the chunk
unloads.
2024-11-19 07:34:32 +01:00
|
|
|
index 3d54f52ed43ceef368804f7dce1dd95de3acc045..03161ef12960cab3b9c81c190dd808a9c5c476e1 100644
|
2021-06-11 14:02:28 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
Rework async chunk api implementation
Firstly, the old methods all routed to the CompletableFuture method.
However, the CF method could not guarantee that if the caller
was off-main that the future would be "completed" on-main. Since
the callback methods used the CF one, this meant that the callback
methods did not guarantee that the callbacks were to be called on
the main thread.
Now, all methods route to getChunkAtAsync(x, z, gen, urgent, cb)
so that the methods with the callback are guaranteed to invoke
the callback on the main thread. The CF behavior remains unchanged;
it may still appear to complete on main if invoked off-main.
Secondly, remove the scheduleOnMain invocation in the async
chunk completion. This unnecessarily delays the callback
by 1 tick.
Thirdly, add getChunksAtAsync(minX, minZ, maxX, maxZ, ...) which
will load chunks within an area. This method is provided as a helper
as keeping all chunks loaded within an area can be complicated to
implement for plugins (due to the lacking ticket API), and is
already implemented internally anyways.
Fourthly, remove the ticket addition that occured with getChunkAt
and getChunkAtAsync. The ticket addition may delay the unloading
of the chunk unnecessarily. It also fixes a very rare timing bug
where the future/callback would be completed after the chunk
unloads.
2024-11-19 07:34:32 +01:00
|
|
|
@@ -1541,12 +1541,17 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
2021-06-11 14:02:28 +02:00
|
|
|
}
|
2023-09-22 00:01:00 +02:00
|
|
|
|
2021-06-11 14:02:28 +02:00
|
|
|
public <T extends ParticleOptions> int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) {
|
2024-01-21 19:37:09 +01:00
|
|
|
+ // Paper start - Particle API
|
2021-06-11 14:02:28 +02:00
|
|
|
+ return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force);
|
|
|
|
+ }
|
2023-10-26 23:56:40 +02:00
|
|
|
+ public <T extends ParticleOptions> int sendParticles(List<ServerPlayer> receivers, @Nullable ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) {
|
2024-01-21 19:37:09 +01:00
|
|
|
+ // Paper end - Particle API
|
2021-06-11 14:02:28 +02:00
|
|
|
ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i);
|
|
|
|
// CraftBukkit end
|
|
|
|
int j = 0;
|
2023-09-22 00:01:00 +02:00
|
|
|
|
2021-06-11 14:02:28 +02:00
|
|
|
- for (int k = 0; k < this.players.size(); ++k) {
|
|
|
|
- ServerPlayer entityplayer = (ServerPlayer) this.players.get(k);
|
2024-01-21 19:37:09 +01:00
|
|
|
+ for (Player entityhuman : receivers) { // Paper - Particle API
|
|
|
|
+ ServerPlayer entityplayer = (ServerPlayer) entityhuman; // Paper - Particle API
|
2021-06-11 14:02:28 +02:00
|
|
|
if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit
|
2023-09-22 00:01:00 +02:00
|
|
|
|
2021-06-11 14:02:28 +02:00
|
|
|
if (this.sendParticles(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit
|
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
2024-12-03 15:47:48 +01:00
|
|
|
index 9ad27a6908ac07d87dc0453b61f69d3b3037a971..51e5cd3e56487c3438d9b4ab1670e551790967ac 100644
|
2021-06-11 14:02:28 +02:00
|
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
2024-12-03 15:47:48 +01:00
|
|
|
@@ -1989,8 +1989,19 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
2023-09-22 00:01:00 +02:00
|
|
|
|
2021-06-11 14:02:28 +02:00
|
|
|
@Override
|
|
|
|
public <T> void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) {
|
2024-01-21 19:37:09 +01:00
|
|
|
+ // Paper start - Particle API
|
2024-04-24 04:21:40 +02:00
|
|
|
+ this.spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, force);
|
2021-06-11 14:02:28 +02:00
|
|
|
+ }
|
2023-10-26 23:56:40 +02:00
|
|
|
+ @Override
|
2021-06-11 14:02:28 +02:00
|
|
|
+ public <T> void spawnParticle(Particle particle, List<Player> receivers, Player sender, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) {
|
2024-01-21 19:37:09 +01:00
|
|
|
+ // Paper end - Particle API
|
2024-04-25 23:21:18 +02:00
|
|
|
+ data = CraftParticle.convertLegacy(data);
|
|
|
|
+ if (data != null) {
|
|
|
|
+ Preconditions.checkArgument(particle.getDataType().isInstance(data), "data (%s) should be %s", data.getClass(), particle.getDataType());
|
|
|
|
+ }
|
2021-06-12 21:30:37 +02:00
|
|
|
this.getHandle().sendParticles(
|
2021-06-11 14:02:28 +02:00
|
|
|
- null, // Sender
|
2024-04-25 23:21:18 +02:00
|
|
|
+ receivers == null ? this.getHandle().players() : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API
|
2024-01-21 19:37:09 +01:00
|
|
|
+ sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API
|
2023-10-26 23:56:40 +02:00
|
|
|
CraftParticle.createParticleParam(particle, data), // Particle
|
2021-06-11 14:02:28 +02:00
|
|
|
x, y, z, // Position
|
|
|
|
count, // Count
|