ProjectAres/PGM/src/main/java/tc/oc/pgm/damage/HitboxPlayerFacet.java

192 lines
6.4 KiB
Java

package tc.oc.pgm.damage;
import java.util.HashSet;
import java.util.Set;
import javax.inject.Inject;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.geometry.Cuboid;
import org.bukkit.geometry.Ray;
import tc.oc.commons.bukkit.util.NMSHacks;
import tc.oc.pgm.map.MapInfo;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.match.MatchPlayer;
import tc.oc.pgm.match.MatchPlayerFacet;
import tc.oc.pgm.match.MatchScope;
import tc.oc.pgm.match.Repeatable;
public class HitboxPlayerFacet implements MatchPlayerFacet {
private static final double FAKE_WIDTH = 0.6;
private static final double FAKE_HEIGHT = 1.8;
private static final double PLAYER_WIDTH = 0.6;
private static final double PLAYER_HEIGHT = 1.8;
private static final double VIEW_RADIUS = 12;
// private final NMSHacks.FakeEntity[] fakes = new NMSHacks.FakeEntity[4];
// private final Location[] locations = new Location[4];
private final Match match;
private final HitboxMatchModule mm;
private final World world;
private final MatchPlayer matchPlayer;
private final Player player;
private final MapInfo mapInfo;
private final Set<Player> viewers = new HashSet<>();
private double width = PLAYER_WIDTH;
@Inject HitboxPlayerFacet(Match match, World world, MatchPlayer matchPlayer, Player player, MapInfo mapInfo) {
this.match = match;
this.mapInfo = mapInfo;
this.mm = match.needMatchModule(HitboxMatchModule.class);
this.world = world;
this.matchPlayer = matchPlayer;
this.player = player;
}
@Override
public void enable() {
/*for(int i = 0; i < fakes.length; i++) {
fakes[i] = new NMSHacks.FakeZombie(world, true);
locations[i] = new Location(world, 0, 0, 0);
mm.facets.put(fakes[i].entityId(), this);
}*/
}
@Override
public void disable() {
/*for(NMSHacks.FakeEntity fake : fakes) {
mm.facets.remove(fake.entityId());
}*/
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public Cuboid hitbox() {
if(hasFakeHitbox()) {
final Location location = player.getLocation();
final double radius = width / 2;
return Cuboid.between(location.position().minus(radius, 0, radius),
location.position().plus(radius, PLAYER_HEIGHT, radius));
} else {
return player.getBoundingBox();
}
}
public static Cuboid hitbox(Match match, LivingEntity victim) {
if(victim instanceof Player) {
final MatchPlayer matchVictim = match.getPlayer(victim);
if(matchVictim != null) {
return matchVictim.facet(HitboxPlayerFacet.class).hitbox();
}
}
return victim.getBoundingBox();
}
public boolean hasFakeHitbox() {
return matchPlayer.canInteract() && width > PLAYER_WIDTH;
}
public Location meleeHitLocation(LivingEntity attacker, double minDistanceFromAttacker, double offsetFromVictim) {
return meleeHitLocation(match, player, attacker, minDistanceFromAttacker, offsetFromVictim);
}
public static Location meleeHitLocation(Match match, LivingEntity victim, LivingEntity attacker, double minDistanceFromAttacker, double offsetFromVictim) {
// Find the attacker's line-of-sight distance to the victim
final Ray ray = attacker.getEyeRay();
double distance = hitbox(match, victim).intersectionDistance(ray);
// If attacker is not looking at the victim, take a rough guess at the distance
if(Double.isNaN(distance)) {
distance = ray.origin().distance(victim.getEyeLocation().position());
}
distance = Math.max(minDistanceFromAttacker, distance + offsetFromVictim);
return ray.atDistance(distance).toLocation(victim.getWorld());
}
void onUse(Player user, boolean attack, EquipmentSlot hand) {
NMSHacks.useEntity(user, player, attack, hand);
}
@Repeatable(scope = MatchScope.RUNNING)
public void updateViewers() {
/*final Location location = player.getLocation();
updateFakeLocations(location);
final Set<Player> remove = new HashSet<>(viewers);
if(hasFakeHitbox()) {
for(Entity entity : world.getNearbyEntities(location, VIEW_RADIUS, VIEW_RADIUS, VIEW_RADIUS)) {
if(entity instanceof Player && !entity.equals(player)) {
final Player viewer = (Player) entity;
if(isAttacker(viewer)) {
if(viewers.add(viewer)) {
spawnFakes(viewer);
} else {
remove.remove(viewer);
moveFakes(viewer);
}
}
}
}
}
for(Player viewer : remove) {
destroyFakes(viewer);
}
viewers.removeAll(remove);*/
}
private boolean isAttacker(Player attacker) {
final MatchPlayer mp = match.getPlayer(attacker);
return mp != null &&
mp.canInteract() &&
(mapInfo.friendlyFire ||
!mp.getParty().equals(matchPlayer.getParty()));
}
private void updateFakeLocations(Location c) {
final double y = c.getY() - (FAKE_HEIGHT - PLAYER_HEIGHT) / 2;
final double h = (width - FAKE_WIDTH) / 2;
final double px = c.getX() + h;
final double mx = c.getX() - h;
final double pz = c.getZ() + h;
final double mz = c.getZ() - h;
/* locations[0].setPosition(mx, y, mz);
locations[1].setPosition(px, y, mz);
locations[2].setPosition(mx, y, pz);
locations[3].setPosition(px, y, pz);*/
}
private void destroyFakes(Player viewer) {
/*for(NMSHacks.FakeEntity fake : fakes) {
fake.destroy(viewer);
}*/
}
private void spawnFakes(Player viewer) {
/*for(int i = 0; i < fakes.length; i++) {
fakes[i].spawn(viewer, locations[i]);
}*/
}
private void moveFakes(Player viewer) {
/*for(int i = 0; i < fakes.length; i++) {
fakes[i].teleport(viewer, locations[i]);
}*/
}
}