Skip to content

Commit 354a6ad

Browse files
committed
Update API
1 parent ffe7d9e commit 354a6ad

7 files changed

Lines changed: 102 additions & 68 deletions

File tree

build.gradle.kts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ publishing {
2020
publications.create<MavenPublication>("maven") {
2121
groupId = "ca.atlasengine"
2222
artifactId = "atlas-projectiles"
23-
version = "1.0.0"
23+
version = "1.0.2"
2424

2525
from(components["java"])
2626
}
@@ -41,8 +41,8 @@ dependencies {
4141
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1")
4242
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
4343

44-
compileOnly("net.minestom:minestom-snapshots:f1d5940855")
45-
testImplementation("net.minestom:minestom-snapshots:f1d5940855")
44+
compileOnly("net.minestom:minestom-snapshots:a521c4e7cd")
45+
testImplementation("net.minestom:minestom-snapshots:a521c4e7cd")
4646
}
4747

4848
tasks.getByName<Test>("test") {

src/main/java/ca/atlasengine/projectiles/AbstractProjectile.java

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
package ca.atlasengine.projectiles;
22

33
import net.minestom.server.ServerFlag;
4-
import net.minestom.server.collision.Aerodynamics;
5-
import net.minestom.server.collision.CollisionUtils;
6-
import net.minestom.server.collision.PhysicsResult;
7-
import net.minestom.server.collision.ShapeImpl;
4+
import net.minestom.server.collision.*;
85
import net.minestom.server.coordinate.Point;
96
import net.minestom.server.coordinate.Pos;
107
import net.minestom.server.coordinate.Vec;
118
import net.minestom.server.entity.Entity;
129
import net.minestom.server.entity.EntityType;
1310
import net.minestom.server.event.EventDispatcher;
1411
import net.minestom.server.event.entity.EntityTickEvent;
12+
import net.minestom.server.event.entity.projectile.ProjectileCollideWithBlockEvent;
13+
import net.minestom.server.event.entity.projectile.ProjectileCollideWithEntityEvent;
1514
import net.minestom.server.instance.Chunk;
1615
import net.minestom.server.instance.block.Block;
1716
import net.minestom.server.utils.chunk.ChunkCache;
@@ -21,6 +20,7 @@
2120
public abstract class AbstractProjectile extends Entity implements Projectile {
2221
protected final Entity shooter;
2322
protected PhysicsResult previousPhysicsResult;
23+
private Pos previousPosition;
2424

2525
public AbstractProjectile(EntityType type, Entity shooter) {
2626
super(type);
@@ -52,6 +52,7 @@ protected void movementTick() {
5252
this.gravityTickCount = onGround ? 0 : gravityTickCount + 1;
5353
if (vehicle != null) return;
5454

55+
this.previousPosition = position;
5556
final Block.Getter chunkCache = new ChunkCache(instance, currentChunk, Block.STONE);
5657
PhysicsResult result = computePhysics(
5758
position, velocity.div(ServerFlag.SERVER_TICKS_PER_SECOND),
@@ -60,44 +61,71 @@ protected void movementTick() {
6061
Chunk finalChunk = ChunkUtils.retrieve(instance, currentChunk, result.newPosition());
6162
if (!ChunkUtils.isLoaded(finalChunk)) return;
6263

63-
if (result.hasCollision()) {
64+
onGround = result.isOnGround();
65+
66+
if (!result.hasCollision()) {
67+
velocity = previousPhysicsResult.newVelocity().mul(ServerFlag.SERVER_TICKS_PER_SECOND).mul(0.99);
68+
}
69+
70+
refreshPosition(result.newPosition(), true, false);
71+
if (hasVelocity()) sendPacketToViewers(getVelocityPacket());
72+
}
73+
74+
protected void callBlockCollision() {
75+
if (previousPhysicsResult.hasCollision()) {
6476
Block hitBlock = null;
6577
Point hitPoint = null;
66-
if (result.collisionShapes()[0] instanceof ShapeImpl block) {
78+
if (previousPhysicsResult.collisionShapes()[0] instanceof ShapeImpl block) {
6779
hitBlock = block.block();
68-
hitPoint = result.collisionPoints()[0];
80+
hitPoint = previousPhysicsResult.collisionPoints()[0];
6981
}
70-
if (result.collisionShapes()[1] instanceof ShapeImpl block) {
82+
if (previousPhysicsResult.collisionShapes()[1] instanceof ShapeImpl block) {
7183
hitBlock = block.block();
72-
hitPoint = result.collisionPoints()[1];
84+
hitPoint = previousPhysicsResult.collisionPoints()[1];
7385
}
74-
if (result.collisionShapes()[2] instanceof ShapeImpl block) {
86+
if (previousPhysicsResult.collisionShapes()[2] instanceof ShapeImpl block) {
7587
hitBlock = block.block();
76-
hitPoint = result.collisionPoints()[2];
88+
hitPoint = previousPhysicsResult.collisionPoints()[2];
7789
}
7890

7991
if (hitBlock == null) return;
80-
handleBlockCollision(hitBlock, hitPoint, position);
81-
} else {
82-
velocity = result.newVelocity().mul(ServerFlag.SERVER_TICKS_PER_SECOND).mul(0.99);
92+
handleBlockCollision(hitBlock, hitPoint, previousPosition);
8393
}
94+
}
8495

85-
onGround = result.isOnGround();
96+
protected void callBlockCollisionEvent(@NotNull Pos pos, Block hitBlock) {
97+
var e = new ProjectileCollideWithBlockEvent(this, pos, hitBlock);
98+
EventDispatcher.call(e);
99+
}
86100

87-
refreshPosition(result.newPosition(), true, false);
88-
if (hasVelocity()) sendPacketToViewers(getVelocityPacket());
101+
protected boolean callEntityCollisionEvent(@NotNull Pos pos, @NotNull Entity entity) {
102+
ProjectileCollideWithEntityEvent e = new ProjectileCollideWithEntityEvent(this, pos, entity);
103+
EventDispatcher.call(e);
104+
if (!e.isCancelled()) {
105+
remove();
106+
return true;
107+
}
108+
109+
return false;
89110
}
90111

91-
protected void checkEntityCollision(Pos previousPos, Pos currentPos) {
92-
var diff = currentPos.sub(previousPos).asVec();
112+
protected boolean callEntityCollision() {
113+
if (previousPhysicsResult == null) return false;
114+
var diff = previousPhysicsResult.newPosition().sub(previousPosition).asVec();
93115

94-
PhysicsResult entityResult = CollisionUtils.checkEntityCollisions(instance, boundingBox, previousPos, diff, diff.length(),
116+
var collidedEntities = CollisionUtils.checkEntityCollisions(instance, boundingBox, previousPosition, diff, diff.length(),
95117
entity -> entity != shooter && entity != this, previousPhysicsResult);
96118

97-
if (entityResult.hasCollision()) {
98-
Entity hitEntity = (Entity) entityResult.collisionShapes()[0];
99-
handleEntityCollision(hitEntity, entityResult.newPosition(), currentPos);
119+
var arr = collidedEntities.stream().sorted().toList();
120+
if (!arr.isEmpty()) {
121+
for (var collision : arr) {
122+
if (handleEntityCollision(collision, previousPhysicsResult.newPosition(), previousPosition)) {
123+
return true;
124+
}
125+
}
100126
}
127+
128+
return false;
101129
}
102130

103131
protected void updatePosition(long time) {
@@ -108,7 +136,16 @@ protected void updatePosition(long time) {
108136
EventDispatcher.call(new EntityTickEvent(this));
109137
}
110138

111-
abstract protected void handleBlockCollision(Block hitBlock, Point hitPos, Pos posBefore);
112-
abstract protected void handleEntityCollision(Entity hitEntity, Point hitPos, Pos posBefore);
113-
abstract protected @NotNull Vec updateVelocity(@NotNull Pos entityPosition, @NotNull Vec currentVelocity, @NotNull Block.@NotNull Getter blockGetter, @NotNull Aerodynamics aerodynamics, boolean positionChanged, boolean entityFlying, boolean entityOnGround, boolean entityNoGravity);
139+
/**
140+
* Handle entity collision
141+
* @param hitEntity the entity that was hit
142+
* @param hitPos the position where the entity was hit
143+
* @param posBefore the position before the collision
144+
* @return true if block collisions should be ignored
145+
*/
146+
protected abstract boolean handleEntityCollision(EntityCollisionResult hitEntity, Point hitPos, Pos posBefore);
147+
148+
protected abstract void handleBlockCollision(Block hitBlock, Point hitPos, Pos posBefore);
149+
150+
protected abstract @NotNull Vec updateVelocity(@NotNull Pos entityPosition, @NotNull Vec currentVelocity, @NotNull Block.@NotNull Getter blockGetter, @NotNull Aerodynamics aerodynamics, boolean positionChanged, boolean entityFlying, boolean entityOnGround, boolean entityNoGravity);
114151
}

src/main/java/ca/atlasengine/projectiles/entities/ArrowProjectile.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import net.minestom.server.ServerFlag;
66
import net.minestom.server.collision.Aerodynamics;
77
import net.minestom.server.collision.BoundingBox;
8+
import net.minestom.server.collision.EntityCollisionResult;
89
import net.minestom.server.coordinate.Point;
910
import net.minestom.server.coordinate.Pos;
1011
import net.minestom.server.coordinate.Vec;
@@ -14,7 +15,6 @@
1415
import net.minestom.server.entity.metadata.projectile.ProjectileMeta;
1516
import net.minestom.server.event.EventDispatcher;
1617
import net.minestom.server.event.entity.EntityShootEvent;
17-
import net.minestom.server.event.entity.projectile.ProjectileCollideWithEntityEvent;
1818
import net.minestom.server.instance.block.Block;
1919
import net.minestom.server.instance.block.BlockHandler;
2020
import org.jetbrains.annotations.NotNull;
@@ -72,7 +72,8 @@ public void tick(long time) {
7272
setView(yaw, pitch);
7373
}
7474

75-
checkEntityCollision(posBefore, posNow);
75+
if (!callEntityCollision())
76+
callBlockCollision();
7677
}
7778

7879
public void shoot(@NotNull Point from, @NotNull Point to, double power, double spread) {
@@ -132,23 +133,23 @@ protected void handleBlockCollision(Block hitBlock, Point hitPos, Pos posBefore)
132133

133134
inBlock = true;
134135
velocity = Vec.fromPoint(hitPos.sub(posBefore));
136+
135137
Vec v = velocity.normalize().mul(0.01f); // required so the entity is lit (just outside the block)
136138

137139
// if the value is zero, it will be unlit. If the value is more than 0.01, there will be noticeable pitch change visually
138140
position = new Pos(hitPos.x()-v.x(), hitPos.y()-v.y(), hitPos.z()-v.z(), posBefore.yaw(), posBefore.pitch());
139141
MinecraftServer.getSchedulerManager().scheduleNextTick(this::synchronizePosition); // required as in rare situations there will be a slight disagreement with the client and server on if it hit or not | also scheduling next tick so it doesn't jump to the hit position until it has actually hit
142+
143+
callBlockCollisionEvent(Pos.fromPoint(hitPos), hitBlock);
144+
140145
BlockHandler blockHandler = hitBlock.handler();
141146
if (blockHandler == null) return;
142147
blockHandler.onTouch(new BlockHandler.Touch(hitBlock, instance, hitPos, this));
143148
}
144149

145150
@Override
146-
protected void handleEntityCollision(Entity hitEntity, Point hitPos, Pos posBefore) {
147-
ProjectileCollideWithEntityEvent e = new ProjectileCollideWithEntityEvent(this, Pos.fromPoint(hitPos), hitEntity);
148-
MinecraftServer.getGlobalEventHandler().call(e);
149-
if (!e.isCancelled()) {
150-
remove();
151-
}
151+
protected boolean handleEntityCollision(EntityCollisionResult result, Point hitPos, Pos posBefore) {
152+
return callEntityCollisionEvent(Pos.fromPoint(hitPos), result.entity());
152153
}
153154

154155
protected @NotNull Vec updateVelocity(@NotNull Pos entityPosition, @NotNull Vec currentVelocity, @NotNull Block.@NotNull Getter blockGetter, @NotNull Aerodynamics aerodynamics, boolean positionChanged, boolean entityFlying, boolean entityOnGround, boolean entityNoGravity) {

src/main/java/ca/atlasengine/projectiles/entities/FireballProjectile.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
import net.minestom.server.MinecraftServer;
55
import net.minestom.server.ServerFlag;
66
import net.minestom.server.collision.Aerodynamics;
7+
import net.minestom.server.collision.EntityCollisionResult;
78
import net.minestom.server.coordinate.Point;
89
import net.minestom.server.coordinate.Pos;
910
import net.minestom.server.coordinate.Vec;
1011
import net.minestom.server.entity.Entity;
1112
import net.minestom.server.entity.EntityType;
1213
import net.minestom.server.event.EventDispatcher;
1314
import net.minestom.server.event.entity.EntityShootEvent;
14-
import net.minestom.server.event.entity.projectile.ProjectileCollideWithEntityEvent;
1515
import net.minestom.server.instance.block.Block;
1616
import net.minestom.server.instance.block.BlockHandler;
1717
import org.jetbrains.annotations.NotNull;
@@ -31,11 +31,9 @@ public FireballProjectile(EntityType type, Entity shooter) {
3131
public void tick(long time) {
3232
if (removed || inBlock) return;
3333

34-
final Pos posBefore = getPosition();
3534
updatePosition(time);
36-
final Pos posNow = getPosition();
37-
38-
checkEntityCollision(posBefore, posNow);
35+
callEntityCollision();
36+
callBlockCollision();
3937
}
4038

4139
@Override
@@ -99,15 +97,17 @@ protected void handleBlockCollision(Block hitBlock, Point hitPos, Pos posBefore)
9997
// if the value is zero, it will be unlit. If the value is more than 0.01, there will be noticeable pitch change visually
10098
position = new Pos(hitPos.x()-v.x(), hitPos.y()-v.y(), hitPos.z()-v.z(), posBefore.yaw(), posBefore.pitch());
10199
MinecraftServer.getSchedulerManager().scheduleNextTick(this::synchronizePosition); // required as in rare situations there will be a slight disagreement with the client and server on if it hit or not | also scheduling next tick so it doesn't jump to the hit position until it has actually hit
100+
101+
callBlockCollisionEvent(Pos.fromPoint(hitPos), hitBlock);
102+
102103
BlockHandler blockHandler = hitBlock.handler();
103104
if (blockHandler == null) return;
104105
blockHandler.onTouch(new BlockHandler.Touch(hitBlock, instance, hitPos, this));
105106
}
106107

107108
@Override
108-
protected void handleEntityCollision(Entity hitEntity, Point hitPos, Pos posBefore) {
109-
ProjectileCollideWithEntityEvent e = new ProjectileCollideWithEntityEvent(this, Pos.fromPoint(hitPos), hitEntity);
110-
MinecraftServer.getGlobalEventHandler().call(e);
109+
protected boolean handleEntityCollision(EntityCollisionResult result, Point hitPos, Pos posBefore) {
110+
return callEntityCollisionEvent(Pos.fromPoint(hitPos), result.entity());
111111
}
112112

113113
protected @NotNull Vec updateVelocity(@NotNull Pos entityPosition, @NotNull Vec currentVelocity, @NotNull Block.@NotNull Getter blockGetter, @NotNull Aerodynamics aerodynamics, boolean positionChanged, boolean entityFlying, boolean entityOnGround, boolean entityNoGravity) {
@@ -116,4 +116,4 @@ protected void handleEntityCollision(Entity hitEntity, Point hitPos, Pos posBefo
116116
double z = currentVelocity.z();
117117
return new Vec(Math.abs(x) < 1.0E-6 ? 0.0 : x, Math.abs(y) < 1.0E-6 ? 0.0 : y, Math.abs(z) < 1.0E-6 ? 0.0 : z);
118118
}
119-
}
119+
}

src/main/java/ca/atlasengine/projectiles/entities/FollowProjectile.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
import net.minestom.server.MinecraftServer;
55
import net.minestom.server.ServerFlag;
66
import net.minestom.server.collision.Aerodynamics;
7+
import net.minestom.server.collision.EntityCollisionResult;
78
import net.minestom.server.coordinate.Point;
89
import net.minestom.server.coordinate.Pos;
910
import net.minestom.server.coordinate.Vec;
1011
import net.minestom.server.entity.Entity;
1112
import net.minestom.server.entity.EntityType;
1213
import net.minestom.server.event.EventDispatcher;
1314
import net.minestom.server.event.entity.EntityShootEvent;
14-
import net.minestom.server.event.entity.projectile.ProjectileCollideWithEntityEvent;
1515
import net.minestom.server.instance.block.Block;
1616
import net.minestom.server.instance.block.BlockHandler;
1717
import org.jetbrains.annotations.NotNull;
@@ -40,11 +40,8 @@ public FollowProjectile(EntityType type, Entity shooter, Entity target, float at
4040
public void tick(long time) {
4141
if (removed || inBlock) return;
4242

43-
final Pos posBefore = getPosition();
4443
updatePosition(time);
45-
final Pos posNow = getPosition();
46-
47-
checkEntityCollision(posBefore, posNow);
44+
callEntityCollision();
4845

4946
ticks++;
5047
}
@@ -114,15 +111,17 @@ protected void handleBlockCollision(Block hitBlock, Point hitPos, Pos posBefore)
114111
// if the value is zero, it will be unlit. If the value is more than 0.01, there will be noticeable pitch change visually
115112
position = new Pos(hitPos.x(), hitPos.y(), hitPos.z(), posBefore.yaw(), posBefore.pitch());
116113
MinecraftServer.getSchedulerManager().scheduleNextTick(this::synchronizePosition); // required as in rare situations there will be a slight disagreement with the client and server on if it hit or not | also scheduling next tick so it doesn't jump to the hit position until it has actually hit
114+
115+
callBlockCollisionEvent(Pos.fromPoint(hitPos), hitBlock);
116+
117117
BlockHandler blockHandler = hitBlock.handler();
118118
if (blockHandler == null) return;
119119
blockHandler.onTouch(new BlockHandler.Touch(hitBlock, instance, hitPos, this));
120120
}
121121

122122
@Override
123-
protected void handleEntityCollision(Entity hitEntity, Point hitPos, Pos posBefore) {
124-
ProjectileCollideWithEntityEvent e = new ProjectileCollideWithEntityEvent(this, Pos.fromPoint(hitPos), hitEntity);
125-
MinecraftServer.getGlobalEventHandler().call(e);
123+
protected boolean handleEntityCollision(EntityCollisionResult result, Point hitPos, Pos posBefore) {
124+
return callEntityCollisionEvent(Pos.fromPoint(hitPos), result.entity());
126125
}
127126

128127
protected @NotNull Vec updateVelocity(@NotNull Pos entityPosition, @NotNull Vec currentVelocity, @NotNull Block.@NotNull Getter blockGetter, @NotNull Aerodynamics aerodynamics, boolean positionChanged, boolean entityFlying, boolean entityOnGround, boolean entityNoGravity) {

src/main/java/ca/atlasengine/projectiles/entities/ThrownItemProjectile.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@
44
import net.minestom.server.MinecraftServer;
55
import net.minestom.server.ServerFlag;
66
import net.minestom.server.collision.Aerodynamics;
7+
import net.minestom.server.collision.EntityCollisionResult;
78
import net.minestom.server.coordinate.Point;
89
import net.minestom.server.coordinate.Pos;
910
import net.minestom.server.coordinate.Vec;
1011
import net.minestom.server.entity.Entity;
1112
import net.minestom.server.entity.EntityType;
1213
import net.minestom.server.event.EventDispatcher;
1314
import net.minestom.server.event.entity.EntityShootEvent;
14-
import net.minestom.server.event.entity.projectile.ProjectileCollideWithEntityEvent;
1515
import net.minestom.server.instance.block.Block;
1616
import net.minestom.server.instance.block.BlockHandler;
17-
import net.minestom.server.network.packet.server.play.ParticlePacket;
18-
import net.minestom.server.particle.Particle;
1917
import org.jetbrains.annotations.NotNull;
2018

2119
import java.util.Random;
@@ -31,12 +29,8 @@ public ThrownItemProjectile(EntityType type, Entity shooter) {
3129
@Override
3230
public void tick(long time) {
3331
if (removed || inBlock) return;
34-
35-
final Pos posBefore = getPosition();
3632
updatePosition(time);
37-
final Pos posNow = getPosition();
38-
39-
checkEntityCollision(posBefore, posNow);
33+
callEntityCollision();
4034
}
4135

4236
@Override
@@ -99,15 +93,17 @@ protected void handleBlockCollision(Block hitBlock, Point hitPos, Pos posBefore)
9993
// if the value is zero, it will be unlit. If the value is more than 0.01, there will be noticeable pitch change visually
10094
position = new Pos(hitPos.x(), hitPos.y(), hitPos.z(), posBefore.yaw(), posBefore.pitch());
10195
MinecraftServer.getSchedulerManager().scheduleNextTick(this::synchronizePosition); // required as in rare situations there will be a slight disagreement with the client and server on if it hit or not | also scheduling next tick so it doesn't jump to the hit position until it has actually hit
96+
97+
callBlockCollisionEvent(Pos.fromPoint(hitPos), hitBlock);
98+
10299
BlockHandler blockHandler = hitBlock.handler();
103100
if (blockHandler == null) return;
104101
blockHandler.onTouch(new BlockHandler.Touch(hitBlock, instance, hitPos, this));
105102
}
106103

107104
@Override
108-
protected void handleEntityCollision(Entity hitEntity, Point hitPos, Pos posBefore) {
109-
ProjectileCollideWithEntityEvent e = new ProjectileCollideWithEntityEvent(this, Pos.fromPoint(hitPos), hitEntity);
110-
MinecraftServer.getGlobalEventHandler().call(e);
105+
protected boolean handleEntityCollision(EntityCollisionResult result, Point hitPos, Pos posBefore) {
106+
return callEntityCollisionEvent(Pos.fromPoint(hitPos), result.entity());
111107
}
112108

113109
protected @NotNull Vec updateVelocity(@NotNull Pos entityPosition, @NotNull Vec currentVelocity, @NotNull Block.@NotNull Getter blockGetter, @NotNull Aerodynamics aerodynamics, boolean positionChanged, boolean entityFlying, boolean entityOnGround, boolean entityNoGravity) {

0 commit comments

Comments
 (0)