match vanilla arrow/trident orientation incl. arrow impact shake, add projectile test scenes
This commit is contained in:
1 parent
addebffba1
commit
fbea9dfe08
3 files changed
+154
-3
No files matched your search
@@ -65,6 +65,21 @@ public class PPTest extends JavaPlugin {
|
||||
scenes.put("chests_e", new Scene("chests_e", this::chests, 16, 5, 3, 4.5, 0, 3));
|
||||
scenes.put("chests_w", new Scene("chests_w", this::chests, -7, 5, 3, 4.5, 0, 3));
|
||||
scenes.put("translucent", new Scene("translucent", this::translucent, 4.5, 2.8, -5.5, 4.5, 0.8, 2));
|
||||
// Projectile orientation (vanilla ArrowRenderer/ThrownTridentRenderer): flying stars around gold pillars
|
||||
// (tips point radially outward, rings level / +35 deg / -35 deg) and arrows/tridents stuck in stone pillars.
|
||||
scenes.put("proj_fly_top", new Scene("proj_fly_top", this::projFly, 6.5, 13, 2.2, 6.5, 0, 2));
|
||||
scenes.put("proj_fly_side", new Scene("proj_fly_side", this::projFly, 6.5, 2.6, -8, 6.5, 2.4, 2));
|
||||
scenes.put("proj_fly_obl", new Scene("proj_fly_obl", this::projFly, -2, 6, -6, 6.5, 2, 2));
|
||||
scenes.put("proj_stuck_nw", new Scene("proj_stuck_nw", this::projStuck, -3, 6, -6, 8, 1.5, 2));
|
||||
scenes.put("proj_stuck_se", new Scene("proj_stuck_se", this::projStuck, 19, 6, 10, 8, 1.5, 2));
|
||||
scenes.put("proj_stuck_ne", new Scene("proj_stuck_ne", this::projStuck, 19, 6, -6, 8, 1.5, 2));
|
||||
scenes.put("proj_fly_gold", new Scene("proj_fly_gold", this::projFly, 2.6, 8.5, 2.5, 2.5, 0, 2.5));
|
||||
scenes.put("proj_fly_gold_side", new Scene("proj_fly_gold_side", this::projFly, 2.5, 2.6, -3.5, 2.5, 2.4, 2.5));
|
||||
scenes.put("proj_stuck_close_a", new Scene("proj_stuck_close_a", this::projStuck, -2.5, 2.4, -2.5, 2.5, 1.6, 1));
|
||||
scenes.put("proj_stuck_close_t", new Scene("proj_stuck_close_t", this::projStuck, 18.5, 2.6, -3, 13.5, 1.6, 1));
|
||||
// Rendered 4 ticks after the shots: freshly stuck arrows still wobble (vanilla shakeTime -> pitch offset).
|
||||
scenes.put("proj_shake", new Scene("proj_shake", this::projStuck, -2.5, 2.4, -2.5, 2.5, 1.6, 1));
|
||||
scenes.put("proj_stuck_sw", new Scene("proj_stuck_sw", this::projStuck, -3, 6, 10, 8, 1.5, 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +109,7 @@ public class PPTest extends JavaPlugin {
|
||||
t.printStackTrace();
|
||||
}
|
||||
// Let one tick pass (passengers/leashes settle), then render.
|
||||
Bukkit.getScheduler().runTaskLater(this, () -> render(sc, o), 10);
|
||||
Bukkit.getScheduler().runTaskLater(this, () -> render(sc, o), sc.name.equals("proj_shake") ? 4 : sc.name.startsWith("proj_") ? 30 : 10);
|
||||
}
|
||||
|
||||
private void render(Scene sc, Location o) {
|
||||
@@ -102,7 +117,7 @@ public class PPTest extends JavaPlugin {
|
||||
Location eye = o.clone().add(sc.camX, sc.camY, sc.camZ);
|
||||
Vector look = o.clone().add(sc.lookX, sc.lookY, sc.lookZ).toVector().subtract(eye.toVector());
|
||||
eye.setDirection(look);
|
||||
RenderJob job = r.prepare(eye, new Resolution(480, 320), null);
|
||||
RenderJob job = r.prepare(eye, sc.name.startsWith("proj_") ? new Resolution(960, 640) : new Resolution(480, 320), null);
|
||||
if (sc.name.equals("dbg")) {
|
||||
try {
|
||||
java.lang.reflect.Field f = DefaultScreenRenderer.class.getDeclaredField("objectBaker");
|
||||
@@ -124,6 +139,30 @@ public class PPTest extends JavaPlugin {
|
||||
getLogger().warning("dbg: " + t);
|
||||
}
|
||||
}
|
||||
if (sc.name.startsWith("proj_"))
|
||||
for (Entity e : w.getNearbyEntities(o.clone().add(8, 3, 2), 12, 8, 12))
|
||||
if (e instanceof Projectile pr) {
|
||||
Vector v = pr.getVelocity();
|
||||
getLogger().info(String.format("proj %s yaw=%.1f pitch=%.1f velYaw=%.1f velPitch=%.1f ground=%s",
|
||||
e.getType(), e.getLocation().getYaw(), e.getLocation().getPitch(),
|
||||
Math.toDegrees(Math.atan2(v.getX(), v.getZ())),
|
||||
Math.toDegrees(Math.atan2(v.getY(), Math.hypot(v.getX(), v.getZ()))),
|
||||
pr instanceof AbstractArrow a && a.isInBlock()));
|
||||
}
|
||||
if (sc.name.equals("proj_shake"))
|
||||
for (var st : job.entities())
|
||||
if (st.typeKey().contains("arrow"))
|
||||
getLogger().info(String.format("state %s pitch=%.2f", st.typeKey(), st.pitch()));
|
||||
if (sc.name.equals("proj_shake"))
|
||||
for (Entity e : w.getNearbyEntities(o.clone().add(8, 3, 2), 12, 8, 12))
|
||||
if (e instanceof AbstractArrow a && !(e instanceof Trident))
|
||||
try {
|
||||
Object h = e.getClass().getMethod("getHandle").invoke(e);
|
||||
getLogger().info(String.format("shake %s pitch=%.2f shakeTime=%d", e.getType(), e.getLocation().getPitch(),
|
||||
h.getClass().getField("shakeTime").getInt(h)));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
getLogger().warning("shake: " + ex);
|
||||
}
|
||||
getLogger().info("scene " + sc.name + ": " + job.entities().size() + " entities, " + job.objects().size()
|
||||
+ " objects, " + job.blockEntities().size() + " block entities");
|
||||
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
|
||||
@@ -573,4 +612,81 @@ public class PPTest extends JavaPlugin {
|
||||
t.text(Component.text("Default background"));
|
||||
t.setBillboard(Display.Billboard.CENTER);
|
||||
}
|
||||
|
||||
// --- projectiles -----------------------------------------------------------------------------
|
||||
|
||||
/** Spawns a projectile at p moving along dir, rotated like vanilla Projectile#shoot (yaw atan2(x,z), pitch up). */
|
||||
private Projectile projectile(Location p, Vector dir, double speed, boolean gravity, Class<? extends Projectile> type) {
|
||||
Vector d = dir.clone().normalize();
|
||||
Location l = p.clone();
|
||||
l.setYaw((float) Math.toDegrees(Math.atan2(d.getX(), d.getZ())));
|
||||
l.setPitch((float) Math.toDegrees(Math.atan2(d.getY(), Math.hypot(d.getX(), d.getZ()))));
|
||||
Projectile pr = w.spawn(l, type, e -> {
|
||||
e.setPersistent(false);
|
||||
e.setGravity(gravity);
|
||||
e.setVelocity(d.clone().multiply(speed));
|
||||
if (e instanceof AbstractArrow a) a.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED);
|
||||
});
|
||||
pr.setRotation(l.getYaw(), l.getPitch()); // spawning resets it to 0 (it would only lerp over ~20 ticks)
|
||||
return pr;
|
||||
}
|
||||
|
||||
private static Vector dir(double yawDeg, double pitchDeg) {
|
||||
double y = Math.toRadians(yawDeg), p = Math.toRadians(pitchDeg);
|
||||
return new Vector(Math.sin(y) * Math.cos(p), Math.sin(p), Math.cos(y) * Math.cos(p));
|
||||
}
|
||||
|
||||
/** Hovering (almost still, no gravity) arrows, spectral arrows and tridents pointing radially away from a pillar. */
|
||||
private void projFly(Location o) {
|
||||
for (int y = 0; y <= 4; y++) {
|
||||
o.clone().add(2, y, 2).getBlock().setType(Material.GOLD_BLOCK, false);
|
||||
o.clone().add(11, y, 2).getBlock().setType(Material.DIAMOND_BLOCK, false);
|
||||
}
|
||||
double[][] rings = {{2.5, 0}, {4.3, 35}, {0.9, -35}}; // height, pitch
|
||||
for (double[] ring : rings)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
double yaw = i * 45;
|
||||
Vector d = dir(yaw, ring[1]);
|
||||
Vector h = dir(yaw, 0);
|
||||
Location a = o.clone().add(2.5 + h.getX() * 1.3, ring[0], 2.5 + h.getZ() * 1.3);
|
||||
projectile(a, d, 1e-4, false, (Class<? extends AbstractArrow>) (i % 2 == 0 ? Arrow.class : SpectralArrow.class));
|
||||
Location t = o.clone().add(11.5 + h.getX() * 2.1, ring[0], 2.5 + h.getZ() * 2.1);
|
||||
projectile(t, d, 1e-4, false, Trident.class);
|
||||
}
|
||||
}
|
||||
|
||||
/** Arrows and tridents shot into stone pillars from all four sides (rising, level+sideways, falling) and the floor. */
|
||||
private void projStuck(Location o) {
|
||||
for (int x = 0; x < 3; x++)
|
||||
for (int z = 0; z < 3; z++)
|
||||
for (int y = 0; y < 4; y++) {
|
||||
o.clone().add(1 + x, y, 1 + z).getBlock().setType(Material.STONE, false);
|
||||
o.clone().add(12 + x, y, 1 + z).getBlock().setType(Material.STONE, false);
|
||||
}
|
||||
double[][] pillars = {{2.5, 2.5}, {13.5, 2.5}}; // centres; arrows left, tridents right
|
||||
for (int pi = 0; pi < 2; pi++) {
|
||||
boolean trident = pi == 1;
|
||||
double cx = pillars[pi][0], cz = pillars[pi][1];
|
||||
for (int side = 0; side < 4; side++) {
|
||||
double out = side * 90; // yaw (projectile convention) pointing away from the pillar
|
||||
Vector n = dir(out, 0);
|
||||
Vector t = new Vector(n.getZ(), 0, -n.getX());
|
||||
double dist = 1.5 + 3.5;
|
||||
// rising from low, level but 20 deg sideways, falling from high
|
||||
double[][] shots = {{-1, 0.6, 25, 0}, {0, 1.6, 0, 20}, {1, 3.4, -25, 0}};
|
||||
for (double[] sh : shots) {
|
||||
Location p = o.clone().add(cx + n.getX() * dist + t.getX() * sh[0], sh[1], cz + n.getZ() * dist + t.getZ() * sh[0]);
|
||||
Vector d = dir(out + 180 + sh[3], sh[2]);
|
||||
if (trident) projectile(p, d, 2.0, true, Trident.class);
|
||||
else projectile(p, d, 1.5, true, (Class<? extends AbstractArrow>) (side % 2 == 0 ? Arrow.class : SpectralArrow.class));
|
||||
}
|
||||
// steep shot into the floor, diagonally away from the pillar
|
||||
Vector diag = dir(out + 45, 0);
|
||||
Location p = o.clone().add(cx + diag.getX() * 2.6, 3, cz + diag.getZ() * 2.6);
|
||||
Vector d = dir(out + 45, trident ? -70 : -60);
|
||||
if (trident) projectile(p, d, 2.0, true, Trident.class);
|
||||
else projectile(p, d, 1.5, true, Arrow.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user