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
|
package de.hysky.skyblocker.skyblock.crimson.dojo;
import de.hysky.skyblocker.utils.render.RenderHelper;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.Entity;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.RaycastContext;
public class TenacityTestHelper {
private static final MinecraftClient CLIENT = MinecraftClient.getInstance();
private static final Object2ObjectOpenHashMap<ArmorStandEntity, Vec3d> fireBallsWithStartPos = new Object2ObjectOpenHashMap<>();
private static final Object2ObjectOpenHashMap<ArmorStandEntity, Vec3d> particleOffsets = new Object2ObjectOpenHashMap<>();
protected static void reset() {
fireBallsWithStartPos.clear();
particleOffsets.clear();
}
protected static void render(WorldRenderContext context) {
for (ArmorStandEntity fireball : fireBallsWithStartPos.keySet()) {
Vec3d lineStart = fireBallsWithStartPos.get(fireball).add(particleOffsets.getOrDefault(fireball, Vec3d.ZERO));
Vec3d fireballPos = fireball.getPos().add(particleOffsets.getOrDefault(fireball, Vec3d.ZERO));
Vec3d distance = fireballPos.subtract(lineStart);
if (distance.length() > 0.02) { //if big enough gap try from start calculate and show trajectory
distance = distance.multiply(100);
Vec3d lineEnd = lineStart.add(distance);
RenderHelper.renderLinesFromPoints(context, new Vec3d[]{lineStart, lineEnd}, new float[]{1f, 0f, 0f}, 1, 3, false);
//get highlighted block
HitResult hitResult = raycast(lineStart, lineEnd, fireball);
if (hitResult != null && hitResult.getType() == HitResult.Type.BLOCK && hitResult instanceof BlockHitResult blockHitResult) {
RenderHelper.renderFilled(context, blockHitResult.getBlockPos(), new float[]{1f, 0f, 0f}, 0.5f, false);
}
}
}
}
protected static HitResult raycast(Vec3d start, Vec3d end, ArmorStandEntity fireball) {
if (CLIENT == null || CLIENT.world == null) {
return null;
}
return CLIENT.world.raycast(new RaycastContext(start, end, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.ANY, fireball));
}
/**
* If a spawned entity is an armour stand add it to the fireballs map (assuming all armour stands are fireballs)
*
* @param entity spawned entity
*/
protected static void onEntitySpawn(Entity entity) {
if (entity instanceof ArmorStandEntity armorStand) {
fireBallsWithStartPos.put(armorStand, armorStand.getPos());
}
}
protected static void onEntityDespawn(Entity entity) {
if (entity instanceof ArmorStandEntity armorStand) {
fireBallsWithStartPos.remove(armorStand);
}
}
/**
* Uses the particles spawned with the fireballs to offset from the armour stand position to get a more accurate guess of where it's going
*
* @param packet particle packet
*/
protected static void onParticle(ParticleS2CPacket packet) {
if (!ParticleTypes.FLAME.equals(packet.getParameters().getType())) {
return;
}
//get nearest fireball to particle
Vec3d particlePos = new Vec3d(packet.getX(), packet.getY(), packet.getZ());
ArmorStandEntity neareastFireball = null;
double clostestDistance = 50;
for (ArmorStandEntity fireball : fireBallsWithStartPos.keySet()) {
double distance = fireball.getPos().distanceTo(particlePos);
if (distance < clostestDistance) {
neareastFireball = fireball;
clostestDistance = distance;
}
}
if (neareastFireball == null) { //can not find fireball near particle
return;
}
//adjust fireball offset with particle pos
Vec3d delta = particlePos.subtract(neareastFireball.getPos());
//update values
particleOffsets.put(neareastFireball, delta);
}
}
|