added lazer gun item
This commit is contained in:
@@ -182,6 +182,12 @@ public abstract class ItemPresets {
|
|||||||
.customModelData(1111)
|
.customModelData(1111)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static ItemStack LAZER_GUN = ItemBuilder.create()
|
||||||
|
.material(Material.IRON_HORSE_ARMOR)
|
||||||
|
.name(Text.ofAll("&aGreen &7Lazer Blaster"))
|
||||||
|
.lore(Text.ofAll("&8click to shoot"))
|
||||||
|
.build();
|
||||||
|
|
||||||
public static ItemStack BLANK = ItemBuilder.create()
|
public static ItemStack BLANK = ItemBuilder.create()
|
||||||
.material(Material.LIGHT_GRAY_STAINED_GLASS_PANE)
|
.material(Material.LIGHT_GRAY_STAINED_GLASS_PANE)
|
||||||
.name(" ")
|
.name(" ")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package fun.ogre.ogredupealias.plugin.custom.items;
|
package fun.ogre.ogredupealias.plugin.custom.items;
|
||||||
|
|
||||||
|
import fun.ogre.ogredupealias.plugin.custom.items.customitems.LazerGunItem;
|
||||||
import fun.ogre.ogredupealias.plugin.custom.items.customitems.LazerItem;
|
import fun.ogre.ogredupealias.plugin.custom.items.customitems.LazerItem;
|
||||||
import fun.ogre.ogredupealias.plugin.custom.items.customitems.RailgunItem;
|
import fun.ogre.ogredupealias.plugin.custom.items.customitems.RailgunItem;
|
||||||
import fun.ogre.ogredupealias.plugin.custom.items.customitems.TazerItem;
|
import fun.ogre.ogredupealias.plugin.custom.items.customitems.TazerItem;
|
||||||
@@ -21,6 +22,7 @@ public final class CustomItems implements Listener {
|
|||||||
register(new TazerItem());
|
register(new TazerItem());
|
||||||
register(new LazerItem());
|
register(new LazerItem());
|
||||||
register(new RailgunItem());
|
register(new RailgunItem());
|
||||||
|
register(new LazerGunItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack register(ItemStack item, CustomItemInteractionCallback interactionCallback) {
|
public static ItemStack register(ItemStack item, CustomItemInteractionCallback interactionCallback) {
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package fun.ogre.ogredupealias.plugin.custom.items.customitems;
|
||||||
|
|
||||||
|
import fun.ogre.ogredupealias.plugin.ItemPresets;
|
||||||
|
import fun.ogre.ogredupealias.plugin.custom.items.CustomItem;
|
||||||
|
import fun.ogre.ogredupealias.plugin.custom.items.CustomItemInteractionCallback;
|
||||||
|
import fun.ogre.ogredupealias.utils.SoundPlayer;
|
||||||
|
import fun.ogre.ogredupealias.utils.raytracers.BlockDisplayRaytracer;
|
||||||
|
import fun.ogre.ogredupealias.utils.raytracers.CustomDisplayRaytracer;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class LazerGunItem extends CustomItem {
|
||||||
|
|
||||||
|
public static final Material LAZER_COLOR = Material.LIME_CONCRETE;
|
||||||
|
|
||||||
|
public LazerGunItem() {
|
||||||
|
super("lazergun", ItemPresets.LAZER_GUN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CustomItemInteractionCallback getCallback() {
|
||||||
|
return (player, item, event) -> {
|
||||||
|
Action action = event.getAction();
|
||||||
|
|
||||||
|
if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) {
|
||||||
|
SoundPlayer shootSound = new SoundPlayer(player.getLocation(), Sound.BLOCK_BEACON_DEACTIVATE, 10, 10);
|
||||||
|
shootSound.playWithin(10);
|
||||||
|
trace(0, 10, player, player.getEyeLocation().add(0, -0.2, 0), player.getLocation().getDirection(), 64, 10);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trace(int attempts, int maxAttempts, LivingEntity shooter, Location start, Vector direction, double distance, double damage) {
|
||||||
|
CustomDisplayRaytracer.Point result = CustomDisplayRaytracer.trace(start, direction, distance, 0.05, point -> {
|
||||||
|
List<Entity> nearby = point.getNearbyEntities(shooter, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead());
|
||||||
|
if (!nearby.isEmpty() && nearby.get(0) instanceof LivingEntity entity) {
|
||||||
|
entity.damage(damage, shooter);
|
||||||
|
}
|
||||||
|
return (!nearby.isEmpty() || CustomDisplayRaytracer.HIT_BLOCK.test(point)) && point.getTraveledDist() > 0.3;
|
||||||
|
});
|
||||||
|
BlockDisplayRaytracer.trace(LAZER_COLOR, start, result.getLoc(), 10);
|
||||||
|
SoundPlayer shootSound = new SoundPlayer(result.getLoc(), Sound.BLOCK_BEACON_ACTIVATE, 1, 10);
|
||||||
|
shootSound.playWithin(10);
|
||||||
|
|
||||||
|
if (CustomDisplayRaytracer.HIT_BLOCK.test(result)) {
|
||||||
|
BlockDisplayRaytracer.outline(LAZER_COLOR, result.getLoc(), 10);
|
||||||
|
if (attempts < maxAttempts) {
|
||||||
|
trace(attempts + 1, maxAttempts, shooter, result.getLoc(), reflect(result.getLoc(), direction), distance, damage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector reflect(Location pointOfContact, Vector incoming) {
|
||||||
|
Vector negate = incoming.clone().multiply(-1).normalize();
|
||||||
|
Vector contact = getContactingVector(pointOfContact.getBlock(), pointOfContact).multiply(-1);
|
||||||
|
Vector reflect = contact.subtract(negate).normalize();
|
||||||
|
return reflect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector getContactingVector(Block block, Location pointOfContact) {
|
||||||
|
Vector center = block.getLocation().add(0.5, 0.5, 0.5).toVector();
|
||||||
|
Vector incoming = center.subtract(pointOfContact.toVector()).normalize();
|
||||||
|
double x = incoming.dot(new Vector(1, 0, 0));
|
||||||
|
double y = incoming.dot(new Vector(0, 1, 0));
|
||||||
|
double z = incoming.dot(new Vector(0, 0, 1));
|
||||||
|
double ax = Math.abs(x);
|
||||||
|
double ay = Math.abs(y);
|
||||||
|
double az = Math.abs(z);
|
||||||
|
|
||||||
|
if (ax > ay && ax > az) {
|
||||||
|
return new Vector(x, 0, 0).normalize();
|
||||||
|
}
|
||||||
|
else if (ay > ax && ay > az) {
|
||||||
|
return new Vector(0, y, 0).normalize();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new Vector(0, 0, z).normalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package fun.ogre.ogredupealias.utils.raytracers;
|
||||||
|
|
||||||
|
import fun.ogre.ogredupealias.OgreDupeAlias;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.BlockDisplay;
|
||||||
|
import org.bukkit.entity.Display;
|
||||||
|
import org.bukkit.util.Consumer;
|
||||||
|
import org.bukkit.util.Transformation;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.joml.AxisAngle4f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
public class BlockDisplayRaytracer {
|
||||||
|
|
||||||
|
private static final OgreDupeAlias system = OgreDupeAlias.instance;
|
||||||
|
|
||||||
|
public static void outline(Material display, Location location, long stayTime) {
|
||||||
|
outline(display, location, 0.05, stayTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void outline(Material display, Location location, double thickness, long stayTime) {
|
||||||
|
Location og = location.getBlock().getLocation();
|
||||||
|
|
||||||
|
Location a1 = og.clone().add(0, 0, 0);
|
||||||
|
Location a2 = og.clone().add(1, 0, 0);
|
||||||
|
Location a3 = og.clone().add(1, 0, 1);
|
||||||
|
Location a4 = og.clone().add(0, 0, 1);
|
||||||
|
|
||||||
|
Location b1 = og.clone().add(0, 1, 0);
|
||||||
|
Location b2 = og.clone().add(1, 1, 0);
|
||||||
|
Location b3 = og.clone().add(1, 1, 1);
|
||||||
|
Location b4 = og.clone().add(0, 1, 1);
|
||||||
|
|
||||||
|
trace(display, a1, a2, thickness, stayTime);
|
||||||
|
trace(display, a2, a3, thickness, stayTime);
|
||||||
|
trace(display, a3, a4, thickness, stayTime);
|
||||||
|
trace(display, a4, a1, thickness, stayTime);
|
||||||
|
|
||||||
|
trace(display, b1, b2, thickness, stayTime);
|
||||||
|
trace(display, b2, b3, thickness, stayTime);
|
||||||
|
trace(display, b3, b4, thickness, stayTime);
|
||||||
|
trace(display, b4, b1, thickness, stayTime);
|
||||||
|
|
||||||
|
trace(display, a1, b1, thickness, stayTime);
|
||||||
|
trace(display, a2, b2, thickness, stayTime);
|
||||||
|
trace(display, a3, b3, thickness, stayTime);
|
||||||
|
trace(display, a4, b4, thickness, stayTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void trace(Material display, Location start, Location end, long stayTime) {
|
||||||
|
trace(display, start, end.toVector().subtract(start.toVector()), 0.05, end.distance(start), stayTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void trace(Material display, Location start, Location end, double thickness, long stayTime) {
|
||||||
|
trace(display, start, end.toVector().subtract(start.toVector()), thickness, end.distance(start), stayTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime) {
|
||||||
|
World world = start.getWorld();
|
||||||
|
|
||||||
|
BlockDisplay beam = world.spawn(start, BlockDisplay.class, entity -> {
|
||||||
|
AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1);
|
||||||
|
Vector3f transition = new Vector3f(-(float)(thickness / 2F));
|
||||||
|
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
||||||
|
Transformation trans = new Transformation(transition, angle, scale, angle);
|
||||||
|
Location vector = entity.getLocation();
|
||||||
|
|
||||||
|
vector.setDirection(direction);
|
||||||
|
entity.teleport(vector);
|
||||||
|
entity.setBlock(display.createBlockData());
|
||||||
|
entity.setBrightness(new Display.Brightness(15, 15));
|
||||||
|
entity.setInterpolationDelay(0);
|
||||||
|
entity.setTransformation(trans);
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(system, entity::remove, stayTime);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void trace(Material display, Location start, Vector direction, double thickness, double distance, long stayTime, Consumer<BlockDisplay> onEntitySpawn) {
|
||||||
|
World world = start.getWorld();
|
||||||
|
|
||||||
|
BlockDisplay beam = world.spawn(start, BlockDisplay.class, entity -> {
|
||||||
|
AxisAngle4f angle = new AxisAngle4f(0, 0, 0, 1);
|
||||||
|
Vector3f transition = new Vector3f(-(float)(thickness / 2F));
|
||||||
|
Vector3f scale = new Vector3f((float)thickness, (float)thickness, (float)distance);
|
||||||
|
Transformation trans = new Transformation(transition, angle, scale, angle);
|
||||||
|
Location vector = entity.getLocation();
|
||||||
|
|
||||||
|
vector.setDirection(direction);
|
||||||
|
entity.teleport(vector);
|
||||||
|
entity.setBlock(display.createBlockData());
|
||||||
|
entity.setBrightness(new Display.Brightness(15, 15));
|
||||||
|
entity.setInterpolationDelay(0);
|
||||||
|
entity.setTransformation(trans);
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(system, entity::remove, stayTime);
|
||||||
|
Bukkit.getScheduler().runTaskLater(system, () -> onEntitySpawn.accept(entity), 5);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
package fun.ogre.ogredupealias.utils.raytracers;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class CustomDisplayRaytracer {
|
||||||
|
|
||||||
|
public static final Predicate<Point> HIT_BLOCK = point -> {
|
||||||
|
Block b = point.getBlock();
|
||||||
|
Vector v = point.getLoc().toVector();
|
||||||
|
return !b.isPassable() && b.getCollisionShape().getBoundingBoxes().stream().noneMatch(box -> box.contains(v));
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final Predicate<Point> HIT_ENTITY = point -> {
|
||||||
|
return !point.getNearbyEntities(null, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead()).isEmpty();
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final Predicate<Point> HIT_BLOCK_OR_ENTITY = point -> {
|
||||||
|
return HIT_BLOCK.test(point) || HIT_ENTITY.test(point);
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final Predicate<Point> HIT_BLOCK_AND_ENTITY = point -> {
|
||||||
|
return HIT_BLOCK.test(point) && HIT_ENTITY.test(point);
|
||||||
|
};
|
||||||
|
|
||||||
|
public static Predicate<Point> hitEntityExclude(Entity exclude) {
|
||||||
|
return point -> !point.getNearbyEntities(exclude, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<Point> hitAnythingExclude(Entity exclude) {
|
||||||
|
return point -> HIT_BLOCK.test(point) || !point.getNearbyEntities(exclude, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<Point> hitEverythingExclude(Entity exclude) {
|
||||||
|
return point -> HIT_BLOCK.test(point) && !point.getNearbyEntities(exclude, 5, true, 0.1, e -> e instanceof LivingEntity le && !le.isDead()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Point trace(Location start, Location end, Predicate<Point> hitCondition) {
|
||||||
|
return trace(start, end, 0.5, hitCondition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Point trace(Location start, Location end, double interval, Predicate<Point> hitCondition) {
|
||||||
|
return trace(start, end.toVector().subtract(end.toVector()), end.distance(start), interval, hitCondition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Point trace(Location start, Vector direction, double distance, Predicate<Point> hitCondition) {
|
||||||
|
return trace(start, direction, distance, 0.5, hitCondition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Point trace(Location start, Vector direction, double distance, double interval, Predicate<Point> hitCondition) {
|
||||||
|
if (interval < 0) throw new IllegalArgumentException("interval cannot be zero!");
|
||||||
|
if (distance < 0) throw new IllegalArgumentException("distance cannot be zero!");
|
||||||
|
|
||||||
|
for (double i = 0.0; i < distance; i += interval) {
|
||||||
|
Point point = blocksInFrontOf(start, direction, i, false);
|
||||||
|
if (hitCondition.test(point)) {
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return blocksInFrontOf(start, direction, distance, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Point blocksInFrontOf(Location loc, Vector dir, double blocks, boolean missed) {
|
||||||
|
return new Point(loc.clone().add(dir.getX() * blocks, dir.getY() * blocks, dir.getZ() * blocks), blocks, missed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Point {
|
||||||
|
private final Location loc;
|
||||||
|
private final World world;
|
||||||
|
private final Block block;
|
||||||
|
private final boolean missed;
|
||||||
|
private final double traveledDist;
|
||||||
|
|
||||||
|
private Point(Location loc, double traveledDist, boolean missed) {
|
||||||
|
this.loc = loc;
|
||||||
|
this.world = loc.getWorld();
|
||||||
|
this.block = loc.getBlock();
|
||||||
|
this.missed = missed;
|
||||||
|
this.traveledDist = traveledDist;
|
||||||
|
|
||||||
|
if (world == null) {
|
||||||
|
throw new IllegalArgumentException("point world cannot be null!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Entity> getNearbyEntities(Entity exclude, int range, boolean requireContact, double expansionX, double expansionY, double expansionZ, Predicate<Entity> filter) {
|
||||||
|
return new ArrayList<>(world.getNearbyEntities(loc, range, range, range, e -> {
|
||||||
|
if (requireContact && !e.getBoundingBox().expand(expansionX, expansionY, expansionZ).contains(loc.toVector())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return filter.test(e) && e != exclude;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Entity> getNearbyEntities(Entity exclude, int range, boolean requireContact, double expansion, Predicate<Entity> filter) {
|
||||||
|
return getNearbyEntities(exclude, range, requireContact, expansion, expansion, expansion, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Entity> getNearbyEntities(Entity exclude, int range, boolean requireContact, Predicate<Entity> filter) {
|
||||||
|
return getNearbyEntities(exclude, range, requireContact, 0, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Entity> getNearbyEntities(Entity exclude, int range, Predicate<Entity> filter) {
|
||||||
|
return getNearbyEntities(exclude, range, false, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTraveledDist() {
|
||||||
|
return traveledDist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wasMissed() {
|
||||||
|
return missed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block getBlock() {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getLoc() {
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public World getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double distance(Location other) {
|
||||||
|
return other.distance(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user