1010import com .denizenscript .denizencore .objects .ObjectTag ;
1111import com .denizenscript .denizencore .objects .core .ElementTag ;
1212import com .denizenscript .denizencore .objects .core .ListTag ;
13+ import com .denizenscript .denizencore .objects .core .QuaternionTag ;
1314import com .denizenscript .denizencore .tags .Attribute ;
1415import com .denizenscript .denizencore .tags .ObjectTagProcessor ;
1516import com .denizenscript .denizencore .tags .TagContext ;
1617import com .denizenscript .denizencore .utilities .CoreUtilities ;
1718import com .denizenscript .denizencore .utilities .debugging .Debug ;
1819import kr .toxicity .model .api .BetterModel ;
1920import kr .toxicity .model .api .bone .RenderedBone ;
20- import kr .toxicity .model .api .nms .ModelDisplay ;
21- import kr .toxicity .model .api .nms .PacketBundler ;
2221import kr .toxicity .model .api .tracker .EntityTracker ;
23- import kr .toxicity .model .api .util .TransformedItemStack ;
24- import kr .toxicity .model .api .util .function .BonePredicate ;
2522import net .openproject .dbettermodel .api .BMBone ;
2623import org .bukkit .entity .Player ;
2724import org .bukkit .util .Vector ;
25+ import org .joml .Quaternionf ;
2826import org .joml .Vector3f ;
2927
3028import java .util .List ;
@@ -57,10 +55,8 @@ public static BMBoneTag valueOf(String string) {
5755 public static BMBoneTag valueOf (String string , TagContext context ) {
5856 if (string == null ) return null ;
5957 String lower = CoreUtilities .toLowerCase (string );
60-
6158 if (!lower .startsWith (PREFIX + "@" )) return null ;
6259 String body = string .substring (PREFIX .length () + 1 );
63-
6460 String [] parts = body .split ("," , 3 );
6561 if (parts .length < 3 ) return null ;
6662
@@ -93,26 +89,47 @@ public BMBoneTag(EntityTracker tracker, RenderedBone bone) {
9389 this .boneApi = new BMBone (tracker , bone );
9490 }
9591
96- public RenderedBone getBone () { return bone ; }
92+ public RenderedBone getBone () {
93+ return bone ;
94+ }
9795
9896 private String prefix = PREFIX ;
9997
100- @ Override public String getPrefix () { return prefix ; }
101- @ Override public ObjectTag setPrefix (String s ) { this .prefix = s ;
102- return this ; }
103- @ Override public boolean isUnique () { return true ; }
98+ @ Override
99+ public String getPrefix () {
100+ return prefix ;
101+ }
102+
103+ @ Override
104+ public ObjectTag setPrefix (String s ) {
105+ this .prefix = s ;
106+ return this ;
107+ }
108+
109+ @ Override
110+ public boolean isUnique () {
111+ return true ;
112+ }
104113
105114 @ Override
106115 public String identify () {
107- return PREFIX + "@"
108- + tracker .registry ().uuid ()
109- + "," + tracker .name ()
110- + "," + bone .getName ().name ();
116+ return PREFIX + "@" + tracker .registry ().uuid () + "," + tracker .name () + "," + bone .getName ().name ();
117+ }
118+
119+ @ Override
120+ public String identifySimple () {
121+ return identify ();
122+ }
123+
124+ @ Override
125+ public Object getJavaObject () {
126+ return bone ;
111127 }
112128
113- @ Override public String identifySimple () { return identify (); }
114- @ Override public Object getJavaObject () { return bone ; }
115- @ Override public String toString () { return identify (); }
129+ @ Override
130+ public String toString () {
131+ return identify ();
132+ }
116133
117134 public static final ObjectTagProcessor <BMBoneTag > tagProcessor = new ObjectTagProcessor <>();
118135
@@ -124,8 +141,7 @@ public static void registerTags() {
124141 // @description
125142 // Returns the name of the bone.
126143 // -->
127- tagProcessor .registerTag (ElementTag .class , "name" , (attr , obj ) ->
128- new ElementTag (obj .getBone ().getName ().name ())
144+ tagProcessor .registerTag (ElementTag .class , "name" , (attr , obj ) -> new ElementTag (obj .getBone ().getName ().name ())
129145 );
130146
131147 // <--[tag]
@@ -148,8 +164,7 @@ public static void registerTags() {
148164 // @description
149165 // Returns whether the bone is currently visible.
150166 // -->
151- tagProcessor .registerTag (ElementTag .class , "is_visible" , (attr , obj ) ->
152- new ElementTag (obj .getBone ().isVisible ())
167+ tagProcessor .registerTag (ElementTag .class , "is_visible" , (attr , obj ) -> new ElementTag (obj .getBone ().isVisible ())
153168 );
154169
155170 // <--[tag]
@@ -159,17 +174,20 @@ public static void registerTags() {
159174 // @description
160175 // Returns the parent model of this bone.
161176 // -->
162- tagProcessor .registerTag (BMModelTag .class , "bm_model" , (attr , obj ) ->
163- new BMModelTag (obj .tracker )
177+ tagProcessor .registerTag (BMModelTag .class , "bm_model" , (attr , obj ) -> new BMModelTag (obj .tracker )
164178 );
165179 }
166180
167- @ Override public ObjectTag getObjectAttribute (Attribute attribute ) {
181+ @ Override
182+ public ObjectTag getObjectAttribute (Attribute attribute ) {
168183 return tagProcessor .getObjectAttribute (this , attribute );
169184 }
170185
171186 @ Override
172187 public void adjust (Mechanism mechanism ) {
188+ // All mechanisms are handled by the BMBone API class for cleanliness.
189+ // The BMBone class abstracts away direct calls to the tracker and bone.
190+
173191 // <--[mechanism]
174192 // @object BMBoneTag
175193 // @name tint
@@ -204,16 +222,13 @@ public void adjust(Mechanism mechanism) {
204222 // @example
205223 // # Show the 'sword' bone only to a specific player
206224 // - adjust <[my_model].bone[sword]> visible:<list[true|<player>]>
207- // @example
208- // # Hide the 'cape' bone for a list of players
209- // - adjust <[my_model].bone[cape]> visible:<list[false|<server.online_players.exclude[<player>]>]>
210225 // -->
211226 if (mechanism .matches ("visible" )) {
212227 boolean visible ;
213228 ListTag targets = null ;
214229 if (mechanism .value .canBeType (ListTag .class )) {
215230 ListTag list = mechanism .valueAsType (ListTag .class );
216- if (list .isEmpty () ||!list .getObject (0 ).canBeType (ElementTag .class ) ||!list .getObject (0 ).asElement ().isBoolean ()) {
231+ if (list .isEmpty () || !list .getObject (0 ).canBeType (ElementTag .class ) || !list .getObject (0 ).asElement ().isBoolean ()) {
217232 mechanism .echoError ("If using a ListTag for 'visible', the first element must be a boolean (true/false)." );
218233 return ;
219234 }
@@ -288,18 +303,39 @@ public void adjust(Mechanism mechanism) {
288303 // This sets the base scale and will be multiplied by any animation scales.
289304 // @example
290305 // # Make a bone twice as wide
291- // - adjust <[my_bone]> scale:<location>
306+ // - adjust <[my_bone]> scale:<location[2,1,1] >
292307 // -->
293308 if (mechanism .matches ("scale" ) && mechanism .requireObject (LocationTag .class )) {
294309 LocationTag loc = mechanism .valueAsType (LocationTag .class );
295310 Vector3f scaleVector = new Vector3f ((float ) loc .getX (), (float ) loc .getY (), (float ) loc .getZ ());
296311 boneApi .setScale (scaleVector );
297312 }
298313
314+ // <--[mechanism]
315+ // @object BMBoneTag
316+ // @name rotate
317+ // @input QuaternionTag
318+ // @plugin DBetterModel
319+ // @description
320+ // Sets an additional rotation for the bone, which is applied on top of its current animation.
321+ // Each use of this mechanism replaces the previous rotation value, it does not add to it.
322+ // This allows for dynamic, script-controlled rotation independent of predefined animations.
323+ // @example
324+ // # Rotate a bone 45 degrees around the world's Y (up/down) axis.
325+ // - adjust <[my_bone]> rotate:<location[0,1,0].to_axis_angle_quaternion[<element[45].to_radians>]>
326+ // -->
327+ if (mechanism .matches ("rotate" ) && mechanism .requireObject (QuaternionTag .class )) {
328+ QuaternionTag quatTag = mechanism .valueAsType (QuaternionTag .class );
329+ // Construct a JOML Quaternionf from the Denizen QuaternionTag's public fields.
330+ // A cast from double to float is required.
331+ boneApi .setRotation (new Quaternionf ((float ) quatTag .x , (float ) quatTag .y , (float ) quatTag .z , (float ) quatTag .w ));
332+ }
333+
299334 tagProcessor .processMechanism (this , mechanism );
300335 }
301336
302- @ Override public void applyProperty (Mechanism mechanism ) {
337+ @ Override
338+ public void applyProperty (Mechanism mechanism ) {
303339 Debug .echoError ("Cannot apply properties to a BMBoneTag!" );
304340 }
305- }
341+ }
0 commit comments