20
20
import java .util .Set ;
21
21
22
22
public class AnimationHandler {
23
+ // Cache of item frames positions that are currently being animated
23
24
private static final Set <BlockPos > cachedFrames = new HashSet <>();
24
25
26
+ /**
27
+ * Handles the animation for the armor stand when an item frame is powered while holding a compatible armor poser book
28
+ *
29
+ * @param frame The item frame that is being checked
30
+ */
25
31
public static void onFrameUpdate (ItemFrame frame ) {
26
32
if (frame .level () instanceof ServerLevel serverLevel && frame .getDirection () == Direction .UP ) {
27
33
BlockPos pos = frame .blockPosition ();
28
34
ItemStack frameStack = frame .getItem ();
35
+ // Check if the item frame is holding a valid armor poser book
29
36
if (isValidArmorPoserBook (frameStack )) {
37
+ // Check if the item frame is powered
30
38
if (serverLevel .getSignal (pos , Direction .UP ) >= 1 ) {
31
39
if (!cachedFrames .contains (pos )) {
32
40
cachedFrames .add (pos );
33
41
WrittenBookContent bookContent = frameStack .getOrDefault (DataComponents .WRITTEN_BOOK_CONTENT , WrittenBookContent .EMPTY );
42
+ // The name to match the armor stand with (empty string if no match required)
34
43
String match = "" ;
35
44
if (!bookContent .pages ().isEmpty ()) {
36
45
var firstPage = bookContent .pages ().getFirst ();
37
46
if (!firstPage .raw ().getString ().isEmpty ())
38
47
match = firstPage .raw ().getString ();
39
48
}
49
+ // Targeting conditions for the armor stand
40
50
TargetingConditions conditions = TargetingConditions .forNonCombat ();
41
51
if (!match .isEmpty ()) {
42
52
String finalMatch = match ;
43
53
conditions .selector ((livingEntity , level ) ->
44
54
livingEntity .getName ().getString ().equals (finalMatch ));
45
55
}
56
+ // Search for the nearest armor stand within the search radius
46
57
var nearestStand = serverLevel .getNearestEntity (ArmorStand .class , conditions , null , pos .getX (), pos .getY (), pos .getZ (),
47
58
AABB .ofSize (frame .position (), Reference .ANIMATION_SEARCH_RADIUS , Reference .ANIMATION_SEARCH_RADIUS , Reference .ANIMATION_SEARCH_RADIUS ));
48
59
if (nearestStand != null ) {
49
60
CompoundTag customTag = frameStack .getOrDefault (DataComponents .CUSTOM_DATA , CustomData .EMPTY ).copyTag ();
61
+ // Check if the book contains a saved pose
50
62
if (customTag .contains ("SavedPose" )) {
51
63
CompoundTag poseTag = customTag .getCompound ("SavedPose" );
52
64
BookCopyData bookCopyData = new BookCopyData (nearestStand .getUUID (), poseTag );
@@ -61,6 +73,12 @@ public static void onFrameUpdate(ItemFrame frame) {
61
73
}
62
74
}
63
75
76
+ /**
77
+ * Checks if the item frame is holding a valid armor poser book
78
+ *
79
+ * @param stack The item stack that is being checked
80
+ * @return True if the item stack is a valid armor poser book
81
+ */
64
82
private static boolean isValidArmorPoserBook (ItemStack stack ) {
65
83
return stack .is (Items .WRITTEN_BOOK )
66
84
&& stack .getCustomName () != null
0 commit comments