Skip to content

Commit a74f4b1

Browse files
author
meigoc
committed
DBetterModel 3.3.0
1 parent 37a33ef commit a74f4b1

4 files changed

Lines changed: 91 additions & 37 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ project.build.sourceEncoding=UTF-8
22
craftbukkit.version=1.21.4-R0.1-SNAPSHOT
33
denizen.version=1.3.1-SNAPSHOT
44
bettermodel.version=1.10.1
5-
BUILD_NUMBER=3.2.0
5+
BUILD_NUMBER=3.3.0

src/main/java/net/openproject/dbettermodel/DBetterModel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class DBetterModel extends JavaPlugin {
2525
private SkinsRestorer skinsRestorerApi;
2626

2727
public static final String BETTERMODEL_VERSION = "1.10.1";
28-
public static final String DBETTERMODEL_VERSION = "3.2.0";
28+
public static final String DBETTERMODEL_VERSION = "3.3.0";
2929

3030
public static long skinApplyDelay;
3131
public static boolean enablePluginLogging;

src/main/java/net/openproject/dbettermodel/api/BMBone.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.bukkit.entity.Player;
1010
import org.bukkit.inventory.ItemStack;
1111
import org.jetbrains.annotations.Nullable;
12+
import org.joml.Quaternionf;
1213
import org.joml.Vector3f;
1314

1415
import java.util.List;
@@ -22,6 +23,7 @@ public class BMBone {
2223

2324
private final EntityTracker tracker;
2425
private final RenderedBone bone;
26+
private final Quaternionf customRotation = new Quaternionf(); // Identity quaternion
2527

2628
/**
2729
* Constructs a new BMBone API object.
@@ -32,6 +34,24 @@ public class BMBone {
3234
public BMBone(EntityTracker tracker, RenderedBone bone) {
3335
this.tracker = tracker;
3436
this.bone = bone;
37+
38+
// Add a persistent rotation modifier that applies our custom rotation.
39+
// This ensures we are *adding* to the animation, and by changing the
40+
// customRotation field, we can "set" the rotation without adding more modifiers.
41+
this.bone.addRotationModifier(BonePredicate.TRUE, animationRotation ->
42+
animationRotation.mul(customRotation)
43+
);
44+
}
45+
46+
/**
47+
* Sets an additional rotation to be applied to the bone, post-animation.
48+
* Each call to this method replaces the previous custom rotation.
49+
*
50+
* @param rotation The Quaternionf representing the desired additional rotation.
51+
*/
52+
public void setRotation(Quaternionf rotation) {
53+
this.customRotation.set(rotation);
54+
tracker.forceUpdate(true);
3555
}
3656

3757
/**
@@ -96,14 +116,12 @@ public void setItem(ItemStack itemStack, @Nullable Vector3f localOffset) {
96116
// to avoid resetting other transformations. The offset is replaced if provided.
97117
TransformedItemStack defaultTis = bone.getGroup().getItemStack();
98118
Vector3f offset = (localOffset != null) ? localOffset : defaultTis.offset();
99-
100119
TransformedItemStack newTis = new TransformedItemStack(
101120
defaultTis.position(),
102121
offset,
103122
defaultTis.scale(),
104123
itemStack
105124
);
106-
107125
if (bone.itemStack(BonePredicate.TRUE, newTis)) {
108126
tracker.forceUpdate(true);
109127
}
@@ -129,4 +147,4 @@ public void setScale(Vector3f scale) {
129147
tracker.forceUpdate(true);
130148
}
131149
}
132-
}
150+
}

src/main/java/net/openproject/dbettermodel/objects/BMBoneTag.java

Lines changed: 68 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,19 @@
1010
import com.denizenscript.denizencore.objects.ObjectTag;
1111
import com.denizenscript.denizencore.objects.core.ElementTag;
1212
import com.denizenscript.denizencore.objects.core.ListTag;
13+
import com.denizenscript.denizencore.objects.core.QuaternionTag;
1314
import com.denizenscript.denizencore.tags.Attribute;
1415
import com.denizenscript.denizencore.tags.ObjectTagProcessor;
1516
import com.denizenscript.denizencore.tags.TagContext;
1617
import com.denizenscript.denizencore.utilities.CoreUtilities;
1718
import com.denizenscript.denizencore.utilities.debugging.Debug;
1819
import kr.toxicity.model.api.BetterModel;
1920
import kr.toxicity.model.api.bone.RenderedBone;
20-
import kr.toxicity.model.api.nms.ModelDisplay;
21-
import kr.toxicity.model.api.nms.PacketBundler;
2221
import kr.toxicity.model.api.tracker.EntityTracker;
23-
import kr.toxicity.model.api.util.TransformedItemStack;
24-
import kr.toxicity.model.api.util.function.BonePredicate;
2522
import net.openproject.dbettermodel.api.BMBone;
2623
import org.bukkit.entity.Player;
2724
import org.bukkit.util.Vector;
25+
import org.joml.Quaternionf;
2826
import org.joml.Vector3f;
2927

3028
import 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

Comments
 (0)