-
-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathProjectileManager.java
More file actions
235 lines (192 loc) · 8.11 KB
/
Copy pathProjectileManager.java
File metadata and controls
235 lines (192 loc) · 8.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
package at.pavlov.cannons.projectile;
import at.pavlov.cannons.Cannons;
import at.pavlov.cannons.CreateExplosion;
import at.pavlov.cannons.Enum.ProjectileCause;
import at.pavlov.cannons.dao.AsyncTaskManager;
import at.pavlov.internal.key.registries.Registries;
import at.pavlov.internal.projectile.definition.CustomProjectileDefinition;
import at.pavlov.internal.projectile.definition.ProjectilePhysics;
import com.google.common.base.Preconditions;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.AbstractArrow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.ThrowableProjectile;
import org.bukkit.entity.WitherSkull;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class ProjectileManager
{
private static ProjectileManager instance = null;
private final Cannons plugin;
private final ConcurrentHashMap<UUID, FlyingProjectile> flyingProjectilesMap = new ConcurrentHashMap<>();
public static void initialize(Cannons plugin) {
if (instance != null)
return;
instance = new ProjectileManager(plugin);
}
public static ProjectileManager getInstance() {
return instance;
}
/**
* ProjectileManager
* @param plugin - Cannons instance
*/
private ProjectileManager(Cannons plugin) {
this.plugin = plugin;
}
public Entity spawnProjectile(Projectile projectile, @NotNull UUID shooter, org.bukkit.projectiles.ProjectileSource source, Location playerLoc, Location spawnLoc, Vector velocity, UUID cannonId, ProjectileCause projectileCause) {
Preconditions.checkNotNull(shooter, "shooter for the projectile can't be null");
World world = spawnLoc.getWorld();
//set yaw, pitch for fireballs
double v = velocity.length();
spawnLoc.setPitch((float) (Math.acos(velocity.getY()/v)*180.0/Math.PI - 90));
spawnLoc.setYaw((float) (Math.atan2(velocity.getZ(),velocity.getX())*180.0/Math.PI - 90));
Entity projectileEntity = spawnProjectile(projectile, spawnLoc, velocity, world);
if (projectile.isProjectileOnFire())
projectileEntity.setFireTicks(100);
//projectileEntity.setTicksLived(2);
//create a new flying projectile container
FlyingProjectile cannonball = new FlyingProjectile(projectile, projectileEntity, shooter, source, playerLoc, cannonId, projectileCause);
flyingProjectilesMap.put(cannonball.getUID(), cannonball);
//detonate timefused projectiles
detonateTimefuse(cannonball);
return projectileEntity;
}
private @NotNull Entity spawnProjectile(Projectile projectile, Location spawnLoc, Vector velocity, World world) {
Entity entity = world.spawnEntity(spawnLoc, projectile.getProjectileEntity());
//calculate firing vector
entity.setVelocity(velocity);
CustomProjectileDefinition definition = Registries.CUSTOM_PROJECTILE_DEFINITION.of(projectile.getProjectileDefinitionKey());
if (definition == null) {
return entity;
}
entity.setVisualFire(definition.isOnFire());
entity.setGlowing(definition.isGlowing());
ProjectilePhysics defaultCase = Registries.DEFAULT_PROJECTILE_DEFINITION_REGISTRY.of(definition.getEntityKey());
if (defaultCase == null) {
defaultCase = ProjectilePhysics.DEFAULT;
}
if (!defaultCase.matches(definition)) {
entity.setGravity(false);
}
if (entity instanceof WitherSkull witherSkull) {
witherSkull.setCharged(definition.isCharged());
} else if (entity instanceof AbstractArrow arrow) {
arrow.setCritical(definition.isCritical());
} else if (entity instanceof ThrowableProjectile throwable) {
Material material = Material.matchMaterial(definition.getMaterial().full());
if (material == null) {
plugin.logSevere("In custom projectile: " + definition.getKey().full() + " the material key is invalid.");
material = Material.SNOWBALL;
}
ItemStack stack = new ItemStack(material);
ItemMeta meta = stack.getItemMeta();
meta.setCustomModelData(definition.getCustomModelData());
stack.setItemMeta(meta);
throwable.setItem(stack);
}
return entity;
}
/**
* detonate a timefused projectile mid air
* @param cannonball - the cannonball to detonate
*/
private void detonateTimefuse(final FlyingProjectile cannonball) {
if (cannonball.getProjectile().getTimefuse() <= 0) {
return;
}
//Delayed Task
AsyncTaskManager.get().scheduler.runTaskLater(() -> {
//find given UID in list
FlyingProjectile fproj = flyingProjectilesMap.get(cannonball.getUID());
if (fproj == null) {
return;
}
//detonate timefuse
var projectile_entity = fproj.getProjectileEntity();
//the projectile might be null
if (projectile_entity != null) {
CreateExplosion.getInstance().detonate(cannonball, projectile_entity);
projectile_entity.remove();
}
flyingProjectilesMap.remove(cannonball.getUID());
}, (long) (cannonball.getProjectile().getTimefuse()*20));
}
/**
* detonates the given projectile entity
* @param projectile - the projectile with this entity
*/
public void detonateProjectile(Entity projectile)
{
if(projectile == null || !(projectile instanceof org.bukkit.entity.Projectile))
return;
FlyingProjectile fproj = flyingProjectilesMap.get(projectile.getUniqueId());
if (fproj!=null)
{
CreateExplosion.getInstance().detonate(fproj, (org.bukkit.entity.Projectile) projectile);
projectile.remove();
flyingProjectilesMap.remove(fproj.getUID());
}
}
/**
* detonates the given projectile entity
* @param cannonball - the projectile with this entity
* @param target the entity hit by the projectile
*/
public void directHitProjectile(Entity cannonball, Entity target) {
if(cannonball == null || target == null) return;
FlyingProjectile fproj = flyingProjectilesMap.get(cannonball.getUniqueId());
if (fproj == null) {
return;
}
Entity projectile_entity = fproj.getProjectileEntity();
if (!fproj.hasDetonated() && cannonball.isValid()) {
fproj.setHasDetonated(true);
CreateExplosion.getInstance().directHit(fproj, projectile_entity, target);
projectile_entity.remove();
}
flyingProjectilesMap.remove(fproj.getUID());
}
/**
* returns true if the given entity is a cannonball projectile
* @param projectile flying projectile
* @return true if cannonball projectile
*/
public boolean isFlyingProjectile(Entity projectile)
{
FlyingProjectile fproj = flyingProjectilesMap.get(projectile.getUniqueId());
return fproj != null;
}
/**
* returns the list of all flying projectiles
* @return - the list of all flying projectiles
*/
public ConcurrentHashMap<UUID, FlyingProjectile> getFlyingProjectiles()
{
return flyingProjectilesMap;
}
/**
* returns the projectile of which the player is passenger
* if the player is attached to a projectile he will follow its movement
* @param player is the passenger
* @return the projectile or null
*/
public FlyingProjectile getAttachedProjectile(Player player)
{
if (player == null) {
return null;
}
for (FlyingProjectile proj : flyingProjectilesMap.values())
if (proj.getShooterUID().equals(player.getUniqueId()))
return proj;
return null;
}
}